This repository has been archived by the owner on Jun 6, 2023. It is now read-only.
/
tree.go
98 lines (87 loc) · 2.78 KB
/
tree.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
package states
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
states0 "github.com/filecoin-project/specs-actors/actors/states"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/specs-actors/v8/actors/builtin"
"github.com/filecoin-project/specs-actors/v8/actors/util/adt"
)
// Value type of the top level of the state tree.
// Represents the on-chain state of a single actor.
// type Actor struct {
// Code cid.Cid // CID representing the code associated with the actor
// Head cid.Cid // CID of the head state object for the actor
// CallSeqNum uint64 // CallSeqNum for the next message to be received by the actor (non-zero for accounts only)
// Balance big.Int // Token balance of the actor
// }
type Actor = states0.Actor
// A specialization of a map of ID-addresses to actor heads.
type Tree struct {
Map *adt.Map
Store adt.Store
}
// Initializes a new, empty state tree backed by a store.
func NewTree(store adt.Store) (*Tree, error) {
emptyMap, err := adt.MakeEmptyMap(store, builtin.DefaultHamtBitwidth)
if err != nil {
return nil, err
}
return &Tree{
Map: emptyMap,
Store: store,
}, nil
}
// Loads a tree from a root CID and store.
func LoadTree(s adt.Store, r cid.Cid) (*Tree, error) {
m, err := adt.AsMap(s, r, builtin.DefaultHamtBitwidth)
if err != nil {
return nil, err
}
return &Tree{
Map: m,
Store: s,
}, nil
}
// Writes the tree root node to the store, and returns its CID.
func (t *Tree) Flush() (cid.Cid, error) {
return t.Map.Root()
}
// Loads the state associated with an address.
func (t *Tree) GetActor(addr address.Address) (*Actor, bool, error) {
if addr.Protocol() != address.ID {
return nil, false, xerrors.Errorf("non-ID address %v invalid as actor key", addr)
}
var actor Actor
found, err := t.Map.Get(abi.AddrKey(addr), &actor)
return &actor, found, err
}
// Sets the state associated with an address, overwriting if it already present.
func (t *Tree) SetActor(addr address.Address, actor *Actor) error {
if addr.Protocol() != address.ID {
return xerrors.Errorf("non-ID address %v invalid as actor key", addr)
}
return t.Map.Put(abi.AddrKey(addr), actor)
}
// Traverses all entries in the tree.
func (t *Tree) ForEach(fn func(addr address.Address, actor *Actor) error) error {
var val Actor
return t.Map.ForEach(&val, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return fn(addr, &val)
})
}
// Traverses all keys in the tree, without decoding the actor states.
func (t *Tree) ForEachKey(fn func(addr address.Address) error) error {
return t.Map.ForEach(nil, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return fn(addr)
})
}