From 9ad8fee069f0240c1d7abe3bf77c61d7007c980c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 29 Nov 2023 16:51:24 +0400 Subject: [PATCH 1/6] Improve the correctness of Eth's trace_block - Improve encoding/decoding of parameters and return values: - Encode "native" parameters and return values with Solidity ABI. - Correctly decode parameters to "create" calls. - Use the correct (ish) output for "create" calls. - Handle all forms of "create". - Make robust with respect to reverts: - Use the actor ID/address from the trace instead of looking it up in the state-tree (may not exist in the state-tree due to a revert). - Gracefully handle failed actor/contract creation. - Improve performance: - We avoid looking anything up in the state-tree when translating the trace, which should significantly improve performance. - Improve code readability: - Remove all "backtracking" logic. - Use an "environment" struct to store temporary state instead of attaching it to the trace. - Fix random bugs: - Fix an allocation bug in the "address" logic (need to set the capacity before modifying the slice). - Improved error checking/handling. --- build/openrpc/full.json | 24 +- build/openrpc/full.json.gz | Bin 0 -> 34723 bytes build/openrpc/gateway.json | 24 +- build/openrpc/gateway.json.gz | Bin 0 -> 11942 bytes chain/types/ethtypes/eth_types.go | 38 +- documentation/en/api-v1-unstable-methods.md | 6 +- node/impl/full/eth.go | 58 +- node/impl/full/eth_test.go | 40 ++ node/impl/full/eth_trace.go | 555 ++++++++++++++------ node/impl/full/eth_utils.go | 31 +- 10 files changed, 524 insertions(+), 252 deletions(-) create mode 100644 build/openrpc/full.json.gz create mode 100644 build/openrpc/gateway.json.gz diff --git a/build/openrpc/full.json b/build/openrpc/full.json index 5f70ce52a56..587212849f1 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -8402,7 +8402,8 @@ "traceAddress": [ 123 ], - "Type": "string value", + "type": "string value", + "error": "string value", "blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "blockNumber": 9, "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -8414,9 +8415,6 @@ { "additionalProperties": false, "properties": { - "Type": { - "type": "string" - }, "action": { "additionalProperties": false, "properties": { @@ -8476,6 +8474,9 @@ "title": "number", "type": "number" }, + "error": { + "type": "string" + }, "result": { "additionalProperties": false, "properties": { @@ -8519,6 +8520,9 @@ "transactionPosition": { "title": "number", "type": "number" + }, + "type": { + "type": "string" } }, "type": [ @@ -8613,7 +8617,8 @@ "traceAddress": [ 123 ], - "Type": "string value" + "type": "string value", + "error": "string value" } ], "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -8640,9 +8645,6 @@ "items": { "additionalProperties": false, "properties": { - "Type": { - "type": "string" - }, "action": { "additionalProperties": false, "properties": { @@ -8688,6 +8690,9 @@ }, "type": "object" }, + "error": { + "type": "string" + }, "result": { "additionalProperties": false, "properties": { @@ -8717,6 +8722,9 @@ "type": "number" }, "type": "array" + }, + "type": { + "type": "string" } }, "type": "object" diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..a716b92330ca5fd46db0f448d18223892d01e12a GIT binary patch literal 34723 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 N|Np=jxUb&%1^^%ns4@Tm literal 0 HcmV?d00001 diff --git a/build/openrpc/gateway.json b/build/openrpc/gateway.json index 42521f0c8b0..6baa34443c7 100644 --- a/build/openrpc/gateway.json +++ b/build/openrpc/gateway.json @@ -4455,7 +4455,8 @@ "traceAddress": [ 123 ], - "Type": "string value", + "type": "string value", + "error": "string value", "blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "blockNumber": 9, "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -4467,9 +4468,6 @@ { "additionalProperties": false, "properties": { - "Type": { - "type": "string" - }, "action": { "additionalProperties": false, "properties": { @@ -4529,6 +4527,9 @@ "title": "number", "type": "number" }, + "error": { + "type": "string" + }, "result": { "additionalProperties": false, "properties": { @@ -4572,6 +4573,9 @@ "transactionPosition": { "title": "number", "type": "number" + }, + "type": { + "type": "string" } }, "type": [ @@ -4666,7 +4670,8 @@ "traceAddress": [ 123 ], - "Type": "string value" + "type": "string value", + "error": "string value" } ], "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -4693,9 +4698,6 @@ "items": { "additionalProperties": false, "properties": { - "Type": { - "type": "string" - }, "action": { "additionalProperties": false, "properties": { @@ -4741,6 +4743,9 @@ }, "type": "object" }, + "error": { + "type": "string" + }, "result": { "additionalProperties": false, "properties": { @@ -4770,6 +4775,9 @@ "type": "number" }, "type": "array" + }, + "type": { + "type": "string" } }, "type": "object" diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..be508c8fe76dba3592fbfd9cab208940b5792c54 GIT binary patch literal 11942 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 z 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 0 { + output = env.traces[0].Result.Output } - allTraces = append(allTraces, &t) + allTraces = append(allTraces, ðtypes.EthTraceReplayBlockTransaction{ + Output: output, + TransactionHash: *txHash, + Trace: env.traces, + StateDiff: nil, + VmTrace: nil, + }) } return allTraces, nil diff --git a/node/impl/full/eth_test.go b/node/impl/full/eth_test.go index c364a4873c4..05c3f257504 100644 --- a/node/impl/full/eth_test.go +++ b/node/impl/full/eth_test.go @@ -1,11 +1,14 @@ package full import ( + "bytes" "encoding/hex" "testing" "github.com/ipfs/go-cid" + "github.com/multiformats/go-multicodec" "github.com/stretchr/testify/require" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/big" @@ -177,3 +180,40 @@ func TestABIEncoding(t *testing.T) { require.Equal(t, expectedBytes, encodeAsABIHelper(22, 81, dataBytes)) } + +func TestDecodePayload(t *testing.T) { + // "empty" + b, err := decodePayload(nil, 0) + require.NoError(t, err) + require.Empty(t, b) + + // raw empty + _, err = decodePayload(nil, uint64(multicodec.Raw)) + require.NoError(t, err) + require.Empty(t, b) + + // raw non-empty + b, err = decodePayload([]byte{1}, uint64(multicodec.Raw)) + require.NoError(t, err) + require.EqualValues(t, b, []byte{1}) + + // Invalid cbor bytes + _, err = decodePayload(nil, uint64(multicodec.DagCbor)) + require.Error(t, err) + + // valid cbor bytes + var w bytes.Buffer + require.NoError(t, cbg.WriteByteArray(&w, []byte{1})) + b, err = decodePayload(w.Bytes(), uint64(multicodec.DagCbor)) + require.NoError(t, err) + require.EqualValues(t, b, []byte{1}) + + // regular cbor also works. + b, err = decodePayload(w.Bytes(), uint64(multicodec.Cbor)) + require.NoError(t, err) + require.EqualValues(t, b, []byte{1}) + + // random codec should fail + _, err = decodePayload(w.Bytes(), 42) + require.Error(t, err) +} diff --git a/node/impl/full/eth_trace.go b/node/impl/full/eth_trace.go index 123d96fe103..3901c80ffe5 100644 --- a/node/impl/full/eth_trace.go +++ b/node/impl/full/eth_trace.go @@ -7,8 +7,11 @@ import ( cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/builtin" - "github.com/filecoin-project/go-state-types/builtin/v10/evm" + "github.com/filecoin-project/go-state-types/builtin/v12/eam" + "github.com/filecoin-project/go-state-types/builtin/v12/evm" + "github.com/filecoin-project/go-state-types/exitcode" builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/state" @@ -18,10 +21,6 @@ import ( // decodePayload is a utility function which decodes the payload using the given codec func decodePayload(payload []byte, codec uint64) (ethtypes.EthBytes, error) { - if len(payload) == 0 { - return nil, nil - } - switch multicodec.Code(codec) { case multicodec.Identity: return nil, nil @@ -38,217 +37,441 @@ func decodePayload(payload []byte, codec uint64) (ethtypes.EthBytes, error) { return nil, xerrors.Errorf("decodePayload: unsupported codec: %d", codec) } -// buildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls -func buildTraces(traces *[]*ethtypes.EthTrace, parent *ethtypes.EthTrace, addr []int, et types.ExecutionTrace, height int64, st *state.StateTree) error { - // lookup the eth address from the from/to addresses. Note that this may fail but to support - // this we need to include the ActorID in the trace. For now, just log a warning and skip - // this trace. - // - // TODO: Add ActorID in trace, see https://github.com/filecoin-project/lotus/pull/11100#discussion_r1302442288 - from, err := lookupEthAddress(et.Msg.From, st) +func decodeParams[P any, T interface { + *P + cbg.CBORUnmarshaler +}](msg *types.MessageTrace) (T, error) { + var params T = new(P) + switch msg.ParamsCodec { + case uint64(multicodec.DagCbor), uint64(multicodec.Cbor): + default: + return nil, xerrors.Errorf("Method called with unexpected codec %d", msg.ParamsCodec) + } + + if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil { + return nil, xerrors.Errorf("failed to decode params: %w", err) + } + + return params, nil +} + +func find[T any](values []T, cb func(t *T) *T) *T { + for i := range values { + if o := cb(&values[i]); o != nil { + return o + } + } + return nil +} + +type environment struct { + caller ethtypes.EthAddress + isEVM bool + subtraceCount int + traces []*ethtypes.EthTrace + lastByteCode *ethtypes.EthAddress +} + +func baseEnvironment(st *state.StateTree, from address.Address) (*environment, error) { + sender, err := lookupEthAddress(from, st) if err != nil { - log.Warnf("buildTraces: failed to lookup from address %s: %v", et.Msg.From, err) - return nil + return nil, xerrors.Errorf("top-level message sender %s s could not be found: %w", from, err) } - to, err := lookupEthAddress(et.Msg.To, st) + return &environment{caller: sender}, nil +} + +func traceToAddress(act *types.ActorTrace) ethtypes.EthAddress { + if act.State.Address != nil { + if addr, err := ethtypes.EthAddressFromFilecoinAddress(*act.State.Address); err == nil { + return addr + } + } + return ethtypes.EthAddressFromActorID(act.Id) +} + +// buildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls +func buildTraces(env *environment, addr []int, et *types.ExecutionTrace) error { + trace, recurseInto, err := buildTrace(env, addr, et) if err != nil { - log.Warnf("buildTraces: failed to lookup to address %s: %w", et.Msg.To, err) + return xerrors.Errorf("at trace %v: %w", addr, err) + } + + if trace != nil { + env.traces = append(env.traces, trace) + env.subtraceCount++ + } + + // Skip if there's nothing more to do and/or `buildTrace` told us to skip this one. + if recurseInto == nil || recurseInto.InvokedActor == nil || len(recurseInto.Subcalls) == 0 { return nil } - // Skip the trace if we never reached the point where we invoked this actor. + subEnv := &environment{ + caller: traceToAddress(recurseInto.InvokedActor), + isEVM: builtinactors.IsEvmActor(recurseInto.InvokedActor.State.Code), + traces: env.traces, + } + addr = addr[:len(addr):len(addr)] + for i := range recurseInto.Subcalls { + err := buildTraces(subEnv, append(addr, subEnv.subtraceCount), &recurseInto.Subcalls[i]) + if err != nil { + return err + } + } + trace.Subtraces = subEnv.subtraceCount + env.traces = subEnv.traces + + return nil +} + +func decodeCreate(msg *types.MessageTrace) (callType string, initcode []byte, err error) { + switch msg.Method { + case builtin.MethodsEAM.Create: + params, err := decodeParams[eam.CreateParams](msg) + if err != nil { + return "", nil, err + } + return "create", params.Initcode, nil + case builtin.MethodsEAM.Create2: + params, err := decodeParams[eam.Create2Params](msg) + if err != nil { + return "", nil, err + } + return "create2", params.Initcode, nil + case builtin.MethodsEAM.CreateExternal: + input, err := decodePayload(msg.Params, msg.ParamsCodec) + if err != nil { + return "", nil, err + } + return "create", input, nil + default: + return "", nil, xerrors.Errorf("unexpected CREATE method %d", msg.Method) + } +} + +// buildTrace processes the passed execution trace and updates the environment, if necessary. +// +// On success, it returns a trace to add (or nil to skip) and the trace recurse into (or nil to skip). +func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { + // This function first assumes that the call is a "native" call, then handles all the "not + // native" cases. If we get any unexpected results in any of these special cases, we just + // keep the "native" interpretation and move on. + // + // 1. If we're invoking a contract (even if the caller is a native account/actor), we + // attempt to decode the params/return value as a contract invocation. + // 2. If we're calling the EAM and/or init actor, we try to treat the call as a CREATE. + // 3. Finally, if the caller is an EVM smart contract and it's calling a "private" (1-1023) + // method, we know something special is going on. We look for calls related to + // DELEGATECALL and drop everything else (everything else includes calls triggered by, + // e.g., EXTCODEHASH). + + // If we don't have sufficient funds, or we have a fatal error, or we have some + // other syscall error: skip the entire trace to mimic Ethereum (Ethereum records + // traces _after_ checking things like this). + // + // NOTE: The FFI currently folds all unknown syscall errors into "sys assertion + // failed" which is turned into SysErrFatal. + if len(addr) > 0 { + switch et.MsgRct.ExitCode { + case exitcode.SysErrInsufficientFunds, exitcode.SysErrFatal: + return nil, nil, nil + } + } + + // We may fail before we can even invoke the actor. In that case, we have no 100% reliable + // way of getting its address (e.g., due to reverts) so we're just going to drop the entire + // trace. This is OK (ish) because the call never really "happened". if et.InvokedActor == nil { - return nil + return nil, nil, nil } + ///////////////////////////////////// + // Step 1: Decode as a native call // + ///////////////////////////////////// + + to := traceToAddress(et.InvokedActor) + var errMsg string + if et.MsgRct.ExitCode.IsError() { + errMsg = et.MsgRct.ExitCode.Error() + } trace := ðtypes.EthTrace{ Action: ethtypes.EthTraceAction{ - From: from, - To: to, + From: env.caller, + To: &to, Gas: ethtypes.EthUint64(et.Msg.GasLimit), - Input: nil, Value: ethtypes.EthBigInt(et.Msg.Value), - - FilecoinFrom: et.Msg.From, - FilecoinTo: et.Msg.To, - FilecoinMethod: et.Msg.Method, - FilecoinCodeCid: et.InvokedActor.State.Code, + Input: encodeFilecoinParamsAsABI(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params), }, Result: ethtypes.EthTraceResult{ GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), - Output: nil, + Output: encodeFilecoinReturnAsABI(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return), }, - Subtraces: 0, // will be updated by the children once they are added to the trace TraceAddress: addr, + Error: errMsg, + } - Parent: parent, - LastByteCode: nil, + // Set the assumed call mode. We'll override this if the call ends up looking like a create, + // delegatecall, etc. + if et.Msg.ReadOnly { + trace.SetCallType("staticcall") + } else { + trace.SetCallType("call") } - trace.SetCallType("call") + ///////////////////////////////////////////// + // Step 2: Decode as a contract invocation // + ///////////////////////////////////////////// + // Normal EVM calls. We don't care if the caller/receiver are actually EVM actors, we only + // care if the call _looks_ like an EVM call. If we fail to decode it as an EVM call, we + // fallback on interpreting it as a native call. if et.Msg.Method == builtin.MethodsEVM.InvokeContract { - log.Debugf("COND1 found InvokeContract call at height: %d", height) - - // TODO: ignore return errors since actors can send gibberish and we don't want - // to fail the whole trace in that case - trace.Action.Input, err = decodePayload(et.Msg.Params, et.Msg.ParamsCodec) - if err != nil { - return xerrors.Errorf("buildTraces: %w", err) - } - trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + input, err := decodePayload(et.Msg.Params, et.Msg.ParamsCodec) if err != nil { - return xerrors.Errorf("buildTraces: %w", err) + log.Debugf("failed to decode contract invocation payload: %w", err) + return trace, et, nil } - } else if et.Msg.To == builtin.EthereumAddressManagerActorAddr && - et.Msg.Method == builtin.MethodsEAM.CreateExternal { - log.Debugf("COND2 found CreateExternal call at height: %d", height) - trace.Action.Input, err = decodePayload(et.Msg.Params, et.Msg.ParamsCodec) + output, err := decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) if err != nil { - return xerrors.Errorf("buildTraces: %w", err) + log.Debugf("failed to decode contract invocation return: %w", err) + return trace, et, nil } + trace.Action.Input = input + trace.Result.Output = output + return trace, et, nil + } - if et.MsgRct.ExitCode.IsSuccess() { - // ignore return value - trace.Result.Output = nil - } else { - // return value is the error message - trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) - if err != nil { - return xerrors.Errorf("buildTraces: %w", err) + ///////////////////////////////////////////// + // Step 3: Decode as a contract deployment // + ///////////////////////////////////////////// + + switch et.Msg.To { + // NOTE: this will only catch _direct_ calls to the init actor. Calls through the EAM will + // be caught and _skipped_ below in the next case. + case builtin.InitActorAddr: + switch et.Msg.Method { + case builtin.MethodsInit.Exec, builtin.MethodsInit.Exec4: + if et.Msg.ReadOnly { + // "create" isn't valid in a staticcall, so we just skip this trace + // (couldn't have created an actor anyways). + // This mimic's the EVM: it doesn't trace CREATE calls when in + // read-only mode. + return nil, nil, nil } - } - // treat this as a contract creation - trace.SetCallType("create") - } else { - // we are going to assume a native method, but we may change it in one of the edge cases below - // TODO: only do this if we know it's a native method (optimization) - trace.Action.Input = encodeFilecoinParamsAsABI(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params) - trace.Result.Output = encodeFilecoinReturnAsABI(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return) - } - - // TODO: is it OK to check this here or is this only specific to certain edge case (evm to evm)? - if et.Msg.ReadOnly { - trace.SetCallType("staticcall") - } + subTrace := find(et.Subcalls, func(c *types.ExecutionTrace) *types.ExecutionTrace { + if c.Msg.Method == builtin.MethodConstructor { + return c + } + return nil + }) + if subTrace == nil { + // If we succeed in calling Exec/Exec4 but don't even try to construct + // something, we have a bug in our tracing logic or a mismatch between our + // tracing logic and the actors. + if et.MsgRct.ExitCode.IsSuccess() { + return nil, nil, xerrors.Errorf("successful Exec/Exec4 call failed to call a constructor") + } + // Otherwise, this can happen if creation fails early (bad params, + // out of gas, contract already exists, etc.). The EVM wouldn't + // trace such cases, so we don't either. + // + // NOTE: It's actually impossible to run out of gas before calling + // initcode in the EVM (without running out of gas in the calling + // contract), but this is an equivalent edge-case to InvokedActor + // being nil, so we treat it the same way and skip the entire + // operation. + return nil, nil, nil + } - // there are several edge cases that require special handling when displaying the traces. Note that while iterating over - // the traces we update the trace backwards (through the parent pointer) - if parent != nil { - // Handle Native actor creation - // - // Actor A calls to the init actor on method 2 and The init actor creates the target actor B then calls it on method 1 - 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.InvokedActor.State.Code.String(), height) - parent.SetCallType("create") - parent.Action.To = to - parent.Action.Input = []byte{0xFE} - parent.Result.Output = nil - - // there should never be any subcalls when creating a native actor - // - // TODO: add support for native actors calling another when created - return nil - } + // Native actors that aren't the EAM can attempt to call Exec4, but such + // call should fail immediately without ever attempting to construct an + // actor. I'm catching this here because it likely means that there's a bug + // in our trace-conversion logic. + if et.Msg.Method == builtin.MethodsInit.Exec4 { + return nil, nil, xerrors.Errorf("direct call to Exec4 successfully called a constructor!") + } - // Handle EVM contract creation - // - // To detect EVM contract creation we need to check for the following sequence of events: - // - // 1) EVM contract A calls the EAM (Ethereum Address Manager) on method 2 (create) or 3 (create2). - // 2) The EAM calls the init actor on method 3 (Exec4). - // 3) The init actor creates the target actor B then calls it on method 1. - if parent.Parent != nil { - calledCreateOnEAM := parent.Parent.Action.FilecoinTo == builtin.EthereumAddressManagerActorAddr && - (parent.Parent.Action.FilecoinMethod == builtin.MethodsEAM.Create || parent.Parent.Action.FilecoinMethod == builtin.MethodsEAM.Create2) - eamCalledInitOnExec4 := parent.Action.FilecoinTo == builtin.InitActorAddr && - parent.Action.FilecoinMethod == builtin.MethodsInit.Exec4 - initCreatedActor := trace.Action.FilecoinMethod == builtin.MethodConstructor - - // 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.InvokedActor.State.Code.String(), height) - - if parent.Parent.Action.FilecoinMethod == builtin.MethodsEAM.Create { - parent.Parent.SetCallType("create") + // Contract creation has no "to". + trace.Action.To = nil + // If we get here, this isn't a native EVM create. Those always go through + // the EAM. So we have no "real" initcode and must use the sentinel value + // for "invalid" initcode. + trace.Action.Input = []byte{0xFE} + trace.SetCallType("create") + // Handle the output. + if et.MsgRct.ExitCode.IsError() { + // If the sub-call fails, record the reason. It's possible for the + // call to the init actor to fail, but for the construction to + // succeed, so we need to check the exit code here. + if subTrace.MsgRct.ExitCode.IsError() { + trace.Result.Output = encodeFilecoinReturnAsABI( + subTrace.MsgRct.ExitCode, + subTrace.MsgRct.ReturnCodec, + subTrace.MsgRct.Return, + ) } else { - parent.Parent.SetCallType("create2") + // Otherwise, output nothing. + trace.Result.Output = nil } + } else { + // We're supposed to put the "installed bytecode" here. But this + // isn't an EVM actor, so we just put some invalid bytecode (this is + // the answer you'd get if you called EXTCODECOPY on a native + // non-account actor, anyways). + trace.Result.Output = []byte{0xFE} + } + return trace, subTrace, nil + } + case builtin.EthereumAddressManagerActorAddr: + switch et.Msg.Method { + case builtin.MethodsEAM.Create, builtin.MethodsEAM.Create2, builtin.MethodsEAM.CreateExternal: + // Same as the Init actor case above, see the comment there. + if et.Msg.ReadOnly { + return nil, nil, nil + } - // update the parent.parent to make this - parent.Parent.Action.To = trace.Action.To - parent.Parent.Subtraces = 0 - - // delete the parent (the EAM) and skip the current trace (init) - *traces = (*traces)[:len(*traces)-1] - + // Look for a call to either a constructor or the EVM's resurrect method. + subTrace := find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { + if et.Msg.To == builtinactors.InitActorAddr { + return find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { + if et.Msg.Method == builtinactors.MethodConstructor { + return et + } + return nil + }) + } + if et.Msg.Method == builtin.MethodsEVM.Resurrect { + return et + } return nil + }) + + // Same as the Init actor case above, see the comment there. + if subTrace == nil { + if et.MsgRct.ExitCode.IsSuccess() { + return nil, nil, xerrors.Errorf("successful Create/Create2 call failed to call a constructor") + } + return nil, nil, nil } - } - if builtinactors.IsEvmActor(parent.Action.FilecoinCodeCid) { - // Handle delegate calls - // - // 1) Look for trace from an EVM actor to itself on InvokeContractDelegate, method 6. - // 2) Check that the previous trace calls another actor on method 3 (GetByteCode) and they are at the same level (same parent) - // 3) Treat this as a delegate call to actor A. - if parent.LastByteCode != nil && trace.Action.From == trace.Action.To && - trace.Action.FilecoinMethod == builtin.MethodsEVM.InvokeContractDelegate { - log.Debugf("COND7 found delegate call, height: %d", height) - prev := parent.LastByteCode - if prev.Action.From == trace.Action.From && prev.Action.FilecoinMethod == builtin.MethodsEVM.GetBytecode && prev.Parent == trace.Parent { - trace.SetCallType("delegatecall") - trace.Action.To = prev.Action.To - - var dp evm.DelegateCallParams - err := dp.UnmarshalCBOR(bytes.NewReader(et.Msg.Params)) - if err != nil { - return xerrors.Errorf("failed UnmarshalCBOR: %w", err) - } - trace.Action.Input = dp.Input + // Contract creation has no "to". + trace.Action.To = nil - trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + // Decode inputs & determine create type. + method, initcode, err := decodeCreate(&et.Msg) + if err != nil { + return nil, nil, xerrors.Errorf("EAM called with invalid params, but it still tried to construct the contract: %w", err) + } + trace.Action.Input = initcode + trace.SetCallType(method) + + // Handle the output. + if et.MsgRct.ExitCode.IsError() { + if subTrace.MsgRct.ExitCode.IsError() { + // If we managed to call the constructor, parse/return its + // revert message. + output, err := decodePayload(subTrace.MsgRct.Return, subTrace.MsgRct.ReturnCodec) if err != nil { - return xerrors.Errorf("failed decodePayload: %w", err) + log.Debugf("EVM actor returned indecipherable create error: %w", err) + output = encodeFilecoinReturnAsABI( + subTrace.MsgRct.ExitCode, + subTrace.MsgRct.ReturnCodec, + subTrace.MsgRct.Return, + ) } + trace.Result.Output = output + } else { + // Otherwise, if we failed before that, we have no revert + // message. + trace.Result.Output = nil } } else { - // Handle EVM call special casing - // - // Any outbound call from an EVM actor on methods 1-1023 are side-effects from EVM instructions - // and should be dropped from the trace. - if et.Msg.Method > 0 && - et.Msg.Method <= 1023 { - log.Debugf("Infof found outbound call from an EVM actor on method 1-1023 method:%d, code:%s, height:%d", et.Msg.Method, parent.Action.FilecoinCodeCid.String(), height) - - if et.Msg.Method == builtin.MethodsEVM.GetBytecode { - // save the last bytecode trace to handle delegate calls - parent.LastByteCode = trace - } - - return nil - } + // We're _supposed_ to include the contracts bytecode here, but we + // can't do that reliably (e.g., if some part of the trace reverts). + // So we don't try and include a sentinel "impossible bytecode" + // value (the value specified by EIP-3541). + trace.Result.Output = []byte{0xFE} } + return trace, subTrace, nil } - } - // we are adding trace to the traces so update the parent subtraces count as it was originally set to zero - if parent != nil { - parent.Subtraces++ - } + ///////////////////////////////// + // Step 4: Handle DELEGATECALL // + ///////////////////////////////// - *traces = append(*traces, trace) + // EVM contracts cannot call methods in the range 1-1023, only the EVM itself can. So, if we + // see a call in this range, we know it's an implementation detail of the EVM and not an + // explicit call by the user. + // + // While the EVM calls several methods in this range (some we've already handled above with + // respect to the EAM), we only care about the ones relevant DELEGATECALL and can _ignore_ + // all the others. + if env.isEVM && et.Msg.Method > 0 && et.Msg.Method < 1024 { + // The EVM actor implements DELEGATECALL by: + // + // 1. Asking the callee for its bytecode by calling it on the GetBytecode method. + // 2. Recursively invoking the currently executing contract on the + // InvokeContractDelegate method. + // + // The code below "reconstructs" that delegate call by: + // + // 1. Remembering the last contract on which we called GetBytecode. + // 2. Treating the contract invoked in step 1 as the DELEGATECALL receiver. + // + // Note, however: GetBytecode will be called, e.g., if the user invokes the + // EXTCODECOPY instruction. It's not an error to see multiple GetBytecode calls + // before we see an InvokeContractDelegate. + switch et.Msg.Method { + case builtin.MethodsEVM.GetBytecode: + // NOTE: I'm not checking anything about the receiver here. The EVM won't + // DELEGATECALL any non-EVM actor, but there's no need to encode that fact + // here in case we decide to loosen this up in the future. + if et.MsgRct.ExitCode.IsSuccess() { + env.lastByteCode = &to + } else { + env.lastByteCode = nil + } + return nil, nil, nil + case builtin.MethodsEVM.InvokeContractDelegate: + // NOTE: We return errors in all the failure cases below instead of trying + // to continue because the caller is an EVM actor. If something goes wrong + // here, there's a bug in our EVM implementation. - for i, call := range et.Subcalls { - err := buildTraces(traces, trace, append(addr, i), call, height, st) - if err != nil { - return err + // Handle delegate calls + // + // 1) Look for trace from an EVM actor to itself on InvokeContractDelegate, + // method 6. + // 2) Check that the previous trace calls another actor on method 3 + // (GetByteCode) and they are at the same level (same parent) + // 3) Treat this as a delegate call to actor A. + if env.lastByteCode == nil { + return nil, nil, xerrors.Errorf("unknown bytecode for delegate call") + } + if env.caller != to { + return nil, nil, xerrors.Errorf("delegate-call not from & to self: %s != %s", env.caller, to) + } + + trace.SetCallType("delegatecall") + trace.Action.To = env.lastByteCode + + dp, err := decodeParams[evm.DelegateCallParams](&et.Msg) + if err != nil { + return nil, nil, xerrors.Errorf("failed to decode delegate-call params: %w", err) + } + trace.Action.Input = dp.Input + + trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + if err != nil { + return nil, nil, xerrors.Errorf("failed to decode delegate-call return: %w", err) + } + + return trace, et, nil } + // We drop all other "private" calls from FEVM. We _forbid_ explicit calls between 0 and 1024 (exclusive), so any calls in this range must be implementation details. + return nil, nil, nil } - return nil + return trace, et, nil } diff --git a/node/impl/full/eth_utils.go b/node/impl/full/eth_utils.go index 90e6d054a9c..6186c2645f9 100644 --- a/node/impl/full/eth_utils.go +++ b/node/impl/full/eth_utils.go @@ -382,34 +382,35 @@ func parseEthRevert(ret []byte) string { // 3. Otherwise, we fall back to returning a masked ID Ethereum address. If the supplied address is an f0 address, we // use that ID to form the masked ID address. // 4. Otherwise, we fetch the actor's ID from the state tree and form the masked ID with it. +// +// If the actor doesn't exist in the state-tree but we have its ID, we use a masked ID address. It could have been deleted. func lookupEthAddress(addr address.Address, st *state.StateTree) (ethtypes.EthAddress, error) { - // BLOCK A: We are trying to get an actual Ethereum address from an f410 address. // Attempt to convert directly, if it's an f4 address. ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(addr) if err == nil && !ethAddr.IsMaskedID() { return ethAddr, nil } - // Lookup on the target actor and try to get an f410 address. - if actor, err := st.GetActor(addr); err != nil { + // Otherwise, resolve the ID addr. + idAddr, err := st.LookupID(addr) + if err != nil { return ethtypes.EthAddress{}, err - } else if actor.Address != nil { - if ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(*actor.Address); err == nil && !ethAddr.IsMaskedID() { - return ethAddr, nil - } } - // BLOCK B: We gave up on getting an actual Ethereum address and are falling back to a Masked ID address. - // Check if we already have an ID addr, and use it if possible. - if err == nil && ethAddr.IsMaskedID() { + // Lookup on the target actor and try to get an f410 address. + if actor, err := st.GetActor(idAddr); errors.Is(err, types.ErrActorNotFound) { + // Not found -> use a masked ID address + } else if err != nil { + // Any other error -> fail. + return ethtypes.EthAddress{}, err + } else if actor.Address == nil { + // No delegated address -> use masked ID address. + } else if ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(*actor.Address); err == nil && !ethAddr.IsMaskedID() { + // Conversable into an eth address, use it. return ethAddr, nil } - // Otherwise, resolve the ID addr. - idAddr, err := st.LookupID(addr) - if err != nil { - return ethtypes.EthAddress{}, err - } + // Otherwise, use the masked address. return ethtypes.EthAddressFromFilecoinAddress(idAddr) } From aaeafbdb6c3f3206afd787c6c521d7dd2dda6437 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 12 Feb 2024 11:58:21 -0800 Subject: [PATCH 2/6] chore: comment on why we slice the `addr` --- node/impl/full/eth_trace.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/impl/full/eth_trace.go b/node/impl/full/eth_trace.go index 3901c80ffe5..e1d30003d95 100644 --- a/node/impl/full/eth_trace.go +++ b/node/impl/full/eth_trace.go @@ -111,6 +111,8 @@ func buildTraces(env *environment, addr []int, et *types.ExecutionTrace) error { isEVM: builtinactors.IsEvmActor(recurseInto.InvokedActor.State.Code), traces: env.traces, } + // Set capacity to the length so each `append` below creates a new slice. Otherwise, we'll + // end up repeatedly mutating previous paths. addr = addr[:len(addr):len(addr)] for i := range recurseInto.Subcalls { err := buildTraces(subEnv, append(addr, subEnv.subtraceCount), &recurseInto.Subcalls[i]) From 91d6b5b3cfe38226336659661107d8fe8472f111 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 12 Feb 2024 15:17:03 -0800 Subject: [PATCH 3/6] refactor: split trace logic into multiple functions --- node/impl/full/eth_trace.go | 453 ++++++++++++++++++------------------ 1 file changed, 230 insertions(+), 223 deletions(-) diff --git a/node/impl/full/eth_trace.go b/node/impl/full/eth_trace.go index e1d30003d95..352d7427866 100644 --- a/node/impl/full/eth_trace.go +++ b/node/impl/full/eth_trace.go @@ -187,10 +187,7 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp return nil, nil, nil } - ///////////////////////////////////// - // Step 1: Decode as a native call // - ///////////////////////////////////// - + // Step 1: Decode as a native call to := traceToAddress(et.InvokedActor) var errMsg string if et.MsgRct.ExitCode.IsError() { @@ -220,189 +217,33 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp trace.SetCallType("call") } - ///////////////////////////////////////////// - // Step 2: Decode as a contract invocation // - ///////////////////////////////////////////// - + // Step 2: Decode as a contract invocation + // // Normal EVM calls. We don't care if the caller/receiver are actually EVM actors, we only // care if the call _looks_ like an EVM call. If we fail to decode it as an EVM call, we // fallback on interpreting it as a native call. if et.Msg.Method == builtin.MethodsEVM.InvokeContract { - input, err := decodePayload(et.Msg.Params, et.Msg.ParamsCodec) - if err != nil { - log.Debugf("failed to decode contract invocation payload: %w", err) - return trace, et, nil - } - output, err := decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) - if err != nil { - log.Debugf("failed to decode contract invocation return: %w", err) - return trace, et, nil - } - trace.Action.Input = input - trace.Result.Output = output - return trace, et, nil + return traceInvokeEVM(env, et, trace) } - ///////////////////////////////////////////// - // Step 3: Decode as a contract deployment // - ///////////////////////////////////////////// - + // Step 3: Decode as a contract deployment switch et.Msg.To { // NOTE: this will only catch _direct_ calls to the init actor. Calls through the EAM will // be caught and _skipped_ below in the next case. case builtin.InitActorAddr: switch et.Msg.Method { case builtin.MethodsInit.Exec, builtin.MethodsInit.Exec4: - if et.Msg.ReadOnly { - // "create" isn't valid in a staticcall, so we just skip this trace - // (couldn't have created an actor anyways). - // This mimic's the EVM: it doesn't trace CREATE calls when in - // read-only mode. - return nil, nil, nil - } - - subTrace := find(et.Subcalls, func(c *types.ExecutionTrace) *types.ExecutionTrace { - if c.Msg.Method == builtin.MethodConstructor { - return c - } - return nil - }) - if subTrace == nil { - // If we succeed in calling Exec/Exec4 but don't even try to construct - // something, we have a bug in our tracing logic or a mismatch between our - // tracing logic and the actors. - if et.MsgRct.ExitCode.IsSuccess() { - return nil, nil, xerrors.Errorf("successful Exec/Exec4 call failed to call a constructor") - } - // Otherwise, this can happen if creation fails early (bad params, - // out of gas, contract already exists, etc.). The EVM wouldn't - // trace such cases, so we don't either. - // - // NOTE: It's actually impossible to run out of gas before calling - // initcode in the EVM (without running out of gas in the calling - // contract), but this is an equivalent edge-case to InvokedActor - // being nil, so we treat it the same way and skip the entire - // operation. - return nil, nil, nil - } - - // Native actors that aren't the EAM can attempt to call Exec4, but such - // call should fail immediately without ever attempting to construct an - // actor. I'm catching this here because it likely means that there's a bug - // in our trace-conversion logic. - if et.Msg.Method == builtin.MethodsInit.Exec4 { - return nil, nil, xerrors.Errorf("direct call to Exec4 successfully called a constructor!") - } - - // Contract creation has no "to". - trace.Action.To = nil - // If we get here, this isn't a native EVM create. Those always go through - // the EAM. So we have no "real" initcode and must use the sentinel value - // for "invalid" initcode. - trace.Action.Input = []byte{0xFE} - trace.SetCallType("create") - // Handle the output. - if et.MsgRct.ExitCode.IsError() { - // If the sub-call fails, record the reason. It's possible for the - // call to the init actor to fail, but for the construction to - // succeed, so we need to check the exit code here. - if subTrace.MsgRct.ExitCode.IsError() { - trace.Result.Output = encodeFilecoinReturnAsABI( - subTrace.MsgRct.ExitCode, - subTrace.MsgRct.ReturnCodec, - subTrace.MsgRct.Return, - ) - } else { - // Otherwise, output nothing. - trace.Result.Output = nil - } - } else { - // We're supposed to put the "installed bytecode" here. But this - // isn't an EVM actor, so we just put some invalid bytecode (this is - // the answer you'd get if you called EXTCODECOPY on a native - // non-account actor, anyways). - trace.Result.Output = []byte{0xFE} - } - return trace, subTrace, nil + return traceNativeCreate(env, et, trace) } case builtin.EthereumAddressManagerActorAddr: switch et.Msg.Method { case builtin.MethodsEAM.Create, builtin.MethodsEAM.Create2, builtin.MethodsEAM.CreateExternal: - // Same as the Init actor case above, see the comment there. - if et.Msg.ReadOnly { - return nil, nil, nil - } - - // Look for a call to either a constructor or the EVM's resurrect method. - subTrace := find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { - if et.Msg.To == builtinactors.InitActorAddr { - return find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { - if et.Msg.Method == builtinactors.MethodConstructor { - return et - } - return nil - }) - } - if et.Msg.Method == builtin.MethodsEVM.Resurrect { - return et - } - return nil - }) - - // Same as the Init actor case above, see the comment there. - if subTrace == nil { - if et.MsgRct.ExitCode.IsSuccess() { - return nil, nil, xerrors.Errorf("successful Create/Create2 call failed to call a constructor") - } - return nil, nil, nil - } - - // Contract creation has no "to". - trace.Action.To = nil - - // Decode inputs & determine create type. - method, initcode, err := decodeCreate(&et.Msg) - if err != nil { - return nil, nil, xerrors.Errorf("EAM called with invalid params, but it still tried to construct the contract: %w", err) - } - trace.Action.Input = initcode - trace.SetCallType(method) - - // Handle the output. - if et.MsgRct.ExitCode.IsError() { - if subTrace.MsgRct.ExitCode.IsError() { - // If we managed to call the constructor, parse/return its - // revert message. - output, err := decodePayload(subTrace.MsgRct.Return, subTrace.MsgRct.ReturnCodec) - if err != nil { - log.Debugf("EVM actor returned indecipherable create error: %w", err) - output = encodeFilecoinReturnAsABI( - subTrace.MsgRct.ExitCode, - subTrace.MsgRct.ReturnCodec, - subTrace.MsgRct.Return, - ) - } - trace.Result.Output = output - } else { - // Otherwise, if we failed before that, we have no revert - // message. - trace.Result.Output = nil - } - } else { - // We're _supposed_ to include the contracts bytecode here, but we - // can't do that reliably (e.g., if some part of the trace reverts). - // So we don't try and include a sentinel "impossible bytecode" - // value (the value specified by EIP-3541). - trace.Result.Output = []byte{0xFE} - } - return trace, subTrace, nil + return traceEthCreate(env, et, trace) } } - ///////////////////////////////// - // Step 4: Handle DELEGATECALL // - ///////////////////////////////// - + // Step 4: Handle DELEGATECALL + // // EVM contracts cannot call methods in the range 1-1023, only the EVM itself can. So, if we // see a call in this range, we know it's an implementation detail of the EVM and not an // explicit call by the user. @@ -411,69 +252,235 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp // respect to the EAM), we only care about the ones relevant DELEGATECALL and can _ignore_ // all the others. if env.isEVM && et.Msg.Method > 0 && et.Msg.Method < 1024 { - // The EVM actor implements DELEGATECALL by: - // - // 1. Asking the callee for its bytecode by calling it on the GetBytecode method. - // 2. Recursively invoking the currently executing contract on the - // InvokeContractDelegate method. - // - // The code below "reconstructs" that delegate call by: - // - // 1. Remembering the last contract on which we called GetBytecode. - // 2. Treating the contract invoked in step 1 as the DELEGATECALL receiver. + return traceEVMPrivate(env, et, trace, to) + } + + return trace, et, nil +} + +func traceInvokeEVM(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { + input, err := decodePayload(et.Msg.Params, et.Msg.ParamsCodec) + if err != nil { + log.Debugf("failed to decode contract invocation payload: %w", err) + return trace, et, nil + } + output, err := decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + if err != nil { + log.Debugf("failed to decode contract invocation return: %w", err) + return trace, et, nil + } + trace.Action.Input = input + trace.Result.Output = output + return trace, et, nil +} + +func traceNativeCreate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { + if et.Msg.ReadOnly { + // "create" isn't valid in a staticcall, so we just skip this trace + // (couldn't have created an actor anyways). + // This mimic's the EVM: it doesn't trace CREATE calls when in + // read-only mode. + return nil, nil, nil + } + + subTrace := find(et.Subcalls, func(c *types.ExecutionTrace) *types.ExecutionTrace { + if c.Msg.Method == builtin.MethodConstructor { + return c + } + return nil + }) + if subTrace == nil { + // If we succeed in calling Exec/Exec4 but don't even try to construct + // something, we have a bug in our tracing logic or a mismatch between our + // tracing logic and the actors. + if et.MsgRct.ExitCode.IsSuccess() { + return nil, nil, xerrors.Errorf("successful Exec/Exec4 call failed to call a constructor") + } + // Otherwise, this can happen if creation fails early (bad params, + // out of gas, contract already exists, etc.). The EVM wouldn't + // trace such cases, so we don't either. // - // Note, however: GetBytecode will be called, e.g., if the user invokes the - // EXTCODECOPY instruction. It's not an error to see multiple GetBytecode calls - // before we see an InvokeContractDelegate. - switch et.Msg.Method { - case builtin.MethodsEVM.GetBytecode: - // NOTE: I'm not checking anything about the receiver here. The EVM won't - // DELEGATECALL any non-EVM actor, but there's no need to encode that fact - // here in case we decide to loosen this up in the future. - if et.MsgRct.ExitCode.IsSuccess() { - env.lastByteCode = &to - } else { - env.lastByteCode = nil - } - return nil, nil, nil - case builtin.MethodsEVM.InvokeContractDelegate: - // NOTE: We return errors in all the failure cases below instead of trying - // to continue because the caller is an EVM actor. If something goes wrong - // here, there's a bug in our EVM implementation. - - // Handle delegate calls - // - // 1) Look for trace from an EVM actor to itself on InvokeContractDelegate, - // method 6. - // 2) Check that the previous trace calls another actor on method 3 - // (GetByteCode) and they are at the same level (same parent) - // 3) Treat this as a delegate call to actor A. - if env.lastByteCode == nil { - return nil, nil, xerrors.Errorf("unknown bytecode for delegate call") - } - if env.caller != to { - return nil, nil, xerrors.Errorf("delegate-call not from & to self: %s != %s", env.caller, to) - } + // NOTE: It's actually impossible to run out of gas before calling + // initcode in the EVM (without running out of gas in the calling + // contract), but this is an equivalent edge-case to InvokedActor + // being nil, so we treat it the same way and skip the entire + // operation. + return nil, nil, nil + } - trace.SetCallType("delegatecall") - trace.Action.To = env.lastByteCode + // Native actors that aren't the EAM can attempt to call Exec4, but such + // call should fail immediately without ever attempting to construct an + // actor. I'm catching this here because it likely means that there's a bug + // in our trace-conversion logic. + if et.Msg.Method == builtin.MethodsInit.Exec4 { + return nil, nil, xerrors.Errorf("direct call to Exec4 successfully called a constructor!") + } - dp, err := decodeParams[evm.DelegateCallParams](&et.Msg) - if err != nil { - return nil, nil, xerrors.Errorf("failed to decode delegate-call params: %w", err) - } - trace.Action.Input = dp.Input + // Contract creation has no "to". + trace.Action.To = nil + // If we get here, this isn't a native EVM create. Those always go through + // the EAM. So we have no "real" initcode and must use the sentinel value + // for "invalid" initcode. + trace.Action.Input = []byte{0xFE} + trace.SetCallType("create") + // Handle the output. + if et.MsgRct.ExitCode.IsError() { + // If the sub-call fails, record the reason. It's possible for the + // call to the init actor to fail, but for the construction to + // succeed, so we need to check the exit code here. + if subTrace.MsgRct.ExitCode.IsError() { + trace.Result.Output = encodeFilecoinReturnAsABI( + subTrace.MsgRct.ExitCode, + subTrace.MsgRct.ReturnCodec, + subTrace.MsgRct.Return, + ) + } else { + // Otherwise, output nothing. + trace.Result.Output = nil + } + } else { + // We're supposed to put the "installed bytecode" here. But this + // isn't an EVM actor, so we just put some invalid bytecode (this is + // the answer you'd get if you called EXTCODECOPY on a native + // non-account actor, anyways). + trace.Result.Output = []byte{0xFE} + } + return trace, subTrace, nil +} + +func traceEthCreate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { + // Same as the Init actor case above, see the comment there. + if et.Msg.ReadOnly { + return nil, nil, nil + } - trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + // Look for a call to either a constructor or the EVM's resurrect method. + subTrace := find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { + if et.Msg.To == builtinactors.InitActorAddr { + return find(et.Subcalls, func(et *types.ExecutionTrace) *types.ExecutionTrace { + if et.Msg.Method == builtinactors.MethodConstructor { + return et + } + return nil + }) + } + if et.Msg.Method == builtin.MethodsEVM.Resurrect { + return et + } + return nil + }) + + // Same as the Init actor case above, see the comment there. + if subTrace == nil { + if et.MsgRct.ExitCode.IsSuccess() { + return nil, nil, xerrors.Errorf("successful Create/Create2 call failed to call a constructor") + } + return nil, nil, nil + } + + // Contract creation has no "to". + trace.Action.To = nil + + // Decode inputs & determine create type. + method, initcode, err := decodeCreate(&et.Msg) + if err != nil { + return nil, nil, xerrors.Errorf("EAM called with invalid params, but it still tried to construct the contract: %w", err) + } + trace.Action.Input = initcode + trace.SetCallType(method) + + // Handle the output. + if et.MsgRct.ExitCode.IsError() { + if subTrace.MsgRct.ExitCode.IsError() { + // If we managed to call the constructor, parse/return its + // revert message. + output, err := decodePayload(subTrace.MsgRct.Return, subTrace.MsgRct.ReturnCodec) if err != nil { - return nil, nil, xerrors.Errorf("failed to decode delegate-call return: %w", err) + log.Debugf("EVM actor returned indecipherable create error: %w", err) + output = encodeFilecoinReturnAsABI( + subTrace.MsgRct.ExitCode, + subTrace.MsgRct.ReturnCodec, + subTrace.MsgRct.Return, + ) } + trace.Result.Output = output + } else { + // Otherwise, if we failed before that, we have no revert + // message. + trace.Result.Output = nil + } + } else { + // We're _supposed_ to include the contracts bytecode here, but we + // can't do that reliably (e.g., if some part of the trace reverts). + // So we don't try and include a sentinel "impossible bytecode" + // value (the value specified by EIP-3541). + trace.Result.Output = []byte{0xFE} + } + return trace, subTrace, nil +} - return trace, et, nil +func traceEVMPrivate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace, to ethtypes.EthAddress) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { + // The EVM actor implements DELEGATECALL by: + // + // 1. Asking the callee for its bytecode by calling it on the GetBytecode method. + // 2. Recursively invoking the currently executing contract on the + // InvokeContractDelegate method. + // + // The code below "reconstructs" that delegate call by: + // + // 1. Remembering the last contract on which we called GetBytecode. + // 2. Treating the contract invoked in step 1 as the DELEGATECALL receiver. + // + // Note, however: GetBytecode will be called, e.g., if the user invokes the + // EXTCODECOPY instruction. It's not an error to see multiple GetBytecode calls + // before we see an InvokeContractDelegate. + switch et.Msg.Method { + case builtin.MethodsEVM.GetBytecode: + // NOTE: I'm not checking anything about the receiver here. The EVM won't + // DELEGATECALL any non-EVM actor, but there's no need to encode that fact + // here in case we decide to loosen this up in the future. + if et.MsgRct.ExitCode.IsSuccess() { + env.lastByteCode = &to + } else { + env.lastByteCode = nil } - // We drop all other "private" calls from FEVM. We _forbid_ explicit calls between 0 and 1024 (exclusive), so any calls in this range must be implementation details. return nil, nil, nil - } + case builtin.MethodsEVM.InvokeContractDelegate: + // NOTE: We return errors in all the failure cases below instead of trying + // to continue because the caller is an EVM actor. If something goes wrong + // here, there's a bug in our EVM implementation. - return trace, et, nil + // Handle delegate calls + // + // 1) Look for trace from an EVM actor to itself on InvokeContractDelegate, + // method 6. + // 2) Check that the previous trace calls another actor on method 3 + // (GetByteCode) and they are at the same level (same parent) + // 3) Treat this as a delegate call to actor A. + if env.lastByteCode == nil { + return nil, nil, xerrors.Errorf("unknown bytecode for delegate call") + } + if env.caller != to { + return nil, nil, xerrors.Errorf("delegate-call not from & to self: %s != %s", env.caller, to) + } + + trace.SetCallType("delegatecall") + trace.Action.To = env.lastByteCode + + dp, err := decodeParams[evm.DelegateCallParams](&et.Msg) + if err != nil { + return nil, nil, xerrors.Errorf("failed to decode delegate-call params: %w", err) + } + trace.Action.Input = dp.Input + + trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + if err != nil { + return nil, nil, xerrors.Errorf("failed to decode delegate-call return: %w", err) + } + + return trace, et, nil + } + // We drop all other "private" calls from FEVM. We _forbid_ explicit calls between 0 and + // 1024 (exclusive), so any calls in this range must be implementation details. + return nil, nil, nil } From cf910a8d1a25d46267412b3e5f7a569ef16b592d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 12 Feb 2024 18:04:46 -0800 Subject: [PATCH 4/6] fix: eth: use correct types for trace_block action/results - The top-level type is call/create. - The action/result is specific to the operation. --- build/openrpc/full.json | 154 +------- build/openrpc/full.json.gz | Bin 34723 -> 34654 bytes build/openrpc/gateway.json | 154 +------- build/openrpc/gateway.json.gz | Bin 11942 -> 11862 bytes chain/actors/builtin/evm/actor.go.template | 13 + chain/actors/builtin/evm/evm.go | 12 + chain/types/ethtypes/eth_types.go | 46 ++- documentation/en/api-v1-unstable-methods.md | 36 +- node/impl/full/eth.go | 7 +- node/impl/full/eth_trace.go | 385 +++++++++++++------- 10 files changed, 342 insertions(+), 465 deletions(-) diff --git a/build/openrpc/full.json b/build/openrpc/full.json index 587212849f1..d0601deb795 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -8386,24 +8386,14 @@ "examples": [ [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value", + "action": {}, + "result": {}, "blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "blockNumber": 9, "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -8416,48 +8406,7 @@ "additionalProperties": false, "properties": { "action": { - "additionalProperties": false, - "properties": { - "callType": { - "type": "string" - }, - "from": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "gas": { - "title": "number", - "type": "number" - }, - "input": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - }, - "to": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "value": { - "additionalProperties": false, - "type": "object" - } - }, + "additionalProperties": true, "type": "object" }, "blockHash": { @@ -8478,21 +8427,7 @@ "type": "string" }, "result": { - "additionalProperties": false, - "properties": { - "gasUsed": { - "title": "number", - "type": "number" - }, - "output": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - } - }, + "additionalProperties": true, "type": "object" }, "subtraces": { @@ -8601,24 +8536,14 @@ "stateDiff": "string value", "trace": [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value" + "action": {}, + "result": {} } ], "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -8646,69 +8571,14 @@ "additionalProperties": false, "properties": { "action": { - "additionalProperties": false, - "properties": { - "callType": { - "type": "string" - }, - "from": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "gas": { - "title": "number", - "type": "number" - }, - "input": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - }, - "to": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "value": { - "additionalProperties": false, - "type": "object" - } - }, + "additionalProperties": true, "type": "object" }, "error": { "type": "string" }, "result": { - "additionalProperties": false, - "properties": { - "gasUsed": { - "title": "number", - "type": "number" - }, - "output": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - } - }, + "additionalProperties": true, "type": "object" }, "subtraces": { diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index a716b92330ca5fd46db0f448d18223892d01e12a..09793ae3323bbc5d6740bb52e230c346936074de 100644 GIT binary patch delta 11608 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 W`}c3(|9=1g0RR6g57qP<^9BH`V2`B$ delta 11633 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 diff --git a/build/openrpc/gateway.json b/build/openrpc/gateway.json index 6baa34443c7..269566dd94a 100644 --- a/build/openrpc/gateway.json +++ b/build/openrpc/gateway.json @@ -4439,24 +4439,14 @@ "examples": [ [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value", + "action": {}, + "result": {}, "blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "blockNumber": 9, "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -4469,48 +4459,7 @@ "additionalProperties": false, "properties": { "action": { - "additionalProperties": false, - "properties": { - "callType": { - "type": "string" - }, - "from": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "gas": { - "title": "number", - "type": "number" - }, - "input": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - }, - "to": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "value": { - "additionalProperties": false, - "type": "object" - } - }, + "additionalProperties": true, "type": "object" }, "blockHash": { @@ -4531,21 +4480,7 @@ "type": "string" }, "result": { - "additionalProperties": false, - "properties": { - "gasUsed": { - "title": "number", - "type": "number" - }, - "output": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - } - }, + "additionalProperties": true, "type": "object" }, "subtraces": { @@ -4654,24 +4589,14 @@ "stateDiff": "string value", "trace": [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value" + "action": {}, + "result": {} } ], "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -4699,69 +4624,14 @@ "additionalProperties": false, "properties": { "action": { - "additionalProperties": false, - "properties": { - "callType": { - "type": "string" - }, - "from": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "gas": { - "title": "number", - "type": "number" - }, - "input": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - }, - "to": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "maxItems": 20, - "minItems": 20, - "type": "array" - }, - "value": { - "additionalProperties": false, - "type": "object" - } - }, + "additionalProperties": true, "type": "object" }, "error": { "type": "string" }, "result": { - "additionalProperties": false, - "properties": { - "gasUsed": { - "title": "number", - "type": "number" - }, - "output": { - "items": { - "description": "Number is a number", - "title": "number", - "type": "number" - }, - "type": "array" - } - }, + "additionalProperties": true, "type": "object" }, "subtraces": { diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index be508c8fe76dba3592fbfd9cab208940b5792c54..bc012704306a49b7ceaa35f33cc4559eaca6a432 100644 GIT binary patch delta 3409 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ƻ-Rx8@z!`lpDZtU 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 diff --git a/chain/actors/builtin/evm/actor.go.template b/chain/actors/builtin/evm/actor.go.template index 62da0686796..2090c7bc926 100644 --- a/chain/actors/builtin/evm/actor.go.template +++ b/chain/actors/builtin/evm/actor.go.template @@ -10,6 +10,8 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/manifest" builtin{{.latestVersion}} "github.com/filecoin-project/go-state-types/builtin" @@ -17,6 +19,17 @@ import ( var Methods = builtin{{.latestVersion}}.MethodsEVM +const ( + ErrReverted exitcode.ExitCode = iota + 33 + ErrInvalidInstruction + ErrUndefinedInstruction + ErrStackUnderflow + ErrStackOverflow + ErrIllegalMemoryAccess + ErrBadJumpdest + ErrSelfdestructFailed +) + func Load(store adt.Store, act *types.Actor) (State, error) { if name, av, ok := actors.GetActorMetaByCode(act.Code); ok { if name != manifest.EvmKey { diff --git a/chain/actors/builtin/evm/evm.go b/chain/actors/builtin/evm/evm.go index 98f860cac4a..e81e7cb4c9e 100644 --- a/chain/actors/builtin/evm/evm.go +++ b/chain/actors/builtin/evm/evm.go @@ -7,6 +7,7 @@ import ( actorstypes "github.com/filecoin-project/go-state-types/actors" builtin12 "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/cbor" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/manifest" "github.com/filecoin-project/lotus/chain/actors" @@ -16,6 +17,17 @@ import ( var Methods = builtin12.MethodsEVM +const ( + ErrReverted exitcode.ExitCode = iota + 33 + ErrInvalidInstruction + ErrUndefinedInstruction + ErrStackUnderflow + ErrStackOverflow + ErrIllegalMemoryAccess + ErrBadJumpdest + ErrSelfdestructFailed +) + func Load(store adt.Store, act *types.Actor) (State, error) { if name, av, ok := actors.GetActorMetaByCode(act.Code); ok { if name != manifest.EvmKey { diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index a7341aac40f..acc0d5c9454 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -987,17 +987,12 @@ func (e *EthBlockNumberOrHash) UnmarshalJSON(b []byte) error { } type EthTrace struct { - Action EthTraceAction `json:"action"` - Result EthTraceResult `json:"result"` - Subtraces int `json:"subtraces"` - TraceAddress []int `json:"traceAddress"` - Type string `json:"type"` - Error string `json:"error,omitempty"` -} - -func (t *EthTrace) SetCallType(callType string) { - t.Action.CallType = callType - t.Type = callType + Type string `json:"type"` + Error string `json:"error,omitempty"` + Subtraces int `json:"subtraces"` + TraceAddress []int `json:"traceAddress"` + Action any `json:"action"` + Result any `json:"result"` } type EthTraceBlock struct { @@ -1016,16 +1011,29 @@ type EthTraceReplayBlockTransaction struct { VmTrace *string `json:"vmTrace"` } -type EthTraceAction struct { - CallType string `json:"callType"` - From EthAddress `json:"from"` - To *EthAddress `json:"to"` - Gas EthUint64 `json:"gas"` - Input EthBytes `json:"input"` - Value EthBigInt `json:"value"` +type EthCallTraceAction struct { + CallType string `json:"callType"` + From EthAddress `json:"from"` + To EthAddress `json:"to"` + Gas EthUint64 `json:"gas"` + Value EthBigInt `json:"value"` + Input EthBytes `json:"input"` } -type EthTraceResult struct { +type EthCallTraceResult struct { GasUsed EthUint64 `json:"gasUsed"` Output EthBytes `json:"output"` } + +type EthCreateTraceAction struct { + From EthAddress `json:"from"` + Gas EthUint64 `json:"gas"` + Value EthBigInt `json:"value"` + Init EthBytes `json:"init"` +} + +type EthCreateTraceResult struct { + Address *EthAddress `json:"address,omitempty"` + GasUsed EthUint64 `json:"gasUsed"` + Code EthBytes `json:"code"` +} diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 6c128010c3e..d58a10c8b59 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -3094,24 +3094,14 @@ Response: ```json [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value", + "action": {}, + "result": {}, "blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "blockNumber": 9, "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", @@ -3144,24 +3134,14 @@ Response: "stateDiff": "string value", "trace": [ { - "action": { - "callType": "string value", - "from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", - "gas": "0x5", - "input": "0x07", - "value": "0x0" - }, - "result": { - "gasUsed": "0x5", - "output": "0x07" - }, + "type": "string value", + "error": "string value", "subtraces": 123, "traceAddress": [ 123 ], - "type": "string value", - "error": "string value" + "action": {}, + "result": {} } ], "transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 92f3fe81336..5c3ab316562 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -948,7 +948,12 @@ func (a *EthModule) EthTraceReplayBlockTransactions(ctx context.Context, blkNum var output []byte if len(env.traces) > 0 { - output = env.traces[0].Result.Output + switch r := env.traces[0].Result.(type) { + case *ethtypes.EthCallTraceResult: + output = r.Output + case *ethtypes.EthCreateTraceResult: + output = r.Code + } } allTraces = append(allTraces, ðtypes.EthTraceReplayBlockTransaction{ diff --git a/node/impl/full/eth_trace.go b/node/impl/full/eth_trace.go index 352d7427866..e4e5d794d0e 100644 --- a/node/impl/full/eth_trace.go +++ b/node/impl/full/eth_trace.go @@ -2,18 +2,22 @@ package full import ( "bytes" + "fmt" "github.com/multiformats/go-multicodec" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin" - "github.com/filecoin-project/go-state-types/builtin/v12/eam" - "github.com/filecoin-project/go-state-types/builtin/v12/evm" + eam12 "github.com/filecoin-project/go-state-types/builtin/v12/eam" + evm12 "github.com/filecoin-project/go-state-types/builtin/v12/evm" + init12 "github.com/filecoin-project/go-state-types/builtin/v12/init" "github.com/filecoin-project/go-state-types/exitcode" builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/evm" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" @@ -55,6 +59,24 @@ func decodeParams[P any, T interface { return params, nil } +func decodeReturn[R any, T interface { + *R + cbg.CBORUnmarshaler +}](ret *types.ReturnTrace) (T, error) { + var retval T = new(R) + switch ret.ReturnCodec { + case uint64(multicodec.DagCbor), uint64(multicodec.Cbor): + default: + return nil, xerrors.Errorf("Method returned an unexpected codec %d", ret.ReturnCodec) + } + + if err := retval.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil { + return nil, xerrors.Errorf("failed to decode return value: %w", err) + } + + return retval, nil +} + func find[T any](values []T, cb func(t *T) *T) *T { for i := range values { if o := cb(&values[i]); o != nil { @@ -89,6 +111,57 @@ func traceToAddress(act *types.ActorTrace) ethtypes.EthAddress { return ethtypes.EthAddressFromActorID(act.Id) } +// traceIsEVMOrEAM returns true if the trace is a call to an EVM or EAM actor. +func traceIsEVMOrEAM(et *types.ExecutionTrace) bool { + if et.InvokedActor == nil { + return false + } + return builtinactors.IsEvmActor(et.InvokedActor.State.Code) || + et.InvokedActor.Id != abi.ActorID(builtin.EthereumAddressManagerActorID) +} + +func traceErrMsg(et *types.ExecutionTrace) string { + code := et.MsgRct.ExitCode + + if code.IsSuccess() { + return "" + } + + // EVM tools often expect this literal string. + if code == exitcode.SysErrOutOfGas { + return "out of gas" + } + + // indicate when we have a "system" error. + if code < exitcode.FirstActorErrorCode { + return fmt.Sprintf("vm error: %s", code) + } + + // handle special exit codes from the EVM/EAM. + if traceIsEVMOrEAM(et) { + switch code { + case evm.ErrReverted: + return "Reverted" // capitalized for compatibility + case evm.ErrInvalidInstruction: + return "invalid instruction" + case evm.ErrUndefinedInstruction: + return "undefined instruction" + case evm.ErrStackUnderflow: + return "stack underflow" + case evm.ErrStackOverflow: + return "stack overflow" + case evm.ErrIllegalMemoryAccess: + return "illegal memory access" + case evm.ErrBadJumpdest: + return "invalid jump destination" + case evm.ErrSelfdestructFailed: + return "self destruct failed" + } + } + // everything else... + return fmt.Sprintf("actor error: %s", code.Error()) +} + // buildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls func buildTraces(env *environment, addr []int, et *types.ExecutionTrace) error { trace, recurseInto, err := buildTrace(env, addr, et) @@ -126,31 +199,6 @@ func buildTraces(env *environment, addr []int, et *types.ExecutionTrace) error { return nil } -func decodeCreate(msg *types.MessageTrace) (callType string, initcode []byte, err error) { - switch msg.Method { - case builtin.MethodsEAM.Create: - params, err := decodeParams[eam.CreateParams](msg) - if err != nil { - return "", nil, err - } - return "create", params.Initcode, nil - case builtin.MethodsEAM.Create2: - params, err := decodeParams[eam.Create2Params](msg) - if err != nil { - return "", nil, err - } - return "create2", params.Initcode, nil - case builtin.MethodsEAM.CreateExternal: - input, err := decodePayload(msg.Params, msg.ParamsCodec) - if err != nil { - return "", nil, err - } - return "create", input, nil - default: - return "", nil, xerrors.Errorf("unexpected CREATE method %d", msg.Method) - } -} - // buildTrace processes the passed execution trace and updates the environment, if necessary. // // On success, it returns a trace to add (or nil to skip) and the trace recurse into (or nil to skip). @@ -187,43 +235,13 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp return nil, nil, nil } - // Step 1: Decode as a native call - to := traceToAddress(et.InvokedActor) - var errMsg string - if et.MsgRct.ExitCode.IsError() { - errMsg = et.MsgRct.ExitCode.Error() - } - trace := ðtypes.EthTrace{ - Action: ethtypes.EthTraceAction{ - From: env.caller, - To: &to, - Gas: ethtypes.EthUint64(et.Msg.GasLimit), - Value: ethtypes.EthBigInt(et.Msg.Value), - Input: encodeFilecoinParamsAsABI(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params), - }, - Result: ethtypes.EthTraceResult{ - GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), - Output: encodeFilecoinReturnAsABI(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return), - }, - TraceAddress: addr, - Error: errMsg, - } - - // Set the assumed call mode. We'll override this if the call ends up looking like a create, - // delegatecall, etc. - if et.Msg.ReadOnly { - trace.SetCallType("staticcall") - } else { - trace.SetCallType("call") - } - // Step 2: Decode as a contract invocation // // Normal EVM calls. We don't care if the caller/receiver are actually EVM actors, we only // care if the call _looks_ like an EVM call. If we fail to decode it as an EVM call, we // fallback on interpreting it as a native call. if et.Msg.Method == builtin.MethodsEVM.InvokeContract { - return traceInvokeEVM(env, et, trace) + return traceEVMCall(env, addr, et) } // Step 3: Decode as a contract deployment @@ -233,12 +251,12 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp case builtin.InitActorAddr: switch et.Msg.Method { case builtin.MethodsInit.Exec, builtin.MethodsInit.Exec4: - return traceNativeCreate(env, et, trace) + return traceNativeCreate(env, addr, et) } case builtin.EthereumAddressManagerActorAddr: switch et.Msg.Method { case builtin.MethodsEAM.Create, builtin.MethodsEAM.Create2, builtin.MethodsEAM.CreateExternal: - return traceEthCreate(env, et, trace) + return traceEthCreate(env, addr, et) } } @@ -252,29 +270,65 @@ func buildTrace(env *environment, addr []int, et *types.ExecutionTrace) (*ethtyp // respect to the EAM), we only care about the ones relevant DELEGATECALL and can _ignore_ // all the others. if env.isEVM && et.Msg.Method > 0 && et.Msg.Method < 1024 { - return traceEVMPrivate(env, et, trace, to) + return traceEVMPrivate(env, addr, et) } - return trace, et, nil + return traceNativeCall(env, addr, et), et, nil } -func traceInvokeEVM(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { +// Build an EthTrace for a "call" with the given input & output. +func traceCall(env *environment, addr []int, et *types.ExecutionTrace, input, output ethtypes.EthBytes) *ethtypes.EthTrace { + to := traceToAddress(et.InvokedActor) + callType := "call" + if et.Msg.ReadOnly { + callType = "staticcall" + } + return ðtypes.EthTrace{ + Type: "call", + Action: ðtypes.EthCallTraceAction{ + CallType: callType, + From: env.caller, + To: to, + Gas: ethtypes.EthUint64(et.Msg.GasLimit), + Value: ethtypes.EthBigInt(et.Msg.Value), + Input: input, + }, + Result: ðtypes.EthCallTraceResult{ + GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), + Output: output, + }, + TraceAddress: addr, + Error: traceErrMsg(et), + } +} + +// Build an EthTrace for a "call", parsing the inputs & outputs as a "native" FVM call. +func traceNativeCall(env *environment, addr []int, et *types.ExecutionTrace) *ethtypes.EthTrace { + return traceCall(env, addr, et, + encodeFilecoinParamsAsABI(et.Msg.Method, et.Msg.ParamsCodec, et.Msg.Params), + encodeFilecoinReturnAsABI(et.MsgRct.ExitCode, et.MsgRct.ReturnCodec, et.MsgRct.Return), + ) +} + +// Build an EthTrace for a "call", parsing the inputs & outputs as an EVM call (falling back on +// treating it as a native call). +func traceEVMCall(env *environment, addr []int, et *types.ExecutionTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { input, err := decodePayload(et.Msg.Params, et.Msg.ParamsCodec) if err != nil { log.Debugf("failed to decode contract invocation payload: %w", err) - return trace, et, nil + return traceNativeCall(env, addr, et), et, nil } output, err := decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) if err != nil { log.Debugf("failed to decode contract invocation return: %w", err) - return trace, et, nil + return traceNativeCall(env, addr, et), et, nil } - trace.Action.Input = input - trace.Result.Output = output - return trace, et, nil + return traceCall(env, addr, et, input, output), et, nil } -func traceNativeCreate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { +// Build an EthTrace for a native "create" operation. This should only be called with an +// ExecutionTrace is an Exec or Exec4 method invocation on the Init actor. +func traceNativeCreate(env *environment, addr []int, et *types.ExecutionTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { if et.Msg.ReadOnly { // "create" isn't valid in a staticcall, so we just skip this trace // (couldn't have created an actor anyways). @@ -316,39 +370,90 @@ func traceNativeCreate(env *environment, et *types.ExecutionTrace, trace *ethtyp return nil, nil, xerrors.Errorf("direct call to Exec4 successfully called a constructor!") } - // Contract creation has no "to". - trace.Action.To = nil - // If we get here, this isn't a native EVM create. Those always go through - // the EAM. So we have no "real" initcode and must use the sentinel value - // for "invalid" initcode. - trace.Action.Input = []byte{0xFE} - trace.SetCallType("create") - // Handle the output. - if et.MsgRct.ExitCode.IsError() { - // If the sub-call fails, record the reason. It's possible for the - // call to the init actor to fail, but for the construction to - // succeed, so we need to check the exit code here. - if subTrace.MsgRct.ExitCode.IsError() { - trace.Result.Output = encodeFilecoinReturnAsABI( - subTrace.MsgRct.ExitCode, - subTrace.MsgRct.ReturnCodec, - subTrace.MsgRct.Return, - ) - } else { - // Otherwise, output nothing. - trace.Result.Output = nil - } - } else { + var output ethtypes.EthBytes + var createdAddr *ethtypes.EthAddress + if et.MsgRct.ExitCode.IsSuccess() { // We're supposed to put the "installed bytecode" here. But this // isn't an EVM actor, so we just put some invalid bytecode (this is // the answer you'd get if you called EXTCODECOPY on a native // non-account actor, anyways). - trace.Result.Output = []byte{0xFE} + output = []byte{0xFE} + + // Extract the address of the created actor from the return value. + initReturn, err := decodeReturn[init12.ExecReturn](&et.MsgRct) + if err != nil { + return nil, nil, xerrors.Errorf("failed to decode init params after a successful Init.Exec call: %w", err) + } + actorId, err := address.IDFromAddress(initReturn.IDAddress) + if err != nil { + return nil, nil, xerrors.Errorf("failed to extract created actor ID from address: %w", err) + } + ethAddr := ethtypes.EthAddressFromActorID(abi.ActorID(actorId)) + createdAddr = ðAddr + } + + return ðtypes.EthTrace{ + Type: "create", + Action: ðtypes.EthCreateTraceAction{ + From: env.caller, + Gas: ethtypes.EthUint64(et.Msg.GasLimit), + Value: ethtypes.EthBigInt(et.Msg.Value), + // If we get here, this isn't a native EVM create. Those always go through + // the EAM. So we have no "real" initcode and must use the sentinel value + // for "invalid" initcode. + Init: []byte{0xFE}, + }, + Result: ðtypes.EthCreateTraceResult{ + GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), + Address: createdAddr, + Code: output, + }, + TraceAddress: addr, + Error: traceErrMsg(et), + }, subTrace, nil +} + +// Assert that these are all identical so we can simplify the below code and decode once. +var _ *eam12.Return = (*eam12.Return)((*eam12.CreateReturn)(nil)) +var _ *eam12.Return = (*eam12.Return)((*eam12.Create2Return)(nil)) +var _ *eam12.Return = (*eam12.Return)((*eam12.CreateExternalReturn)(nil)) + +// Decode the parameters and return value of an EVM smart contract creation through the EAM. This +// should only be called with an ExecutionTrace for a Create, Create2, or CreateExternal method +// invocation on the EAM. +func decodeCreateViaEAM(et *types.ExecutionTrace) (initcode []byte, addr *ethtypes.EthAddress, err error) { + switch et.Msg.Method { + case builtin.MethodsEAM.Create: + params, err := decodeParams[eam12.CreateParams](&et.Msg) + if err != nil { + return nil, nil, err + } + initcode = params.Initcode + case builtin.MethodsEAM.Create2: + params, err := decodeParams[eam12.Create2Params](&et.Msg) + if err != nil { + return nil, nil, err + } + initcode = params.Initcode + case builtin.MethodsEAM.CreateExternal: + input, err := decodePayload(et.Msg.Params, et.Msg.ParamsCodec) + if err != nil { + return nil, nil, err + } + initcode = input + default: + return nil, nil, xerrors.Errorf("unexpected CREATE method %d", et.Msg.Method) + } + ret, err := decodeReturn[eam12.CreateReturn](&et.MsgRct) + if err != nil { + return nil, (*ethtypes.EthAddress)(&ret.EthAddress), err } - return trace, subTrace, nil + return initcode, (*ethtypes.EthAddress)(&ret.EthAddress), nil } -func traceEthCreate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { +// Build an EthTrace for an EVM "create" operation. This should only be called with an +// ExecutionTrace for a Create, Create2, or CreateExternal method invocation on the EAM. +func traceEthCreate(env *environment, addr []int, et *types.ExecutionTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { // Same as the Init actor case above, see the comment there. if et.Msg.ReadOnly { return nil, nil, nil @@ -378,48 +483,48 @@ func traceEthCreate(env *environment, et *types.ExecutionTrace, trace *ethtypes. return nil, nil, nil } - // Contract creation has no "to". - trace.Action.To = nil - // Decode inputs & determine create type. - method, initcode, err := decodeCreate(&et.Msg) + initcode, createdAddr, err := decodeCreateViaEAM(et) if err != nil { - return nil, nil, xerrors.Errorf("EAM called with invalid params, but it still tried to construct the contract: %w", err) + return nil, nil, xerrors.Errorf("EAM called with invalid params or returned an invalid result, but it still tried to construct the contract: %w", err) } - trace.Action.Input = initcode - trace.SetCallType(method) + var output ethtypes.EthBytes // Handle the output. - if et.MsgRct.ExitCode.IsError() { - if subTrace.MsgRct.ExitCode.IsError() { - // If we managed to call the constructor, parse/return its - // revert message. - output, err := decodePayload(subTrace.MsgRct.Return, subTrace.MsgRct.ReturnCodec) - if err != nil { - log.Debugf("EVM actor returned indecipherable create error: %w", err) - output = encodeFilecoinReturnAsABI( - subTrace.MsgRct.ExitCode, - subTrace.MsgRct.ReturnCodec, - subTrace.MsgRct.Return, - ) - } - trace.Result.Output = output - } else { - // Otherwise, if we failed before that, we have no revert - // message. - trace.Result.Output = nil - } - } else { + switch et.MsgRct.ExitCode { + case 0: // success // We're _supposed_ to include the contracts bytecode here, but we // can't do that reliably (e.g., if some part of the trace reverts). // So we don't try and include a sentinel "impossible bytecode" // value (the value specified by EIP-3541). - trace.Result.Output = []byte{0xFE} + output = []byte{0xFE} + case 33: // Reverted, parse the revert message. + // If we managed to call the constructor, parse/return its revert message. If we + // fail, we just return no output. + output, _ = decodePayload(subTrace.MsgRct.Return, subTrace.MsgRct.ReturnCodec) } - return trace, subTrace, nil + + return ðtypes.EthTrace{ + Type: "create", + Action: ðtypes.EthCreateTraceAction{ + From: env.caller, + Gas: ethtypes.EthUint64(et.Msg.GasLimit), + Value: ethtypes.EthBigInt(et.Msg.Value), + Init: initcode, + }, + Result: ðtypes.EthCreateTraceResult{ + GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), + Address: createdAddr, + Code: output, + }, + TraceAddress: addr, + Error: traceErrMsg(et), + }, subTrace, nil } -func traceEVMPrivate(env *environment, et *types.ExecutionTrace, trace *ethtypes.EthTrace, to ethtypes.EthAddress) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { +// Build an EthTrace for a "private" method invocation from the EVM. This should only be called with +// an ExecutionTrace from an EVM instance and on a method between 1 and 1023 inclusive. +func traceEVMPrivate(env *environment, addr []int, et *types.ExecutionTrace) (*ethtypes.EthTrace, *types.ExecutionTrace, error) { // The EVM actor implements DELEGATECALL by: // // 1. Asking the callee for its bytecode by calling it on the GetBytecode method. @@ -440,6 +545,7 @@ func traceEVMPrivate(env *environment, et *types.ExecutionTrace, trace *ethtypes // DELEGATECALL any non-EVM actor, but there's no need to encode that fact // here in case we decide to loosen this up in the future. if et.MsgRct.ExitCode.IsSuccess() { + to := traceToAddress(et.InvokedActor) env.lastByteCode = &to } else { env.lastByteCode = nil @@ -460,25 +566,38 @@ func traceEVMPrivate(env *environment, et *types.ExecutionTrace, trace *ethtypes if env.lastByteCode == nil { return nil, nil, xerrors.Errorf("unknown bytecode for delegate call") } - if env.caller != to { + + if to := traceToAddress(et.InvokedActor); env.caller != to { return nil, nil, xerrors.Errorf("delegate-call not from & to self: %s != %s", env.caller, to) } - trace.SetCallType("delegatecall") - trace.Action.To = env.lastByteCode - - dp, err := decodeParams[evm.DelegateCallParams](&et.Msg) + dp, err := decodeParams[evm12.DelegateCallParams](&et.Msg) if err != nil { return nil, nil, xerrors.Errorf("failed to decode delegate-call params: %w", err) } - trace.Action.Input = dp.Input - trace.Result.Output, err = decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) + output, err := decodePayload(et.MsgRct.Return, et.MsgRct.ReturnCodec) if err != nil { return nil, nil, xerrors.Errorf("failed to decode delegate-call return: %w", err) } - return trace, et, nil + return ðtypes.EthTrace{ + Type: "call", + Action: ðtypes.EthCallTraceAction{ + CallType: "delegatecall", + From: env.caller, + To: *env.lastByteCode, + Gas: ethtypes.EthUint64(et.Msg.GasLimit), + Value: ethtypes.EthBigInt(et.Msg.Value), + Input: dp.Input, + }, + Result: ðtypes.EthCallTraceResult{ + GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas), + Output: output, + }, + TraceAddress: addr, + Error: traceErrMsg(et), + }, et, nil } // We drop all other "private" calls from FEVM. We _forbid_ explicit calls between 0 and // 1024 (exclusive), so any calls in this range must be implementation details. From eb8349778d9460dcf0aa9c1752d12353d4630f94 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 20 Feb 2024 08:56:28 -0800 Subject: [PATCH 5/6] document why we start EVM exit codes at 33 --- chain/actors/builtin/evm/actor.go.template | 3 ++- chain/actors/builtin/evm/evm.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/chain/actors/builtin/evm/actor.go.template b/chain/actors/builtin/evm/actor.go.template index 2090c7bc926..a3681979d63 100644 --- a/chain/actors/builtin/evm/actor.go.template +++ b/chain/actors/builtin/evm/actor.go.template @@ -19,8 +19,9 @@ import ( var Methods = builtin{{.latestVersion}}.MethodsEVM +// See https://github.com/filecoin-project/builtin-actors/blob/6e781444cee5965278c46ef4ffe1fb1970f18d7d/actors/evm/src/lib.rs#L35-L42 const ( - ErrReverted exitcode.ExitCode = iota + 33 + ErrReverted exitcode.ExitCode = iota + 33 // EVM exit codes start at 33 ErrInvalidInstruction ErrUndefinedInstruction ErrStackUnderflow diff --git a/chain/actors/builtin/evm/evm.go b/chain/actors/builtin/evm/evm.go index e81e7cb4c9e..774cded8d08 100644 --- a/chain/actors/builtin/evm/evm.go +++ b/chain/actors/builtin/evm/evm.go @@ -17,8 +17,9 @@ import ( var Methods = builtin12.MethodsEVM +// See https://github.com/filecoin-project/builtin-actors/blob/6e781444cee5965278c46ef4ffe1fb1970f18d7d/actors/evm/src/lib.rs#L35-L42 const ( - ErrReverted exitcode.ExitCode = iota + 33 + ErrReverted exitcode.ExitCode = iota + 33 // EVM exit codes start at 33 ErrInvalidInstruction ErrUndefinedInstruction ErrStackUnderflow From 88dba5dff68fdd5ee69fa96812d7e74c8b028642 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 20 Feb 2024 10:31:34 -0800 Subject: [PATCH 6/6] documentation & changelog --- CHANGELOG.md | 17 +++++++++++++++++ api/api_full.go | 19 ++++++++++++++++++- build/openrpc/full.json | 2 +- documentation/en/api-v1-unstable-methods.md | 18 ++++++++++++++++-- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c18f2f6a4a8..21943bc6ae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,23 @@ Replace the `CodeCid` field in the message trace (added in 1.23.4) with an `Invo 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. +### Ethereum Tracing API (`trace_block` and `trace_replayBlockTransactions`) + +For those with the Ethereum JSON-RPC API enabled, the experimental Ethereum Tracing API has been improved significantly and should be considered "functional". However, it's still new and should be tested extensively before relying on it. This API translates FVM traces to Ethereum-style traces, implementing the OpenEthereum `trace_block` and `trace_replayBlockTransactions` APIs. + +This release fixes numerous bugs with this API and now ABI-encodes non-EVM inputs/outputs as if they were explicit EVM calls to [`handle_filecoin_method`][handlefilecoinmethod] for better block explorer compatibility. + +However, there are some _significant_ limitations: + +1. The Geth APIs are not implemented, only the OpenEthereum (Erigon, etc.) APIs. +2. Block rewards are not (yet) included in the trace. +3. Selfdestruct operations are not included in the trace. +4. EVM smart contract "create" events always specify `0xfe` as the "code" for newly created EVM smart contracts. + +Additionally, Filecoin is not Ethereum no matter how much we try to provide API/tooling compatibility. This API attempts to translate Filecoin semantics into Ethereum semantics as accurately as possible, but it's hardly the best source of data unless you _need_ Filecoin to look like an Ethereum compatible chain. If you're trying to build a new integration with Filecoin, please use the native `StateCompute` method instead. + +[handlefilecoinmethod]: https://fips.filecoin.io/FIPS/fip-0054.html#handlefilecoinmethod-general-handler-for-method-numbers--1024 + # 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/api_full.go b/api/api_full.go index 3dc7f8bb2dd..a9adb1c4bd6 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -868,9 +868,26 @@ type FullNode interface { Web3ClientVersion(ctx context.Context) (string, error) //perm:read // TraceAPI related methods + + // Returns an OpenEthereum-compatible trace of the given block (implementing `trace_block`), + // translating Filecoin semantics into Ethereum semantics and tracing both EVM and FVM calls. + // + // Features: + // + // - FVM actor create events, calls, etc. show up as if they were EVM smart contract events. + // - Native FVM call inputs are ABI-encoded (Solidity ABI) as if they were calls to a + // `handle_filecoin_method(uint64 method, uint64 codec, bytes params)` function + // (where `codec` is the IPLD codec of `params`). + // - Native FVM call outputs (return values) are ABI-encoded as `(uint32 exit_code, uint64 + // codec, bytes output)` where `codec` is the IPLD codec of `output`. // - // Returns traces created at given block + // Limitations (for now): + // + // 1. Block rewards are not included in the trace. + // 2. SELFDESTRUCT operations are not included in the trace. + // 3. EVM smart contract "create" events always specify `0xfe` as the "code" for newly created EVM smart contracts. EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) //perm:read + // Replays all transactions in a block returning the requested traces for each transaction EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) //perm:read diff --git a/build/openrpc/full.json b/build/openrpc/full.json index d0601deb795..54d241a48ab 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -8359,7 +8359,7 @@ { "name": "Filecoin.EthTraceBlock", "description": "```go\nfunc (s *FullNodeStruct) EthTraceBlock(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) {\n\tif s.Internal.EthTraceBlock == nil {\n\t\treturn *new([]*ethtypes.EthTraceBlock), ErrNotSupported\n\t}\n\treturn s.Internal.EthTraceBlock(p0, p1)\n}\n```", - "summary": "TraceAPI related methods\n\nReturns traces created at given block\n", + "summary": "Returns an OpenEthereum-compatible trace of the given block (implementing `trace_block`),\ntranslating Filecoin semantics into Ethereum semantics and tracing both EVM and FVM calls.\n\nFeatures:\n\n- FVM actor create events, calls, etc. show up as if they were EVM smart contract events.\n- Native FVM call inputs are ABI-encoded (Solidity ABI) as if they were calls to a\n `handle_filecoin_method(uint64 method, uint64 codec, bytes params)` function\n (where `codec` is the IPLD codec of `params`).\n- Native FVM call outputs (return values) are ABI-encoded as `(uint32 exit_code, uint64\n codec, bytes output)` where `codec` is the IPLD codec of `output`.\n\nLimitations (for now):\n\n1. Block rewards are not included in the trace.\n2. SELFDESTRUCT operations are not included in the trace.\n3. EVM smart contract \"create\" events always specify `0xfe` as the \"code\" for newly created EVM smart contracts.\n", "paramStructure": "by-position", "params": [ { diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index d58a10c8b59..c65c102d39b 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -3076,9 +3076,23 @@ Inputs: `null` Response: `false` ### EthTraceBlock -TraceAPI related methods +Returns an OpenEthereum-compatible trace of the given block (implementing `trace_block`), +translating Filecoin semantics into Ethereum semantics and tracing both EVM and FVM calls. -Returns traces created at given block +Features: + +- FVM actor create events, calls, etc. show up as if they were EVM smart contract events. +- Native FVM call inputs are ABI-encoded (Solidity ABI) as if they were calls to a + `handle_filecoin_method(uint64 method, uint64 codec, bytes params)` function + (where `codec` is the IPLD codec of `params`). +- Native FVM call outputs (return values) are ABI-encoded as `(uint32 exit_code, uint64 + codec, bytes output)` where `codec` is the IPLD codec of `output`. + +Limitations (for now): + +1. Block rewards are not included in the trace. +2. SELFDESTRUCT operations are not included in the trace. +3. EVM smart contract "create" events always specify `0xfe` as the "code" for newly created EVM smart contracts. Perms: read