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 }