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 }