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

     1  package mock
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"reflect"
     8  	goruntime "runtime"
     9  	"runtime/debug"
    10  	"strings"
    11  	"testing"
    12  
    13  	addr "github.com/filecoin-project/go-address"
    14  	"github.com/filecoin-project/go-state-types/abi"
    15  	"github.com/filecoin-project/go-state-types/big"
    16  	"github.com/filecoin-project/go-state-types/cbor"
    17  	"github.com/filecoin-project/go-state-types/crypto"
    18  	"github.com/filecoin-project/go-state-types/exitcode"
    19  	"github.com/filecoin-project/go-state-types/network"
    20  	"github.com/filecoin-project/go-state-types/rt"
    21  	cid "github.com/ipfs/go-cid"
    22  	mh "github.com/multiformats/go-multihash"
    23  
    24  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    25  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/exported"
    26  	"github.com/filecoin-project/specs-actors/v4/actors/runtime"
    27  	"github.com/filecoin-project/specs-actors/v4/actors/runtime/proof"
    28  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    29  	"github.com/filecoin-project/specs-actors/v4/support/ipld"
    30  )
    31  
    32  // A mock runtime for unit testing of actors in isolation.
    33  // The mock allows direct specification of the runtime context as observable by an actor, supports
    34  // the storage interface, and mocks out side-effect-inducing calls.
    35  type Runtime struct {
    36  	// Execution context
    37  	ctx               context.Context
    38  	epoch             abi.ChainEpoch
    39  	networkVersion    network.Version
    40  	receiver          addr.Address
    41  	caller            addr.Address
    42  	callerType        cid.Cid
    43  	miner             addr.Address
    44  	valueReceived     abi.TokenAmount
    45  	idAddresses       map[addr.Address]addr.Address
    46  	actorCodeCIDs     map[addr.Address]cid.Cid
    47  	newActorAddr      addr.Address
    48  	circulatingSupply abi.TokenAmount
    49  
    50  	// Actor state
    51  	state   cid.Cid
    52  	balance abi.TokenAmount
    53  
    54  	// VM implementation
    55  	store         map[cid.Cid][]byte
    56  	inCall        bool
    57  	inTransaction bool
    58  	// Maps (references to) loaded state objs to their expected cid.
    59  	// Used for detecting modifications to state outside of transactions.
    60  	stateUsedObjs map[cbor.Marshaler]cid.Cid
    61  	// Syscalls
    62  	hashfunc func(data []byte) [32]byte
    63  
    64  	// Expectations
    65  	t                              testing.TB
    66  	expectValidateCallerAny        bool
    67  	expectValidateCallerAddr       []addr.Address
    68  	expectValidateCallerType       []cid.Cid
    69  	expectRandomnessBeacon         []*expectRandomness
    70  	expectRandomnessTickets        []*expectRandomness
    71  	expectSends                    []*expectedMessage
    72  	expectVerifySigs               []*expectVerifySig
    73  	expectCreateActor              *expectCreateActor
    74  	expectVerifySeal               *expectVerifySeal
    75  	expectComputeUnsealedSectorCID *expectComputeUnsealedSectorCID
    76  	expectVerifyPoSt               *expectVerifyPoSt
    77  	expectVerifyConsensusFault     *expectVerifyConsensusFault
    78  	expectDeleteActor              *addr.Address
    79  	expectBatchVerifySeals         *expectBatchVerifySeals
    80  
    81  	logs []string
    82  	// Gas charged explicitly through rt.ChargeGas. Note: most charges are implicit
    83  	gasCharged int64
    84  }
    85  
    86  type expectBatchVerifySeals struct {
    87  	in  map[addr.Address][]proof.SealVerifyInfo
    88  	out map[addr.Address][]bool
    89  	err error
    90  }
    91  
    92  type expectRandomness struct {
    93  	// Expected parameters.
    94  	tag     crypto.DomainSeparationTag
    95  	epoch   abi.ChainEpoch
    96  	entropy []byte
    97  	// Result.
    98  	out abi.Randomness
    99  }
   100  
   101  type expectedMessage struct {
   102  	// expectedMessage values
   103  	to     addr.Address
   104  	method abi.MethodNum
   105  	params cbor.Marshaler
   106  	value  abi.TokenAmount
   107  
   108  	// returns from applying expectedMessage
   109  	sendReturn cbor.Er
   110  	exitCode   exitcode.ExitCode
   111  }
   112  
   113  type expectVerifySig struct {
   114  	// Expected arguments
   115  	sig       crypto.Signature
   116  	signer    addr.Address
   117  	plaintext []byte
   118  	// Result
   119  	result error
   120  }
   121  
   122  type expectVerifySeal struct {
   123  	seal   proof.SealVerifyInfo
   124  	result error
   125  }
   126  
   127  type expectComputeUnsealedSectorCID struct {
   128  	reg       abi.RegisteredSealProof
   129  	pieces    []abi.PieceInfo
   130  	cid       cid.Cid
   131  	resultErr error
   132  }
   133  
   134  type expectVerifyPoSt struct {
   135  	post   proof.WindowPoStVerifyInfo
   136  	result error
   137  }
   138  
   139  func (m *expectedMessage) Equal(to addr.Address, method abi.MethodNum, params cbor.Marshaler, value abi.TokenAmount) bool {
   140  	// avoid nil vs. zero/empty discrepancies that would disappear in serialization
   141  	paramBuf1 := new(bytes.Buffer)
   142  	if m.params != nil {
   143  		m.params.MarshalCBOR(paramBuf1) // nolint: errcheck
   144  	}
   145  	paramBuf2 := new(bytes.Buffer)
   146  	if params != nil {
   147  		params.MarshalCBOR(paramBuf2) // nolint: errcheck
   148  	}
   149  
   150  	return m.to == to && m.method == method && m.value.Equals(value) && bytes.Equal(paramBuf1.Bytes(), paramBuf2.Bytes())
   151  }
   152  
   153  func (m *expectedMessage) String() string {
   154  	return fmt.Sprintf("to: %v method: %v value: %v params: %v sendReturn: %v exitCode: %v", m.to, m.method, m.value, m.params, m.sendReturn, m.exitCode)
   155  }
   156  
   157  type expectCreateActor struct {
   158  	// Expected parameters
   159  	codeId  cid.Cid
   160  	address addr.Address
   161  }
   162  
   163  type expectVerifyConsensusFault struct {
   164  	requireCorrectInput bool
   165  	BlockHeader1        []byte
   166  	BlockHeader2        []byte
   167  	BlockHeaderExtra    []byte
   168  
   169  	Fault *runtime.ConsensusFault
   170  	Err   error
   171  }
   172  
   173  var _ runtime.Runtime = &Runtime{}
   174  var _ runtime.StateHandle = &Runtime{}
   175  var typeOfRuntimeInterface = reflect.TypeOf((*runtime.Runtime)(nil)).Elem()
   176  var typeOfCborUnmarshaler = reflect.TypeOf((*cbor.Unmarshaler)(nil)).Elem()
   177  var typeOfCborMarshaler = reflect.TypeOf((*cbor.Marshaler)(nil)).Elem()
   178  
   179  ///// Implementation of the runtime API /////
   180  
   181  func (rt *Runtime) NetworkVersion() network.Version {
   182  	return rt.networkVersion
   183  }
   184  
   185  func (rt *Runtime) CurrEpoch() abi.ChainEpoch {
   186  	rt.requireInCall()
   187  	return rt.epoch
   188  }
   189  
   190  func (rt *Runtime) ValidateImmediateCallerAcceptAny() {
   191  	rt.requireInCall()
   192  	if !rt.expectValidateCallerAny {
   193  		rt.failTest("unexpected validate-caller-any")
   194  	}
   195  	rt.expectValidateCallerAny = false
   196  }
   197  
   198  func (rt *Runtime) ValidateImmediateCallerIs(addrs ...addr.Address) {
   199  	rt.requireInCall()
   200  	rt.checkArgument(len(addrs) > 0, "addrs must be non-empty")
   201  	// Check and clear expectations.
   202  	if len(rt.expectValidateCallerAddr) == 0 {
   203  		rt.failTest("unexpected validate caller addrs")
   204  		return
   205  	}
   206  	if !reflect.DeepEqual(rt.expectValidateCallerAddr, addrs) {
   207  		rt.failTest("unexpected validate caller addrs %v, expected %+v", addrs, rt.expectValidateCallerAddr)
   208  		return
   209  	}
   210  	defer func() {
   211  		rt.expectValidateCallerAddr = nil
   212  	}()
   213  
   214  	// Implement method.
   215  	for _, expected := range addrs {
   216  		if rt.caller == expected {
   217  			return
   218  		}
   219  	}
   220  	rt.Abortf(exitcode.SysErrForbidden, "caller address %v forbidden, allowed: %v", rt.caller, addrs)
   221  }
   222  
   223  func (rt *Runtime) ValidateImmediateCallerType(types ...cid.Cid) {
   224  	rt.requireInCall()
   225  	rt.checkArgument(len(types) > 0, "types must be non-empty")
   226  
   227  	// Check and clear expectations.
   228  	if len(rt.expectValidateCallerType) == 0 {
   229  		rt.failTest("unexpected validate caller code")
   230  	}
   231  	if !reflect.DeepEqual(rt.expectValidateCallerType, types) {
   232  		rt.failTest("unexpected validate caller code %v, expected %+v", types, rt.expectValidateCallerType)
   233  	}
   234  	defer func() {
   235  		rt.expectValidateCallerType = nil
   236  	}()
   237  
   238  	// Implement method.
   239  	for _, expected := range types {
   240  		if rt.callerType.Equals(expected) {
   241  			return
   242  		}
   243  	}
   244  	rt.Abortf(exitcode.SysErrForbidden, "caller type %v forbidden, allowed: %v", rt.callerType, types)
   245  }
   246  
   247  func (rt *Runtime) CurrentBalance() abi.TokenAmount {
   248  	rt.requireInCall()
   249  	return rt.balance
   250  }
   251  
   252  func (rt *Runtime) ResolveAddress(address addr.Address) (ret addr.Address, ok bool) {
   253  	rt.requireInCall()
   254  	if address.Protocol() == addr.ID {
   255  		return address, true
   256  	}
   257  	resolved, ok := rt.idAddresses[address]
   258  	return resolved, ok
   259  }
   260  
   261  func (rt *Runtime) GetIdAddr(raw addr.Address) (addr.Address, bool) {
   262  	if raw.Protocol() == addr.ID {
   263  		return raw, true
   264  	}
   265  	a, found := rt.idAddresses[raw]
   266  	return a, found
   267  }
   268  
   269  func (rt *Runtime) GetActorCodeCID(addr addr.Address) (ret cid.Cid, ok bool) {
   270  	rt.requireInCall()
   271  	ret, ok = rt.actorCodeCIDs[addr]
   272  	return
   273  }
   274  
   275  func (rt *Runtime) GetRandomnessFromBeacon(tag crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte) abi.Randomness {
   276  	rt.requireInCall()
   277  	if len(rt.expectRandomnessBeacon) == 0 {
   278  		rt.failTestNow("unexpected call to get randomness for tag %v, epoch %v", tag, epoch)
   279  	}
   280  
   281  	if epoch > rt.epoch {
   282  		rt.failTestNow("attempt to get randomness from future\n"+
   283  			"         requested epoch: %d greater than current epoch %d\n", epoch, rt.epoch)
   284  	}
   285  
   286  	exp := rt.expectRandomnessBeacon[0]
   287  	if tag != exp.tag || epoch != exp.epoch || !bytes.Equal(entropy, exp.entropy) {
   288  		rt.failTest("unexpected get randomness\n"+
   289  			"         tag: %d, epoch: %d, entropy: %v\n"+
   290  			"expected tag: %d, epoch: %d, entropy: %v", tag, epoch, entropy, exp.tag, exp.epoch, exp.entropy)
   291  	}
   292  	defer func() {
   293  		rt.expectRandomnessBeacon = rt.expectRandomnessBeacon[1:]
   294  	}()
   295  	return exp.out
   296  }
   297  
   298  func (rt *Runtime) GetRandomnessFromTickets(tag crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte) abi.Randomness {
   299  	rt.requireInCall()
   300  	if len(rt.expectRandomnessTickets) == 0 {
   301  		rt.failTestNow("unexpected call to get randomness for tag %v, epoch %v", tag, epoch)
   302  	}
   303  
   304  	if epoch > rt.epoch {
   305  		rt.failTestNow("attempt to get randomness from future\n"+
   306  			"         requested epoch: %d greater than current epoch %d\n", epoch, rt.epoch)
   307  	}
   308  
   309  	exp := rt.expectRandomnessTickets[0]
   310  	if tag != exp.tag || epoch != exp.epoch || !bytes.Equal(entropy, exp.entropy) {
   311  		rt.failTest("unexpected get randomness\n"+
   312  			"         tag: %d, epoch: %d, entropy: %v\n"+
   313  			"expected tag: %d, epoch: %d, entropy: %v", tag, epoch, entropy, exp.tag, exp.epoch, exp.entropy)
   314  	}
   315  	defer func() {
   316  		rt.expectRandomnessTickets = rt.expectRandomnessTickets[1:]
   317  	}()
   318  	return exp.out
   319  }
   320  
   321  func (rt *Runtime) Send(toAddr addr.Address, methodNum abi.MethodNum, params cbor.Marshaler, value abi.TokenAmount, out cbor.Er) exitcode.ExitCode {
   322  	rt.requireInCall()
   323  	if rt.inTransaction {
   324  		rt.Abortf(exitcode.SysErrorIllegalActor, "side-effect within transaction")
   325  	}
   326  	if len(rt.expectSends) == 0 {
   327  		rt.failTestNow("unexpected send to: %v method: %v, value: %v, params: %v", toAddr, methodNum, value, params)
   328  	}
   329  	exp := rt.expectSends[0]
   330  
   331  	if !exp.Equal(toAddr, methodNum, params, value) {
   332  		toName := "unknown"
   333  		toMeth := "unknown"
   334  		expToName := "unknown"
   335  		expToMeth := "unknown"
   336  		if code, ok := rt.GetActorCodeCID(toAddr); ok && builtin.IsBuiltinActor(code) {
   337  			toName = builtin.ActorNameByCode(code)
   338  			toMeth = getMethodName(code, methodNum)
   339  		}
   340  		if code, ok := rt.GetActorCodeCID(exp.to); ok && builtin.IsBuiltinActor(code) {
   341  			expToName = builtin.ActorNameByCode(code)
   342  			expToMeth = getMethodName(code, exp.method)
   343  		}
   344  
   345  		rt.failTestNow("unexpected send\n"+
   346  			"          to: %s (%s) method: %d (%s) value: %v params: %v\n"+
   347  			"Expected  to: %s (%s) method: %d (%s) value: %v params: %v",
   348  			toAddr, toName, methodNum, toMeth, value, params, exp.to, expToName, exp.method, expToMeth, exp.value, exp.params)
   349  	}
   350  
   351  	if value.GreaterThan(rt.balance) {
   352  		rt.Abortf(exitcode.SysErrSenderStateInvalid, "cannot send value: %v exceeds balance: %v", value, rt.balance)
   353  	}
   354  
   355  	// pop the expectedMessage from the queue and modify the mockrt balance to reflect the send.
   356  	defer func() {
   357  		rt.expectSends = rt.expectSends[1:]
   358  		rt.balance = big.Sub(rt.balance, value)
   359  	}()
   360  
   361  	// populate the output argument
   362  	var buf bytes.Buffer
   363  	err := exp.sendReturn.MarshalCBOR(&buf)
   364  	if err != nil {
   365  		rt.failTestNow("error serializing expected send return: %v", err)
   366  	}
   367  	err = out.UnmarshalCBOR(&buf)
   368  	if err != nil {
   369  		rt.failTestNow("error deserializing send return bytes to output param: %v", err)
   370  	}
   371  
   372  	return exp.exitCode
   373  }
   374  
   375  func (rt *Runtime) NewActorAddress() addr.Address {
   376  	rt.requireInCall()
   377  	if rt.newActorAddr == addr.Undef {
   378  		rt.failTestNow("unexpected call to new actor address")
   379  	}
   380  	defer func() { rt.newActorAddr = addr.Undef }()
   381  	return rt.newActorAddr
   382  }
   383  
   384  func (rt *Runtime) CreateActor(codeId cid.Cid, address addr.Address) {
   385  	rt.requireInCall()
   386  	if rt.inTransaction {
   387  		rt.Abortf(exitcode.SysErrorIllegalActor, "side-effect within transaction")
   388  	}
   389  	exp := rt.expectCreateActor
   390  	if exp != nil {
   391  		if !exp.codeId.Equals(codeId) || exp.address != address {
   392  			rt.failTest("unexpected create actor, code: %s, address: %s; expected code: %s, address: %s",
   393  				codeId, address, exp.codeId, exp.address)
   394  		}
   395  		defer func() {
   396  			rt.expectCreateActor = nil
   397  		}()
   398  		return
   399  	}
   400  	rt.failTestNow("unexpected call to create actor")
   401  }
   402  
   403  func (rt *Runtime) DeleteActor(addr addr.Address) {
   404  	rt.requireInCall()
   405  	if rt.inTransaction {
   406  		rt.Abortf(exitcode.SysErrorIllegalActor, "side-effect within transaction")
   407  	}
   408  	if rt.expectDeleteActor == nil {
   409  		rt.failTestNow("unexpected call to delete actor %s", addr.String())
   410  	}
   411  
   412  	if *rt.expectDeleteActor != addr {
   413  		rt.failTestNow("attempt to delete wrong actor. Expected %s, got %s.", rt.expectDeleteActor.String(), addr.String())
   414  	}
   415  	rt.expectDeleteActor = nil
   416  }
   417  
   418  func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
   419  	return rt.circulatingSupply
   420  }
   421  
   422  func (rt *Runtime) Abortf(errExitCode exitcode.ExitCode, msg string, args ...interface{}) {
   423  	rt.requireInCall()
   424  	rt.t.Logf("Mock Runtime Abort ExitCode: %v Reason: %s", errExitCode, fmt.Sprintf(msg, args...))
   425  	panic(abort{errExitCode, fmt.Sprintf(msg, args...)})
   426  }
   427  
   428  func (rt *Runtime) Context() context.Context {
   429  	// requireInCall omitted because it makes using this mock runtime as a store awkward.
   430  	return rt.ctx
   431  }
   432  
   433  func (rt *Runtime) StartSpan(_ string) func() {
   434  	rt.requireInCall()
   435  	return func() {}
   436  }
   437  
   438  func (rt *Runtime) checkArgument(predicate bool, msg string, args ...interface{}) {
   439  	if !predicate {
   440  		rt.Abortf(exitcode.SysErrorIllegalArgument, msg, args...)
   441  	}
   442  }
   443  
   444  ///// Store implementation /////
   445  
   446  // Gets raw data from the state. This function will extract inline data from the
   447  // CID to better mimic what filecoin implementations should do.
   448  func (rt *Runtime) get(c cid.Cid) ([]byte, bool) {
   449  	prefix := c.Prefix()
   450  	if prefix.Codec != cid.DagCBOR {
   451  		rt.Abortf(exitcode.ErrSerialization, "tried to fetch a non-cbor object: %s", c)
   452  	}
   453  
   454  	var data []byte
   455  	if prefix.MhType == mh.IDENTITY {
   456  		decoded, err := mh.Decode(c.Hash())
   457  		if err != nil {
   458  			rt.Abortf(exitcode.ErrSerialization, "failed to parse identity cid %s: %s", c, err)
   459  		}
   460  		data = decoded.Digest
   461  	} else if stored, found := rt.store[c]; found {
   462  		data = stored
   463  	} else {
   464  		return nil, false
   465  	}
   466  	return data, true
   467  }
   468  
   469  // Puts raw data into the state, but only if it's not "inlined" into the CID.
   470  func (rt *Runtime) put(c cid.Cid, data []byte) {
   471  	if c.Prefix().MhType != mh.IDENTITY {
   472  		rt.store[c] = data
   473  	}
   474  }
   475  
   476  func (rt *Runtime) StoreGet(c cid.Cid, o cbor.Unmarshaler) bool {
   477  	// requireInCall omitted because it makes using this mock runtime as a store awkward.
   478  	data, found := rt.get(c)
   479  	if found {
   480  		err := o.UnmarshalCBOR(bytes.NewReader(data))
   481  		if err != nil {
   482  			rt.Abortf(exitcode.ErrSerialization, err.Error())
   483  		}
   484  	}
   485  
   486  	return found
   487  }
   488  
   489  func (rt *Runtime) StorePut(o cbor.Marshaler) cid.Cid {
   490  	// requireInCall omitted because it makes using this mock runtime as a store awkward.
   491  	key, data, err := ipld.MarshalCBOR(o)
   492  	if err != nil {
   493  		rt.Abortf(exitcode.ErrSerialization, err.Error())
   494  	}
   495  	rt.put(key, data)
   496  	return key
   497  }
   498  
   499  ///// Message implementation /////
   500  
   501  func (rt *Runtime) BlockMiner() addr.Address {
   502  	return rt.miner
   503  }
   504  
   505  func (rt *Runtime) Caller() addr.Address {
   506  	return rt.caller
   507  }
   508  
   509  func (rt *Runtime) Receiver() addr.Address {
   510  	return rt.receiver
   511  }
   512  
   513  func (rt *Runtime) ValueReceived() abi.TokenAmount {
   514  	return rt.valueReceived
   515  }
   516  
   517  ///// State handle implementation /////
   518  
   519  func (rt *Runtime) StateCreate(obj cbor.Marshaler) {
   520  	if rt.state.Defined() {
   521  		rt.Abortf(exitcode.SysErrorIllegalActor, "state already constructed")
   522  	}
   523  	rt.state = rt.StorePut(obj)
   524  	// Track the expected CID of the object.
   525  	rt.stateUsedObjs[obj] = rt.state
   526  }
   527  
   528  func (rt *Runtime) StateReadonly(st cbor.Unmarshaler) {
   529  	found := rt.StoreGet(rt.state, st)
   530  	if !found {
   531  		panic(fmt.Sprintf("actor state not found: %v", rt.state))
   532  	}
   533  	// Track the expected CID of the object.
   534  	rt.stateUsedObjs[st.(cbor.Marshaler)] = rt.state
   535  }
   536  
   537  func (rt *Runtime) StateTransaction(st cbor.Er, f func()) {
   538  	if rt.inTransaction {
   539  		rt.Abortf(exitcode.SysErrorIllegalActor, "nested transaction")
   540  	}
   541  	rt.checkStateObjectsUnmodified()
   542  	rt.StateReadonly(st)
   543  	rt.inTransaction = true
   544  	defer func() { rt.inTransaction = false }()
   545  	f()
   546  	rt.state = rt.StorePut(st)
   547  	// Track the expected CID of the object.
   548  	rt.stateUsedObjs[st] = rt.state
   549  }
   550  
   551  ///// Syscalls implementation /////
   552  
   553  func (rt *Runtime) VerifySignature(sig crypto.Signature, signer addr.Address, plaintext []byte) error {
   554  	if len(rt.expectVerifySigs) == 0 {
   555  		rt.failTest("unexpected signature verification sig: %v, signer: %s, plaintext: %v", sig, signer, plaintext)
   556  	}
   557  
   558  	exp := rt.expectVerifySigs[0]
   559  	if exp != nil {
   560  		if !exp.sig.Equals(&sig) || exp.signer != signer || !bytes.Equal(exp.plaintext, plaintext) {
   561  			rt.failTest("unexpected signature verification\n"+
   562  				"         sig: %v, signer: %s, plaintext: %v\n"+
   563  				"expected sig: %v, signer: %s, plaintext: %v",
   564  				sig, signer, plaintext, exp.sig, exp.signer, exp.plaintext)
   565  		}
   566  		defer func() {
   567  			rt.expectVerifySigs = rt.expectVerifySigs[1:]
   568  		}()
   569  		return exp.result
   570  	}
   571  	rt.failTestNow("unexpected syscall to verify signature %v, signer %s, plaintext %v", sig, signer, plaintext)
   572  	return nil
   573  }
   574  
   575  func (rt *Runtime) HashBlake2b(data []byte) [32]byte {
   576  	return rt.hashfunc(data)
   577  }
   578  
   579  func (rt *Runtime) ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
   580  	exp := rt.expectComputeUnsealedSectorCID
   581  	if exp != nil {
   582  		if !reflect.DeepEqual(exp.reg, reg) {
   583  			rt.failTest("unexpected ComputeUnsealedSectorCID proof, expected: %v, got: %v", exp.reg, reg)
   584  		}
   585  		if !reflect.DeepEqual(exp.pieces, pieces) {
   586  			rt.failTest("unexpected ComputeUnsealedSectorCID pieces, expected: %v, got: %v", exp.pieces, pieces)
   587  		}
   588  
   589  		defer func() {
   590  			rt.expectComputeUnsealedSectorCID = nil
   591  		}()
   592  		return exp.cid, exp.resultErr
   593  	}
   594  	rt.failTestNow("unexpected syscall to ComputeUnsealedSectorCID %v", reg)
   595  	return cid.Cid{}, nil
   596  }
   597  
   598  func (rt *Runtime) VerifySeal(seal proof.SealVerifyInfo) error {
   599  	exp := rt.expectVerifySeal
   600  	if exp != nil {
   601  		if !reflect.DeepEqual(exp.seal, seal) {
   602  			rt.failTest("unexpected seal verification\n"+
   603  				"        : %v\n"+
   604  				"expected: %v",
   605  				seal, exp.seal)
   606  		}
   607  		defer func() {
   608  			rt.expectVerifySeal = nil
   609  		}()
   610  		return exp.result
   611  	}
   612  	rt.failTestNow("unexpected syscall to verify seal %v", seal)
   613  	return nil
   614  }
   615  
   616  func (rt *Runtime) ExpectBatchVerifySeals(in map[addr.Address][]proof.SealVerifyInfo, out map[addr.Address][]bool, err error) {
   617  	rt.expectBatchVerifySeals = &expectBatchVerifySeals{
   618  		in, out, err,
   619  	}
   620  }
   621  
   622  func (rt *Runtime) BatchVerifySeals(vis map[addr.Address][]proof.SealVerifyInfo) (map[addr.Address][]bool, error) {
   623  	exp := rt.expectBatchVerifySeals
   624  	if exp != nil {
   625  		if len(vis) != len(exp.in) {
   626  			rt.failTest("length mismatch, expected: %v, actual: %v", exp.in, vis)
   627  		}
   628  
   629  		for key, value := range exp.in { //nolint:nomaprange
   630  			v, ok := vis[key]
   631  			if !ok {
   632  				rt.failTest("address %v expected but not found", key)
   633  			}
   634  
   635  			if len(v) != len(value) {
   636  				rt.failTest("sector info length mismatch for address %v, \n expected: %v, \n actual: %v", key, value, v)
   637  			}
   638  			for i, info := range value {
   639  				if v[i].SealedCID != info.SealedCID {
   640  					rt.failTest("sealed cid does not match for address %v", key)
   641  				}
   642  
   643  				if v[i].UnsealedCID != info.UnsealedCID {
   644  					rt.failTest("unsealed cid does not match for address %v", key)
   645  				}
   646  			}
   647  
   648  			delete(exp.in, key)
   649  		}
   650  
   651  		if len(exp.in) != 0 {
   652  			rt.failTest("addresses in expected map absent in actual: %v", exp.in)
   653  		}
   654  		defer func() {
   655  			rt.expectBatchVerifySeals = nil
   656  		}()
   657  		return exp.out, exp.err
   658  	}
   659  	rt.failTestNow("unexpected syscall to batch verify seals with %v", vis)
   660  	return nil, nil
   661  }
   662  
   663  func (rt *Runtime) VerifyPoSt(vi proof.WindowPoStVerifyInfo) error {
   664  	exp := rt.expectVerifyPoSt
   665  	if exp != nil {
   666  		if !reflect.DeepEqual(exp.post, vi) {
   667  			rt.failTest("unexpected PoSt verification\n"+
   668  				"        : %v\n"+
   669  				"expected: %v",
   670  				vi, exp.post)
   671  		}
   672  		defer func() {
   673  			rt.expectVerifyPoSt = nil
   674  		}()
   675  		return exp.result
   676  	}
   677  	rt.failTestNow("unexpected syscall to verify PoSt %v", vi)
   678  	return nil
   679  }
   680  
   681  func (rt *Runtime) VerifyConsensusFault(h1, h2, extra []byte) (*runtime.ConsensusFault, error) {
   682  	if rt.expectVerifyConsensusFault == nil {
   683  		rt.failTestNow("Unexpected syscall VerifyConsensusFault")
   684  		return nil, nil
   685  	}
   686  
   687  	if rt.expectVerifyConsensusFault.requireCorrectInput {
   688  		if !bytes.Equal(h1, rt.expectVerifyConsensusFault.BlockHeader1) {
   689  			rt.failTest("block header 1 does not equal expected block header 1 (%v != %v)", h1, rt.expectVerifyConsensusFault.BlockHeader1)
   690  		}
   691  		if !bytes.Equal(h2, rt.expectVerifyConsensusFault.BlockHeader2) {
   692  			rt.failTest("block header 2 does not equal expected block header 2 (%v != %v)", h2, rt.expectVerifyConsensusFault.BlockHeader2)
   693  		}
   694  		if !bytes.Equal(extra, rt.expectVerifyConsensusFault.BlockHeaderExtra) {
   695  			rt.failTest("block header extra does not equal expected block header extra (%v != %v)", extra, rt.expectVerifyConsensusFault.BlockHeaderExtra)
   696  		}
   697  	}
   698  
   699  	fault := rt.expectVerifyConsensusFault.Fault
   700  	err := rt.expectVerifyConsensusFault.Err
   701  	rt.expectVerifyConsensusFault = nil
   702  	return fault, err
   703  }
   704  
   705  func (rt *Runtime) Log(level rt.LogLevel, msg string, args ...interface{}) {
   706  	rt.logs = append(rt.logs, fmt.Sprintf(msg, args...))
   707  }
   708  
   709  ///// Trace span implementation /////
   710  
   711  type TraceSpan struct {
   712  }
   713  
   714  func (t TraceSpan) End() {
   715  	// no-op
   716  }
   717  
   718  type abort struct {
   719  	code exitcode.ExitCode
   720  	msg  string
   721  }
   722  
   723  func (a abort) String() string {
   724  	return fmt.Sprintf("abort(%v): %s", a.code, a.msg)
   725  }
   726  
   727  ///// Inspection facilities /////
   728  
   729  func (rt *Runtime) AdtStore() adt.Store {
   730  	return adt.AsStore(rt)
   731  }
   732  
   733  func (rt *Runtime) StateRoot() cid.Cid {
   734  	return rt.state
   735  }
   736  
   737  func (rt *Runtime) GetState(o cbor.Unmarshaler) {
   738  	data, found := rt.get(rt.state)
   739  	if !found {
   740  		rt.failTestNow("can't find state at root %v", rt.state) // something internal is messed up
   741  	}
   742  	err := o.UnmarshalCBOR(bytes.NewReader(data))
   743  	if err != nil {
   744  		rt.failTestNow("error loading state: %v", err)
   745  	}
   746  }
   747  
   748  func (rt *Runtime) Balance() abi.TokenAmount {
   749  	return rt.balance
   750  }
   751  
   752  func (rt *Runtime) Epoch() abi.ChainEpoch {
   753  	return rt.epoch
   754  }
   755  
   756  ///// Mocking facilities /////
   757  
   758  func (rt *Runtime) SetCaller(address addr.Address, actorType cid.Cid) {
   759  	rt.caller = address
   760  	rt.callerType = actorType
   761  	rt.actorCodeCIDs[address] = actorType
   762  }
   763  
   764  func (rt *Runtime) SetAddressActorType(address addr.Address, actorType cid.Cid) {
   765  	rt.actorCodeCIDs[address] = actorType
   766  }
   767  
   768  func (rt *Runtime) SetBalance(amt abi.TokenAmount) {
   769  	rt.balance = amt
   770  }
   771  
   772  func (rt *Runtime) SetReceived(amt abi.TokenAmount) {
   773  	rt.valueReceived = amt
   774  }
   775  
   776  func (rt *Runtime) SetNetworkVersion(v network.Version) {
   777  	rt.networkVersion = v
   778  }
   779  
   780  func (rt *Runtime) SetEpoch(epoch abi.ChainEpoch) {
   781  	rt.epoch = epoch
   782  }
   783  
   784  func (rt *Runtime) ReplaceState(o cbor.Marshaler) {
   785  	rt.state = rt.StorePut(o)
   786  }
   787  
   788  func (rt *Runtime) SetCirculatingSupply(amt abi.TokenAmount) {
   789  	rt.circulatingSupply = amt
   790  }
   791  
   792  func (rt *Runtime) AddIDAddress(src addr.Address, target addr.Address) {
   793  	rt.require(target.Protocol() == addr.ID, "target must use ID address protocol")
   794  	rt.idAddresses[src] = target
   795  }
   796  
   797  func (rt *Runtime) SetNewActorAddress(actAddr addr.Address) {
   798  	rt.require(actAddr.Protocol() == addr.Actor, "new actor address must be protocol: Actor, got protocol: %v", actAddr.Protocol())
   799  	rt.newActorAddr = actAddr
   800  }
   801  
   802  func (rt *Runtime) ExpectValidateCallerAny() {
   803  	rt.expectValidateCallerAny = true
   804  }
   805  
   806  func (rt *Runtime) ExpectValidateCallerAddr(addrs ...addr.Address) {
   807  	rt.require(len(addrs) > 0, "addrs must be non-empty")
   808  	rt.expectValidateCallerAddr = addrs[:]
   809  }
   810  
   811  func (rt *Runtime) ExpectValidateCallerType(types ...cid.Cid) {
   812  	rt.require(len(types) > 0, "types must be non-empty")
   813  	rt.expectValidateCallerType = types[:]
   814  }
   815  
   816  func (rt *Runtime) ExpectGetRandomnessBeacon(tag crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte, out abi.Randomness) {
   817  	rt.expectRandomnessBeacon = append(rt.expectRandomnessBeacon, &expectRandomness{
   818  		tag:     tag,
   819  		epoch:   epoch,
   820  		entropy: entropy,
   821  		out:     out,
   822  	})
   823  }
   824  
   825  func (rt *Runtime) ExpectGetRandomnessTickets(tag crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte, out abi.Randomness) {
   826  	rt.expectRandomnessTickets = append(rt.expectRandomnessTickets, &expectRandomness{
   827  		tag:     tag,
   828  		epoch:   epoch,
   829  		entropy: entropy,
   830  		out:     out,
   831  	})
   832  }
   833  
   834  func (rt *Runtime) ExpectSend(toAddr addr.Address, methodNum abi.MethodNum, params cbor.Marshaler, value abi.TokenAmount, ret cbor.Er, exitCode exitcode.ExitCode) {
   835  	// Adapt nil to Empty as convenience for the caller (otherwise we would require non-nil here).
   836  	if ret == nil {
   837  		ret = abi.Empty
   838  	}
   839  	rt.expectSends = append(rt.expectSends, &expectedMessage{
   840  		to:         toAddr,
   841  		method:     methodNum,
   842  		params:     params,
   843  		value:      value,
   844  		sendReturn: ret,
   845  		exitCode:   exitCode,
   846  	})
   847  }
   848  
   849  func (rt *Runtime) ExpectVerifySignature(sig crypto.Signature, signer addr.Address, plaintext []byte, result error) {
   850  	rt.expectVerifySigs = append(rt.expectVerifySigs, &expectVerifySig{
   851  		sig:       sig,
   852  		signer:    signer,
   853  		plaintext: plaintext,
   854  		result:    result,
   855  	})
   856  }
   857  
   858  func (rt *Runtime) ExpectCreateActor(codeId cid.Cid, address addr.Address) {
   859  	rt.expectCreateActor = &expectCreateActor{
   860  		codeId:  codeId,
   861  		address: address,
   862  	}
   863  }
   864  
   865  func (rt *Runtime) ExpectDeleteActor(beneficiary addr.Address) {
   866  	rt.expectDeleteActor = &beneficiary
   867  }
   868  
   869  func (rt *Runtime) SetHasher(f func(data []byte) [32]byte) {
   870  	rt.hashfunc = f
   871  }
   872  
   873  func (rt *Runtime) ExpectVerifySeal(seal proof.SealVerifyInfo, result error) {
   874  	rt.expectVerifySeal = &expectVerifySeal{
   875  		seal:   seal,
   876  		result: result,
   877  	}
   878  }
   879  
   880  func (rt *Runtime) ExpectComputeUnsealedSectorCID(reg abi.RegisteredSealProof, pieces []abi.PieceInfo, cid cid.Cid, err error) {
   881  	rt.expectComputeUnsealedSectorCID = &expectComputeUnsealedSectorCID{
   882  		reg, pieces, cid, err,
   883  	}
   884  }
   885  
   886  func (rt *Runtime) ExpectVerifyPoSt(post proof.WindowPoStVerifyInfo, result error) {
   887  	rt.expectVerifyPoSt = &expectVerifyPoSt{
   888  		post:   post,
   889  		result: result,
   890  	}
   891  }
   892  
   893  func (rt *Runtime) ExpectVerifyConsensusFault(h1, h2, extra []byte, result *runtime.ConsensusFault, resultErr error) {
   894  	rt.expectVerifyConsensusFault = &expectVerifyConsensusFault{
   895  		requireCorrectInput: true,
   896  		BlockHeader1:        h1,
   897  		BlockHeader2:        h2,
   898  		BlockHeaderExtra:    extra,
   899  		Fault:               result,
   900  		Err:                 resultErr,
   901  	}
   902  }
   903  
   904  // Verifies that expected calls were received, and resets all expectations.
   905  func (rt *Runtime) Verify() {
   906  	rt.t.Helper()
   907  	if rt.expectValidateCallerAny {
   908  		rt.failTest("expected ValidateCallerAny, not received")
   909  	}
   910  	if len(rt.expectValidateCallerAddr) > 0 {
   911  		rt.failTest("missing expected ValidateCallerAddr %v", rt.expectValidateCallerAddr)
   912  	}
   913  	if len(rt.expectValidateCallerType) > 0 {
   914  		rt.failTest("missing expected ValidateCallerType %v", rt.expectValidateCallerType)
   915  	}
   916  	if len(rt.expectRandomnessBeacon) > 0 {
   917  		rt.failTest("missing expected beacon randomness %v", rt.expectRandomnessBeacon)
   918  	}
   919  	if len(rt.expectRandomnessTickets) > 0 {
   920  		rt.failTest("missing expected ticket randomness %v", rt.expectRandomnessTickets)
   921  	}
   922  	if len(rt.expectSends) > 0 {
   923  		rt.failTest("missing expected send %v", rt.expectSends)
   924  	}
   925  	if len(rt.expectVerifySigs) > 0 {
   926  		rt.failTest("missing expected verify signature %v", rt.expectVerifySigs)
   927  	}
   928  	if rt.expectCreateActor != nil {
   929  		rt.failTest("missing expected create actor with code %s, address %s",
   930  			rt.expectCreateActor.codeId, rt.expectCreateActor.address)
   931  	}
   932  
   933  	if rt.expectVerifySeal != nil {
   934  		rt.failTest("missing expected verify seal with %v", rt.expectVerifySeal.seal)
   935  	}
   936  
   937  	if rt.expectBatchVerifySeals != nil {
   938  		rt.failTest("missing expected batch verify seals with %v", rt.expectBatchVerifySeals)
   939  	}
   940  
   941  	if rt.expectComputeUnsealedSectorCID != nil {
   942  		rt.failTest("missing expected ComputeUnsealedSectorCID with %v", rt.expectComputeUnsealedSectorCID)
   943  	}
   944  
   945  	if rt.expectVerifyPoSt != nil {
   946  		rt.failTest("missing expected PoSt verification with %v", rt.expectVerifyPoSt)
   947  	}
   948  
   949  	if rt.expectVerifyConsensusFault != nil {
   950  		rt.failTest("missing expected verify consensus fault")
   951  	}
   952  	if rt.expectDeleteActor != nil {
   953  		rt.failTest("missing expected delete actor with address %s", rt.expectDeleteActor.String())
   954  	}
   955  
   956  	rt.Reset()
   957  }
   958  
   959  // Resets expectations
   960  func (rt *Runtime) Reset() {
   961  	rt.expectValidateCallerAny = false
   962  	rt.expectValidateCallerAddr = nil
   963  	rt.expectValidateCallerType = nil
   964  	rt.expectRandomnessBeacon = nil
   965  	rt.expectRandomnessTickets = nil
   966  	rt.expectSends = nil
   967  	rt.expectCreateActor = nil
   968  	rt.expectVerifySigs = nil
   969  	rt.expectVerifySeal = nil
   970  	rt.expectBatchVerifySeals = nil
   971  	rt.expectComputeUnsealedSectorCID = nil
   972  }
   973  
   974  // Calls f() expecting it to invoke Runtime.Abortf() with a specified exit code.
   975  func (rt *Runtime) ExpectAbort(expected exitcode.ExitCode, f func()) {
   976  	rt.ExpectAbortContainsMessage(expected, "", f)
   977  }
   978  
   979  // Calls f() expecting it to invoke Runtime.Abortf() with a specified exit code and message.
   980  func (rt *Runtime) ExpectAbortContainsMessage(expected exitcode.ExitCode, substr string, f func()) {
   981  	rt.t.Helper()
   982  	prevState := rt.state
   983  
   984  	defer func() {
   985  		rt.t.Helper()
   986  		r := recover()
   987  		if r == nil {
   988  			rt.failTest("expected abort with code %v but call succeeded", expected)
   989  			return
   990  		}
   991  		a, ok := r.(abort)
   992  		if !ok {
   993  			panic(r)
   994  		}
   995  		if a.code != expected {
   996  			rt.failTest("abort expected code %v, got %v %s", expected, a.code, a.msg)
   997  		}
   998  		if substr != "" {
   999  			if !strings.Contains(a.msg, substr) {
  1000  				rt.failTest("abort expected message\n'%s'\nto contain\n'%s'\n", a.msg, substr)
  1001  			}
  1002  		}
  1003  		// Roll back state change.
  1004  		rt.state = prevState
  1005  	}()
  1006  	f()
  1007  }
  1008  
  1009  func (rt *Runtime) ExpectLogsContain(substr string) {
  1010  	for _, msg := range rt.logs {
  1011  		if strings.Contains(msg, substr) {
  1012  			return
  1013  		}
  1014  	}
  1015  	rt.failTest("logs contain %d message(s) and do not contain \"%s\"", len(rt.logs), substr)
  1016  }
  1017  
  1018  func (rt *Runtime) ClearLogs() {
  1019  	rt.logs = []string{}
  1020  }
  1021  
  1022  func (rt *Runtime) ExpectGasCharged(gas int64) {
  1023  	if gas != rt.gasCharged {
  1024  		rt.failTest("expected gas charged: %d, actual gas charged: %d", gas, rt.gasCharged)
  1025  	}
  1026  }
  1027  
  1028  func (rt *Runtime) Call(method interface{}, params interface{}) interface{} {
  1029  	meth := reflect.ValueOf(method)
  1030  	rt.verifyExportedMethodType(meth)
  1031  
  1032  	// There's no panic recovery here. If an abort is expected, this call will be inside an ExpectAbort block.
  1033  	// If not expected, the panic will escape and cause the test to fail.
  1034  
  1035  	rt.inCall = true
  1036  	rt.stateUsedObjs = map[cbor.Marshaler]cid.Cid{}
  1037  	defer func() {
  1038  		rt.inCall = false
  1039  		rt.stateUsedObjs = nil
  1040  	}()
  1041  	var arg reflect.Value
  1042  	if params != nil {
  1043  		arg = reflect.ValueOf(params)
  1044  	} else {
  1045  		arg = reflect.ValueOf(abi.Empty)
  1046  	}
  1047  	ret := meth.Call([]reflect.Value{reflect.ValueOf(rt), arg})
  1048  	rt.checkStateObjectsUnmodified()
  1049  	return ret[0].Interface()
  1050  }
  1051  
  1052  // Checks that state objects weren't modified outside of transaction.
  1053  func (rt *Runtime) checkStateObjectsUnmodified() {
  1054  	for obj, expectedKey := range rt.stateUsedObjs { // nolint:nomaprange
  1055  		// Recompute the CID of the object and check it's the same as was recorded
  1056  		// when the object was loaded.
  1057  		finalKey, _, err := ipld.MarshalCBOR(obj)
  1058  		if err != nil {
  1059  			rt.Abortf(exitcode.SysErrorIllegalActor, "error marshalling state object for validation: %v", err)
  1060  		}
  1061  		if finalKey != expectedKey {
  1062  			rt.Abortf(exitcode.SysErrorIllegalActor, "State mutated outside of transaction scope")
  1063  		}
  1064  	}
  1065  }
  1066  
  1067  func (rt *Runtime) verifyExportedMethodType(meth reflect.Value) {
  1068  	rt.t.Helper()
  1069  	t := meth.Type()
  1070  	rt.require(t.Kind() == reflect.Func, "%v is not a function", meth)
  1071  	rt.require(t.NumIn() == 2, "exported method %v must have two parameters, got %v", meth, t.NumIn())
  1072  	rt.require(t.In(0) == typeOfRuntimeInterface, "exported method first parameter must be runtime, got %v", t.In(0))
  1073  	rt.require(t.In(1).Kind() == reflect.Ptr, "exported method second parameter must be pointer to params, got %v", t.In(1))
  1074  	rt.require(t.In(1).Implements(typeOfCborUnmarshaler), "exported method second parameter must be CBOR-unmarshalable params, got %v", t.In(1))
  1075  	rt.require(t.NumOut() == 1, "exported method must return a single value")
  1076  	rt.require(t.Out(0).Implements(typeOfCborMarshaler), "exported method must return CBOR-marshalable value")
  1077  }
  1078  
  1079  func (rt *Runtime) requireInCall() {
  1080  	rt.t.Helper()
  1081  	rt.require(rt.inCall, "invalid runtime invocation outside of method call")
  1082  }
  1083  
  1084  func (rt *Runtime) require(predicate bool, msg string, args ...interface{}) {
  1085  	rt.t.Helper()
  1086  	if !predicate {
  1087  		rt.failTestNow(msg, args...)
  1088  	}
  1089  }
  1090  
  1091  func (rt *Runtime) failTest(msg string, args ...interface{}) {
  1092  	rt.t.Helper()
  1093  	rt.t.Logf(msg, args...)
  1094  	rt.t.Logf("%s", debug.Stack())
  1095  	rt.t.Fail()
  1096  }
  1097  
  1098  func (rt *Runtime) failTestNow(msg string, args ...interface{}) {
  1099  	rt.t.Helper()
  1100  	rt.t.Logf(msg, args...)
  1101  	rt.t.Logf("%s", debug.Stack())
  1102  	rt.t.FailNow()
  1103  }
  1104  
  1105  func (rt *Runtime) ChargeGas(_ string, gas, _ int64) {
  1106  	rt.gasCharged += gas
  1107  }
  1108  
  1109  func getMethodName(code cid.Cid, num abi.MethodNum) string {
  1110  	for _, actor := range exported.BuiltinActors() {
  1111  		if actor.Code().Equals(code) {
  1112  			exports := actor.Exports()
  1113  			if len(exports) <= int(num) {
  1114  				return "<invalid>"
  1115  			}
  1116  			meth := exports[num]
  1117  			if meth == nil {
  1118  				return "<invalid>"
  1119  			}
  1120  			name := goruntime.FuncForPC(reflect.ValueOf(meth).Pointer()).Name()
  1121  			name = strings.TrimSuffix(name, "-fm")
  1122  			lastDot := strings.LastIndexByte(name, '.')
  1123  			name = name[lastDot+1:]
  1124  			return name
  1125  		}
  1126  	}
  1127  	return "<unknown actor>"
  1128  }