diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99baf80f01d..7c3bb8c3282 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,159 @@
# Lotus changelog
+# UNRELEASED
+
+## Execution Trace Format Changes
+
+Execution traces (returned from `lotus state exec-trace`, `lotus state replay`, etc.), has changed to account for changes introduced by the FVM. Specifically:
+
+- The `Msg` field no longer matches the Filecoin message format as many of the message fields didn't make sense in on-chain sub-calls. Instead, it now has the fields `To`, `From`, `Value`, `Method`, `Params`, and `ParamsCodec` where `ParamsCodec` is a new field indicating the IPLD codec of the parameters.
+ - Importantly, the `Msg.CID` field has been removed. This field is still present in top-level invocation results, just not inside the execution trace itself.
+- The `MsgRct` field no longer includes a `GasUsed` field and now has a `ReturnCodec` field to indicating the IPLD codec of the return value.
+- The `Error` and `Duration` fields have been removed as these are not set by the FVM. The top-level message "invocation result" retains the `Error` and `Duration` fields, they've only been removed from the trace itself.
+- Gas Charges no longer include "virtual" gas fields (those starting with `v...`) or source location information (`loc`) as neither field is set by the FVM.
+
+A note on "codecs": FVM parameters and return values are IPLD blocks where the "codec" specifies the data encoding. The codec will generally be one of:
+
+- `0x51`, `0x71` - CBOR or DagCBOR. You should generally treat these as equivalent.
+- `0x55` - Raw bytes.
+- `0x00` - Nothing. If the codec is `0x00`, the parameter and/or return value should be empty and should be treated as "void" (not specified).
+
+
+
+Old ExecutionTrace
:
+
+
+```json
+{
+ "Msg": {
+ "Version": 0,
+ "To": "f01234",
+ "From": "f04321",
+ "Nonce": 1,
+ "Value": "0",
+ "GasLimit": 0,
+ "GasFeeCap": "1234",
+ "GasPremium": "1234",
+ "Method": 42,
+ "Params": "",
+ "CID": {
+ "/": "bafyxyz....."
+ },
+ },
+ "MsgRct": {
+ "ExitCode": 0,
+ "Return": "",
+ "GasUsed": 12345,
+ },
+ "Error": "",
+ "Duration": 568191845,
+ "GasCharges": [
+ {
+ "Name": "OnMethodInvocation",
+ "loc": null,
+ "tg": 23856,
+ "cg": 23856,
+ "sg": 0,
+ "vtg": 0,
+ "vcg": 0,
+ "vsg": 0,
+ "tt": 0
+ },
+ {
+ "Name": "wasm_exec",
+ "loc": null,
+ "tg": 1764,
+ "cg": 1764,
+ "sg": 0,
+ "vtg": 0,
+ "vcg": 0,
+ "vsg": 0,
+ "tt": 0
+ },
+ {
+ "Name": "OnSyscall",
+ "loc": null,
+ "tg": 14000,
+ "cg": 14000,
+ "sg": 0,
+ "vtg": 0,
+ "vcg": 0,
+ "vsg": 0,
+ "tt": 0
+ },
+ ],
+ "Subcalls": [
+ {
+ "Msg": { },
+ "MsgRct": { },
+ "Error": "",
+ "Duration": 1235,
+ "GasCharges": [],
+ "Subcalls": [],
+ },
+ ]
+}
+```
+
+
+
+
+New ExecutionTrace
:
+
+
+```json
+{
+ "Msg": {
+ "To": "f01234",
+ "From": "f04321",
+ "Value": "0",
+ "Method": 42,
+ "Params": "",
+ "ParamsCodec": 81
+ },
+ "MsgRct": {
+ "ExitCode": 0,
+ "Return": "",
+ "ReturnCodec": 81
+ },
+ "GasCharges": [
+ {
+ "Name": "OnMethodInvocation",
+ "loc": null,
+ "tg": 23856,
+ "cg": 23856,
+ "tt": 0
+ },
+ {
+ "Name": "wasm_exec",
+ "loc": null,
+ "tg": 1764,
+ "cg": 1764,
+ "sg": 0,
+ "tt": 0
+ },
+ {
+ "Name": "OnSyscall",
+ "loc": null,
+ "tg": 14000,
+ "cg": 14000,
+ "sg": 0,
+ "tt": 0
+ },
+ ],
+ "Subcalls": [
+ {
+ "Msg": { },
+ "MsgRct": { },
+ "GasCharges": [],
+ "Subcalls": [],
+ },
+ ]
+}
+```
+
+
+
# v1.20.4 / 2023-03-17
This is a patch release intended to alleviate performance issues reported by some users since the nv18 upgrade.
diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go
index 0e97997a6d8..10e9c2fce57 100644
--- a/api/docgen/docgen.go
+++ b/api/docgen/docgen.go
@@ -152,8 +152,8 @@ func init() {
addExample(map[string]int{"name": 42})
addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()})
addExample(&types.ExecutionTrace{
- Msg: ExampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message),
- MsgRct: ExampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
+ Msg: ExampleValue("init", reflect.TypeOf(types.MessageTrace{}), nil).(types.MessageTrace),
+ MsgRct: ExampleValue("init", reflect.TypeOf(types.ReturnTrace{}), nil).(types.ReturnTrace),
})
addExample(map[string]types.Actor{
"t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor),
diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz
index 95cea8d6c97..fe0ffec32f8 100644
Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ
diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz
index a505c3a71d1..546c1691889 100644
Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ
diff --git a/chain/consensus/filcns/upgrades.go b/chain/consensus/filcns/upgrades.go
index b61f142c4ea..583a174f2b7 100644
--- a/chain/consensus/filcns/upgrades.go
+++ b/chain/consensus/filcns/upgrades.go
@@ -525,12 +525,11 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *stmgr.StateManager, _ st
MessageReceipt: *stmgr.MakeFakeRct(),
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{
- Msg: fakeMsg,
- MsgRct: stmgr.MakeFakeRct(),
- Error: "",
- Duration: 0,
- GasCharges: nil,
- Subcalls: subcalls,
+ Msg: types.MessageTrace{
+ To: fakeMsg.To,
+ From: fakeMsg.From,
+ },
+ Subcalls: subcalls,
},
Duration: 0,
GasCosts: nil,
@@ -703,12 +702,11 @@ func splitGenesisMultisig0(ctx context.Context, em stmgr.ExecMonitor, addr addre
MessageReceipt: *stmgr.MakeFakeRct(),
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{
- Msg: fakeMsg,
- MsgRct: stmgr.MakeFakeRct(),
- Error: "",
- Duration: 0,
- GasCharges: nil,
- Subcalls: subcalls,
+ Msg: types.MessageTrace{
+ From: fakeMsg.From,
+ To: fakeMsg.To,
+ },
+ Subcalls: subcalls,
},
Duration: 0,
GasCosts: nil,
diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go
index 514f78f762d..80e30197ef6 100644
--- a/chain/stmgr/forks.go
+++ b/chain/stmgr/forks.go
@@ -347,12 +347,11 @@ func DoTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmo
// record the transfer in execution traces
cb(types.ExecutionTrace{
- Msg: MakeFakeMsg(from, to, amt, 0),
- MsgRct: MakeFakeRct(),
- Error: "",
- Duration: 0,
- GasCharges: nil,
- Subcalls: nil,
+ Msg: types.MessageTrace{
+ From: from,
+ To: to,
+ Value: amt,
+ },
})
}
diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go
index 314b2be6c56..c22cf3e2024 100644
--- a/chain/types/cbor_gen.go
+++ b/chain/types/cbor_gen.go
@@ -7,6 +7,7 @@ import (
"io"
"math"
"sort"
+ time "time"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
@@ -15,6 +16,7 @@ import (
address "github.com/filecoin-project/go-address"
abi "github.com/filecoin-project/go-state-types/abi"
crypto "github.com/filecoin-project/go-state-types/crypto"
+ exitcode "github.com/filecoin-project/go-state-types/exitcode"
proof "github.com/filecoin-project/go-state-types/proof"
)
@@ -2078,3 +2080,659 @@ func (t *EventEntry) UnmarshalCBOR(r io.Reader) (err error) {
}
return nil
}
+
+var lengthBufGasTrace = []byte{133}
+
+func (t *GasTrace) MarshalCBOR(w io.Writer) error {
+ if t == nil {
+ _, err := w.Write(cbg.CborNull)
+ return err
+ }
+
+ cw := cbg.NewCborWriter(w)
+
+ if _, err := cw.Write(lengthBufGasTrace); err != nil {
+ return err
+ }
+
+ // t.Name (string) (string)
+ if len(t.Name) > cbg.MaxLength {
+ return xerrors.Errorf("Value in field t.Name was too long")
+ }
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil {
+ return err
+ }
+ if _, err := io.WriteString(w, string(t.Name)); err != nil {
+ return err
+ }
+
+ // t.TotalGas (int64) (int64)
+ if t.TotalGas >= 0 {
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.TotalGas)); err != nil {
+ return err
+ }
+ } else {
+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.TotalGas-1)); err != nil {
+ return err
+ }
+ }
+
+ // t.ComputeGas (int64) (int64)
+ if t.ComputeGas >= 0 {
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ComputeGas)); err != nil {
+ return err
+ }
+ } else {
+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ComputeGas-1)); err != nil {
+ return err
+ }
+ }
+
+ // t.StorageGas (int64) (int64)
+ if t.StorageGas >= 0 {
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.StorageGas)); err != nil {
+ return err
+ }
+ } else {
+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.StorageGas-1)); err != nil {
+ return err
+ }
+ }
+
+ // t.TimeTaken (time.Duration) (int64)
+ if t.TimeTaken >= 0 {
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.TimeTaken)); err != nil {
+ return err
+ }
+ } else {
+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.TimeTaken-1)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (t *GasTrace) UnmarshalCBOR(r io.Reader) (err error) {
+ *t = GasTrace{}
+
+ cr := cbg.NewCborReader(r)
+
+ maj, extra, err := cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ }()
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("cbor input should be of type array")
+ }
+
+ if extra != 5 {
+ return fmt.Errorf("cbor input had wrong number of fields")
+ }
+
+ // t.Name (string) (string)
+
+ {
+ sval, err := cbg.ReadString(cr)
+ if err != nil {
+ return err
+ }
+
+ t.Name = string(sval)
+ }
+ // t.TotalGas (int64) (int64)
+ {
+ maj, extra, err := cr.ReadHeader()
+ var extraI int64
+ if err != nil {
+ return err
+ }
+ switch maj {
+ case cbg.MajUnsignedInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 positive overflow")
+ }
+ case cbg.MajNegativeInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 negative oveflow")
+ }
+ extraI = -1 - extraI
+ default:
+ return fmt.Errorf("wrong type for int64 field: %d", maj)
+ }
+
+ t.TotalGas = int64(extraI)
+ }
+ // t.ComputeGas (int64) (int64)
+ {
+ maj, extra, err := cr.ReadHeader()
+ var extraI int64
+ if err != nil {
+ return err
+ }
+ switch maj {
+ case cbg.MajUnsignedInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 positive overflow")
+ }
+ case cbg.MajNegativeInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 negative oveflow")
+ }
+ extraI = -1 - extraI
+ default:
+ return fmt.Errorf("wrong type for int64 field: %d", maj)
+ }
+
+ t.ComputeGas = int64(extraI)
+ }
+ // t.StorageGas (int64) (int64)
+ {
+ maj, extra, err := cr.ReadHeader()
+ var extraI int64
+ if err != nil {
+ return err
+ }
+ switch maj {
+ case cbg.MajUnsignedInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 positive overflow")
+ }
+ case cbg.MajNegativeInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 negative oveflow")
+ }
+ extraI = -1 - extraI
+ default:
+ return fmt.Errorf("wrong type for int64 field: %d", maj)
+ }
+
+ t.StorageGas = int64(extraI)
+ }
+ // t.TimeTaken (time.Duration) (int64)
+ {
+ maj, extra, err := cr.ReadHeader()
+ var extraI int64
+ if err != nil {
+ return err
+ }
+ switch maj {
+ case cbg.MajUnsignedInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 positive overflow")
+ }
+ case cbg.MajNegativeInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 negative oveflow")
+ }
+ extraI = -1 - extraI
+ default:
+ return fmt.Errorf("wrong type for int64 field: %d", maj)
+ }
+
+ t.TimeTaken = time.Duration(extraI)
+ }
+ return nil
+}
+
+var lengthBufMessageTrace = []byte{134}
+
+func (t *MessageTrace) MarshalCBOR(w io.Writer) error {
+ if t == nil {
+ _, err := w.Write(cbg.CborNull)
+ return err
+ }
+
+ cw := cbg.NewCborWriter(w)
+
+ if _, err := cw.Write(lengthBufMessageTrace); err != nil {
+ return err
+ }
+
+ // t.From (address.Address) (struct)
+ if err := t.From.MarshalCBOR(cw); err != nil {
+ return err
+ }
+
+ // t.To (address.Address) (struct)
+ if err := t.To.MarshalCBOR(cw); err != nil {
+ return err
+ }
+
+ // t.Value (big.Int) (struct)
+ if err := t.Value.MarshalCBOR(cw); err != nil {
+ return err
+ }
+
+ // t.Method (abi.MethodNum) (uint64)
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Method)); err != nil {
+ return err
+ }
+
+ // t.Params ([]uint8) (slice)
+ if len(t.Params) > cbg.ByteArrayMaxLen {
+ return xerrors.Errorf("Byte array in field t.Params was too long")
+ }
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Params))); err != nil {
+ return err
+ }
+
+ if _, err := cw.Write(t.Params[:]); err != nil {
+ return err
+ }
+
+ // t.ParamsCodec (uint64) (uint64)
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ParamsCodec)); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (t *MessageTrace) UnmarshalCBOR(r io.Reader) (err error) {
+ *t = MessageTrace{}
+
+ cr := cbg.NewCborReader(r)
+
+ maj, extra, err := cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ }()
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("cbor input should be of type array")
+ }
+
+ if extra != 6 {
+ return fmt.Errorf("cbor input had wrong number of fields")
+ }
+
+ // t.From (address.Address) (struct)
+
+ {
+
+ if err := t.From.UnmarshalCBOR(cr); err != nil {
+ return xerrors.Errorf("unmarshaling t.From: %w", err)
+ }
+
+ }
+ // t.To (address.Address) (struct)
+
+ {
+
+ if err := t.To.UnmarshalCBOR(cr); err != nil {
+ return xerrors.Errorf("unmarshaling t.To: %w", err)
+ }
+
+ }
+ // t.Value (big.Int) (struct)
+
+ {
+
+ if err := t.Value.UnmarshalCBOR(cr); err != nil {
+ return xerrors.Errorf("unmarshaling t.Value: %w", err)
+ }
+
+ }
+ // t.Method (abi.MethodNum) (uint64)
+
+ {
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ if maj != cbg.MajUnsignedInt {
+ return fmt.Errorf("wrong type for uint64 field")
+ }
+ t.Method = abi.MethodNum(extra)
+
+ }
+ // t.Params ([]uint8) (slice)
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+
+ if extra > cbg.ByteArrayMaxLen {
+ return fmt.Errorf("t.Params: byte array too large (%d)", extra)
+ }
+ if maj != cbg.MajByteString {
+ return fmt.Errorf("expected byte array")
+ }
+
+ if extra > 0 {
+ t.Params = make([]uint8, extra)
+ }
+
+ if _, err := io.ReadFull(cr, t.Params[:]); err != nil {
+ return err
+ }
+ // t.ParamsCodec (uint64) (uint64)
+
+ {
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ if maj != cbg.MajUnsignedInt {
+ return fmt.Errorf("wrong type for uint64 field")
+ }
+ t.ParamsCodec = uint64(extra)
+
+ }
+ return nil
+}
+
+var lengthBufReturnTrace = []byte{131}
+
+func (t *ReturnTrace) MarshalCBOR(w io.Writer) error {
+ if t == nil {
+ _, err := w.Write(cbg.CborNull)
+ return err
+ }
+
+ cw := cbg.NewCborWriter(w)
+
+ if _, err := cw.Write(lengthBufReturnTrace); err != nil {
+ return err
+ }
+
+ // t.ExitCode (exitcode.ExitCode) (int64)
+ if t.ExitCode >= 0 {
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
+ return err
+ }
+ } else {
+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
+ return err
+ }
+ }
+
+ // t.Return ([]uint8) (slice)
+ if len(t.Return) > cbg.ByteArrayMaxLen {
+ return xerrors.Errorf("Byte array in field t.Return was too long")
+ }
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
+ return err
+ }
+
+ if _, err := cw.Write(t.Return[:]); err != nil {
+ return err
+ }
+
+ // t.ReturnCodec (uint64) (uint64)
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ReturnCodec)); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (t *ReturnTrace) UnmarshalCBOR(r io.Reader) (err error) {
+ *t = ReturnTrace{}
+
+ cr := cbg.NewCborReader(r)
+
+ maj, extra, err := cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ }()
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("cbor input should be of type array")
+ }
+
+ if extra != 3 {
+ return fmt.Errorf("cbor input had wrong number of fields")
+ }
+
+ // t.ExitCode (exitcode.ExitCode) (int64)
+ {
+ maj, extra, err := cr.ReadHeader()
+ var extraI int64
+ if err != nil {
+ return err
+ }
+ switch maj {
+ case cbg.MajUnsignedInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 positive overflow")
+ }
+ case cbg.MajNegativeInt:
+ extraI = int64(extra)
+ if extraI < 0 {
+ return fmt.Errorf("int64 negative oveflow")
+ }
+ extraI = -1 - extraI
+ default:
+ return fmt.Errorf("wrong type for int64 field: %d", maj)
+ }
+
+ t.ExitCode = exitcode.ExitCode(extraI)
+ }
+ // t.Return ([]uint8) (slice)
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+
+ if extra > cbg.ByteArrayMaxLen {
+ return fmt.Errorf("t.Return: byte array too large (%d)", extra)
+ }
+ if maj != cbg.MajByteString {
+ return fmt.Errorf("expected byte array")
+ }
+
+ if extra > 0 {
+ t.Return = make([]uint8, extra)
+ }
+
+ if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
+ return err
+ }
+ // t.ReturnCodec (uint64) (uint64)
+
+ {
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ if maj != cbg.MajUnsignedInt {
+ return fmt.Errorf("wrong type for uint64 field")
+ }
+ t.ReturnCodec = uint64(extra)
+
+ }
+ return nil
+}
+
+var lengthBufExecutionTrace = []byte{132}
+
+func (t *ExecutionTrace) MarshalCBOR(w io.Writer) error {
+ if t == nil {
+ _, err := w.Write(cbg.CborNull)
+ return err
+ }
+
+ cw := cbg.NewCborWriter(w)
+
+ if _, err := cw.Write(lengthBufExecutionTrace); err != nil {
+ return err
+ }
+
+ // t.Msg (types.MessageTrace) (struct)
+ if err := t.Msg.MarshalCBOR(cw); err != nil {
+ return err
+ }
+
+ // t.MsgRct (types.ReturnTrace) (struct)
+ if err := t.MsgRct.MarshalCBOR(cw); err != nil {
+ return err
+ }
+
+ // t.GasCharges ([]*types.GasTrace) (slice)
+ if len(t.GasCharges) > 1000000000 {
+ return xerrors.Errorf("Slice value in field t.GasCharges was too long")
+ }
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.GasCharges))); err != nil {
+ return err
+ }
+ for _, v := range t.GasCharges {
+ if err := v.MarshalCBOR(cw); err != nil {
+ return err
+ }
+ }
+
+ // t.Subcalls ([]types.ExecutionTrace) (slice)
+ if len(t.Subcalls) > 1000000000 {
+ return xerrors.Errorf("Slice value in field t.Subcalls was too long")
+ }
+
+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Subcalls))); err != nil {
+ return err
+ }
+ for _, v := range t.Subcalls {
+ if err := v.MarshalCBOR(cw); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (t *ExecutionTrace) UnmarshalCBOR(r io.Reader) (err error) {
+ *t = ExecutionTrace{}
+
+ cr := cbg.NewCborReader(r)
+
+ maj, extra, err := cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ }()
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("cbor input should be of type array")
+ }
+
+ if extra != 4 {
+ return fmt.Errorf("cbor input had wrong number of fields")
+ }
+
+ // t.Msg (types.MessageTrace) (struct)
+
+ {
+
+ if err := t.Msg.UnmarshalCBOR(cr); err != nil {
+ return xerrors.Errorf("unmarshaling t.Msg: %w", err)
+ }
+
+ }
+ // t.MsgRct (types.ReturnTrace) (struct)
+
+ {
+
+ if err := t.MsgRct.UnmarshalCBOR(cr); err != nil {
+ return xerrors.Errorf("unmarshaling t.MsgRct: %w", err)
+ }
+
+ }
+ // t.GasCharges ([]*types.GasTrace) (slice)
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+
+ if extra > 1000000000 {
+ return fmt.Errorf("t.GasCharges: array too large (%d)", extra)
+ }
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("expected cbor array")
+ }
+
+ if extra > 0 {
+ t.GasCharges = make([]*GasTrace, extra)
+ }
+
+ for i := 0; i < int(extra); i++ {
+
+ var v GasTrace
+ if err := v.UnmarshalCBOR(cr); err != nil {
+ return err
+ }
+
+ t.GasCharges[i] = &v
+ }
+
+ // t.Subcalls ([]types.ExecutionTrace) (slice)
+
+ maj, extra, err = cr.ReadHeader()
+ if err != nil {
+ return err
+ }
+
+ if extra > 1000000000 {
+ return fmt.Errorf("t.Subcalls: array too large (%d)", extra)
+ }
+
+ if maj != cbg.MajArray {
+ return fmt.Errorf("expected cbor array")
+ }
+
+ if extra > 0 {
+ t.Subcalls = make([]ExecutionTrace, extra)
+ }
+
+ for i := 0; i < int(extra); i++ {
+
+ var v ExecutionTrace
+ if err := v.UnmarshalCBOR(cr); err != nil {
+ return err
+ }
+
+ t.Subcalls[i] = v
+ }
+
+ return nil
+}
diff --git a/chain/types/execresult.go b/chain/types/execresult.go
index 98d06a390ab..2a25d22e28a 100644
--- a/chain/types/execresult.go
+++ b/chain/types/execresult.go
@@ -2,44 +2,41 @@ package types
import (
"encoding/json"
- "fmt"
- "regexp"
- "runtime"
- "strings"
"time"
-)
-
-type ExecutionTrace struct {
- Msg *Message
- MsgRct *MessageReceipt
- Error string
- Duration time.Duration
- GasCharges []*GasTrace
- Subcalls []ExecutionTrace
-}
+ "github.com/filecoin-project/go-address"
+ "github.com/filecoin-project/go-state-types/abi"
+ "github.com/filecoin-project/go-state-types/exitcode"
+)
type GasTrace struct {
- Name string
-
- Location []Loc `json:"loc"`
- TotalGas int64 `json:"tg"`
- ComputeGas int64 `json:"cg"`
- StorageGas int64 `json:"sg"`
- TotalVirtualGas int64 `json:"vtg"`
- VirtualComputeGas int64 `json:"vcg"`
- VirtualStorageGas int64 `json:"vsg"`
+ Name string
+ TotalGas int64 `json:"tg"`
+ ComputeGas int64 `json:"cg"`
+ StorageGas int64 `json:"sg"`
+ TimeTaken time.Duration `json:"tt"`
+}
- TimeTaken time.Duration `json:"tt"`
- Extra interface{} `json:"ex,omitempty"`
+type MessageTrace struct {
+ From address.Address
+ To address.Address
+ Value abi.TokenAmount
+ Method abi.MethodNum
+ Params []byte
+ ParamsCodec uint64
+}
- Callers []uintptr `json:"-"`
+type ReturnTrace struct {
+ ExitCode exitcode.ExitCode
+ Return []byte
+ ReturnCodec uint64
}
-type Loc struct {
- File string
- Line int
- Function string
+type ExecutionTrace struct {
+ Msg MessageTrace
+ MsgRct ReturnTrace
+ GasCharges []*GasTrace `cborgen:"maxlen=1000000000"`
+ Subcalls []ExecutionTrace `cborgen:"maxlen=1000000000"`
}
func (et ExecutionTrace) SumGas() GasTrace {
@@ -52,71 +49,13 @@ func SumGas(charges []*GasTrace) GasTrace {
out.TotalGas += gc.TotalGas
out.ComputeGas += gc.ComputeGas
out.StorageGas += gc.StorageGas
-
- out.TotalVirtualGas += gc.TotalVirtualGas
- out.VirtualComputeGas += gc.VirtualComputeGas
- out.VirtualStorageGas += gc.VirtualStorageGas
}
return out
}
-func (l Loc) Show() bool {
- ignorePrefix := []string{
- "reflect.",
- "github.com/filecoin-project/lotus/chain/vm.(*Invoker).transform",
- "github.com/filecoin-project/go-amt-ipld/",
- }
- for _, pre := range ignorePrefix {
- if strings.HasPrefix(l.Function, pre) {
- return false
- }
- }
- return true
-}
-func (l Loc) String() string {
- file := strings.Split(l.File, "/")
-
- fn := strings.Split(l.Function, "/")
- var fnpkg string
- if len(fn) > 2 {
- fnpkg = strings.Join(fn[len(fn)-2:], "/")
- } else {
- fnpkg = l.Function
- }
-
- return fmt.Sprintf("%s@%s:%d", fnpkg, file[len(file)-1], l.Line)
-}
-
-var importantRegex = regexp.MustCompile(`github.com/filecoin-project/specs-actors/(v\d+/)?actors/builtin`)
-
-func (l Loc) Important() bool {
- return importantRegex.MatchString(l.Function)
-}
-
func (gt *GasTrace) MarshalJSON() ([]byte, error) {
type GasTraceCopy GasTrace
- if len(gt.Location) == 0 {
- if len(gt.Callers) != 0 {
- frames := runtime.CallersFrames(gt.Callers)
- for {
- frame, more := frames.Next()
- if frame.Function == "github.com/filecoin-project/lotus/chain/vm.(*VM).ApplyMessage" {
- break
- }
- l := Loc{
- File: frame.File,
- Line: frame.Line,
- Function: frame.Function,
- }
- gt.Location = append(gt.Location, l)
- if !more {
- break
- }
- }
- }
- }
-
cpy := (*GasTraceCopy)(gt)
return json.Marshal(cpy)
}
diff --git a/chain/vm/cbor_gen.go b/chain/vm/cbor_gen.go
deleted file mode 100644
index edcf065608c..00000000000
--- a/chain/vm/cbor_gen.go
+++ /dev/null
@@ -1,391 +0,0 @@
-// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
-
-package vm
-
-import (
- "fmt"
- "io"
- "math"
- "sort"
-
- cid "github.com/ipfs/go-cid"
- cbg "github.com/whyrusleeping/cbor-gen"
- xerrors "golang.org/x/xerrors"
-
- types "github.com/filecoin-project/lotus/chain/types"
-)
-
-var _ = xerrors.Errorf
-var _ = cid.Undef
-var _ = math.E
-var _ = sort.Sort
-
-var lengthBufFvmExecutionTrace = []byte{133}
-
-func (t *FvmExecutionTrace) MarshalCBOR(w io.Writer) error {
- if t == nil {
- _, err := w.Write(cbg.CborNull)
- return err
- }
-
- cw := cbg.NewCborWriter(w)
-
- if _, err := cw.Write(lengthBufFvmExecutionTrace); err != nil {
- return err
- }
-
- // t.Msg (types.Message) (struct)
- if err := t.Msg.MarshalCBOR(cw); err != nil {
- return err
- }
-
- // t.MsgRct (types.MessageReceipt) (struct)
- if err := t.MsgRct.MarshalCBOR(cw); err != nil {
- return err
- }
-
- // t.Error (string) (string)
- if len(t.Error) > cbg.MaxLength {
- return xerrors.Errorf("Value in field t.Error was too long")
- }
-
- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Error))); err != nil {
- return err
- }
- if _, err := io.WriteString(w, string(t.Error)); err != nil {
- return err
- }
-
- // t.GasCharges ([]vm.FvmGasCharge) (slice)
- if len(t.GasCharges) > 1000000000 {
- return xerrors.Errorf("Slice value in field t.GasCharges was too long")
- }
-
- if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.GasCharges))); err != nil {
- return err
- }
- for _, v := range t.GasCharges {
- if err := v.MarshalCBOR(cw); err != nil {
- return err
- }
- }
-
- // t.Subcalls ([]vm.FvmExecutionTrace) (slice)
- if len(t.Subcalls) > 1000000000 {
- return xerrors.Errorf("Slice value in field t.Subcalls was too long")
- }
-
- if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Subcalls))); err != nil {
- return err
- }
- for _, v := range t.Subcalls {
- if err := v.MarshalCBOR(cw); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (t *FvmExecutionTrace) UnmarshalCBOR(r io.Reader) (err error) {
- *t = FvmExecutionTrace{}
-
- cr := cbg.NewCborReader(r)
-
- maj, extra, err := cr.ReadHeader()
- if err != nil {
- return err
- }
- defer func() {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- }()
-
- if maj != cbg.MajArray {
- return fmt.Errorf("cbor input should be of type array")
- }
-
- if extra != 5 {
- return fmt.Errorf("cbor input had wrong number of fields")
- }
-
- // t.Msg (types.Message) (struct)
-
- {
-
- b, err := cr.ReadByte()
- if err != nil {
- return err
- }
- if b != cbg.CborNull[0] {
- if err := cr.UnreadByte(); err != nil {
- return err
- }
- t.Msg = new(types.Message)
- if err := t.Msg.UnmarshalCBOR(cr); err != nil {
- return xerrors.Errorf("unmarshaling t.Msg pointer: %w", err)
- }
- }
-
- }
- // t.MsgRct (types.MessageReceipt) (struct)
-
- {
-
- b, err := cr.ReadByte()
- if err != nil {
- return err
- }
- if b != cbg.CborNull[0] {
- if err := cr.UnreadByte(); err != nil {
- return err
- }
- t.MsgRct = new(types.MessageReceipt)
- if err := t.MsgRct.UnmarshalCBOR(cr); err != nil {
- return xerrors.Errorf("unmarshaling t.MsgRct pointer: %w", err)
- }
- }
-
- }
- // t.Error (string) (string)
-
- {
- sval, err := cbg.ReadString(cr)
- if err != nil {
- return err
- }
-
- t.Error = string(sval)
- }
- // t.GasCharges ([]vm.FvmGasCharge) (slice)
-
- maj, extra, err = cr.ReadHeader()
- if err != nil {
- return err
- }
-
- if extra > 1000000000 {
- return fmt.Errorf("t.GasCharges: array too large (%d)", extra)
- }
-
- if maj != cbg.MajArray {
- return fmt.Errorf("expected cbor array")
- }
-
- if extra > 0 {
- t.GasCharges = make([]FvmGasCharge, extra)
- }
-
- for i := 0; i < int(extra); i++ {
-
- var v FvmGasCharge
- if err := v.UnmarshalCBOR(cr); err != nil {
- return err
- }
-
- t.GasCharges[i] = v
- }
-
- // t.Subcalls ([]vm.FvmExecutionTrace) (slice)
-
- maj, extra, err = cr.ReadHeader()
- if err != nil {
- return err
- }
-
- if extra > 1000000000 {
- return fmt.Errorf("t.Subcalls: array too large (%d)", extra)
- }
-
- if maj != cbg.MajArray {
- return fmt.Errorf("expected cbor array")
- }
-
- if extra > 0 {
- t.Subcalls = make([]FvmExecutionTrace, extra)
- }
-
- for i := 0; i < int(extra); i++ {
-
- var v FvmExecutionTrace
- if err := v.UnmarshalCBOR(cr); err != nil {
- return err
- }
-
- t.Subcalls[i] = v
- }
-
- return nil
-}
-
-var lengthBufFvmGasCharge = []byte{132}
-
-func (t *FvmGasCharge) MarshalCBOR(w io.Writer) error {
- if t == nil {
- _, err := w.Write(cbg.CborNull)
- return err
- }
-
- cw := cbg.NewCborWriter(w)
-
- if _, err := cw.Write(lengthBufFvmGasCharge); err != nil {
- return err
- }
-
- // t.Name (string) (string)
- if len(t.Name) > cbg.MaxLength {
- return xerrors.Errorf("Value in field t.Name was too long")
- }
-
- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil {
- return err
- }
- if _, err := io.WriteString(w, string(t.Name)); err != nil {
- return err
- }
-
- // t.TotalGas (int64) (int64)
- if t.TotalGas >= 0 {
- if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.TotalGas)); err != nil {
- return err
- }
- } else {
- if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.TotalGas-1)); err != nil {
- return err
- }
- }
-
- // t.ComputeGas (int64) (int64)
- if t.ComputeGas >= 0 {
- if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ComputeGas)); err != nil {
- return err
- }
- } else {
- if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ComputeGas-1)); err != nil {
- return err
- }
- }
-
- // t.StorageGas (int64) (int64)
- if t.StorageGas >= 0 {
- if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.StorageGas)); err != nil {
- return err
- }
- } else {
- if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.StorageGas-1)); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (t *FvmGasCharge) UnmarshalCBOR(r io.Reader) (err error) {
- *t = FvmGasCharge{}
-
- cr := cbg.NewCborReader(r)
-
- maj, extra, err := cr.ReadHeader()
- if err != nil {
- return err
- }
- defer func() {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- }()
-
- if maj != cbg.MajArray {
- return fmt.Errorf("cbor input should be of type array")
- }
-
- if extra != 4 {
- return fmt.Errorf("cbor input had wrong number of fields")
- }
-
- // t.Name (string) (string)
-
- {
- sval, err := cbg.ReadString(cr)
- if err != nil {
- return err
- }
-
- t.Name = string(sval)
- }
- // t.TotalGas (int64) (int64)
- {
- maj, extra, err := cr.ReadHeader()
- var extraI int64
- if err != nil {
- return err
- }
- switch maj {
- case cbg.MajUnsignedInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 positive overflow")
- }
- case cbg.MajNegativeInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 negative oveflow")
- }
- extraI = -1 - extraI
- default:
- return fmt.Errorf("wrong type for int64 field: %d", maj)
- }
-
- t.TotalGas = int64(extraI)
- }
- // t.ComputeGas (int64) (int64)
- {
- maj, extra, err := cr.ReadHeader()
- var extraI int64
- if err != nil {
- return err
- }
- switch maj {
- case cbg.MajUnsignedInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 positive overflow")
- }
- case cbg.MajNegativeInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 negative oveflow")
- }
- extraI = -1 - extraI
- default:
- return fmt.Errorf("wrong type for int64 field: %d", maj)
- }
-
- t.ComputeGas = int64(extraI)
- }
- // t.StorageGas (int64) (int64)
- {
- maj, extra, err := cr.ReadHeader()
- var extraI int64
- if err != nil {
- return err
- }
- switch maj {
- case cbg.MajUnsignedInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 positive overflow")
- }
- case cbg.MajNegativeInt:
- extraI = int64(extra)
- if extraI < 0 {
- return fmt.Errorf("int64 negative oveflow")
- }
- extraI = -1 - extraI
- default:
- return fmt.Errorf("wrong type for int64 field: %d", maj)
- }
-
- t.StorageGas = int64(extraI)
- }
- return nil
-}
diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go
index 8e78e58d9df..7c79972c7ee 100644
--- a/chain/vm/fvm.go
+++ b/chain/vm/fvm.go
@@ -51,57 +51,6 @@ type FvmExtern struct {
base cid.Cid
}
-type FvmGasCharge struct {
- Name string
- TotalGas int64
- ComputeGas int64
- StorageGas int64
-}
-
-// This may eventually become identical to ExecutionTrace, but we can make incremental progress towards that
-type FvmExecutionTrace struct {
- Msg *types.Message
- MsgRct *types.MessageReceipt
- Error string
- GasCharges []FvmGasCharge `cborgen:"maxlen=1000000000"`
- Subcalls []FvmExecutionTrace `cborgen:"maxlen=1000000000"`
-}
-
-func (t *FvmExecutionTrace) ToExecutionTrace() types.ExecutionTrace {
- if t == nil {
- return types.ExecutionTrace{}
- }
-
- ret := types.ExecutionTrace{
- Msg: t.Msg,
- MsgRct: t.MsgRct,
- Error: t.Error,
- Subcalls: nil, // Should be nil when there are no subcalls for backwards compatibility
- }
-
- if len(t.GasCharges) > 0 {
- ret.GasCharges = make([]*types.GasTrace, len(t.GasCharges))
- for i, v := range t.GasCharges {
- ret.GasCharges[i] = &types.GasTrace{
- Name: v.Name,
- TotalGas: v.TotalGas,
- ComputeGas: v.ComputeGas,
- StorageGas: v.StorageGas,
- }
- }
- }
-
- if len(t.Subcalls) > 0 {
- ret.Subcalls = make([]types.ExecutionTrace, len(t.Subcalls))
-
- for i, v := range t.Subcalls {
- ret.Subcalls[i] = v.ToExecutionTrace()
- }
- }
-
- return ret
-}
-
func (x *FvmExtern) TipsetCid(ctx context.Context, epoch abi.ChainEpoch) (cid.Cid, error) {
tsk, err := x.tsGet(ctx, epoch)
if err != nil {
@@ -487,19 +436,9 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
var et types.ExecutionTrace
if len(ret.ExecTraceBytes) != 0 {
- var fvmEt FvmExecutionTrace
- if err = fvmEt.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
+ if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err)
}
- et = fvmEt.ToExecutionTrace()
- }
-
- // Set the top-level exectrace info from the message and receipt for backwards compatibility
- et.Msg = vmMsg
- et.MsgRct = &receipt
- et.Duration = duration
- if aerr != nil {
- et.Error = aerr.Error()
}
applyRet := &ApplyRet{
@@ -562,18 +501,9 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
var et types.ExecutionTrace
if len(ret.ExecTraceBytes) != 0 {
- var fvmEt FvmExecutionTrace
- if err = fvmEt.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
+ if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err)
}
- et = fvmEt.ToExecutionTrace()
- } else {
- et.Msg = vmMsg
- et.MsgRct = &receipt
- et.Duration = duration
- if aerr != nil {
- et.Error = aerr.Error()
- }
}
applyRet := &ApplyRet{
diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go
index daa55e4f4bd..a5b10823813 100644
--- a/chain/vm/runtime.go
+++ b/chain/vm/runtime.go
@@ -6,7 +6,6 @@ import (
"encoding/binary"
"fmt"
"os"
- gruntime "runtime"
"time"
"github.com/ipfs/go-cid"
@@ -571,35 +570,18 @@ func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total()
if EnableDetailedTracing {
- var callers [10]uintptr
-
- cout := gruntime.Callers(2+skip, callers[:])
-
now := build.Clock.Now()
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime)
}
gasTrace := types.GasTrace{
- Name: gas.Name,
- Extra: gas.Extra,
+ Name: gas.Name,
TotalGas: toUse,
ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas,
-
- VirtualComputeGas: gas.VirtualCompute,
- VirtualStorageGas: gas.VirtualStorage,
-
- Callers: callers[:cout],
- }
- if gasTrace.VirtualStorageGas == 0 {
- gasTrace.VirtualStorageGas = gasTrace.StorageGas
- }
- if gasTrace.VirtualComputeGas == 0 {
- gasTrace.VirtualComputeGas = gasTrace.ComputeGas
}
- gasTrace.TotalVirtualGas = gasTrace.VirtualComputeGas + gasTrace.VirtualStorageGas
rt.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now
diff --git a/chain/vm/vm.go b/chain/vm/vm.go
index f09864c2ddc..c8e3f251907 100644
--- a/chain/vm/vm.go
+++ b/chain/vm/vm.go
@@ -38,6 +38,7 @@ import (
)
const MaxCallDepth = 4096
+const CborCodec = 0x51
var (
log = logging.Logger("vm")
@@ -125,6 +126,10 @@ func (bs *gasChargingBlocks) Put(ctx context.Context, blk block.Block) error {
}
func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime {
+ paramsCodec := uint64(0)
+ if len(msg.Params) > 0 {
+ paramsCodec = CborCodec
+ }
rt := &Runtime{
ctx: ctx,
vm: vm,
@@ -140,7 +145,14 @@ func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent
pricelist: PricelistByEpoch(vm.blockHeight),
allowInternal: true,
callerValidated: false,
- executionTrace: types.ExecutionTrace{Msg: msg},
+ executionTrace: types.ExecutionTrace{Msg: types.MessageTrace{
+ From: msg.From,
+ To: msg.To,
+ Value: msg.Value,
+ Method: msg.Method,
+ Params: msg.Params,
+ ParamsCodec: paramsCodec,
+ }},
}
if parent != nil {
@@ -369,15 +381,14 @@ func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtim
return nil, nil
}()
- mr := types.MessageReceipt{
- ExitCode: aerrors.RetCode(err),
- Return: ret,
- GasUsed: rt.gasUsed,
+ retCodec := uint64(0)
+ if len(ret) > 0 {
+ retCodec = CborCodec
}
- rt.executionTrace.MsgRct = &mr
- rt.executionTrace.Duration = time.Since(start)
- if err != nil {
- rt.executionTrace.Error = err.Error()
+ rt.executionTrace.MsgRct = types.ReturnTrace{
+ ExitCode: aerrors.RetCode(err),
+ Return: ret,
+ ReturnCodec: retCodec,
}
return ret, err, rt
diff --git a/cli/state.go b/cli/state.go
index 3d629bb0b8f..b2926d540ed 100644
--- a/cli/state.go
+++ b/cli/state.go
@@ -22,7 +22,6 @@ import (
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/multiformats/go-multiaddr"
- "github.com/multiformats/go-multihash"
"github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
@@ -1228,7 +1227,7 @@ var compStateTemplate = `
State CID: {{.Comp.Root}}
Calls
{{range .Comp.Trace}}
- {{template "message" (Call .ExecutionTrace false .Msg.Cid.String)}}
+ {{template "message" (Call .ExecutionTrace false .MsgCid.String)}}
{{end}}