github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/states/tree.go (about) 1 package states 2 3 import ( 4 "github.com/filecoin-project/go-address" 5 "github.com/filecoin-project/go-state-types/abi" 6 states0 "github.com/filecoin-project/specs-actors/actors/states" 7 "github.com/ipfs/go-cid" 8 "golang.org/x/xerrors" 9 10 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 11 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" 12 ) 13 14 // Value type of the top level of the state tree. 15 // Represents the on-chain state of a single actor. 16 // type Actor struct { 17 // Code cid.Cid // CID representing the code associated with the actor 18 // Head cid.Cid // CID of the head state object for the actor 19 // CallSeqNum uint64 // CallSeqNum for the next message to be received by the actor (non-zero for accounts only) 20 // Balance big.Int // Token balance of the actor 21 // } 22 type Actor = states0.Actor 23 24 // A specialization of a map of ID-addresses to actor heads. 25 type Tree struct { 26 Map *adt.Map 27 Store adt.Store 28 } 29 30 // Initializes a new, empty state tree backed by a store. 31 func NewTree(store adt.Store) (*Tree, error) { 32 emptyMap, err := adt.MakeEmptyMap(store, builtin.DefaultHamtBitwidth) 33 if err != nil { 34 return nil, err 35 } 36 return &Tree{ 37 Map: emptyMap, 38 Store: store, 39 }, nil 40 } 41 42 // Loads a tree from a root CID and store. 43 func LoadTree(s adt.Store, r cid.Cid) (*Tree, error) { 44 m, err := adt.AsMap(s, r, builtin.DefaultHamtBitwidth) 45 if err != nil { 46 return nil, err 47 } 48 return &Tree{ 49 Map: m, 50 Store: s, 51 }, nil 52 } 53 54 // Writes the tree root node to the store, and returns its CID. 55 func (t *Tree) Flush() (cid.Cid, error) { 56 return t.Map.Root() 57 } 58 59 // Loads the state associated with an address. 60 func (t *Tree) GetActor(addr address.Address) (*Actor, bool, error) { 61 if addr.Protocol() != address.ID { 62 return nil, false, xerrors.Errorf("non-ID address %v invalid as actor key", addr) 63 } 64 var actor Actor 65 found, err := t.Map.Get(abi.AddrKey(addr), &actor) 66 return &actor, found, err 67 } 68 69 // Sets the state associated with an address, overwriting if it already present. 70 func (t *Tree) SetActor(addr address.Address, actor *Actor) error { 71 if addr.Protocol() != address.ID { 72 return xerrors.Errorf("non-ID address %v invalid as actor key", addr) 73 } 74 return t.Map.Put(abi.AddrKey(addr), actor) 75 } 76 77 // Traverses all entries in the tree. 78 func (t *Tree) ForEach(fn func(addr address.Address, actor *Actor) error) error { 79 var val Actor 80 return t.Map.ForEach(&val, func(key string) error { 81 addr, err := address.NewFromBytes([]byte(key)) 82 if err != nil { 83 return err 84 } 85 return fn(addr, &val) 86 }) 87 } 88 89 // Traverses all keys in the tree, without decoding the actor states. 90 func (t *Tree) ForEachKey(fn func(addr address.Address) error) error { 91 return t.Map.ForEach(nil, func(key string) error { 92 addr, err := address.NewFromBytes([]byte(key)) 93 if err != nil { 94 return err 95 } 96 return fn(addr) 97 }) 98 }