github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/init/init_test.go (about) 1 package init_test 2 3 import ( 4 "strings" 5 "testing" 6 7 addr "github.com/filecoin-project/go-address" 8 "github.com/filecoin-project/go-state-types/abi" 9 "github.com/filecoin-project/go-state-types/big" 10 "github.com/filecoin-project/go-state-types/exitcode" 11 cid "github.com/ipfs/go-cid" 12 assert "github.com/stretchr/testify/assert" 13 14 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 15 init_ "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" 16 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" 17 "github.com/filecoin-project/specs-actors/v4/support/mock" 18 tutil "github.com/filecoin-project/specs-actors/v4/support/testing" 19 ) 20 21 func TestExports(t *testing.T) { 22 mock.CheckActorExports(t, init_.Actor{}) 23 } 24 25 func TestConstructor(t *testing.T) { 26 actor := initHarness{init_.Actor{}, t} 27 28 receiver := tutil.NewIDAddr(t, 1000) 29 builder := mock.NewBuilder(receiver).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 30 rt := builder.Build(t) 31 actor.constructAndVerify(rt) 32 actor.checkState(rt) 33 } 34 35 func TestExec(t *testing.T) { 36 actor := initHarness{init_.Actor{}, t} 37 38 receiver := tutil.NewIDAddr(t, 1000) 39 anne := tutil.NewIDAddr(t, 1001) 40 builder := mock.NewBuilder(receiver).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 41 42 t.Run("abort actors that cannot call exec", func(t *testing.T) { 43 rt := builder.Build(t) 44 actor.constructAndVerify(rt) 45 46 rt.SetCaller(anne, builtin.AccountActorCodeID) 47 rt.ExpectAbort(exitcode.ErrForbidden, func() { 48 actor.execAndVerify(rt, builtin.StoragePowerActorCodeID, []byte{}) 49 }) 50 rt.ExpectAbort(exitcode.ErrForbidden, func() { 51 actor.execAndVerify(rt, builtin.StorageMinerActorCodeID, []byte{}) 52 }) 53 rt.ExpectAbort(exitcode.ErrForbidden, func() { 54 actor.execAndVerify(rt, cid.Undef, []byte{}) 55 }) 56 actor.checkState(rt) 57 }) 58 59 var fakeParams = builtin.CBORBytes([]byte{'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'}) 60 var balance = abi.NewTokenAmount(100) 61 62 t.Run("happy path exec create 2 payment channels", func(t *testing.T) { 63 rt := builder.Build(t) 64 65 actor.constructAndVerify(rt) 66 // anne execs a payment channel actor with 100 FIL. 67 rt.SetCaller(anne, builtin.AccountActorCodeID) 68 69 rt.SetBalance(balance) 70 rt.SetReceived(balance) 71 72 // re-org-stable address of the payment channel actor 73 uniqueAddr1 := tutil.NewActorAddr(t, "paych") 74 rt.SetNewActorAddress(uniqueAddr1) 75 76 // next id address 77 expectedIdAddr1 := tutil.NewIDAddr(t, 100) 78 rt.ExpectCreateActor(builtin.PaymentChannelActorCodeID, expectedIdAddr1) 79 80 // expect anne creating a payment channel to trigger a send to the payment channels constructor 81 rt.ExpectSend(expectedIdAddr1, builtin.MethodConstructor, fakeParams, balance, nil, exitcode.Ok) 82 execRet1 := actor.execAndVerify(rt, builtin.PaymentChannelActorCodeID, fakeParams) 83 assert.Equal(t, uniqueAddr1, execRet1.RobustAddress) 84 assert.Equal(t, expectedIdAddr1, execRet1.IDAddress) 85 86 var st init_.State 87 rt.GetState(&st) 88 actualIdAddr, found, err := st.ResolveAddress(adt.AsStore(rt), uniqueAddr1) 89 assert.NoError(t, err) 90 assert.True(t, found) 91 assert.Equal(t, expectedIdAddr1, actualIdAddr) 92 93 // creating another actor should get a different address, the below logic is a repeat of the above to insure 94 // the next ID address created is incremented. 100 -> 101 95 rt.SetBalance(balance) 96 rt.SetReceived(balance) 97 uniqueAddr2 := tutil.NewActorAddr(t, "paych2") 98 rt.SetNewActorAddress(uniqueAddr2) 99 // the incremented ID address. 100 expectedIdAddr2 := tutil.NewIDAddr(t, 101) 101 rt.ExpectCreateActor(builtin.PaymentChannelActorCodeID, expectedIdAddr2) 102 103 // expect anne creating a payment channel to trigger a send to the payment channels constructor 104 rt.ExpectSend(expectedIdAddr2, builtin.MethodConstructor, fakeParams, balance, nil, exitcode.Ok) 105 execRet2 := actor.execAndVerify(rt, builtin.PaymentChannelActorCodeID, fakeParams) 106 assert.Equal(t, uniqueAddr2, execRet2.RobustAddress) 107 assert.Equal(t, expectedIdAddr2, execRet2.IDAddress) 108 109 var st2 init_.State 110 rt.GetState(&st2) 111 actualIdAddr2, found, err := st2.ResolveAddress(adt.AsStore(rt), uniqueAddr2) 112 assert.NoError(t, err) 113 assert.True(t, found) 114 assert.Equal(t, expectedIdAddr2, actualIdAddr2) 115 actor.checkState(rt) 116 }) 117 118 t.Run("happy path exec create storage miner", func(t *testing.T) { 119 rt := builder.Build(t) 120 121 actor.constructAndVerify(rt) 122 123 // only the storage power actor can create a miner 124 rt.SetCaller(builtin.StoragePowerActorAddr, builtin.StoragePowerActorCodeID) 125 126 // re-org-stable address of the storage miner actor 127 uniqueAddr := tutil.NewActorAddr(t, "miner") 128 rt.SetNewActorAddress(uniqueAddr) 129 130 // next id address 131 expectedIdAddr := tutil.NewIDAddr(t, 100) 132 rt.ExpectCreateActor(builtin.StorageMinerActorCodeID, expectedIdAddr) 133 134 // expect storage power actor creating a storage miner actor to trigger a send to the storage miner actors constructor 135 rt.ExpectSend(expectedIdAddr, builtin.MethodConstructor, fakeParams, big.Zero(), nil, exitcode.Ok) 136 execRet := actor.execAndVerify(rt, builtin.StorageMinerActorCodeID, fakeParams) 137 assert.Equal(t, uniqueAddr, execRet.RobustAddress) 138 assert.Equal(t, expectedIdAddr, execRet.IDAddress) 139 140 var st init_.State 141 rt.GetState(&st) 142 actualIdAddr, found, err := st.ResolveAddress(adt.AsStore(rt), uniqueAddr) 143 assert.NoError(t, err) 144 assert.True(t, found) 145 assert.Equal(t, expectedIdAddr, actualIdAddr) 146 147 // returns false if not able to resolve 148 expUnknowAddr := tutil.NewActorAddr(t, "flurbo") 149 actualUnknownAddr, found, err := st.ResolveAddress(adt.AsStore(rt), expUnknowAddr) 150 assert.NoError(t, err) 151 assert.False(t, found) 152 assert.Equal(t, addr.Undef, actualUnknownAddr) 153 actor.checkState(rt) 154 }) 155 156 t.Run("happy path create multisig actor", func(t *testing.T) { 157 rt := builder.Build(t) 158 159 actor.constructAndVerify(rt) 160 161 // actor creating the multisig actor 162 someAccountActor := tutil.NewIDAddr(t, 1234) 163 rt.SetCaller(someAccountActor, builtin.AccountActorCodeID) 164 165 uniqueAddr := tutil.NewActorAddr(t, "multisig") 166 rt.SetNewActorAddress(uniqueAddr) 167 168 // next id address 169 expectedIdAddr := tutil.NewIDAddr(t, 100) 170 rt.ExpectCreateActor(builtin.MultisigActorCodeID, expectedIdAddr) 171 172 // expect a send to the multisig actor constructor 173 rt.ExpectSend(expectedIdAddr, builtin.MethodConstructor, fakeParams, big.Zero(), nil, exitcode.Ok) 174 execRet := actor.execAndVerify(rt, builtin.MultisigActorCodeID, fakeParams) 175 assert.Equal(t, uniqueAddr, execRet.RobustAddress) 176 assert.Equal(t, expectedIdAddr, execRet.IDAddress) 177 actor.checkState(rt) 178 }) 179 180 t.Run("sending to constructor failure", func(t *testing.T) { 181 rt := builder.Build(t) 182 183 actor.constructAndVerify(rt) 184 185 // only the storage power actor can create a miner 186 rt.SetCaller(builtin.StoragePowerActorAddr, builtin.StoragePowerActorCodeID) 187 188 // re-org-stable address of the storage miner actor 189 uniqueAddr := tutil.NewActorAddr(t, "miner") 190 rt.SetNewActorAddress(uniqueAddr) 191 192 // next id address 193 expectedIdAddr := tutil.NewIDAddr(t, 100) 194 rt.ExpectCreateActor(builtin.StorageMinerActorCodeID, expectedIdAddr) 195 196 // expect storage power actor creating a storage miner actor to trigger a send to the storage miner actors constructor 197 rt.ExpectSend(expectedIdAddr, builtin.MethodConstructor, fakeParams, big.Zero(), nil, exitcode.ErrIllegalState) 198 var execRet *init_.ExecReturn 199 rt.ExpectAbort(exitcode.ErrIllegalState, func() { 200 execRet = actor.execAndVerify(rt, builtin.StorageMinerActorCodeID, fakeParams) 201 assert.Nil(t, execRet) 202 }) 203 204 // since the send failed the uniqueAddr not resolve 205 var st init_.State 206 rt.GetState(&st) 207 noResoAddr, found, err := st.ResolveAddress(adt.AsStore(rt), uniqueAddr) 208 assert.NoError(t, err) 209 assert.False(t, found) 210 assert.Equal(t, addr.Undef, noResoAddr) 211 actor.checkState(rt) 212 }) 213 } 214 215 type initHarness struct { 216 init_.Actor 217 t testing.TB 218 } 219 220 func (h *initHarness) state(rt *mock.Runtime) *init_.State { 221 var st init_.State 222 rt.GetState(&st) 223 return &st 224 } 225 226 func (h *initHarness) checkState(rt *mock.Runtime) { 227 st := h.state(rt) 228 _, msgs := init_.CheckStateInvariants(st, rt.AdtStore()) 229 assert.True(h.t, msgs.IsEmpty(), strings.Join(msgs.Messages(), "\n")) 230 } 231 232 func (h *initHarness) constructAndVerify(rt *mock.Runtime) { 233 rt.ExpectValidateCallerAddr(builtin.SystemActorAddr) 234 ret := rt.Call(h.Constructor, &init_.ConstructorParams{NetworkName: "mock"}) 235 assert.Nil(h.t, ret) 236 rt.Verify() 237 238 var st init_.State 239 rt.GetState(&st) 240 emptyMap, err := adt.AsMap(adt.AsStore(rt), st.AddressMap, builtin.DefaultHamtBitwidth) 241 assert.NoError(h.t, err) 242 assert.Equal(h.t, tutil.MustRoot(h.t, emptyMap), st.AddressMap) 243 assert.Equal(h.t, abi.ActorID(builtin.FirstNonSingletonActorId), st.NextID) 244 assert.Equal(h.t, "mock", st.NetworkName) 245 } 246 247 func (h *initHarness) execAndVerify(rt *mock.Runtime, codeID cid.Cid, constructorParams []byte) *init_.ExecReturn { 248 rt.ExpectValidateCallerAny() 249 ret := rt.Call(h.Exec, &init_.ExecParams{ 250 CodeCID: codeID, 251 ConstructorParams: constructorParams, 252 }).(*init_.ExecReturn) 253 rt.Verify() 254 return ret 255 }