diff --git a/gen/builders/builder_message.go b/gen/builders/builder_message.go index 7689b50d..2f064213 100644 --- a/gen/builders/builder_message.go +++ b/gen/builders/builder_message.go @@ -103,7 +103,7 @@ func (b *MessageVectorBuilder) CommitApplies() { for _, am := range b.Messages.All() { // apply all messages that are pending application. - if am.Result == nil { + if !am.Applied { b.StateTracker.ApplyMessage(am) } @@ -112,11 +112,17 @@ func (b *MessageVectorBuilder) CommitApplies() { Bytes: MustSerialize(am.Message), Epoch: &epoch, }) - b.vector.Post.Receipts = append(b.vector.Post.Receipts, &schema.Receipt{ - ExitCode: int64(am.Result.ExitCode), - ReturnValue: am.Result.Return, - GasUsed: am.Result.GasUsed, - }) + + // am.Result may still be nil if the message failed to be applied + if am.Result != nil { + b.vector.Post.Receipts = append(b.vector.Post.Receipts, &schema.Receipt{ + ExitCode: int64(am.Result.ExitCode), + ReturnValue: am.Result.Return, + GasUsed: am.Result.GasUsed, + }) + } else { + b.vector.Post.Receipts = append(b.vector.Post.Receipts, nil) + } } // update the internal state. @@ -124,7 +130,6 @@ func (b *MessageVectorBuilder) CommitApplies() { b.vector.Post.StateTree = &schema.StateTree{RootCID: b.PostRoot} b.Stage = StageChecks b.Assert.enterStage(StageChecks) - } // Finish signals to the builder that the checks stage is complete and that the diff --git a/gen/builders/messages.go b/gen/builders/messages.go index 4e6cb502..8c13d94d 100644 --- a/gen/builders/messages.go +++ b/gen/builders/messages.go @@ -38,6 +38,10 @@ type ApplicableMessage struct { Epoch abi.ChainEpoch Message *types.Message Result *vm.ApplyRet + // Applied is true if this message has already been applied. Note it's + // not safe to rely on non-nil Result as indication of application + // since applied messages may fail without a result. + Applied bool } func (m *Messages) Sugar() *sugarMsg { diff --git a/gen/builders/predicates.go b/gen/builders/predicates.go index 84987e37..ff56606c 100644 --- a/gen/builders/predicates.go +++ b/gen/builders/predicates.go @@ -48,12 +48,14 @@ func MessageReturns(expect cbg.CBORMarshaler) ApplyRetPredicate { } } -// PanickedRet represents a non-return value, a placeholder for when an actor panicked while applying a message. -var PanickedRet = vm.ApplyRet{} - -// Panicked returns an ApplyRetPredicate that passes if the message response is the PanickedRet. -func Panicked() ApplyRetPredicate { - return MessageReturns(&PanickedRet) +// Nil returns an ApplyRetPredicate that passes if the message receipt is nil. +func Nil() ApplyRetPredicate { + return func(ret *vm.ApplyRet) error { + if ret != nil { + return fmt.Errorf("message receipt was not nil: %+v", ret) + } + return nil + } } // BalanceUpdated returns a ActorPredicate that checks whether the balance diff --git a/gen/builders/state_tracker.go b/gen/builders/state_tracker.go index 971576e9..e0af6da3 100644 --- a/gen/builders/state_tracker.go +++ b/gen/builders/state_tracker.go @@ -86,10 +86,16 @@ func (st *StateTracker) Flush() cid.Cid { // root, refreshes the state tree, and updates the underlying vector with the // message and its receipt. func (st *StateTracker) ApplyMessage(am *ApplicableMessage) { + var postRoot cid.Cid var err error - am.Result, st.CurrRoot, err = st.Driver.ExecuteMessage(st.Stores.Blockstore, st.CurrRoot, am.Epoch, am.Message) - st.bc.Assert.NoError(err) + am.Applied = true + am.Result, postRoot, err = st.Driver.ExecuteMessage(st.Stores.Blockstore, st.CurrRoot, am.Epoch, am.Message) + if err != nil { + return + } + + st.CurrRoot = postRoot // replace the state tree. st.StateTree, err = state.LoadStateTree(st.Stores.CBORStore, st.CurrRoot) st.bc.Assert.NoError(err) diff --git a/gen/suites/vm_violations/actor_abort.go b/gen/suites/vm_violations/actor_abort.go index ce80b1e9..25cea74a 100644 --- a/gen/suites/vm_violations/actor_abort.go +++ b/gen/suites/vm_violations/actor_abort.go @@ -48,6 +48,6 @@ func actorPanic(msg string) func(*MessageVectorBuilder) { ) v.CommitApplies() - v.Assert.LastMessageResultSatisfies(Panicked()) + v.Assert.LastMessageResultSatisfies(Nil()) } } diff --git a/schema.json b/schema.json index 07ef5753..cdccac2b 100644 --- a/schema.json +++ b/schema.json @@ -148,7 +148,14 @@ "type": "array", "additionalItems": false, "items": { - "$ref": "#/definitions/receipt" + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/definitions/receipt" + } + ] } }, "receipts_roots": {