feat: vm: switch to the new exec trace format (#10372)

This is now "FVM" native. Changes include:

1. Don't treat "trace" messages like off-chain messages. E.g., don't
include CIDs, versions, etc.
2. Include IPLD codecs where applicable.
3. Remove fields that aren't filled by the FVM (timing, some errors,
code locations, etc.).
This commit is contained in:
Steven Allen 2023-03-01 16:02:18 -08:00 committed by GitHub
parent 570773259a
commit dbbcf4b2ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 964 additions and 1112 deletions

View File

@ -1,5 +1,159 @@
# Lotus changelog # 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).
<details>
<summary>
Old <code>ExecutionTrace</code>:
</summary>
```json
{
"Msg": {
"Version": 0,
"To": "f01234",
"From": "f04321",
"Nonce": 1,
"Value": "0",
"GasLimit": 0,
"GasFeeCap": "1234",
"GasPremium": "1234",
"Method": 42,
"Params": "<base64-data-or-null>",
"CID": {
"/": "bafyxyz....."
},
},
"MsgRct": {
"ExitCode": 0,
"Return": "<base64-data-or-null>",
"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": [],
},
]
}
```
</details>
<details>
<summary>
New <code>ExecutionTrace</code>:
</summary>
```json
{
"Msg": {
"To": "f01234",
"From": "f04321",
"Value": "0",
"Method": 42,
"Params": "<base64-data-or-null>",
"ParamsCodec": 81
},
"MsgRct": {
"ExitCode": 0,
"Return": "<base64-data-or-null>",
"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": [],
},
]
}
```
</details>
# 1.20.0 / 2023-02-28 # 1.20.0 / 2023-02-28
This is a MANDATORY release of Lotus that delivers the [Hygge network upgrade](https://github.com/filecoin-project/community/discussions/74?sort=top#discussioncomment-4313888), introducing Filecoin network version 18. The centerpiece of the upgrade is the introduction of the [Filecoin Virtual Machine (FVM)s Milestone 2.1](https://fvm.filecoin.io/), which will allow for EVM-compatible contracts to be deployed on the Filecoin network. This upgrade delivers user-programmablity to the Filecoin network for the first time! This is a MANDATORY release of Lotus that delivers the [Hygge network upgrade](https://github.com/filecoin-project/community/discussions/74?sort=top#discussioncomment-4313888), introducing Filecoin network version 18. The centerpiece of the upgrade is the introduction of the [Filecoin Virtual Machine (FVM)s Milestone 2.1](https://fvm.filecoin.io/), which will allow for EVM-compatible contracts to be deployed on the Filecoin network. This upgrade delivers user-programmablity to the Filecoin network for the first time!

View File

@ -152,8 +152,8 @@ func init() {
addExample(map[string]int{"name": 42}) addExample(map[string]int{"name": 42})
addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()}) addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()})
addExample(&types.ExecutionTrace{ addExample(&types.ExecutionTrace{
Msg: ExampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message), Msg: ExampleValue("init", reflect.TypeOf(types.MessageTrace{}), nil).(types.MessageTrace),
MsgRct: ExampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt), MsgRct: ExampleValue("init", reflect.TypeOf(types.ReturnTrace{}), nil).(types.ReturnTrace),
}) })
addExample(map[string]types.Actor{ addExample(map[string]types.Actor{
"t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor), "t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor),

Binary file not shown.

View File

@ -517,12 +517,11 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *stmgr.StateManager, _ st
MessageReceipt: *stmgr.MakeFakeRct(), MessageReceipt: *stmgr.MakeFakeRct(),
ActorErr: nil, ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{ ExecutionTrace: types.ExecutionTrace{
Msg: fakeMsg, Msg: types.MessageTrace{
MsgRct: stmgr.MakeFakeRct(), To: fakeMsg.To,
Error: "", From: fakeMsg.From,
Duration: 0, },
GasCharges: nil, Subcalls: subcalls,
Subcalls: subcalls,
}, },
Duration: 0, Duration: 0,
GasCosts: nil, GasCosts: nil,
@ -695,12 +694,11 @@ func splitGenesisMultisig0(ctx context.Context, em stmgr.ExecMonitor, addr addre
MessageReceipt: *stmgr.MakeFakeRct(), MessageReceipt: *stmgr.MakeFakeRct(),
ActorErr: nil, ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{ ExecutionTrace: types.ExecutionTrace{
Msg: fakeMsg, Msg: types.MessageTrace{
MsgRct: stmgr.MakeFakeRct(), From: fakeMsg.From,
Error: "", To: fakeMsg.To,
Duration: 0, },
GasCharges: nil, Subcalls: subcalls,
Subcalls: subcalls,
}, },
Duration: 0, Duration: 0,
GasCosts: nil, GasCosts: nil,

View File

@ -357,12 +357,11 @@ func DoTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmo
// record the transfer in execution traces // record the transfer in execution traces
cb(types.ExecutionTrace{ cb(types.ExecutionTrace{
Msg: MakeFakeMsg(from, to, amt, 0), Msg: types.MessageTrace{
MsgRct: MakeFakeRct(), From: from,
Error: "", To: to,
Duration: 0, Value: amt,
GasCharges: nil, },
Subcalls: nil,
}) })
} }

View File

@ -7,6 +7,7 @@ import (
"io" "io"
"math" "math"
"sort" "sort"
time "time"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -15,6 +16,7 @@ import (
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
abi "github.com/filecoin-project/go-state-types/abi" abi "github.com/filecoin-project/go-state-types/abi"
crypto "github.com/filecoin-project/go-state-types/crypto" 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" proof "github.com/filecoin-project/go-state-types/proof"
) )
@ -2078,3 +2080,659 @@ func (t *EventEntry) UnmarshalCBOR(r io.Reader) (err error) {
} }
return nil 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
}

