-
Notifications
You must be signed in to change notification settings - Fork 109
/
state.go
103 lines (87 loc) · 2.75 KB
/
state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package state
import (
"context"
"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/keyformat"
abciAPI "github.com/oasisprotocol/oasis-core/go/consensus/tendermint/api"
"github.com/oasisprotocol/oasis-core/go/keymanager/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
)
// statusKeyFmt is the key manager status key format.
//
// Value is CBOR-serialized key manager status.
var statusKeyFmt = keyformat.New(0x70, keyformat.H(&common.Namespace{}))
// ImmutableState is the immutable key manager state wrapper.
type ImmutableState struct {
is *abciAPI.ImmutableState
}
func (st *ImmutableState) Statuses(ctx context.Context) ([]*api.Status, error) {
rawStatuses, err := st.getStatusesRaw(ctx)
if err != nil {
return nil, err
}
var statuses []*api.Status
for _, raw := range rawStatuses {
var status api.Status
if err = cbor.Unmarshal(raw, &status); err != nil {
return nil, abciAPI.UnavailableStateError(err)
}
statuses = append(statuses, &status)
}
return statuses, nil
}
func (st *ImmutableState) getStatusesRaw(ctx context.Context) ([][]byte, error) {
it := st.is.NewIterator(ctx)
defer it.Close()
var rawVec [][]byte
for it.Seek(statusKeyFmt.Encode()); it.Valid(); it.Next() {
if !statusKeyFmt.Decode(it.Key()) {
break
}
rawVec = append(rawVec, it.Value())
}
if it.Err() != nil {
return nil, abciAPI.UnavailableStateError(it.Err())
}
return rawVec, nil
}
func (st *ImmutableState) Status(ctx context.Context, id common.Namespace) (*api.Status, error) {
data, err := st.is.Get(ctx, statusKeyFmt.Encode(&id))
if err != nil {
return nil, abciAPI.UnavailableStateError(err)
}
if data == nil {
return nil, api.ErrNoSuchStatus
}
var status api.Status
if err := cbor.Unmarshal(data, &status); err != nil {
return nil, abciAPI.UnavailableStateError(err)
}
return &status, nil
}
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
}
return &ImmutableState{is}, nil
}
// MutableState is a mutable key manager state wrapper.
type MutableState struct {
*ImmutableState
ms mkvs.KeyValueTree
}
func (st *MutableState) SetStatus(ctx context.Context, status *api.Status) error {
err := st.ms.Insert(ctx, statusKeyFmt.Encode(&status.ID), cbor.Marshal(status))
return abciAPI.UnavailableStateError(err)
}
// NewMutableState creates a new mutable key manager state wrapper.
func NewMutableState(tree mkvs.KeyValueTree) *MutableState {
return &MutableState{
ImmutableState: &ImmutableState{
&abciAPI.ImmutableState{ImmutableKeyValueTree: tree},
},
ms: tree,
}
}