github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/init/init_actor.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  	"github.com/filecoin-project/go-state-types/cbor"
     7  	"github.com/filecoin-project/go-state-types/exitcode"
     8  	init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
     9  	cid "github.com/ipfs/go-cid"
    10  
    11  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    12  	"github.com/filecoin-project/specs-actors/v4/actors/runtime"
    13  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    14  )
    15  
    16  // The init actor uniquely has the power to create new actors.
    17  // It maintains a table resolving pubkey and temporary actor addresses to the canonical ID-addresses.
    18  type Actor struct{}
    19  
    20  func (a Actor) Exports() []interface{} {
    21  	return []interface{}{
    22  		builtin.MethodConstructor: a.Constructor,
    23  		2:                         a.Exec,
    24  	}
    25  }
    26  
    27  func (a Actor) Code() cid.Cid {
    28  	return builtin.InitActorCodeID
    29  }
    30  
    31  func (a Actor) IsSingleton() bool {
    32  	return true
    33  }
    34  
    35  func (a Actor) State() cbor.Er { return new(State) }
    36  
    37  var _ runtime.VMActor = Actor{}
    38  
    39  //type ConstructorParams struct {
    40  //	NetworkName string
    41  //}
    42  type ConstructorParams = init0.ConstructorParams
    43  
    44  func (a Actor) Constructor(rt runtime.Runtime, params *ConstructorParams) *abi.EmptyValue {
    45  	rt.ValidateImmediateCallerIs(builtin.SystemActorAddr)
    46  	st, err := ConstructState(adt.AsStore(rt), params.NetworkName)
    47  	builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to construct state")
    48  	rt.StateCreate(st)
    49  	return nil
    50  }
    51  
    52  //type ExecParams struct {
    53  //	CodeCID           cid.Cid `checked:"true"` // invalid CIDs won't get committed to the state tree
    54  //	ConstructorParams []byte
    55  //}
    56  type ExecParams = init0.ExecParams
    57  
    58  //type ExecReturn struct {
    59  //	IDAddress     addr.Address // The canonical ID-based address for the actor.
    60  //	RobustAddress addr.Address // A more expensive but re-org-safe address for the newly created actor.
    61  //}
    62  type ExecReturn = init0.ExecReturn
    63  
    64  func (a Actor) Exec(rt runtime.Runtime, params *ExecParams) *ExecReturn {
    65  	rt.ValidateImmediateCallerAcceptAny()
    66  	callerCodeCID, ok := rt.GetActorCodeCID(rt.Caller())
    67  	builtin.RequireState(rt, ok, "no code for caller at %s", rt.Caller())
    68  	if !canExec(callerCodeCID, params.CodeCID) {
    69  		rt.Abortf(exitcode.ErrForbidden, "caller type %v cannot exec actor type %v", callerCodeCID, params.CodeCID)
    70  	}
    71  
    72  	// Compute a re-org-stable address.
    73  	// This address exists for use by messages coming from outside the system, in order to
    74  	// stably address the newly created actor even if a chain re-org causes it to end up with
    75  	// a different ID.
    76  	uniqueAddress := rt.NewActorAddress()
    77  
    78  	// Allocate an ID for this actor.
    79  	// Store mapping of pubkey or actor address to actor ID
    80  	var st State
    81  	var idAddr addr.Address
    82  	rt.StateTransaction(&st, func() {
    83  		var err error
    84  		idAddr, err = st.MapAddressToNewID(adt.AsStore(rt), uniqueAddress)
    85  		builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to allocate ID address")
    86  	})
    87  
    88  	// Create an empty actor.
    89  	rt.CreateActor(params.CodeCID, idAddr)
    90  
    91  	// Invoke constructor.
    92  	code := rt.Send(idAddr, builtin.MethodConstructor, builtin.CBORBytes(params.ConstructorParams), rt.ValueReceived(), &builtin.Discard{})
    93  	builtin.RequireSuccess(rt, code, "constructor failed")
    94  
    95  	return &ExecReturn{IDAddress: idAddr, RobustAddress: uniqueAddress}
    96  }
    97  
    98  func canExec(callerCodeID cid.Cid, execCodeID cid.Cid) bool {
    99  	switch execCodeID {
   100  	case builtin.StorageMinerActorCodeID:
   101  		if callerCodeID == builtin.StoragePowerActorCodeID {
   102  			return true
   103  		}
   104  		return false
   105  	case builtin.PaymentChannelActorCodeID, builtin.MultisigActorCodeID:
   106  		return true
   107  	default:
   108  		return false
   109  	}
   110  }