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

     1  package vm_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/binary"
     7  	"fmt"
     8  	"reflect"
     9  	"runtime/debug"
    10  
    11  	"github.com/filecoin-project/go-address"
    12  	"github.com/filecoin-project/go-state-types/abi"
    13  	"github.com/filecoin-project/go-state-types/big"
    14  	"github.com/filecoin-project/go-state-types/cbor"
    15  	"github.com/filecoin-project/go-state-types/crypto"
    16  	"github.com/filecoin-project/go-state-types/exitcode"
    17  	"github.com/filecoin-project/go-state-types/network"
    18  	"github.com/filecoin-project/go-state-types/rt"
    19  	vm2 "github.com/filecoin-project/specs-actors/v2/support/vm"
    20  	"github.com/ipfs/go-cid"
    21  	"github.com/minio/blake2b-simd"
    22  	"github.com/pkg/errors"
    23  
    24  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    25  	init_ "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
    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/states"
    29  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    30  	"github.com/filecoin-project/specs-actors/v4/support/ipld"
    31  	"github.com/filecoin-project/specs-actors/v4/support/testing"
    32  )
    33  
    34  var EmptyObjectCid cid.Cid
    35  
    36  // Context for an individual message invocation, including inter-actor sends.
    37  type invocationContext struct {
    38  	rt               *VM
    39  	topLevel         *topLevelContext
    40  	msg              InternalMessage // The message being processed
    41  	fromActor        *states.Actor   // The immediate calling actor
    42  	toActor          *states.Actor   // The actor to which message is addressed
    43  	emptyObject      cid.Cid
    44  	allowSideEffects bool
    45  	callerValidated  bool
    46  	// Maps (references to) loaded state objs to their expected cid.
    47  	// Used for detecting modifications to state outside of transactions.
    48  	stateUsedObjs map[cbor.Marshaler]cid.Cid
    49  	stats         *CallStats
    50  }
    51  
    52  // Context for a top-level invocation sequence
    53  type topLevelContext struct {
    54  	originatorStableAddress address.Address // Stable (public key) address of the top-level message sender.
    55  	originatorCallSeq       uint64          // Call sequence number of the top-level message.
    56  	newActorAddressCount    uint64          // Count of calls to NewActorAddress (mutable).
    57  	statsSource             StatsSource     // optional source of external statistics that can be used to profile calls
    58  	circSupply              abi.TokenAmount // default or externally specified circulating FIL supply
    59  }
    60  
    61  func newInvocationContext(rt *VM, topLevel *topLevelContext, msg InternalMessage, fromActor *states.Actor, emptyObject cid.Cid) invocationContext {
    62  	// Note: the toActor and stateHandle are loaded during the `invoke()`
    63  	return invocationContext{
    64  		rt:               rt,
    65  		topLevel:         topLevel,
    66  		msg:              msg,
    67  		fromActor:        fromActor,
    68  		toActor:          nil,
    69  		emptyObject:      emptyObject,
    70  		allowSideEffects: true,
    71  		callerValidated:  false,
    72  		stateUsedObjs:    map[cbor.Marshaler]cid.Cid{},
    73  		stats:            vm2.NewCallStats(topLevel.statsSource),
    74  	}
    75  }
    76  
    77  var _ runtime.StateHandle = (*invocationContext)(nil)
    78  
    79  func (ic *invocationContext) loadState(obj cbor.Unmarshaler) cid.Cid {
    80  	// The actor must be loaded from store every time since the state may have changed via a different state handle
    81  	// (e.g. in a recursive call).
    82  	actr := ic.loadActor()
    83  	c := actr.Head
    84  	if !c.Defined() {
    85  		ic.Abortf(exitcode.SysErrorIllegalActor, "failed to load undefined state, must construct first")
    86  	}
    87  	err := ic.rt.store.Get(ic.rt.ctx, c, obj)
    88  	if err != nil {
    89  		panic(errors.Wrapf(err, "failed to load state for actor %s, CID %s", ic.msg.to, c))
    90  	}
    91  	return c
    92  }
    93  
    94  func (ic *invocationContext) loadActor() *states.Actor {
    95  	actr, found, err := ic.rt.GetActor(ic.msg.to)
    96  	if err != nil {
    97  		panic(err)
    98  	}
    99  	if !found {
   100  		panic(fmt.Errorf("failed to find actor %s for state", ic.msg.to))
   101  	}
   102  	return actr
   103  }
   104  
   105  func (ic *invocationContext) storeActor(actr *states.Actor) {
   106  	err := ic.rt.setActor(ic.rt.ctx, ic.msg.to, actr)
   107  	if err != nil {
   108  		panic(err)
   109  	}
   110  }
   111  
   112  /////////////////////////////////////////////
   113  //          Runtime methods
   114  /////////////////////////////////////////////
   115  
   116  var _ runtime.Runtime = (*invocationContext)(nil)
   117  
   118  // Store implements runtime.Runtime.
   119  func (ic *invocationContext) StoreGet(c cid.Cid, o cbor.Unmarshaler) bool {
   120  	sw := &storeWrapper{s: ic.rt.store, rt: ic.rt}
   121  	return sw.StoreGet(c, o)
   122  }
   123  
   124  func (ic *invocationContext) StorePut(x cbor.Marshaler) cid.Cid {
   125  	sw := &storeWrapper{s: ic.rt.store, rt: ic.rt}
   126  	return sw.StorePut(x)
   127  }
   128  
   129  // These methods implement
   130  // ValueReceived implements runtime.Message
   131  func (ic *invocationContext) ValueReceived() abi.TokenAmount {
   132  	return ic.msg.ValueReceived()
   133  }
   134  
   135  // Caller implements runtime.Message
   136  func (ic *invocationContext) Caller() address.Address {
   137  	return ic.msg.Caller()
   138  }
   139  
   140  // Receiver implements runtime.Message
   141  func (ic *invocationContext) Receiver() address.Address {
   142  	return ic.msg.Receiver()
   143  }
   144  
   145  func (ic *invocationContext) StateCreate(obj cbor.Marshaler) {
   146  	actr := ic.loadActor()
   147  	if actr.Head.Defined() && !ic.emptyObject.Equals(actr.Head) {
   148  		ic.Abortf(exitcode.SysErrorIllegalActor, "failed to construct actor state: already initialized")
   149  	}
   150  	c, err := ic.rt.store.Put(ic.rt.ctx, obj)
   151  	if err != nil {
   152  		ic.Abortf(exitcode.ErrIllegalState, "failed to create actor state")
   153  	}
   154  	actr.Head = c
   155  	ic.storeActor(actr)
   156  	ic.stateUsedObjs[obj] = c // Track the expected CID of the object.
   157  }
   158  
   159  // Readonly is the implementation of the ActorStateHandle interface.
   160  func (ic *invocationContext) StateReadonly(obj cbor.Unmarshaler) {
   161  	// Load state to obj.
   162  	c := ic.loadState(obj)
   163  	ic.stateUsedObjs[obj.(cbor.Marshaler)] = c // Track the expected CID of the object.
   164  }
   165  
   166  // Transaction is the implementation of the ActorStateHandle interface.
   167  func (ic *invocationContext) StateTransaction(obj cbor.Er, f func()) {
   168  	if obj == nil {
   169  		ic.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
   170  	}
   171  	ic.checkStateObjectsUnmodified()
   172  
   173  	// Load state to obj.
   174  	ic.loadState(obj)
   175  
   176  	// Call user code allowing mutation but not side-effects
   177  	ic.allowSideEffects = false
   178  	f()
   179  	ic.allowSideEffects = true
   180  
   181  	c := ic.replace(obj)
   182  	ic.stateUsedObjs[obj] = c // Track the expected CID of the object.
   183  }
   184  
   185  func (ic *invocationContext) VerifySignature(signature crypto.Signature, signer address.Address, plaintext []byte) error {
   186  	return ic.Syscalls().VerifySignature(signature, signer, plaintext)
   187  }
   188  
   189  func (ic *invocationContext) HashBlake2b(data []byte) [32]byte {
   190  	return ic.Syscalls().HashBlake2b(data)
   191  }
   192  
   193  func (ic *invocationContext) ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
   194  	return ic.Syscalls().ComputeUnsealedSectorCID(reg, pieces)
   195  }
   196  
   197  func (ic *invocationContext) VerifySeal(vi proof.SealVerifyInfo) error {
   198  	return ic.Syscalls().VerifySeal(vi)
   199  }
   200  
   201  func (ic *invocationContext) BatchVerifySeals(vis map[address.Address][]proof.SealVerifyInfo) (map[address.Address][]bool, error) {
   202  	return ic.Syscalls().BatchVerifySeals(vis)
   203  }
   204  
   205  func (ic *invocationContext) VerifyPoSt(vi proof.WindowPoStVerifyInfo) error {
   206  	return ic.Syscalls().VerifyPoSt(vi)
   207  }
   208  
   209  func (ic *invocationContext) VerifyConsensusFault(h1, h2, extra []byte) (*runtime.ConsensusFault, error) {
   210  	return ic.Syscalls().VerifyConsensusFault(h1, h2, extra)
   211  }
   212  
   213  func (ic *invocationContext) NetworkVersion() network.Version {
   214  	return ic.rt.networkVersion
   215  }
   216  
   217  func (ic *invocationContext) CurrEpoch() abi.ChainEpoch {
   218  	return ic.rt.currentEpoch
   219  }
   220  
   221  func (ic *invocationContext) CurrentBalance() abi.TokenAmount {
   222  	// load balance
   223  	act, found, err := ic.rt.GetActor(ic.msg.to)
   224  	if err != nil {
   225  		ic.Abortf(exitcode.ErrIllegalState, "could not load to actor %v: %v", ic.msg.to, err)
   226  	} else if !found {
   227  		ic.Abortf(exitcode.ErrIllegalState, "could not find to actor %v", ic.msg.to)
   228  	}
   229  	return act.Balance
   230  }
   231  
   232  func (ic *invocationContext) GetActorCodeCID(a address.Address) (cid.Cid, bool) {
   233  	entry, found, err := ic.rt.GetActor(a)
   234  	if !found {
   235  		return cid.Undef, false
   236  	}
   237  	if err != nil {
   238  		panic(err)
   239  	}
   240  	return entry.Code, true
   241  }
   242  
   243  func (ic *invocationContext) GetRandomnessFromBeacon(_ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) abi.Randomness {
   244  	return []byte("not really random")
   245  }
   246  
   247  func (ic *invocationContext) GetRandomnessFromTickets(_ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) abi.Randomness {
   248  	return []byte("not really random")
   249  }
   250  
   251  func (ic *invocationContext) ValidateImmediateCallerAcceptAny() {
   252  	ic.assertf(!ic.callerValidated, "caller has been double validated")
   253  	ic.callerValidated = true
   254  }
   255  
   256  func (ic *invocationContext) ValidateImmediateCallerIs(addrs ...address.Address) {
   257  	ic.assertf(!ic.callerValidated, "caller has been double validated")
   258  	ic.callerValidated = true
   259  	for _, addr := range addrs {
   260  		if ic.msg.from == addr {
   261  			return
   262  		}
   263  	}
   264  	ic.Abortf(exitcode.ErrForbidden, "caller address %v forbidden, allowed: %v", ic.msg.from, addrs)
   265  }
   266  
   267  func (ic *invocationContext) ValidateImmediateCallerType(types ...cid.Cid) {
   268  	ic.assertf(!ic.callerValidated, "caller has been double validated")
   269  	ic.callerValidated = true
   270  	for _, t := range types {
   271  		if t.Equals(ic.fromActor.Code) {
   272  			return
   273  		}
   274  	}
   275  	ic.Abortf(exitcode.ErrForbidden, "caller type %v forbidden, allowed: %v", ic.fromActor.Code, types)
   276  }
   277  
   278  func (ic *invocationContext) Abortf(errExitCode exitcode.ExitCode, msg string, args ...interface{}) {
   279  	ic.rt.Abortf(errExitCode, msg, args...)
   280  }
   281  
   282  func (ic *invocationContext) assertf(condition bool, msg string, args ...interface{}) {
   283  	if !condition {
   284  		panic(fmt.Errorf(msg, args...))
   285  	}
   286  }
   287  
   288  func (ic *invocationContext) ResolveAddress(address address.Address) (address.Address, bool) {
   289  	return ic.rt.NormalizeAddress(address)
   290  }
   291  
   292  func (ic *invocationContext) NewActorAddress() address.Address {
   293  	var buf bytes.Buffer
   294  
   295  	b1, err := ic.topLevel.originatorStableAddress.Marshal()
   296  	if err != nil {
   297  		panic(err)
   298  	}
   299  	_, err = buf.Write(b1)
   300  	if err != nil {
   301  		panic(err)
   302  	}
   303  
   304  	err = binary.Write(&buf, binary.BigEndian, ic.topLevel.originatorCallSeq)
   305  	if err != nil {
   306  		panic(err)
   307  	}
   308  
   309  	err = binary.Write(&buf, binary.BigEndian, ic.topLevel.newActorAddressCount)
   310  	if err != nil {
   311  		panic(err)
   312  	}
   313  
   314  	actorAddress, err := address.NewActorAddress(buf.Bytes())
   315  	if err != nil {
   316  		panic(err)
   317  	}
   318  	return actorAddress
   319  }
   320  
   321  // Send implements runtime.InvocationContext.
   322  func (ic *invocationContext) Send(toAddr address.Address, methodNum abi.MethodNum, params cbor.Marshaler, value abi.TokenAmount, out cbor.Er) (errcode exitcode.ExitCode) {
   323  	// check if side-effects are allowed
   324  	if !ic.allowSideEffects {
   325  		ic.Abortf(exitcode.SysErrorIllegalActor, "Calling Send() is not allowed during side-effect lock")
   326  	}
   327  	from := ic.msg.to
   328  	fromActor, found, err := ic.rt.GetActor(from)
   329  	if err != nil {
   330  		ic.Abortf(exitcode.ErrIllegalState, "could not retrieve send actor %v for internal send: %v", from, err)
   331  	} else if !found {
   332  		ic.Abortf(exitcode.ErrIllegalState, "could not find send actor %v for internal send", from)
   333  	}
   334  
   335  	newMsg := InternalMessage{
   336  		from:   from,
   337  		to:     toAddr,
   338  		value:  value,
   339  		method: methodNum,
   340  		params: params,
   341  	}
   342  
   343  	newCtx := newInvocationContext(ic.rt, ic.topLevel, newMsg, fromActor, ic.emptyObject)
   344  	ret, code := newCtx.invoke()
   345  
   346  	ic.stats.MergeSubStat(newCtx.toActor.Code, newMsg.method, newCtx.stats)
   347  
   348  	err = ret.Into(out)
   349  	if err != nil {
   350  		ic.Abortf(exitcode.ErrSerialization, "failed to serialize send return value into output parameter")
   351  	}
   352  	return code
   353  }
   354  
   355  // CreateActor implements runtime.ExtendedInvocationContext.
   356  func (ic *invocationContext) CreateActor(codeID cid.Cid, addr address.Address) {
   357  	act, ok := ic.rt.ActorImpls[codeID]
   358  	if !ok {
   359  		ic.Abortf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.")
   360  	}
   361  
   362  	if rt.IsSingletonActor(act) {
   363  		ic.Abortf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
   364  	}
   365  
   366  	ic.rt.Log(rt.DEBUG, "creating actor, friendly-name: %s, Exitcode: %s, addr: %s\n", builtin.ActorNameByCode(codeID), codeID, addr)
   367  
   368  	// Check existing address. If nothing there, create empty actor.
   369  	//
   370  	// Note: we are storing the actors by ActorID *address*
   371  	_, found, err := ic.rt.GetActor(addr)
   372  	if err != nil {
   373  		panic(err)
   374  	}
   375  	if found {
   376  		ic.Abortf(exitcode.SysErrorIllegalArgument, "Actor address already exists")
   377  	}
   378  
   379  	newActor := &states.Actor{
   380  		Head:    ic.emptyObject,
   381  		Code:    codeID,
   382  		Balance: abi.NewTokenAmount(0),
   383  	}
   384  	if err := ic.rt.setActor(ic.rt.ctx, addr, newActor); err != nil {
   385  		panic(err)
   386  	}
   387  }
   388  
   389  // deleteActor implements runtime.ExtendedInvocationContext.
   390  func (ic *invocationContext) DeleteActor(beneficiary address.Address) {
   391  	receiver := ic.msg.to
   392  	receiverActor, found, err := ic.rt.GetActor(receiver)
   393  	if err != nil {
   394  		panic(err)
   395  	}
   396  	if !found {
   397  		ic.Abortf(exitcode.SysErrorIllegalActor, "delete non-existent actor %v", receiverActor)
   398  	}
   399  
   400  	// Transfer any remaining balance to the beneficiary.
   401  	// This looks like it could cause a problem with gas refund going to a non-existent actor, but the gas payer
   402  	// is always an account actor, which cannot be the receiver of this message.
   403  	if receiverActor.Balance.GreaterThan(big.Zero()) {
   404  		ic.rt.transfer(receiver, beneficiary, receiverActor.Balance)
   405  	}
   406  
   407  	if err := ic.rt.deleteActor(ic.rt.ctx, receiver); err != nil {
   408  		panic(err)
   409  	}
   410  }
   411  
   412  func (ic *invocationContext) TotalFilCircSupply() abi.TokenAmount {
   413  	return ic.topLevel.circSupply
   414  }
   415  
   416  func (ic *invocationContext) Context() context.Context {
   417  	return ic.rt.ctx
   418  }
   419  
   420  func (ic *invocationContext) ChargeGas(_ string, _ int64, _ int64) {
   421  	// no-op
   422  }
   423  
   424  // Starts a new tracing span. The span must be End()ed explicitly, typically with a deferred invocation.
   425  func (ic *invocationContext) StartSpan(_ string) func() {
   426  	return fakeTraceSpanEnd
   427  }
   428  
   429  // Provides the system call interface.
   430  func (ic *invocationContext) Syscalls() runtime.Syscalls {
   431  	return fakeSyscalls{receiver: ic.msg.to, epoch: ic.rt.currentEpoch}
   432  }
   433  
   434  // Note events that may make debugging easier
   435  func (ic *invocationContext) Log(level rt.LogLevel, msg string, args ...interface{}) {
   436  	ic.rt.Log(level, msg, args...)
   437  }
   438  
   439  type returnWrapper struct {
   440  	inner cbor.Marshaler
   441  }
   442  
   443  func (r returnWrapper) Into(o cbor.Unmarshaler) error {
   444  	if r.inner == nil {
   445  		return fmt.Errorf("failed to unmarshal nil return (did you mean abi.Empty?)")
   446  	}
   447  	b := bytes.Buffer{}
   448  	if err := r.inner.MarshalCBOR(&b); err != nil {
   449  		return err
   450  	}
   451  	return o.UnmarshalCBOR(&b)
   452  }
   453  
   454  /////////////////////////////////////////////
   455  //          Fake syscalls
   456  /////////////////////////////////////////////
   457  
   458  type fakeSyscalls struct {
   459  	receiver address.Address
   460  	epoch    abi.ChainEpoch
   461  }
   462  
   463  func (s fakeSyscalls) VerifySignature(_ crypto.Signature, _ address.Address, _ []byte) error {
   464  	return nil
   465  }
   466  
   467  func (s fakeSyscalls) HashBlake2b(b []byte) [32]byte {
   468  	return blake2b.Sum256(b)
   469  }
   470  
   471  func (s fakeSyscalls) ComputeUnsealedSectorCID(_ abi.RegisteredSealProof, _ []abi.PieceInfo) (cid.Cid, error) {
   472  	return testing.MakeCID("presealedSectorCID", nil), nil
   473  }
   474  
   475  func (s fakeSyscalls) VerifySeal(_ proof.SealVerifyInfo) error {
   476  	return nil
   477  }
   478  
   479  func (s fakeSyscalls) BatchVerifySeals(vi map[address.Address][]proof.SealVerifyInfo) (map[address.Address][]bool, error) {
   480  	res := map[address.Address][]bool{}
   481  	for addr, infos := range vi { //nolint:nomaprange
   482  		verified := make([]bool, len(infos))
   483  		for i := range infos {
   484  			// everyone wins
   485  			verified[i] = true
   486  		}
   487  		res[addr] = verified
   488  	}
   489  	return res, nil
   490  }
   491  
   492  func (s fakeSyscalls) VerifyPoSt(_ proof.WindowPoStVerifyInfo) error {
   493  	return nil
   494  }
   495  
   496  func (s fakeSyscalls) VerifyConsensusFault(_, _, _ []byte) (*runtime.ConsensusFault, error) {
   497  	return &runtime.ConsensusFault{
   498  		Target: s.receiver,
   499  		Epoch:  s.epoch - 1,
   500  		Type:   runtime.ConsensusFaultDoubleForkMining,
   501  	}, nil
   502  }
   503  
   504  /////////////////////////////////////////////
   505  //          Fake trace span
   506  /////////////////////////////////////////////
   507  
   508  func fakeTraceSpanEnd() {
   509  }
   510  
   511  /////////////////////////////////////////////
   512  //          storeWrapper
   513  /////////////////////////////////////////////
   514  
   515  type storeWrapper struct {
   516  	s  adt.Store
   517  	rt *VM
   518  }
   519  
   520  func (s storeWrapper) StoreGet(c cid.Cid, o cbor.Unmarshaler) bool {
   521  	err := s.s.Get(s.rt.ctx, c, o)
   522  	// assume all errors are not found errors (bad assumption, but ok for testing)
   523  	return err == nil
   524  }
   525  
   526  func (s storeWrapper) StorePut(x cbor.Marshaler) cid.Cid {
   527  	c, err := s.s.Put(s.rt.ctx, x)
   528  	if err != nil {
   529  		s.rt.Abortf(exitcode.ErrIllegalState, "could not put object in store")
   530  	}
   531  	return c
   532  }
   533  
   534  /////////////////////////////////////////////
   535  //          invocation
   536  /////////////////////////////////////////////
   537  
   538  // runtime aborts are trapped by invoke, it will always return an exit code.
   539  func (ic *invocationContext) invoke() (ret returnWrapper, errcode exitcode.ExitCode) {
   540  	// Checkpoint state, for restoration on rollback
   541  	// Note that changes prior to invocation (sequence number bump and gas prepayment) persist even if invocation fails.
   542  	priorRoot, err := ic.rt.checkpoint()
   543  	if err != nil {
   544  		panic(err)
   545  	}
   546  
   547  	ic.rt.startInvocation(&ic.msg)
   548  
   549  	// Install handler for abort, which rolls back all state changes from this and any nested invocations.
   550  	// This is the only path by which a non-OK exit code may be returned.
   551  	defer func() {
   552  		ic.stats.Capture()
   553  
   554  		if r := recover(); r != nil {
   555  			if err := ic.rt.rollback(priorRoot); err != nil {
   556  				panic(err)
   557  			}
   558  			switch r := r.(type) {
   559  			case abort:
   560  				ic.rt.Log(rt.WARN, "Abort during actor execution. errMsg: %v exitCode: %d sender: %v receiver; %v method: %d value %v",
   561  					r, r.code, ic.msg.from, ic.msg.to, ic.msg.method, ic.msg.value)
   562  				ic.rt.endInvocation(r.code, abi.Empty)
   563  				ret = returnWrapper{abi.Empty} // The Empty here should never be used, but slightly safer than zero value.
   564  				errcode = r.code
   565  				return
   566  			default:
   567  				// do not trap unknown panics
   568  				debug.PrintStack()
   569  				panic(r)
   570  			}
   571  		}
   572  	}()
   573  
   574  	// pre-dispatch
   575  	// 1. load target actor
   576  	// 2. transfer optional funds
   577  	// 3. short-circuit _Send_ method
   578  	// 4. load target actor code
   579  	// 5. create target state handle
   580  	// assert from address is an ID address.
   581  	if ic.msg.from.Protocol() != address.ID {
   582  		panic("bad Exitcode: sender address MUST be an ID address at invocation time")
   583  	}
   584  
   585  	// 2. load target actor
   586  	// Note: we replace the "to" address with the normalized version
   587  	ic.toActor, ic.msg.to = ic.resolveTarget(ic.msg.to)
   588  
   589  	// 3. transfer funds carried by the msg
   590  	if !ic.msg.value.NilOrZero() {
   591  		if ic.msg.value.LessThan(big.Zero()) {
   592  			ic.Abortf(exitcode.SysErrForbidden, "attempt to transfer negative value %s from %s to %s",
   593  				ic.msg.value, ic.msg.from, ic.msg.to)
   594  		}
   595  		if ic.fromActor.Balance.LessThan(ic.msg.value) {
   596  			ic.Abortf(exitcode.SysErrInsufficientFunds, "sender %s insufficient balance %s to transfer %s to %s",
   597  				ic.msg.from, ic.fromActor.Balance, ic.msg.value, ic.msg.to)
   598  		}
   599  		ic.toActor, ic.fromActor = ic.rt.transfer(ic.msg.from, ic.msg.to, ic.msg.value)
   600  	}
   601  
   602  	// 4. if we are just sending funds, there is nothing else to do.
   603  	if ic.msg.method == builtin.MethodSend {
   604  		ic.rt.endInvocation(exitcode.Ok, abi.Empty)
   605  		return returnWrapper{abi.Empty}, exitcode.Ok
   606  	}
   607  
   608  	// 5. load target actor code
   609  	actorImpl := ic.rt.getActorImpl(ic.toActor.Code)
   610  
   611  	// dispatch
   612  	out, err := ic.dispatch(actorImpl, ic.msg.method, ic.msg.params)
   613  	if err != nil {
   614  		ic.Abortf(exitcode.SysErrInvalidMethod, "could not dispatch method")
   615  	}
   616  
   617  	// assert output implements expected interface
   618  	var marsh cbor.Marshaler = abi.Empty
   619  	if out != nil {
   620  		var ok bool
   621  		marsh, ok = out.(cbor.Marshaler)
   622  		if !ok {
   623  			ic.Abortf(exitcode.SysErrorIllegalActor, "Returned value is not a CBORMarshaler")
   624  		}
   625  	}
   626  	ret = returnWrapper{inner: marsh}
   627  
   628  	ic.checkStateObjectsUnmodified()
   629  
   630  	// 3. success!
   631  	ic.rt.endInvocation(exitcode.Ok, marsh)
   632  	return ret, exitcode.Ok
   633  }
   634  
   635  func (ic *invocationContext) dispatch(actor runtime.VMActor, method abi.MethodNum, arg interface{}) (interface{}, error) {
   636  	// get method signature
   637  	exports := actor.Exports()
   638  
   639  	// get method entry
   640  	methodIdx := (uint64)(method)
   641  	if len(exports) <= (int)(methodIdx) {
   642  		return nil, fmt.Errorf("method undefined. method: %d, Exitcode: %s", method, actor.Code())
   643  	}
   644  	entry := exports[methodIdx]
   645  	if entry == nil {
   646  		return nil, fmt.Errorf("method undefined. method: %d, Exitcode: %s", method, actor.Code())
   647  	}
   648  
   649  	ventry := reflect.ValueOf(entry)
   650  
   651  	// build args to pass to the method
   652  	args := []reflect.Value{
   653  		// the ctx will be automatically coerced
   654  		reflect.ValueOf(ic),
   655  	}
   656  
   657  	t := ventry.Type().In(1)
   658  	if arg == nil {
   659  		args = append(args, reflect.New(t).Elem())
   660  	} else if raw, ok := arg.([]byte); ok {
   661  		obj, err := decodeBytes(t, raw)
   662  		if err != nil {
   663  			return nil, err
   664  		}
   665  		args = append(args, reflect.ValueOf(obj))
   666  	} else if raw, ok := arg.(builtin.CBORBytes); ok {
   667  		obj, err := decodeBytes(t, raw)
   668  		if err != nil {
   669  			return nil, err
   670  		}
   671  		args = append(args, reflect.ValueOf(obj))
   672  	} else {
   673  		args = append(args, reflect.ValueOf(arg))
   674  	}
   675  
   676  	// invoke the method
   677  	out := ventry.Call(args)
   678  
   679  	// Note: we only support single objects being returned
   680  	if len(out) > 1 {
   681  		return nil, fmt.Errorf("actor method returned more than one object. method: %d, Exitcode: %s", method, actor.Code())
   682  	}
   683  
   684  	// method returns unit
   685  	// Note: we need to check for `IsNill()` here because Go doesnt work if you do `== nil` on the interface
   686  	if len(out) == 0 || (out[0].Kind() != reflect.Struct && out[0].IsNil()) {
   687  		return nil, nil
   688  	}
   689  
   690  	// forward return
   691  	return out[0].Interface(), nil
   692  }
   693  
   694  // resolveTarget loads and actor and returns its ActorID address.
   695  //
   696  // If the target actor does not exist, and the target address is a pub-key address,
   697  // a new account actor will be created.
   698  // Otherwise, this method will abort execution.
   699  func (ic *invocationContext) resolveTarget(target address.Address) (*states.Actor, address.Address) {
   700  	// resolve the target address via the InitActor, and attempt to load state.
   701  	initActorEntry, found, err := ic.rt.GetActor(builtin.InitActorAddr)
   702  	if err != nil {
   703  		panic(err)
   704  	}
   705  	if !found {
   706  		ic.Abortf(exitcode.SysErrSenderInvalid, "init actor not found")
   707  	}
   708  
   709  	if target == builtin.InitActorAddr {
   710  		return initActorEntry, target
   711  	}
   712  
   713  	// get a view into the actor state
   714  	var state init_.State
   715  	if err := ic.rt.store.Get(ic.rt.ctx, initActorEntry.Head, &state); err != nil {
   716  		panic(err)
   717  	}
   718  
   719  	// lookup the ActorID based on the address
   720  	targetIDAddr, found, err := state.ResolveAddress(ic.rt.store, target)
   721  	created := false
   722  	if err != nil {
   723  		panic(err)
   724  	} else if !found {
   725  		if target.Protocol() != address.SECP256K1 && target.Protocol() != address.BLS {
   726  			// Don't implicitly create an account actor for an address without an associated key.
   727  			ic.Abortf(exitcode.SysErrInvalidReceiver, "cannot create account for address type")
   728  		}
   729  
   730  		targetIDAddr, err = state.MapAddressToNewID(ic.rt.store, target)
   731  		if err != nil {
   732  			panic(err)
   733  		}
   734  		// store new state
   735  		initHead, err := ic.rt.store.Put(ic.rt.ctx, &state)
   736  		if err != nil {
   737  			panic(err)
   738  		}
   739  		// update init actor
   740  		initActorEntry.Head = initHead
   741  		if err := ic.rt.setActor(ic.rt.ctx, builtin.InitActorAddr, initActorEntry); err != nil {
   742  			panic(err)
   743  		}
   744  
   745  		ic.CreateActor(builtin.AccountActorCodeID, targetIDAddr)
   746  
   747  		// call constructor on account
   748  		newMsg := InternalMessage{
   749  			from:   builtin.SystemActorAddr,
   750  			to:     targetIDAddr,
   751  			value:  big.Zero(),
   752  			method: builtin.MethodsAccount.Constructor,
   753  			// use original address as constructor params
   754  			// Note: constructor takes a pointer
   755  			params: &target,
   756  		}
   757  
   758  		newCtx := newInvocationContext(ic.rt, ic.topLevel, newMsg, nil, ic.emptyObject)
   759  		_, code := newCtx.invoke()
   760  
   761  		ic.stats.MergeSubStat(builtin.InitActorCodeID, builtin.MethodsAccount.Constructor, newCtx.stats)
   762  
   763  		if code.IsError() {
   764  			// we failed to construct an account actor..
   765  			ic.Abortf(code, "failed to construct account actor")
   766  		}
   767  
   768  		created = true
   769  	}
   770  
   771  	// load actor
   772  	targetActor, found, err := ic.rt.GetActor(targetIDAddr)
   773  	if err != nil {
   774  		panic(err)
   775  	}
   776  	if !found && created {
   777  		panic(fmt.Errorf("unreachable: actor is supposed to exist but it does not. addr: %s, idAddr: %s", target, targetIDAddr))
   778  	}
   779  	if !found {
   780  		ic.Abortf(exitcode.SysErrInvalidReceiver, "actor at address %s registered but not found", targetIDAddr.String())
   781  	}
   782  
   783  	return targetActor, targetIDAddr
   784  }
   785  
   786  func (ic *invocationContext) replace(obj cbor.Marshaler) cid.Cid {
   787  	actr, found, err := ic.rt.GetActor(ic.msg.to)
   788  	if err != nil {
   789  		panic(err)
   790  	}
   791  	if !found {
   792  		ic.rt.Abortf(exitcode.ErrIllegalState, "failed to find actor %s for state", ic.msg.to)
   793  	}
   794  	c, err := ic.rt.store.Put(ic.rt.ctx, obj)
   795  	if err != nil {
   796  		ic.rt.Abortf(exitcode.ErrIllegalState, "could not save new state")
   797  	}
   798  	actr.Head = c
   799  	err = ic.rt.setActor(ic.rt.ctx, ic.msg.to, actr)
   800  	if err != nil {
   801  		ic.rt.Abortf(exitcode.ErrIllegalState, "could not save actor %s", ic.msg.to)
   802  	}
   803  	return c
   804  }
   805  
   806  // Checks that state objects weren't modified outside of transaction.
   807  func (ic *invocationContext) checkStateObjectsUnmodified() {
   808  	for obj, expectedKey := range ic.stateUsedObjs { // nolint:nomaprange
   809  		// Recompute the CID of the object and check it's the same as was recorded
   810  		// when the object was loaded.
   811  		finalKey, _, err := ipld.MarshalCBOR(obj)
   812  		if err != nil {
   813  			ic.Abortf(exitcode.SysErrorIllegalActor, "error marshalling state object for validation: %v", err)
   814  		}
   815  		if finalKey != expectedKey {
   816  			ic.Abortf(exitcode.SysErrorIllegalActor, "State mutated outside of transaction scope")
   817  		}
   818  	}
   819  }
   820  
   821  func decodeBytes(t reflect.Type, argBytes []byte) (interface{}, error) {
   822  	// decode arg1 (this is the payload for the actor method)
   823  	v := reflect.New(t)
   824  
   825  	// This would be better fixed in then encoding library.
   826  	obj := v.Elem().Interface()
   827  	if _, ok := obj.(cbor.Unmarshaler); !ok {
   828  		return nil, errors.New("method argument cannot be decoded")
   829  	}
   830  
   831  	buf := bytes.NewBuffer(argBytes)
   832  	auxv := reflect.New(t.Elem())
   833  	obj = auxv.Interface()
   834  
   835  	unmarsh := obj.(cbor.Unmarshaler)
   836  	if err := unmarsh.UnmarshalCBOR(buf); err != nil {
   837  		return nil, err
   838  	}
   839  	return unmarsh, nil
   840  }