github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/init/init_actor_state.go (about)

     1  package init
     2  
     3  import (
     4  	addr "github.com/filecoin-project/go-address"
     5  	"github.com/filecoin-project/go-state-types/abi"
     6  	cid "github.com/ipfs/go-cid"
     7  	cbg "github.com/whyrusleeping/cbor-gen"
     8  	xerrors "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  type State struct {
    15  	AddressMap  cid.Cid // HAMT[addr.Address]abi.ActorID
    16  	NextID      abi.ActorID
    17  	NetworkName string
    18  }
    19  
    20  func ConstructState(store adt.Store, networkName string) (*State, error) {
    21  	emptyAddressMapCid, err := adt.StoreEmptyMap(store, builtin.DefaultHamtBitwidth)
    22  	if err != nil {
    23  		return nil, xerrors.Errorf("failed to create empty map: %w", err)
    24  	}
    25  
    26  	return &State{
    27  		AddressMap:  emptyAddressMapCid,
    28  		NextID:      abi.ActorID(builtin.FirstNonSingletonActorId),
    29  		NetworkName: networkName,
    30  	}, nil
    31  }
    32  
    33  // ResolveAddress resolves an address to an ID-address, if possible.
    34  // If the provided address is an ID address, it is returned as-is.
    35  // This means that mapped ID-addresses (which should only appear as values, not keys) and
    36  // singleton actor addresses (which are not in the map) pass through unchanged.
    37  //
    38  // Returns an ID-address and `true` if the address was already an ID-address or was resolved in the mapping.
    39  // Returns an undefined address and `false` if the address was not an ID-address and not found in the mapping.
    40  // Returns an error only if state was inconsistent.
    41  func (s *State) ResolveAddress(store adt.Store, address addr.Address) (addr.Address, bool, error) {
    42  	// Short-circuit ID address resolution.
    43  	if address.Protocol() == addr.ID {
    44  		return address, true, nil
    45  	}
    46  
    47  	// Lookup address.
    48  	m, err := adt.AsMap(store, s.AddressMap, builtin.DefaultHamtBitwidth)
    49  	if err != nil {
    50  		return addr.Undef, false, xerrors.Errorf("failed to load address map: %w", err)
    51  	}
    52  
    53  	var actorID cbg.CborInt
    54  	if found, err := m.Get(abi.AddrKey(address), &actorID); err != nil {
    55  		return addr.Undef, false, xerrors.Errorf("failed to get from address map: %w", err)
    56  	} else if found {
    57  		// Reconstruct address from the ActorID.
    58  		idAddr, err := addr.NewIDAddress(uint64(actorID))
    59  		return idAddr, true, err
    60  	} else {
    61  		return addr.Undef, false, nil
    62  	}
    63  }
    64  
    65  // Allocates a new ID address and stores a mapping of the argument address to it.
    66  // Returns the newly-allocated address.
    67  func (s *State) MapAddressToNewID(store adt.Store, address addr.Address) (addr.Address, error) {
    68  	actorID := cbg.CborInt(s.NextID)
    69  	s.NextID++
    70  
    71  	m, err := adt.AsMap(store, s.AddressMap, builtin.DefaultHamtBitwidth)
    72  	if err != nil {
    73  		return addr.Undef, xerrors.Errorf("failed to load address map: %w", err)
    74  	}
    75  	err = m.Put(abi.AddrKey(address), &actorID)
    76  	if err != nil {
    77  		return addr.Undef, xerrors.Errorf("map address failed to store entry: %w", err)
    78  	}
    79  	amr, err := m.Root()
    80  	if err != nil {
    81  		return addr.Undef, xerrors.Errorf("failed to get address map root: %w", err)
    82  	}
    83  	s.AddressMap = amr
    84  
    85  	idAddr, err := addr.NewIDAddress(uint64(actorID))
    86  	return idAddr, err
    87  }