diff --git a/core/state_processor.go b/core/state_processor.go index d306d68cf9..d2f1505403 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -112,7 +112,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { var receipt *types.Receipt if evm.Config.Tracer != nil { - evm.Config.Tracer.CaptureTxStart(tx) + evm.Config.Tracer.CaptureTxStart(evm, tx) defer func() { evm.Config.Tracer.CaptureTxEnd(receipt) }() diff --git a/core/vm/evm.go b/core/vm/evm.go index 30cfd2b9a8..26ad3b444e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -192,7 +192,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // Calling a non existing account, don't do anything, but ping the tracer if debug { if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) evm.Config.Tracer.CaptureEnd(ret, 0, nil) } else { evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) @@ -208,7 +208,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // Capture the tracer start/end events in debug mode if debug { if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) defer func(startGas uint64) { // Lazy evaluation of the parameters evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err) }(gas) @@ -456,7 +456,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if evm.Config.Tracer != nil { if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) + evm.Config.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) } else { evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) } diff --git a/core/vm/logger.go b/core/vm/logger.go index 4f67b87d15..b7b0fc4d8e 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -30,10 +30,10 @@ import ( // if you need to retain them beyond the current call. type EVMLogger interface { // Transaction level - CaptureTxStart(tx *types.Transaction) + CaptureTxStart(evm *EVM, tx *types.Transaction) CaptureTxEnd(receipt *types.Receipt) // Top call frame - CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) + CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) CaptureEnd(output []byte, gasUsed uint64, err error) // Rest of call frames CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 479ca58de6..7df7e7526a 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -790,7 +790,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - vmConf.Tracer.CaptureTxStart(tx) + vmConf.Tracer.CaptureTxStart(vmenv, tx) vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)) vmConf.Tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}) if writer != nil { @@ -973,7 +973,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor // Call Prepare to clear out the statedb access list statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - tracer.CaptureTxStart(tx) + tracer.CaptureTxStart(vmenv, tx) res, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit)) if err != nil { return nil, fmt.Errorf("tracing failed: %w", err) diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 8dbcacb3bc..dd33469edf 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -151,7 +151,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - tracer.CaptureTxStart(tx) + tracer.CaptureTxStart(evm, tx) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) if err != nil { t.Fatalf("failed to execute transaction: %v", err) @@ -266,17 +266,13 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { func TestInternals(t *testing.T) { var ( - config = params.AllEthashProtocolChanges + config = params.MainnetChainConfig to = common.HexToAddress("0x00000000000000000000000000000000deadbeef") originHex = "0x71562b71999873db5b286df957af199ec94617f7" origin = common.HexToAddress(originHex) signer = types.LatestSigner(config) key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - txContext = vm.TxContext{ - Origin: origin, - GasPrice: big.NewInt(1), - } - context = vm.BlockContext{ + context = vm.BlockContext{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, Coinbase: common.Address{}, @@ -284,6 +280,7 @@ func TestInternals(t *testing.T) { Time: 5, Difficulty: big.NewInt(0x30000), GasLimit: uint64(6000000), + BaseFee: new(big.Int), } ) mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer { @@ -349,7 +346,7 @@ func TestInternals(t *testing.T) { byte(vm.LOG0), }, tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)), - want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52640350"}}`, originHex), + want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex), }, } { _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), @@ -362,21 +359,25 @@ func TestInternals(t *testing.T) { }, }, false) statedb.SetLogger(tc.tracer) - evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer}) tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ To: &to, Value: big.NewInt(0), Gas: 50000, - GasPrice: big.NewInt(0), + GasPrice: new(big.Int), }) if err != nil { t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err) } + txContext := vm.TxContext{ + Origin: origin, + GasPrice: tx.GasPrice(), + } + evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer}) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) if err != nil { t.Fatalf("test %v: failed to create message: %v", tc.name, err) } - tc.tracer.CaptureTxStart(tx) + tc.tracer.CaptureTxStart(evm, tx) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) if err != nil { t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err) diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index 4f191b1487..dac3ef06cf 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -114,7 +114,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) } - tracer.CaptureTxStart(tx) + tracer.CaptureTxStart(evm, tx) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) if err != nil { return fmt.Errorf("failed to execute transaction: %v", err) diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 8f6edd8e80..9366bc418f 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -120,7 +120,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - tracer.CaptureTxStart(tx) + tracer.CaptureTxStart(evm, tx) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) if err != nil { t.Fatalf("failed to execute transaction: %v", err) diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 2d086a8157..e4a06195f8 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -107,7 +107,6 @@ type jsTracer struct { activePrecompiles []common.Address // List of active precompiles at current block traceStep bool // True if tracer object exposes a `step()` method traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods - gasLimit uint64 // Amount of gas bought for the whole tx err error // Any error that should stop tracing obj *goja.Object // Trace object @@ -215,8 +214,17 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracer // CaptureTxStart implements the Tracer interface and is invoked at the beginning of // transaction processing. -func (t *jsTracer) CaptureTxStart(tx *types.Transaction) { - t.gasLimit = tx.Gas() +func (t *jsTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + t.env = env + // Need statedb access for db object + db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} + t.dbValue = db.setupObject() + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = vm.ActivePrecompiles(rules) + t.ctx["block"] = t.vm.ToValue(t.env.Context.BlockNumber.Uint64()) + t.ctx["gasPrice"] = t.vm.ToValue(t.env.TxContext.GasPrice) + t.ctx["gas"] = t.vm.ToValue(tx.Gas()) } // CaptureTxEnd implements the Tracer interface and is invoked at the end of @@ -226,10 +234,7 @@ func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt) { } // CaptureStart implements the Tracer interface to initialize the tracing operation. -func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.env = env - db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} - t.dbValue = db.setupObject() +func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { if create { t.ctx["type"] = t.vm.ToValue("CREATE") } else { @@ -238,18 +243,12 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr t.ctx["from"] = t.vm.ToValue(from.Bytes()) t.ctx["to"] = t.vm.ToValue(to.Bytes()) t.ctx["input"] = t.vm.ToValue(input) - t.ctx["gas"] = t.vm.ToValue(t.gasLimit) - t.ctx["gasPrice"] = t.vm.ToValue(env.TxContext.GasPrice) valueBig, err := t.toBig(t.vm, value.String()) if err != nil { t.err = err return } t.ctx["value"] = valueBig - t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) - // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) - t.activePrecompiles = vm.ActivePrecompiles(rules) } // CaptureState implements the Tracer interface to trace a single step of VM execution. diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 3f98de306d..c5d3ec3299 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -132,7 +132,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi } } -func (a *AccessListTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (a *AccessListTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } // CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist. @@ -172,7 +172,7 @@ func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {} -func (*AccessListTracer) CaptureTxStart(tx *types.Transaction) {} +func (*AccessListTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {} func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt) {} diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index b06e8d0d03..d1d995424e 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -139,8 +139,7 @@ func (l *StructLogger) Reset() { } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - l.env = env +func (l *StructLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } // CaptureState logs a new structured log message and pushes it out to the environment @@ -265,7 +264,9 @@ func (l *StructLogger) Stop(err error) { l.interrupt.Store(true) } -func (l *StructLogger) CaptureTxStart(tx *types.Transaction) {} +func (l *StructLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + l.env = env +} func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt) { l.usedGas = receipt.GasUsed @@ -356,8 +357,7 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger { return l } -func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.env = env +func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { if !create { fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n", from.String(), to.String(), @@ -413,7 +413,7 @@ func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Ad func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} -func (*mdLogger) CaptureTxStart(tx *types.Transaction) {} +func (*mdLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {} func (*mdLogger) CaptureTxEnd(receipt *types.Receipt) {} diff --git a/eth/tracers/logger/logger_json.go b/eth/tracers/logger/logger_json.go index 99620a9f16..845549b63b 100644 --- a/eth/tracers/logger/logger_json.go +++ b/eth/tracers/logger/logger_json.go @@ -43,8 +43,7 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger { return l } -func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - l.env = env +func (l *JSONLogger) CaptureStart(from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) { @@ -103,7 +102,9 @@ func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common. func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} -func (l *JSONLogger) CaptureTxStart(tx *types.Transaction) {} +func (l *JSONLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + l.env = env +} func (l *JSONLogger) CaptureTxEnd(receipt *types.Receipt) {} diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go index 0699ac887d..25152a098e 100644 --- a/eth/tracers/native/4byte.go +++ b/eth/tracers/native/4byte.go @@ -23,6 +23,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers" ) @@ -47,6 +48,7 @@ func init() { // } type fourByteTracer struct { tracers.NoopTracer + env *vm.EVM ids map[string]int // ids aggregates the 4byte ids found interrupt atomic.Bool // Atomic flag to signal execution interruption reason error // Textual reason for the interruption @@ -78,13 +80,16 @@ func (t *fourByteTracer) store(id []byte, size int) { t.ids[key] += 1 } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *fourByteTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + t.env = env // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + rules := t.env.ChainConfig().Rules(t.env.Context.BlockNumber, t.env.Context.Random != nil, t.env.Context.Time) t.activePrecompiles = vm.ActivePrecompiles(rules) +} - // Save the outer calldata also +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *fourByteTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + // Save the outer calldata if len(input) >= 4 { t.store(input[0:4], len(input)-4) } diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index f3a6eca1bb..87a7bbf958 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -128,7 +128,7 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, e } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *callTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { toCopy := to t.callstack[0] = callFrame{ Type: vm.CALL, @@ -196,7 +196,7 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) { t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call) } -func (t *callTracer) CaptureTxStart(tx *types.Transaction) { +func (t *callTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { t.gasLimit = tx.Gas() } diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index 51183cff6f..9e07c25155 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -146,11 +146,8 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.tracer.CaptureStart(env, from, to, create, input, gas, value) - // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) - t.activePrecompiles = vm.ActivePrecompiles(rules) +func (t *flatCallTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.tracer.CaptureStart(from, to, create, input, gas, value) } // CaptureEnd is called after the call finishes to finalize the tracing. @@ -203,8 +200,11 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } } -func (t *flatCallTracer) CaptureTxStart(tx *types.Transaction) { - t.tracer.CaptureTxStart(tx) +func (t *flatCallTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + t.tracer.CaptureTxStart(env, tx) + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = vm.ActivePrecompiles(rules) } func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt) { diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go index 9abbea3152..3d41a1ebeb 100644 --- a/eth/tracers/native/mux.go +++ b/eth/tracers/native/mux.go @@ -60,9 +60,9 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, er } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *muxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *muxTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { for _, t := range t.tracers { - t.CaptureStart(env, from, to, create, input, gas, value) + t.CaptureStart(from, to, create, input, gas, value) } } @@ -116,9 +116,9 @@ func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } } -func (t *muxTracer) CaptureTxStart(tx *types.Transaction) { +func (t *muxTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { for _, t := range t.tracers { - t.CaptureTxStart(tx) + t.CaptureTxStart(env, tx) } } diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index e9ca93b0a4..63536db1a7 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -19,6 +19,7 @@ package native import ( "bytes" "encoding/json" + "fmt" "math/big" "sync/atomic" @@ -61,7 +62,6 @@ type prestateTracer struct { post state create bool to common.Address - gasLimit uint64 // Amount of gas bought for the whole tx config prestateTracerConfig interrupt atomic.Bool // Atomic flag to signal execution interruption reason error // Textual reason for the interruption @@ -90,31 +90,7 @@ func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.env = env - t.create = create - t.to = to - - t.lookupAccount(from) - t.lookupAccount(to) - t.lookupAccount(env.Context.Coinbase) - - // The recipient balance includes the value transferred. - toBal := new(big.Int).Sub(t.pre[to].Balance, value) - t.pre[to].Balance = toBal - - // The sender balance is after reducing: value and gasLimit. - // We need to re-add them to get the pre-tx balance. - fromBal := new(big.Int).Set(t.pre[from].Balance) - gasPrice := env.TxContext.GasPrice - consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit)) - fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas)) - t.pre[from].Balance = fromBal - t.pre[from].Nonce-- - - if create && t.config.DiffMode { - t.created[to] = true - } +func (t *prestateTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } // CaptureEnd is called after the call finishes to finalize the tracing. @@ -175,8 +151,29 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, } } -func (t *prestateTracer) CaptureTxStart(tx *types.Transaction) { - t.gasLimit = tx.Gas() +func (t *prestateTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { + t.env = env + signer := types.MakeSigner(env.ChainConfig(), env.Context.BlockNumber, env.Context.Time) + from, err := types.Sender(signer, tx) + if err != nil { + t.Stop(fmt.Errorf("could not recover sender address: %v", err)) + return + } + if tx.To() == nil { + t.create = true + t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from)) + } else { + t.to = *tx.To() + t.create = false + } + + t.lookupAccount(from) + t.lookupAccount(t.to) + t.lookupAccount(env.Context.Coinbase) + + if t.create && t.config.DiffMode { + t.created[t.to] = true + } } func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt) { diff --git a/eth/tracers/noop.go b/eth/tracers/noop.go index 082717c3fe..e33570d901 100644 --- a/eth/tracers/noop.go +++ b/eth/tracers/noop.go @@ -39,7 +39,7 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (Tracer, error) { } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *NoopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *NoopTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { } // CaptureEnd is called after the call finishes to finalize the tracing. @@ -69,7 +69,7 @@ func (t *NoopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common. func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } -func (*NoopTracer) CaptureTxStart(tx *types.Transaction) {} +func (*NoopTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {} func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt) {} diff --git a/eth/tracers/printer.go b/eth/tracers/printer.go index 50e6ec58ab..15060cf757 100644 --- a/eth/tracers/printer.go +++ b/eth/tracers/printer.go @@ -16,7 +16,7 @@ func NewPrinter() *Printer { } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (p *Printer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (p *Printer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { fmt.Printf("CaptureStart: from=%v, to=%v, create=%v, input=%v, gas=%v, value=%v\n", from, to, create, input, gas, value) } @@ -49,7 +49,7 @@ func (p *Printer) CaptureExit(output []byte, gasUsed uint64, err error) { fmt.Printf("CaptureExit: output=%v, gasUsed=%v, err=%v\n", output, gasUsed, err) } -func (p *Printer) CaptureTxStart(tx *types.Transaction) { +func (p *Printer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) { fmt.Printf("CaptureTxStart: tx=%v\n", tx) }