github.com/filecoin-project/specs-actors/v4@v4.0.2/support/vm/testing.go (about)

     1  package vm_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/filecoin-project/go-address"
    10  	"github.com/filecoin-project/go-state-types/abi"
    11  	"github.com/filecoin-project/go-state-types/big"
    12  	"github.com/filecoin-project/go-state-types/cbor"
    13  	"github.com/filecoin-project/go-state-types/dline"
    14  	"github.com/filecoin-project/go-state-types/exitcode"
    15  	"github.com/ipfs/go-cid"
    16  	ipldcbor "github.com/ipfs/go-ipld-cbor"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  
    20  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    21  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/account"
    22  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/cron"
    23  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/exported"
    24  	initactor "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
    25  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
    26  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
    27  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
    28  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/reward"
    29  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/system"
    30  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
    31  	"github.com/filecoin-project/specs-actors/v4/actors/runtime"
    32  	"github.com/filecoin-project/specs-actors/v4/actors/states"
    33  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    34  	"github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
    35  	actor_testing "github.com/filecoin-project/specs-actors/v4/support/testing"
    36  )
    37  
    38  var FIL = big.NewInt(1e18)
    39  var VerifregRoot address.Address
    40  
    41  func init() {
    42  	var err error
    43  	VerifregRoot, err = address.NewIDAddress(80)
    44  	if err != nil {
    45  		panic("could not create id address 80")
    46  	}
    47  }
    48  
    49  //
    50  // Genesis like setup
    51  //
    52  
    53  // Creates a new VM and initializes all singleton actors plus a root verifier account.
    54  func NewVMWithSingletons(ctx context.Context, t testing.TB, bs ipldcbor.IpldBlockstore) *VM {
    55  	lookup := map[cid.Cid]runtime.VMActor{}
    56  	for _, ba := range exported.BuiltinActors() {
    57  		lookup[ba.Code()] = ba
    58  	}
    59  
    60  	store := adt.WrapBlockStore(ctx, bs)
    61  	vm := NewVM(ctx, lookup, store)
    62  
    63  	initializeActor(ctx, t, vm, &system.State{}, builtin.SystemActorCodeID, builtin.SystemActorAddr, big.Zero())
    64  
    65  	initState, err := initactor.ConstructState(store, "scenarios")
    66  	require.NoError(t, err)
    67  	initializeActor(ctx, t, vm, initState, builtin.InitActorCodeID, builtin.InitActorAddr, big.Zero())
    68  
    69  	rewardState := reward.ConstructState(abi.NewStoragePower(0))
    70  	initializeActor(ctx, t, vm, rewardState, builtin.RewardActorCodeID, builtin.RewardActorAddr, reward.StorageMiningAllocationCheck)
    71  
    72  	cronState := cron.ConstructState(cron.BuiltInEntries())
    73  	initializeActor(ctx, t, vm, cronState, builtin.CronActorCodeID, builtin.CronActorAddr, big.Zero())
    74  
    75  	powerState, err := power.ConstructState(store)
    76  	require.NoError(t, err)
    77  	initializeActor(ctx, t, vm, powerState, builtin.StoragePowerActorCodeID, builtin.StoragePowerActorAddr, big.Zero())
    78  
    79  	marketState, err := market.ConstructState(store)
    80  	require.NoError(t, err)
    81  	initializeActor(ctx, t, vm, marketState, builtin.StorageMarketActorCodeID, builtin.StorageMarketActorAddr, big.Zero())
    82  
    83  	// this will need to be replaced with the address of a multisig actor for the verified registry to be tested accurately
    84  	initializeActor(ctx, t, vm, &account.State{Address: VerifregRoot}, builtin.AccountActorCodeID, VerifregRoot, big.Zero())
    85  	vrState, err := verifreg.ConstructState(store, VerifregRoot)
    86  	require.NoError(t, err)
    87  	initializeActor(ctx, t, vm, vrState, builtin.VerifiedRegistryActorCodeID, builtin.VerifiedRegistryActorAddr, big.Zero())
    88  
    89  	// burnt funds
    90  	initializeActor(ctx, t, vm, &account.State{Address: builtin.BurntFundsActorAddr}, builtin.AccountActorCodeID, builtin.BurntFundsActorAddr, big.Zero())
    91  
    92  	_, err = vm.checkpoint()
    93  	require.NoError(t, err)
    94  
    95  	return vm
    96  }
    97  
    98  // Creates n account actors in the VM with the given balance
    99  func CreateAccounts(ctx context.Context, t testing.TB, vm *VM, n int, balance abi.TokenAmount, seed int64) []address.Address {
   100  	var initState initactor.State
   101  	err := vm.GetState(builtin.InitActorAddr, &initState)
   102  	require.NoError(t, err)
   103  
   104  	addrPairs := make([]addrPair, n)
   105  	for i := range addrPairs {
   106  		addr := actor_testing.NewBLSAddr(t, seed+int64(i))
   107  		idAddr, err := initState.MapAddressToNewID(vm.store, addr)
   108  		require.NoError(t, err)
   109  
   110  		addrPairs[i] = addrPair{
   111  			pubAddr: addr,
   112  			idAddr:  idAddr,
   113  		}
   114  	}
   115  	err = vm.SetActorState(ctx, builtin.InitActorAddr, &initState)
   116  	require.NoError(t, err)
   117  
   118  	pubAddrs := make([]address.Address, len(addrPairs))
   119  	for i, addrPair := range addrPairs {
   120  		st := &account.State{Address: addrPair.pubAddr}
   121  		initializeActor(ctx, t, vm, st, builtin.AccountActorCodeID, addrPair.idAddr, balance)
   122  		pubAddrs[i] = addrPair.pubAddr
   123  	}
   124  	return pubAddrs
   125  }
   126  
   127  //
   128  // Invocation expectations
   129  //
   130  
   131  // ExpectInvocation is a pattern for a message invocation within the VM.
   132  // The To and Method fields must be supplied. Exitcode defaults to exitcode.Ok.
   133  // All other field are optional, where a nil or Undef value indicates that any value will match.
   134  // SubInvocations will be matched recursively.
   135  type ExpectInvocation struct {
   136  	To     address.Address
   137  	Method abi.MethodNum
   138  
   139  	// optional
   140  	Exitcode       exitcode.ExitCode
   141  	From           address.Address
   142  	Value          *abi.TokenAmount
   143  	Params         *objectExpectation
   144  	Ret            *objectExpectation
   145  	SubInvocations []ExpectInvocation
   146  }
   147  
   148  func (ei ExpectInvocation) Matches(t *testing.T, invocations *Invocation) {
   149  	ei.matches(t, "", invocations)
   150  }
   151  
   152  func (ei ExpectInvocation) matches(t *testing.T, breadcrumb string, invocation *Invocation) {
   153  	identifier := fmt.Sprintf("%s[%s:%d]", breadcrumb, invocation.Msg.to, invocation.Msg.method)
   154  
   155  	// mismatch of to or method probably indicates skipped message or messages out of order. halt.
   156  	require.Equal(t, ei.To, invocation.Msg.to, "%s unexpected 'to' address", identifier)
   157  	require.Equal(t, ei.Method, invocation.Msg.method, "%s unexpected method", identifier)
   158  
   159  	// other expectations are optional
   160  	if address.Undef != ei.From {
   161  		assert.Equal(t, ei.From, invocation.Msg.from, "%s unexpected from address", identifier)
   162  	}
   163  	if ei.Value != nil {
   164  		assert.Equal(t, *ei.Value, invocation.Msg.value, "%s unexpected value", identifier)
   165  	}
   166  	if ei.Params != nil {
   167  		assert.True(t, ei.Params.matches(invocation.Msg.params), "%s params aren't equal (%v != %v)", identifier, ei.Params.val, invocation.Msg.params)
   168  	}
   169  	if ei.SubInvocations != nil {
   170  		for i, invk := range invocation.SubInvocations {
   171  			subidentifier := fmt.Sprintf("%s%d:", identifier, i)
   172  			// attempt match only if methods match
   173  			require.True(t, len(ei.SubInvocations) > i && ei.SubInvocations[i].To == invk.Msg.to && ei.SubInvocations[i].Method == invk.Msg.method,
   174  				"%s unexpected subinvocation [%s:%d]\nexpected:\n%s\nactual:\n%s",
   175  				subidentifier, invk.Msg.to, invk.Msg.method, ei.listSubinvocations(), listInvocations(invocation.SubInvocations))
   176  			ei.SubInvocations[i].matches(t, subidentifier, invk)
   177  		}
   178  		missingInvocations := len(ei.SubInvocations) - len(invocation.SubInvocations)
   179  		if missingInvocations > 0 {
   180  			missingIndex := len(invocation.SubInvocations)
   181  			missingExpect := ei.SubInvocations[missingIndex]
   182  			require.Failf(t, "missing expected invocations", "%s%d: expected invocation [%s:%d]\nexpected:\n%s\nactual:\n%s",
   183  				identifier, missingIndex, missingExpect.To, missingExpect.Method, ei.listSubinvocations(), listInvocations(invocation.SubInvocations))
   184  		}
   185  	}
   186  
   187  	// expect results
   188  	assert.Equal(t, ei.Exitcode, invocation.Exitcode, "%s unexpected exitcode", identifier)
   189  	if ei.Ret != nil {
   190  		assert.True(t, ei.Ret.matches(invocation.Ret), "%s unexpected return value (%v != %v)", identifier, ei.Ret, invocation.Ret)
   191  	}
   192  }
   193  
   194  func (ei ExpectInvocation) listSubinvocations() string {
   195  	if len(ei.SubInvocations) == 0 {
   196  		return "[no invocations]\n"
   197  	}
   198  	list := ""
   199  	for i, si := range ei.SubInvocations {
   200  		list = fmt.Sprintf("%s%2d: [%s:%d]\n", list, i, si.To, si.Method)
   201  	}
   202  	return list
   203  }
   204  
   205  func listInvocations(invocations []*Invocation) string {
   206  	if len(invocations) == 0 {
   207  		return "[no invocations]\n"
   208  	}
   209  	list := ""
   210  	for i, si := range invocations {
   211  		list = fmt.Sprintf("%s%2d: [%s:%d]\n", list, i, si.Msg.to, si.Msg.method)
   212  	}
   213  	return list
   214  }
   215  
   216  // helpers to simplify pointer creation
   217  func ExpectAttoFil(amount big.Int) *big.Int                    { return &amount }
   218  func ExpectBytes(b []byte) *objectExpectation                  { return ExpectObject(builtin.CBORBytes(b)) }
   219  func ExpectExitCode(code exitcode.ExitCode) *exitcode.ExitCode { return &code }
   220  
   221  func ExpectObject(v cbor.Marshaler) *objectExpectation {
   222  	return &objectExpectation{v}
   223  }
   224  
   225  // distinguishes a non-expectation from an expectation of nil
   226  type objectExpectation struct {
   227  	val cbor.Marshaler
   228  }
   229  
   230  // match by cbor encoding to avoid inconsistencies in internal representations of effectively equal objects
   231  func (oe objectExpectation) matches(obj interface{}) bool {
   232  	if oe.val == nil || obj == nil {
   233  		return oe.val == nil && obj == nil
   234  	}
   235  
   236  	paramBuf1 := new(bytes.Buffer)
   237  	oe.val.MarshalCBOR(paramBuf1) // nolint: errcheck
   238  	marshaller, ok := obj.(cbor.Marshaler)
   239  	if !ok {
   240  		return false
   241  	}
   242  	paramBuf2 := new(bytes.Buffer)
   243  	if marshaller != nil {
   244  		marshaller.MarshalCBOR(paramBuf2) // nolint: errcheck
   245  	}
   246  	return bytes.Equal(paramBuf1.Bytes(), paramBuf2.Bytes())
   247  }
   248  
   249  var okExitCode = exitcode.Ok
   250  var ExpectOK = &okExitCode
   251  
   252  func ParamsForInvocation(t *testing.T, vm *VM, idxs ...int) interface{} {
   253  	invocations := vm.Invocations()
   254  	var invocation *Invocation
   255  	for _, idx := range idxs {
   256  		require.Greater(t, len(invocations), idx)
   257  		invocation = invocations[idx]
   258  		invocations = invocation.SubInvocations
   259  	}
   260  	require.NotNil(t, invocation)
   261  	return invocation.Msg.params
   262  }
   263  
   264  func ValueForInvocation(t *testing.T, vm *VM, idxs ...int) abi.TokenAmount {
   265  	invocations := vm.Invocations()
   266  	var invocation *Invocation
   267  	for _, idx := range idxs {
   268  		require.Greater(t, len(invocations), idx)
   269  		invocation = invocations[idx]
   270  		invocations = invocation.SubInvocations
   271  	}
   272  	require.NotNil(t, invocation)
   273  	return invocation.Msg.value
   274  }
   275  
   276  //
   277  // Advancing Time while updating state
   278  //
   279  
   280  type advanceDeadlinePredicate func(dlInfo *dline.Info) bool
   281  
   282  func MinerDLInfo(t *testing.T, v *VM, minerIDAddr address.Address) *dline.Info {
   283  	var minerState miner.State
   284  	err := v.GetState(minerIDAddr, &minerState)
   285  	require.NoError(t, err)
   286  
   287  	return miner.NewDeadlineInfoFromOffsetAndEpoch(minerState.ProvingPeriodStart, v.GetEpoch())
   288  }
   289  
   290  func NextMinerDLInfo(t *testing.T, v *VM, minerIDAddr address.Address) *dline.Info {
   291  	var minerState miner.State
   292  	err := v.GetState(minerIDAddr, &minerState)
   293  	require.NoError(t, err)
   294  
   295  	return miner.NewDeadlineInfoFromOffsetAndEpoch(minerState.ProvingPeriodStart, v.GetEpoch()+1)
   296  }
   297  
   298  // AdvanceByDeadline creates a new VM advanced to an epoch specified by the predicate while keeping the
   299  // miner state upu-to-date by running a cron at the end of each deadline period.
   300  func AdvanceByDeadline(t *testing.T, v *VM, minerIDAddr address.Address, predicate advanceDeadlinePredicate) (*VM, *dline.Info) {
   301  	dlInfo := MinerDLInfo(t, v, minerIDAddr)
   302  	var err error
   303  	for predicate(dlInfo) {
   304  		v, err = v.WithEpoch(dlInfo.Last())
   305  		require.NoError(t, err)
   306  
   307  		_, code := v.ApplyMessage(builtin.SystemActorAddr, builtin.CronActorAddr, big.Zero(), builtin.MethodsCron.EpochTick, nil)
   308  		require.Equal(t, exitcode.Ok, code)
   309  
   310  		dlInfo = NextMinerDLInfo(t, v, minerIDAddr)
   311  	}
   312  	return v, dlInfo
   313  }
   314  
   315  // Advances by deadline until e is contained within the deadline period represented by the returned deadline info.
   316  // The VM returned will be set to the last deadline close, not at e.
   317  func AdvanceByDeadlineTillEpoch(t *testing.T, v *VM, minerIDAddr address.Address, e abi.ChainEpoch) (*VM, *dline.Info) {
   318  	return AdvanceByDeadline(t, v, minerIDAddr, func(dlInfo *dline.Info) bool {
   319  		return dlInfo.Close <= e
   320  	})
   321  }
   322  
   323  // Advances by deadline until the deadline index matches the given index.
   324  // The vm returned will be set to the close epoch of the previous deadline.
   325  func AdvanceByDeadlineTillIndex(t *testing.T, v *VM, minerIDAddr address.Address, i uint64) (*VM, *dline.Info) {
   326  	return AdvanceByDeadline(t, v, minerIDAddr, func(dlInfo *dline.Info) bool {
   327  		return dlInfo.Index != i
   328  	})
   329  }
   330  
   331  // Advance to the epoch when the sector is due to be proven.
   332  // Returns the deadline info for proving deadline for sector, partition index of sector, and a VM at the opening of
   333  // the deadline (ready for SubmitWindowedPoSt).
   334  func AdvanceTillProvingDeadline(t *testing.T, v *VM, minerIDAddress address.Address, sectorNumber abi.SectorNumber) (*dline.Info, uint64, *VM) {
   335  	dlIdx, pIdx := SectorDeadline(t, v, minerIDAddress, sectorNumber)
   336  
   337  	// advance time to next proving period
   338  	v, dlInfo := AdvanceByDeadlineTillIndex(t, v, minerIDAddress, dlIdx)
   339  	v, err := v.WithEpoch(dlInfo.Open)
   340  	require.NoError(t, err)
   341  	return dlInfo, pIdx, v
   342  }
   343  
   344  // find the proving deadline and partition index of a miner's sector
   345  func SectorDeadline(t *testing.T, v *VM, minerIDAddress address.Address, sectorNumber abi.SectorNumber) (uint64, uint64) {
   346  	var minerState miner.State
   347  	err := v.GetState(minerIDAddress, &minerState)
   348  	require.NoError(t, err)
   349  
   350  	dlIdx, pIdx, err := minerState.FindSector(v.Store(), sectorNumber)
   351  	require.NoError(t, err)
   352  	return dlIdx, pIdx
   353  }
   354  
   355  ///
   356  // state abstraction
   357  //
   358  
   359  type MinerBalances struct {
   360  	AvailableBalance abi.TokenAmount
   361  	VestingBalance   abi.TokenAmount
   362  	InitialPledge    abi.TokenAmount
   363  	PreCommitDeposit abi.TokenAmount
   364  }
   365  
   366  func GetMinerBalances(t *testing.T, vm *VM, minerIdAddr address.Address) MinerBalances {
   367  	var state miner.State
   368  	a, found, err := vm.GetActor(minerIdAddr)
   369  	require.NoError(t, err)
   370  	require.True(t, found)
   371  
   372  	err = vm.GetState(minerIdAddr, &state)
   373  	require.NoError(t, err)
   374  
   375  	return MinerBalances{
   376  		AvailableBalance: big.Subtract(a.Balance, state.PreCommitDeposits, state.InitialPledge, state.LockedFunds, state.FeeDebt),
   377  		PreCommitDeposit: state.PreCommitDeposits,
   378  		VestingBalance:   state.LockedFunds,
   379  		InitialPledge:    state.InitialPledge,
   380  	}
   381  }
   382  
   383  func PowerForMinerSector(t *testing.T, vm *VM, minerIdAddr address.Address, sectorNumber abi.SectorNumber) miner.PowerPair {
   384  	var state miner.State
   385  	err := vm.GetState(minerIdAddr, &state)
   386  	require.NoError(t, err)
   387  
   388  	sector, found, err := state.GetSector(vm.store, sectorNumber)
   389  	require.NoError(t, err)
   390  	require.True(t, found)
   391  
   392  	sectorSize, err := sector.SealProof.SectorSize()
   393  	require.NoError(t, err)
   394  	return miner.PowerForSector(sectorSize, sector)
   395  }
   396  
   397  func MinerPower(t *testing.T, vm *VM, minerIdAddr address.Address) miner.PowerPair {
   398  	var state power.State
   399  	err := vm.GetState(builtin.StoragePowerActorAddr, &state)
   400  	require.NoError(t, err)
   401  
   402  	claim, found, err := state.GetClaim(vm.store, minerIdAddr)
   403  	require.NoError(t, err)
   404  	require.True(t, found)
   405  
   406  	return miner.NewPowerPair(claim.RawBytePower, claim.QualityAdjPower)
   407  }
   408  
   409  type NetworkStats struct {
   410  	power.State
   411  	TotalRawBytePower             abi.StoragePower
   412  	TotalBytesCommitted           abi.StoragePower
   413  	TotalQualityAdjPower          abi.StoragePower
   414  	TotalQABytesCommitted         abi.StoragePower
   415  	TotalPledgeCollateral         abi.TokenAmount
   416  	ThisEpochRawBytePower         abi.StoragePower
   417  	ThisEpochQualityAdjPower      abi.StoragePower
   418  	ThisEpochPledgeCollateral     abi.TokenAmount
   419  	MinerCount                    int64
   420  	MinerAboveMinPowerCount       int64
   421  	ThisEpochReward               abi.TokenAmount
   422  	ThisEpochRewardSmoothed       smoothing.FilterEstimate
   423  	ThisEpochBaselinePower        abi.StoragePower
   424  	TotalStoragePowerReward       abi.TokenAmount
   425  	TotalClientLockedCollateral   abi.TokenAmount
   426  	TotalProviderLockedCollateral abi.TokenAmount
   427  	TotalClientStorageFee         abi.TokenAmount
   428  }
   429  
   430  func GetNetworkStats(t *testing.T, vm *VM) NetworkStats {
   431  	var powerState power.State
   432  	err := vm.GetState(builtin.StoragePowerActorAddr, &powerState)
   433  	require.NoError(t, err)
   434  
   435  	var rewardState reward.State
   436  	err = vm.GetState(builtin.RewardActorAddr, &rewardState)
   437  	require.NoError(t, err)
   438  
   439  	var marketState market.State
   440  	err = vm.GetState(builtin.StorageMarketActorAddr, &marketState)
   441  	require.NoError(t, err)
   442  
   443  	return NetworkStats{
   444  		TotalRawBytePower:             powerState.TotalRawBytePower,
   445  		TotalBytesCommitted:           powerState.TotalBytesCommitted,
   446  		TotalQualityAdjPower:          powerState.TotalQualityAdjPower,
   447  		TotalQABytesCommitted:         powerState.TotalQABytesCommitted,
   448  		TotalPledgeCollateral:         powerState.TotalPledgeCollateral,
   449  		ThisEpochRawBytePower:         powerState.ThisEpochRawBytePower,
   450  		ThisEpochQualityAdjPower:      powerState.ThisEpochQualityAdjPower,
   451  		ThisEpochPledgeCollateral:     powerState.ThisEpochPledgeCollateral,
   452  		MinerCount:                    powerState.MinerCount,
   453  		MinerAboveMinPowerCount:       powerState.MinerAboveMinPowerCount,
   454  		ThisEpochReward:               rewardState.ThisEpochReward,
   455  		ThisEpochRewardSmoothed:       rewardState.ThisEpochRewardSmoothed,
   456  		ThisEpochBaselinePower:        rewardState.ThisEpochBaselinePower,
   457  		TotalStoragePowerReward:       rewardState.TotalStoragePowerReward,
   458  		TotalClientLockedCollateral:   marketState.TotalClientLockedCollateral,
   459  		TotalProviderLockedCollateral: marketState.TotalProviderLockedCollateral,
   460  		TotalClientStorageFee:         marketState.TotalClientStorageFee,
   461  	}
   462  }
   463  
   464  func GetDealState(t *testing.T, vm *VM, dealID abi.DealID) (*market.DealState, bool) {
   465  	var marketState market.State
   466  	err := vm.GetState(builtin.StorageMarketActorAddr, &marketState)
   467  	require.NoError(t, err)
   468  
   469  	states, err := market.AsDealStateArray(vm.store, marketState.States)
   470  	require.NoError(t, err)
   471  
   472  	state, found, err := states.Get(dealID)
   473  	require.NoError(t, err)
   474  
   475  	return state, found
   476  }
   477  
   478  //
   479  // Misc. helpers
   480  //
   481  
   482  func ApplyOk(t *testing.T, v *VM, from, to address.Address, value abi.TokenAmount, method abi.MethodNum, params interface{}) cbor.Marshaler {
   483  	ret, code := v.ApplyMessage(from, to, value, method, params)
   484  	require.Equal(t, exitcode.Ok, code)
   485  	return ret
   486  }
   487  
   488  //
   489  //  internal stuff
   490  //
   491  
   492  func initializeActor(ctx context.Context, t testing.TB, vm *VM, state cbor.Marshaler, code cid.Cid, a address.Address, balance abi.TokenAmount) {
   493  	stateCID, err := vm.store.Put(ctx, state)
   494  	require.NoError(t, err)
   495  	actor := &states.Actor{
   496  		Head:    stateCID,
   497  		Code:    code,
   498  		Balance: balance,
   499  	}
   500  	err = vm.setActor(ctx, a, actor)
   501  	require.NoError(t, err)
   502  }
   503  
   504  type addrPair struct {
   505  	pubAddr address.Address
   506  	idAddr  address.Address
   507  }