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  }