View File

@ -2,44 +2,41 @@ package types
import ( import (
"encoding/json" "encoding/json"
"fmt"
"regexp"
"runtime"
"strings"
"time" "time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
) )
type ExecutionTrace struct {
Msg *Message
MsgRct *MessageReceipt
Error string
Duration time.Duration
GasCharges []*GasTrace
Subcalls []ExecutionTrace
}
type GasTrace struct { type GasTrace struct {
Name string Name string
TotalGas int64 `json:"tg"`
Location []Loc `json:"loc"` ComputeGas int64 `json:"cg"`
TotalGas int64 `json:"tg"` StorageGas int64 `json:"sg"`
ComputeGas int64 `json:"cg"` TimeTaken time.Duration `json:"tt"`
StorageGas int64 `json:"sg"`
TotalVirtualGas int64 `json:"vtg"`
VirtualComputeGas int64 `json:"vcg"`
VirtualStorageGas int64 `json:"vsg"`
TimeTaken time.Duration `json:"tt"`
Extra interface{} `json:"ex,omitempty"`
Callers []uintptr `json:"-"`
} }
type Loc struct { type MessageTrace struct {
File string From address.Address
Line int To address.Address
Function string Value abi.TokenAmount
Method abi.MethodNum
Params []byte
ParamsCodec uint64
}
type ReturnTrace struct {
ExitCode exitcode.ExitCode
Return []byte
ReturnCodec uint64
}
type ExecutionTrace struct {
Msg MessageTrace
MsgRct ReturnTrace
GasCharges []*GasTrace `cborgen:"maxlen=1000000000"`
Subcalls []ExecutionTrace `cborgen:"maxlen=1000000000"`
} }
func (et ExecutionTrace) SumGas() GasTrace { func (et ExecutionTrace) SumGas() GasTrace {
@ -52,71 +49,13 @@ func SumGas(charges []*GasTrace) GasTrace {
out.TotalGas += gc.TotalGas out.TotalGas += gc.TotalGas
out.ComputeGas += gc.ComputeGas out.ComputeGas += gc.ComputeGas
out.StorageGas += gc.StorageGas out.StorageGas += gc.StorageGas
out.TotalVirtualGas += gc.TotalVirtualGas
out.VirtualComputeGas += gc.VirtualComputeGas
out.VirtualStorageGas += gc.VirtualStorageGas
} }
return out 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) { func (gt *GasTrace) MarshalJSON() ([]byte, error) {
type GasTraceCopy GasTrace 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) cpy := (*GasTraceCopy)(gt)
return json.Marshal(cpy) return json.Marshal(cpy)
} }

