/
state.go
74 lines (64 loc) · 1.5 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
package owldag
import (
"context"
"crypto/rand"
"encoding/json"
"github.com/brendoncarroll/go-state/cadata"
"github.com/gotvc/got/pkg/gotkv"
"github.com/owlmessenger/owl/pkg/slices2"
)
// State is the current state of the feed.
type State[T any] struct {
Max uint64 `json:"max"`
// Prev is the set of heads needed to reference the entire graph.
Prev []Head `json:"prev"`
// Heads is the root of the head for each peer.
Heads gotkv.Root `json:"heads"`
Epochs []Ref `json:"epochs"`
X T `json:"x"`
}
func ParseState[T any](data []byte) (*State[T], error) {
var state State[T]
if err := json.Unmarshal(data, &state); err != nil {
return nil, err
}
return &state, nil
}
func (s State[T]) PrevRefs() IDSet[Ref] {
return NewIDSet(slices2.Map(s.Prev, func(x Head) Ref { return x.Ref })...)
}
func (s State[T]) Marshal() []byte {
data, err := json.Marshal(s)
if err != nil {
panic(err)
}
return data
}
func InitState[T any](ctx context.Context, s cadata.Store, x T, salt *[32]byte) (*State[T], error) {
if salt == nil {
salt = new([32]byte)
if _, err := rand.Read(salt[:]); err != nil {
return nil, err
}
}
kvop := gotkv.NewOperator(1<<12, MaxNodeSize)
sigsRoot, err := kvop.NewEmpty(ctx, s)
if err != nil {
return nil, err
}
ref, err := PostNode(ctx, s, Node[T]{
Salt: salt[:],
State: x,
Sigs: *sigsRoot,
})
if err != nil {
return nil, err
}
return &State[T]{
Max: 0,
Prev: []Head{{Ref: *ref}},
Epochs: []Ref{*ref},
X: x,
Heads: *sigsRoot,
}, nil
}