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}} @@ -1253,16 +1252,12 @@ var compStateMsg = ` -
{{.Msg.From}} -> {{.Msg.To}} ({{ToFil .Msg.Value}} FIL), M{{.Msg.Method}}
- {{if not .Subcall}}
Msg CID: {{.Msg.Cid}}
{{end}} +
{{.Msg.From}} -> {{.Msg.To}} ({{ToFil .Msg.Value}}), M{{.Msg.Method}}
+ {{if not .Subcall}}
Msg CID: {{.Hash}}
{{end}} {{if gt (len .Msg.Params) 0}}
{{JsonParams ($code) (.Msg.Method) (.Msg.Params) | html}}
{{end}} - {{if PrintTiming}} -
Took {{.Duration}}, Exit: {{.MsgRct.ExitCode}}{{if gt (len .MsgRct.Return) 0}}, Return{{end}}
- {{else}}
Exit: {{.MsgRct.ExitCode}}{{if gt (len .MsgRct.Return) 0}}, Return{{end}}
- {{end}} {{if gt (len .MsgRct.Return) 0}}
{{JsonReturn ($code) (.Msg.Method) (.MsgRct.Return) | html}}
{{end}} @@ -1274,62 +1269,26 @@ var compStateMsg = `
Gas Trace - - {{define "virt" -}} - {{- if . -}} - +({{.}}) - {{- end -}} - {{- end}} + {{define "gasC" -}} - + {{- end}} {{range .GasCharges}} - - {{template "gasC" .}} - - - {{end}} - {{with sumGas .GasCharges}} - - {{template "gasC" .}} - - - {{end}} + + + {{template "gasC" .}} + + + {{end}} + {{with sumGas .GasCharges}} + + + {{template "gasC" .}} + + + {{end}}
NameTotal/Compute/StorageTime TakenLocation
NameTotal/Compute/StorageTime Taken
{{.TotalGas}}{{template "virt" .TotalVirtualGas }}/{{.ComputeGas}}{{template "virt" .VirtualComputeGas}}/{{.StorageGas}}{{template "virt" .VirtualStorageGas}}{{.TotalGas}}/{{.ComputeGas}}/{{.StorageGas}}
{{.Name}}{{if .Extra}}:{{.Extra}}{{end}}{{if PrintTiming}}{{.TimeTaken}}{{end}} - {{ $fImp := FirstImportant .Location }} - {{ if $fImp }} -
- {{ $fImp }}
- {{ $elipOn := false }} - {{ range $index, $ele := .Location -}} - {{- if $index }}
{{end -}} - {{- if .Show -}} - {{ if $elipOn }} - {{ $elipOn = false }} - - {{end}} - - {{- if .Important }}{{end -}} - {{- . -}} - {{if .Important }}{{end}} - {{else}} - {{ if not $elipOn }} - {{ $elipOn = true }} - - {{end}} -
- {{end}} -
Sum{{if PrintTiming}}{{.TimeTaken}}{{end}}
{{.Name}}{{if PrintTiming}}{{.TimeTaken}}{{end}}
Sum{{if PrintTiming}}{{.TimeTaken}}{{end}}
@@ -1337,8 +1296,8 @@ var compStateMsg = ` {{if gt (len .Subcalls) 0}}
Subcalls:
{{$hash := .Hash}} - {{range .Subcalls}} - {{template "message" (Call . true (printf "%s-%s" $hash .Msg.Cid.String))}} + {{range $i, $call := .Subcalls}} + {{template "message" (Call $call true (printf "%s-%d" $hash $i))}} {{end}} {{end}} ` @@ -1359,20 +1318,9 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut "IsVerySlow": isVerySlow, "IntExit": func(i exitcode.ExitCode) int64 { return int64(i) }, "sumGas": types.SumGas, - "CodeStr": codeStr, + "CodeStr": builtin.ActorNameByCode, "Call": call, "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) if err != nil { return err @@ -1402,14 +1350,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 { return filcns.NewActorRegistry().Methods[code][method].Name // todo: use remote } diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 13824d07d62..21eba7d7249 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -466,14 +466,11 @@ var importBenchCmd = &cli.Command{ Duration: time.Since(start), } if enc != nil { - stripCallers(tse.Trace) - if err := enc.Encode(tse); err != nil { return xerrors.Errorf("failed to write out tipsetexec: %w", err) } } if inverseChain[i-1].ParentState() != st { - stripCallers(tse.Trace) lastTrace := tse.Trace d, err := json.MarshalIndent(lastTrace, "", " ") if err != nil { @@ -492,21 +489,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 { TipSet types.TipSetKey Invoc *api.InvocResult @@ -514,28 +496,24 @@ type Invocation struct { const GasPerNs = 10 -func countGasCosts(et *types.ExecutionTrace) (int64, int64) { - var cgas, vgas int64 +func countGasCosts(et *types.ExecutionTrace) int64 { + var cgas int64 for _, gc := range et.GasCharges { cgas += gc.ComputeGas - vgas += gc.VirtualComputeGas } for _, sub := range et.Subcalls { - c, v := countGasCosts(&sub) //nolint + c := countGasCosts(&sub) //nolint cgas += c - vgas += v } - return cgas, vgas + return cgas } type stats struct { timeTaken meanVar gasRatio meanVar - - extraCovar *covar } type covar struct { @@ -680,32 +658,8 @@ func (v1 *meanVar) Combine(v2 *meanVar) { 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) { - for i, gc := range et.GasCharges { + for _, gc := range et.GasCharges { name := gc.Name if name == "OnIpldGetEnd" { continue @@ -716,45 +670,18 @@ func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) { // discard initial very long OnVerifyPost 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 - if compGas == 0 { - compGas = gc.VirtualComputeGas - } - if compGas == 0 { - compGas = 1 - } s := charges[name] if s == nil { s = new(stats) charges[name] = s } - if eSize != nil { - if s.extraCovar == nil { - s.extraCovar = &covar{} - } - s.extraCovar.AddPoint(*eSize, tt) - } - s.timeTaken.AddPoint(tt) + if compGas == 0 { + compGas = 1 + } ratio := tt / float64(compGas) * GasPerNs s.gasRatio.AddPoint(ratio) } @@ -880,13 +807,6 @@ var importAnalyzeCmd = &cli.Command{ } s.timeTaken.Combine(&v.timeTaken) s.gasRatio.Combine(&v.gasRatio) - - if v.extraCovar != nil { - if s.extraCovar == nil { - s.extraCovar = &covar{} - } - s.extraCovar.Combine(v.extraCovar) - } } totalTime += res.totalTime } @@ -902,13 +822,6 @@ var importAnalyzeCmd = &cli.Command{ s := charges[k] fmt.Printf("%s: incr by %.4f~%.4f; tt %.4f~%.4f\n", k, s.gasRatio.Mean(), s.gasRatio.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 { diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 3e5d0dea4da..e0b9d940c36 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4866,95 +4866,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null @@ -5142,95 +5096,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null @@ -6576,95 +6484,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index dc98ffae918..741b1b6e67b 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -6136,95 +6136,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null @@ -6412,95 +6366,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null @@ -7929,95 +7837,49 @@ Response: }, "ExecutionTrace": { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": [ { "Msg": { - "Version": 42, - "To": "f01234", "From": "f01234", - "Nonce": 42, + "To": "f01234", "Value": "0", - "GasLimit": 9, - "GasFeeCap": "0", - "GasPremium": "0", "Method": 1, "Params": "Ynl0ZSBhcnJheQ==", - "CID": { - "/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s" - } + "ParamsCodec": 42 }, "MsgRct": { "ExitCode": 0, "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9, - "EventsRoot": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + "ReturnCodec": 42 }, - "Error": "string value", - "Duration": 60000000000, "GasCharges": [ { "Name": "string value", - "loc": [ - { - "File": "string value", - "Line": 123, - "Function": "string value" - } - ], "tg": 9, "cg": 9, "sg": 9, - "vtg": 9, - "vcg": 9, - "vsg": 9, - "tt": 60000000000, - "ex": {} + "tt": 60000000000 } ], "Subcalls": null diff --git a/gen/main.go b/gen/main.go index a3891778a10..0cd3999c38a 100644 --- a/gen/main.go +++ b/gen/main.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/market" "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/node/hello" "github.com/filecoin-project/lotus/paychmgr" @@ -37,15 +36,11 @@ func main() { types.StateInfo0{}, types.Event{}, types.EventEntry{}, - ) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = gen.WriteTupleEncodersToFile("./chain/vm/cbor_gen.go", "vm", - vm.FvmExecutionTrace{}, - vm.FvmGasCharge{}, + // Tracing + types.GasTrace{}, + types.MessageTrace{}, + types.ReturnTrace{}, + types.ExecutionTrace{}, ) if err != nil { fmt.Println(err)