View File

@ -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
}

View File

@ -51,57 +51,6 @@ type FvmExtern struct {
base cid.Cid 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) { func (x *FvmExtern) TipsetCid(ctx context.Context, epoch abi.ChainEpoch) (cid.Cid, error) {
tsk, err := x.tsGet(ctx, epoch) tsk, err := x.tsGet(ctx, epoch)
if err != nil { if err != nil {
@ -487,19 +436,9 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
var et types.ExecutionTrace var et types.ExecutionTrace
if len(ret.ExecTraceBytes) != 0 { if len(ret.ExecTraceBytes) != 0 {
var fvmEt FvmExecutionTrace if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
if err = fvmEt.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err) 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{ applyRet := &ApplyRet{
@ -562,18 +501,9 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
var et types.ExecutionTrace var et types.ExecutionTrace
if len(ret.ExecTraceBytes) != 0 { if len(ret.ExecTraceBytes) != 0 {
var fvmEt FvmExecutionTrace if err = et.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
if err = fvmEt.UnmarshalCBOR(bytes.NewReader(ret.ExecTraceBytes)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal exectrace: %w", err) 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{ applyRet := &ApplyRet{

View File

@ -6,7 +6,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"os" "os"
gruntime "runtime"
"time" "time"
"github.com/ipfs/go-cid" "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 { func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total() toUse := gas.Total()
if EnableDetailedTracing { if EnableDetailedTracing {
var callers [10]uintptr
cout := gruntime.Callers(2+skip, callers[:])
now := build.Clock.Now() now := build.Clock.Now()
if rt.lastGasCharge != nil { if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime) rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime)
} }
gasTrace := types.GasTrace{ gasTrace := types.GasTrace{
Name: gas.Name, Name: gas.Name,
Extra: gas.Extra,
TotalGas: toUse, TotalGas: toUse,
ComputeGas: gas.ComputeGas, ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas, 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.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now rt.lastGasChargeTime = now

View File

@ -38,6 +38,7 @@ import (
) )
const MaxCallDepth = 4096 const MaxCallDepth = 4096
const CborCodec = 0x51
var ( var (
log = logging.Logger("vm") 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 { 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{ rt := &Runtime{
ctx: ctx, ctx: ctx,
vm: vm, vm: vm,
@ -140,7 +145,14 @@ func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent
pricelist: PricelistByEpoch(vm.blockHeight), pricelist: PricelistByEpoch(vm.blockHeight),
allowInternal: true, allowInternal: true,
callerValidated: false, 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 { if parent != nil {
@ -369,15 +381,14 @@ func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtim
return nil, nil return nil, nil
}() }()
mr := types.MessageReceipt{ retCodec := uint64(0)
ExitCode: aerrors.RetCode(err), if len(ret) > 0 {
Return: ret, retCodec = CborCodec
GasUsed: rt.gasUsed,
} }
rt.executionTrace.MsgRct = &mr rt.executionTrace.MsgRct = types.ReturnTrace{
rt.executionTrace.Duration = time.Since(start) ExitCode: aerrors.RetCode(err),
if err != nil { Return: ret,
rt.executionTrace.Error = err.Error() ReturnCodec: retCodec,
} }
return ret, err, rt return ret, err, rt

View File

@ -22,7 +22,6 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/multiformats/go-multihash"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -1234,7 +1233,7 @@ var compStateTemplate = `
<div>State CID: <b>{{.Comp.Root}}</b></div> <div>State CID: <b>{{.Comp.Root}}</b></div>
<div>Calls</div> <div>Calls</div>
{{range .Comp.Trace}} {{range .Comp.Trace}}
{{template "message" (Call .ExecutionTrace false .Msg.Cid.String)}} {{template "message" (Call .ExecutionTrace false .MsgCid.String)}}
{{end}} {{end}}
</body> </body>
</html> </html>
@ -1259,16 +1258,12 @@ var compStateMsg = `
</a> </a>
</div> </div>
<div><b>{{.Msg.From}}</b> -&gt; <b>{{.Msg.To}}</b> ({{ToFil .Msg.Value}} FIL), M{{.Msg.Method}}</div> <div><b>{{.Msg.From}}</b> -&gt; <b>{{.Msg.To}}</b> ({{ToFil .Msg.Value}}), M{{.Msg.Method}}</div>
{{if not .Subcall}}<div><small>Msg CID: {{.Msg.Cid}}</small></div>{{end}} {{if not .Subcall}}<div><small>Msg CID: {{.Hash}}</small></div>{{end}}
{{if gt (len .Msg.Params) 0}} {{if gt (len .Msg.Params) 0}}
<div><pre class="params">{{JsonParams ($code) (.Msg.Method) (.Msg.Params) | html}}</pre></div> <div><pre class="params">{{JsonParams ($code) (.Msg.Method) (.Msg.Params) | html}}</pre></div>
{{end}} {{end}}
{{if PrintTiming}}
<div><span class="slow-{{IsSlow .Duration}}-{{IsVerySlow .Duration}}">Took {{.Duration}}</span>, <span class="exit{{IntExit .MsgRct.ExitCode}}">Exit: <b>{{.MsgRct.ExitCode}}</b></span>{{if gt (len .MsgRct.Return) 0}}, Return{{end}}</div>
{{else}}
<div><span class="exit{{IntExit .MsgRct.ExitCode}}">Exit: <b>{{.MsgRct.ExitCode}}</b></span>{{if gt (len .MsgRct.Return) 0}}, Return{{end}}</div> <div><span class="exit{{IntExit .MsgRct.ExitCode}}">Exit: <b>{{.MsgRct.ExitCode}}</b></span>{{if gt (len .MsgRct.Return) 0}}, Return{{end}}</div>
{{end}}
{{if gt (len .MsgRct.Return) 0}} {{if gt (len .MsgRct.Return) 0}}
<div><pre class="ret">{{JsonReturn ($code) (.Msg.Method) (.MsgRct.Return) | html}}</pre></div> <div><pre class="ret">{{JsonReturn ($code) (.Msg.Method) (.MsgRct.Return) | html}}</pre></div>
{{end}} {{end}}
@ -1280,62 +1275,26 @@ var compStateMsg = `
<details> <details>
<summary>Gas Trace</summary> <summary>Gas Trace</summary>
<table> <table>
<tr><th>Name</th><th>Total/Compute/Storage</th><th>Time Taken</th><th>Location</th></tr> <tr><th>Name</th><th>Total/Compute/Storage</th><th>Time Taken</th></tr>
{{define "virt" -}}
{{- if . -}}
<span class="deemp">+({{.}})</span>
{{- end -}}
{{- end}}
{{define "gasC" -}} {{define "gasC" -}}
<td>{{.TotalGas}}{{template "virt" .TotalVirtualGas }}/{{.ComputeGas}}{{template "virt" .VirtualComputeGas}}/{{.StorageGas}}{{template "virt" .VirtualStorageGas}}</td> <td>{{.TotalGas}}/{{.ComputeGas}}/{{.StorageGas}}</td>
{{- end}} {{- end}}
{{range .GasCharges}} {{range .GasCharges}}
<tr><td>{{.Name}}{{if .Extra}}:{{.Extra}}{{end}}</td> <tr>
{{template "gasC" .}} <td>{{.Name}}</td>
<td>{{if PrintTiming}}{{.TimeTaken}}{{end}}</td> {{template "gasC" .}}
<td> <td>{{if PrintTiming}}{{.TimeTaken}}{{end}}</td>
{{ $fImp := FirstImportant .Location }} </tr>
{{ if $fImp }} {{end}}
<details> {{with sumGas .GasCharges}}
<summary>{{ $fImp }}</summary><hr /> <tr class="sum">
{{ $elipOn := false }} <td><b>Sum</b></td>
{{ range $index, $ele := .Location -}} {{template "gasC" .}}
{{- if $index }}<br />{{end -}} <td>{{if PrintTiming}}{{.TimeTaken}}{{end}}</td>
{{- if .Show -}} </tr>
{{ if $elipOn }} {{end}}
{{ $elipOn = false }}
</span></label>
{{end}}
{{- if .Important }}<b>{{end -}}
{{- . -}}
{{if .Important }}</b>{{end}}
{{else}}
{{ if not $elipOn }}
{{ $elipOn = true }}
<label class="ellipsis-toggle"><input type="checkbox" /><span class="ellipsis">[]<br /></span>
<span class="ellipsis-content">
{{end}}
{{- "" -}}
{{- . -}}
{{end}}
{{end}}
{{ if $elipOn }}
{{ $elipOn = false }}
</span></label>
{{end}}
</details>
{{end}}
</td></tr>
{{end}}
{{with sumGas .GasCharges}}
<tr class="sum"><td><b>Sum</b></td>
{{template "gasC" .}}
<td>{{if PrintTiming}}{{.TimeTaken}}{{end}}</td>
<td></td></tr>
{{end}}
</table> </table>
</details> </details>
@ -1343,8 +1302,8 @@ var compStateMsg = `
{{if gt (len .Subcalls) 0}} {{if gt (len .Subcalls) 0}}
<div>Subcalls:</div> <div>Subcalls:</div>
{{$hash := .Hash}} {{$hash := .Hash}}
{{range .Subcalls}} {{range $i, $call := .Subcalls}}
{{template "message" (Call . true (printf "%s-%s" $hash .Msg.Cid.String))}} {{template "message" (Call $call true (printf "%s-%d" $hash $i))}}
{{end}} {{end}}
{{end}} {{end}}
</div>` </div>`
@ -1365,20 +1324,9 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut
"IsVerySlow": isVerySlow, "IsVerySlow": isVerySlow,
"IntExit": func(i exitcode.ExitCode) int64 { return int64(i) }, "IntExit": func(i exitcode.ExitCode) int64 { return int64(i) },
"sumGas": types.SumGas, "sumGas": types.SumGas,
"CodeStr": codeStr, "CodeStr": builtin.ActorNameByCode,
"Call": call, "Call": call,
"PrintTiming": func() bool { return printTiming }, "PrintTiming": func() bool { return printTiming },
"FirstImportant": func(locs []types.Loc) *types.Loc {
if len(locs) != 0 {
for _, l := range locs {
if l.Important() {
return &l
}
}
return &locs[0]
}
return nil
},
}).Parse(compStateTemplate) }).Parse(compStateTemplate)
if err != nil { if err != nil {
return err return err
@ -1408,14 +1356,6 @@ func call(e types.ExecutionTrace, subcall bool, hash string) callMeta {
} }
} }
func codeStr(c cid.Cid) string {
cmh, err := multihash.Decode(c.Hash())
if err != nil {
panic(err)
}
return string(cmh.Digest)
}
func getMethod(code cid.Cid, method abi.MethodNum) string { func getMethod(code cid.Cid, method abi.MethodNum) string {
return consensus.NewActorRegistry().Methods[code][method].Name // todo: use remote return consensus.NewActorRegistry().Methods[code][method].Name // todo: use remote
} }

View File

@ -467,14 +467,11 @@ var importBenchCmd = &cli.Command{
Duration: time.Since(start), Duration: time.Since(start),
} }
if enc != nil { if enc != nil {
stripCallers(tse.Trace)
if err := enc.Encode(tse); err != nil { if err := enc.Encode(tse); err != nil {
return xerrors.Errorf("failed to write out tipsetexec: %w", err) return xerrors.Errorf("failed to write out tipsetexec: %w", err)
} }
} }
if inverseChain[i-1].ParentState() != st { if inverseChain[i-1].ParentState() != st {
stripCallers(tse.Trace)
lastTrace := tse.Trace lastTrace := tse.Trace
d, err := json.MarshalIndent(lastTrace, "", " ") d, err := json.MarshalIndent(lastTrace, "", " ")
if err != nil { if err != nil {
@ -493,21 +490,6 @@ var importBenchCmd = &cli.Command{
}, },
} }
func walkExecutionTrace(et *types.ExecutionTrace) {
for _, gc := range et.GasCharges {
gc.Callers = nil
}
for _, sub := range et.Subcalls {
walkExecutionTrace(&sub) //nolint:scopelint,gosec
}
}
func stripCallers(trace []*api.InvocResult) {
for _, t := range trace {
walkExecutionTrace(&t.ExecutionTrace)
}
}
type Invocation struct { type Invocation struct {
TipSet types.TipSetKey TipSet types.TipSetKey
Invoc *api.InvocResult Invoc *api.InvocResult
@ -515,28 +497,24 @@ type Invocation struct {
const GasPerNs = 10 const GasPerNs = 10
func countGasCosts(et *types.ExecutionTrace) (int64, int64) { func countGasCosts(et *types.ExecutionTrace) int64 {
var cgas, vgas int64 var cgas int64
for _, gc := range et.GasCharges { for _, gc := range et.GasCharges {
cgas += gc.ComputeGas cgas += gc.ComputeGas
vgas += gc.VirtualComputeGas
} }
for _, sub := range et.Subcalls { for _, sub := range et.Subcalls {
c, v := countGasCosts(&sub) //nolint c := countGasCosts(&sub) //nolint
cgas += c cgas += c
vgas += v
} }
return cgas, vgas return cgas
} }
type stats struct { type stats struct {
timeTaken meanVar timeTaken meanVar
gasRatio meanVar gasRatio meanVar
extraCovar *covar
} }
type covar struct { type covar struct {
@ -681,32 +659,8 @@ func (v1 *meanVar) Combine(v2 *meanVar) {
v1.m2 = m2 v1.m2 = m2
} }
func getExtras(ex interface{}) (*string, *float64) {
if t, ok := ex.(string); ok {
return &t, nil
}
if size, ok := ex.(float64); ok {
return nil, &size
}
if exMap, ok := ex.(map[string]interface{}); ok {
t, tok := exMap["type"].(string)
size, sok := exMap["size"].(float64)
if tok && sok {
return &t, &size
}
if tok {
return &t, nil
}
if sok {
return nil, &size
}
return nil, nil
}
return nil, nil
}
func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) { func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
for i, gc := range et.GasCharges { for _, gc := range et.GasCharges {
name := gc.Name name := gc.Name
if name == "OnIpldGetEnd" { if name == "OnIpldGetEnd" {
continue continue
@ -717,45 +671,18 @@ func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
// discard initial very long OnVerifyPost // discard initial very long OnVerifyPost
continue continue
} }
eType, eSize := getExtras(gc.Extra)
if name == "OnIpldGet" {
next := &types.GasTrace{}
if i+1 < len(et.GasCharges) {
next = et.GasCharges[i+1]
}
if next.Name != "OnIpldGetEnd" {
log.Warn("OnIpldGet without OnIpldGetEnd")
} else {
_, size := getExtras(next.Extra)
eSize = size
}
}
if eType != nil {
name += "-" + *eType
}
compGas := gc.ComputeGas compGas := gc.ComputeGas
if compGas == 0 {
compGas = gc.VirtualComputeGas
}
if compGas == 0 {
compGas = 1
}
s := charges[name] s := charges[name]
if s == nil { if s == nil {
s = new(stats) s = new(stats)
charges[name] = s charges[name] = s
} }
if eSize != nil {
if s.extraCovar == nil {
s.extraCovar = &covar{}
}
s.extraCovar.AddPoint(*eSize, tt)
}
s.timeTaken.AddPoint(tt) s.timeTaken.AddPoint(tt)
if compGas == 0 {
compGas = 1
}
ratio := tt / float64(compGas) * GasPerNs ratio := tt / float64(compGas) * GasPerNs
s.gasRatio.AddPoint(ratio) s.gasRatio.AddPoint(ratio)
} }
@ -881,13 +808,6 @@ var importAnalyzeCmd = &cli.Command{
} }
s.timeTaken.Combine(&v.timeTaken) s.timeTaken.Combine(&v.timeTaken)
s.gasRatio.Combine(&v.gasRatio) s.gasRatio.Combine(&v.gasRatio)
if v.extraCovar != nil {
if s.extraCovar == nil {
s.extraCovar = &covar{}
}
s.extraCovar.Combine(v.extraCovar)
}
} }
totalTime += res.totalTime totalTime += res.totalTime
} }
@ -903,13 +823,6 @@ var importAnalyzeCmd = &cli.Command{
s := charges[k] s := charges[k]
fmt.Printf("%s: incr by %.4f~%.4f; tt %.4f~%.4f\n", k, s.gasRatio.Mean(), s.gasRatio.Stddev(), fmt.Printf("%s: incr by %.4f~%.4f; tt %.4f~%.4f\n", k, s.gasRatio.Mean(), s.gasRatio.Stddev(),
s.timeTaken.Mean(), s.timeTaken.Stddev()) s.timeTaken.Mean(), s.timeTaken.Stddev())
if s.extraCovar != nil {
fmt.Printf("\t correll: %.2f, tt = %.2f * extra + %.2f\n", s.extraCovar.Correl(),
s.extraCovar.A(), s.extraCovar.B())
fmt.Printf("\t covar: %.2f, extra: %.2f~%.2f, tt2: %.2f~%.2f, count %.0f\n",
s.extraCovar.Covariance(), s.extraCovar.meanX, s.extraCovar.StddevX(),
s.extraCovar.meanY, s.extraCovar.StddevY(), s.extraCovar.n)
}
} }
sort.Slice(invocs, func(i, j int) bool { sort.Slice(invocs, func(i, j int) bool {

View File

@ -4866,95 +4866,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null
@ -5142,95 +5096,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null
@ -6574,95 +6482,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null

View File

@ -6181,95 +6181,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null
@ -6457,95 +6411,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null
@ -7972,95 +7880,49 @@ Response:
}, },
"ExecutionTrace": { "ExecutionTrace": {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": [ "Subcalls": [
{ {
"Msg": { "Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234", "From": "f01234",
"Nonce": 42, "To": "f01234",
"Value": "0", "Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1, "Method": 1,
"Params": "Ynl0ZSBhcnJheQ==", "Params": "Ynl0ZSBhcnJheQ==",
"CID": { "ParamsCodec": 42
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
}, },
"MsgRct": { "MsgRct": {
"ExitCode": 0, "ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==", "Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9, "ReturnCodec": 42
"EventsRoot": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}, },
"Error": "string value",
"Duration": 60000000000,
"GasCharges": [ "GasCharges": [
{ {
"Name": "string value", "Name": "string value",
"loc": [
{
"File": "string value",
"Line": 123,
"Function": "string value"
}
],
"tg": 9, "tg": 9,
"cg": 9, "cg": 9,
"sg": 9, "sg": 9,
"vtg": 9, "tt": 60000000000
"vcg": 9,
"vsg": 9,
"tt": 60000000000,
"ex": {}
} }
], ],
"Subcalls": null "Subcalls": null

2
extern/filecoin-ffi vendored

@ -1 +1 @@
Subproject commit 1bc8bf8b482b2ef34cbce17bfc3a7ec68c047461 Subproject commit 88dc4c4ceb322337818b6508c8e9c23948f36cb1

View File

@ -11,7 +11,6 @@ import (
"github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/exchange"
"github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/market"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/cmd/lotus-shed/shedgen" "github.com/filecoin-project/lotus/cmd/lotus-shed/shedgen"
"github.com/filecoin-project/lotus/node/hello" "github.com/filecoin-project/lotus/node/hello"
"github.com/filecoin-project/lotus/paychmgr" "github.com/filecoin-project/lotus/paychmgr"
@ -37,15 +36,11 @@ func main() {
types.StateInfo0{}, types.StateInfo0{},
types.Event{}, types.Event{},
types.EventEntry{}, types.EventEntry{},
) // Tracing
if err != nil { types.GasTrace{},
fmt.Println(err) types.MessageTrace{},
os.Exit(1) types.ReturnTrace{},
} types.ExecutionTrace{},
err = gen.WriteTupleEncodersToFile("./chain/vm/cbor_gen.go", "vm",
vm.FvmExecutionTrace{},
vm.FvmGasCharge{},
) )
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)