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  }