diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cf98e889bc..c18f2f6a4a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,52 @@ ## Improvements +### Tracing API + +Replace the `CodeCid` field in the message trace (added in 1.23.4) with an `InvokedActor` field. + +**Before:** + +```javascript +{ + "Msg": { + "From": ..., + "To": ..., + ... + "CodeCid": ... // The actor's code CID. + } + "MsgRct": ..., + "GasCharges": [], + "Subcalls": [], +} +``` + +**After:** + +```javascript +{ + "Msg": { + "From": ..., + "To": ... + } + "InvokedActor": { // The invoked actor (ommitted if the actor wasn't invoked). + "Id": 1234, // The ID of the actor. + "State": { // The actor's state object (may change between network versions). + "Code": ..., // The actor's code CID. + "Head": ..., // The actor's state-root (when invoked). + "CallSeqNum": ..., // The actor's nonce. + "Balance": ..., // The actor's balance (when invoked). + "Address": ..., // Delegated address (FEVM only). + } + } + "MsgRct": ..., + "GasCharges": [], + "Subcalls": [], +} +``` + +This means the trace now contains an accurate "snapshot" of the actor at the time of the call, information that may not be present in the final state-tree (e.g., due to reverts). This will hopefully improve the performance and accuracy of indexing services. + # v1.25.2 / 2024-01-11 This is an optional but **highly recommended feature release** of Lotus, as it includes fixes for synchronizations issues that users have experienced. The feature release also introduces `Lotus-Provider` in its alpha testing phase, as well as the ability to call external PC2-binaries during the sealing process. diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 181efeb3015..6028a40f250 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -154,13 +154,14 @@ func init() { addExample(map[verifreg.ClaimId]verifreg.Claim{}) addExample(map[string]int{"name": 42}) addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()}) + addExample(abi.ActorID(1000)) + addExample(map[string]types.Actor{ + "t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor), + }) addExample(&types.ExecutionTrace{ 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), - }) addExample(map[string]api.MarketDeal{ "t026363": ExampleValue("init", reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal), }) @@ -209,7 +210,6 @@ func init() { si := uint64(12) addExample(&si) addExample(retrievalmarket.DealID(5)) - addExample(abi.ActorID(1000)) addExample(map[string]cid.Cid{}) addExample(map[string][]api.SealedRef{ "98000": { diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 0b0acf6dae7..acef3970e73 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 989597d3ae3..1b78f6b0a06 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index fe8e7e3fee2..9bd095f57ad 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -2395,7 +2395,83 @@ func (t *GasTrace) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufMessageTrace = []byte{137} +var lengthBufActorTrace = []byte{130} + +func (t *ActorTrace) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write(lengthBufActorTrace); err != nil { + return err + } + + // t.Id (abi.ActorID) (uint64) + + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Id)); err != nil { + return err + } + + // t.State (types.ActorV5) (struct) + if err := t.State.MarshalCBOR(cw); err != nil { + return err + } + return nil +} + +func (t *ActorTrace) UnmarshalCBOR(r io.Reader) (err error) { + *t = ActorTrace{} + + 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 != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Id (abi.ActorID) (uint64) + + { + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Id = abi.ActorID(extra) + + } + // t.State (types.ActorV5) (struct) + + { + + if err := t.State.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.State: %w", err) + } + + } + return nil +} + +var lengthBufMessageTrace = []byte{136} func (t *MessageTrace) MarshalCBOR(w io.Writer) error { if t == nil { @@ -2459,13 +2535,6 @@ func (t *MessageTrace) MarshalCBOR(w io.Writer) error { if err := cbg.WriteBool(w, t.ReadOnly); err != nil { return err } - - // t.CodeCid (cid.Cid) (struct) - - if err := cbg.WriteCid(cw, t.CodeCid); err != nil { - return xerrors.Errorf("failed to write cid field t.CodeCid: %w", err) - } - return nil } @@ -2488,7 +2557,7 @@ func (t *MessageTrace) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 9 { + if extra != 8 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -2599,18 +2668,6 @@ func (t *MessageTrace) UnmarshalCBOR(r io.Reader) (err error) { default: return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) } - // t.CodeCid (cid.Cid) (struct) - - { - - c, err := cbg.ReadCid(cr) - if err != nil { - return xerrors.Errorf("failed to read cid field t.CodeCid: %w", err) - } - - t.CodeCid = c - - } return nil } @@ -2747,7 +2804,7 @@ func (t *ReturnTrace) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufExecutionTrace = []byte{132} +var lengthBufExecutionTrace = []byte{133} func (t *ExecutionTrace) MarshalCBOR(w io.Writer) error { if t == nil { @@ -2766,6 +2823,11 @@ func (t *ExecutionTrace) MarshalCBOR(w io.Writer) error { return err } + // t.InvokedActor (types.ActorTrace) (struct) + if err := t.InvokedActor.MarshalCBOR(cw); err != nil { + return err + } + // t.MsgRct (types.ReturnTrace) (struct) if err := t.MsgRct.MarshalCBOR(cw); err != nil { return err @@ -2820,7 +2882,7 @@ func (t *ExecutionTrace) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 4 { + if extra != 5 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -2832,6 +2894,25 @@ func (t *ExecutionTrace) UnmarshalCBOR(r io.Reader) (err error) { return xerrors.Errorf("unmarshaling t.Msg: %w", err) } + } + // t.InvokedActor (types.ActorTrace) (struct) + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.InvokedActor = new(ActorTrace) + if err := t.InvokedActor.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.InvokedActor pointer: %w", err) + } + } + } // t.MsgRct (types.ReturnTrace) (struct) diff --git a/chain/types/execresult.go b/chain/types/execresult.go index 4556f7b88ec..261b3328e83 100644 --- a/chain/types/execresult.go +++ b/chain/types/execresult.go @@ -4,8 +4,6 @@ import ( "encoding/json" "time" - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" @@ -28,7 +26,11 @@ type MessageTrace struct { ParamsCodec uint64 GasLimit uint64 ReadOnly bool - CodeCid cid.Cid +} + +type ActorTrace struct { + Id abi.ActorID + State Actor } type ReturnTrace struct { @@ -38,10 +40,11 @@ type ReturnTrace struct { } type ExecutionTrace struct { - Msg MessageTrace - MsgRct ReturnTrace - GasCharges []*GasTrace `cborgen:"maxlen=1000000000"` - Subcalls []ExecutionTrace `cborgen:"maxlen=1000000000"` + Msg MessageTrace + InvokedActor *ActorTrace `json:",omitempty"` + MsgRct ReturnTrace + GasCharges []*GasTrace `cborgen:"maxlen=1000000000"` + Subcalls []ExecutionTrace `cborgen:"maxlen=1000000000"` } func (et ExecutionTrace) SumGas() GasTrace { diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 2eb683f2c78..7a8b50eef74 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4878,9 +4878,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -4907,9 +4918,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -5118,9 +5140,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -5147,9 +5180,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -6518,9 +6562,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -6547,9 +6602,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 6c315a92d39..7d867c6a058 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -6375,9 +6375,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -6404,9 +6415,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -6615,9 +6637,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -6644,9 +6677,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -8144,9 +8188,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { @@ -8173,9 +8228,20 @@ Response: "Params": "Ynl0ZSBhcnJheQ==", "ParamsCodec": 42, "GasLimit": 42, - "ReadOnly": true, - "CodeCid": { - "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + "ReadOnly": true + }, + "InvokedActor": { + "Id": 1000, + "State": { + "Code": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Head": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Nonce": 42, + "Balance": "0", + "Address": "f01234" } }, "MsgRct": { diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 4176a1e662e..b715c9403fa 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 4176a1e662e865834bfdc5861da921dc2d272b45 +Subproject commit b715c9403faf919e95fdc702cd651e842f18d890 diff --git a/gen/main.go b/gen/main.go index 942b3ac2c05..d84343739ea 100644 --- a/gen/main.go +++ b/gen/main.go @@ -38,6 +38,7 @@ func main() { types.EventEntry{}, // Tracing types.GasTrace{}, + types.ActorTrace{}, types.MessageTrace{}, types.ReturnTrace{}, types.ExecutionTrace{}, diff --git a/node/impl/full/eth_trace.go b/node/impl/full/eth_trace.go index 9d24394d7e9..986de034a1d 100644 --- a/node/impl/full/eth_trace.go +++ b/node/impl/full/eth_trace.go @@ -67,7 +67,7 @@ func buildTraces(traces *[]*ethtypes.EthTrace, parent *ethtypes.EthTrace, addr [ FilecoinFrom: et.Msg.From, FilecoinTo: et.Msg.To, FilecoinMethod: et.Msg.Method, - FilecoinCodeCid: et.Msg.CodeCid, + FilecoinCodeCid: et.InvokedActor.State.Code, }, Result: ethtypes.EthTraceResult{ GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), @@ -137,7 +137,7 @@ func buildTraces(traces *[]*ethtypes.EthTrace, parent *ethtypes.EthTrace, addr [ if parent.Action.FilecoinTo == builtin.InitActorAddr && parent.Action.FilecoinMethod == builtin.MethodsInit.Exec && et.Msg.Method == builtin.MethodConstructor { - log.Debugf("COND3 Native actor creation! method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height) + log.Debugf("COND3 Native actor creation! method:%d, code:%s, height:%d", et.Msg.Method, et.InvokedActor.State.Code.String(), height) parent.SetCallType("create") parent.Action.To = to parent.Action.Input = []byte{0xFE} @@ -165,7 +165,7 @@ func buildTraces(traces *[]*ethtypes.EthTrace, parent *ethtypes.EthTrace, addr [ // TODO: We need to handle failures in contract creations and support resurrections on an existing but dead EVM actor) if calledCreateOnEAM && eamCalledInitOnExec4 && initCreatedActor { - log.Debugf("COND4 EVM contract creation method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height) + log.Debugf("COND4 EVM contract creation method:%d, code:%s, height:%d", et.Msg.Method, et.InvokedActor.State.Code.String(), height) if parent.Parent.Action.FilecoinMethod == builtin.MethodsEAM.Create { parent.Parent.SetCallType("create")