pass env in TxStart

This commit is contained in:
Sina Mahmoodi 2023-06-28 21:58:38 +02:00
parent 619ac2948c
commit 54171ee4a8
18 changed files with 97 additions and 94 deletions

View file

@ -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) { 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 var receipt *types.Receipt
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
evm.Config.Tracer.CaptureTxStart(tx) evm.Config.Tracer.CaptureTxStart(evm, tx)
defer func() { defer func() {
evm.Config.Tracer.CaptureTxEnd(receipt) evm.Config.Tracer.CaptureTxEnd(receipt)
}() }()

View file

@ -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 // Calling a non existing account, don't do anything, but ping the tracer
if debug { if debug {
if evm.depth == 0 { 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) evm.Config.Tracer.CaptureEnd(ret, 0, nil)
} else { } else {
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 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 // Capture the tracer start/end events in debug mode
if debug { if debug {
if evm.depth == 0 { 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 defer func(startGas uint64) { // Lazy evaluation of the parameters
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err) evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
}(gas) }(gas)
@ -456,7 +456,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
if evm.depth == 0 { 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 { } else {
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
} }

View file

@ -30,10 +30,10 @@ import (
// if you need to retain them beyond the current call. // if you need to retain them beyond the current call.
type EVMLogger interface { type EVMLogger interface {
// Transaction level // Transaction level
CaptureTxStart(tx *types.Transaction) CaptureTxStart(evm *EVM, tx *types.Transaction)
CaptureTxEnd(receipt *types.Receipt) CaptureTxEnd(receipt *types.Receipt)
// Top call frame // 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) CaptureEnd(output []byte, gasUsed uint64, err error)
// Rest of call frames // Rest of call frames
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)

View file

@ -790,7 +790,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Execute the transaction and flush any traces to disk // Execute the transaction and flush any traces to disk
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
statedb.SetTxContext(tx.Hash(), i) 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)) vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
vmConf.Tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}) vmConf.Tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
if writer != nil { 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 // Call Prepare to clear out the statedb access list
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) 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)) res, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit))
if err != nil { if err != nil {
return nil, fmt.Errorf("tracing failed: %w", err) return nil, fmt.Errorf("tracing failed: %w", err)

View file

@ -151,7 +151,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) 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())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
t.Fatalf("failed to execute transaction: %v", err) 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) { func TestInternals(t *testing.T) {
var ( var (
config = params.AllEthashProtocolChanges config = params.MainnetChainConfig
to = common.HexToAddress("0x00000000000000000000000000000000deadbeef") to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
originHex = "0x71562b71999873db5b286df957af199ec94617f7" originHex = "0x71562b71999873db5b286df957af199ec94617f7"
origin = common.HexToAddress(originHex) origin = common.HexToAddress(originHex)
signer = types.LatestSigner(config) signer = types.LatestSigner(config)
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
txContext = vm.TxContext{ context = vm.BlockContext{
Origin: origin,
GasPrice: big.NewInt(1),
}
context = vm.BlockContext{
CanTransfer: core.CanTransfer, CanTransfer: core.CanTransfer,
Transfer: core.Transfer, Transfer: core.Transfer,
Coinbase: common.Address{}, Coinbase: common.Address{},
@ -284,6 +280,7 @@ func TestInternals(t *testing.T) {
Time: 5, Time: 5,
Difficulty: big.NewInt(0x30000), Difficulty: big.NewInt(0x30000),
GasLimit: uint64(6000000), GasLimit: uint64(6000000),
BaseFee: new(big.Int),
} }
) )
mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer { mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer {
@ -349,7 +346,7 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0), byte(vm.LOG0),
}, },
tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)), 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(), _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
@ -362,21 +359,25 @@ func TestInternals(t *testing.T) {
}, },
}, false) }, false)
statedb.SetLogger(tc.tracer) 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{ tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
To: &to, To: &to,
Value: big.NewInt(0), Value: big.NewInt(0),
Gas: 50000, Gas: 50000,
GasPrice: big.NewInt(0), GasPrice: new(big.Int),
}) })
if err != nil { if err != nil {
t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err) 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)) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
if err != nil { if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err) 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())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err) t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)

View file

@ -114,7 +114,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err != nil { if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err) 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())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute transaction: %v", err) return fmt.Errorf("failed to execute transaction: %v", err)

View file

@ -120,7 +120,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) 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())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
t.Fatalf("failed to execute transaction: %v", err) t.Fatalf("failed to execute transaction: %v", err)

View file

@ -107,7 +107,6 @@ type jsTracer struct {
activePrecompiles []common.Address // List of active precompiles at current block activePrecompiles []common.Address // List of active precompiles at current block
traceStep bool // True if tracer object exposes a `step()` method traceStep bool // True if tracer object exposes a `step()` method
traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods 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 err error // Any error that should stop tracing
obj *goja.Object // Trace object 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 // CaptureTxStart implements the Tracer interface and is invoked at the beginning of
// transaction processing. // transaction processing.
func (t *jsTracer) CaptureTxStart(tx *types.Transaction) { func (t *jsTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
t.gasLimit = tx.Gas() 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 // 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. // 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) { func (t *jsTracer) CaptureStart(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()
if create { if create {
t.ctx["type"] = t.vm.ToValue("CREATE") t.ctx["type"] = t.vm.ToValue("CREATE")
} else { } 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["from"] = t.vm.ToValue(from.Bytes())
t.ctx["to"] = t.vm.ToValue(to.Bytes()) t.ctx["to"] = t.vm.ToValue(to.Bytes())
t.ctx["input"] = t.vm.ToValue(input) 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()) valueBig, err := t.toBig(t.vm, value.String())
if err != nil { if err != nil {
t.err = err t.err = err
return return
} }
t.ctx["value"] = valueBig 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. // CaptureState implements the Tracer interface to trace a single step of VM execution.

View file

@ -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. // 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) 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) {} func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt) {}

View file

@ -139,8 +139,7 @@ func (l *StructLogger) Reset() {
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. // 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) { func (l *StructLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
l.env = env
} }
// CaptureState logs a new structured log message and pushes it out to the environment // 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) 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) { func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt) {
l.usedGas = receipt.GasUsed l.usedGas = receipt.GasUsed
@ -356,8 +357,7 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger {
return l return l
} }
func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
t.env = env
if !create { if !create {
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n", fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
from.String(), to.String(), 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 (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) {} func (*mdLogger) CaptureTxEnd(receipt *types.Receipt) {}

View file

@ -43,8 +43,7 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
return l return l
} }
func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { func (l *JSONLogger) CaptureStart(from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
l.env = env
} }
func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) { 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) 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) {} func (l *JSONLogger) CaptureTxEnd(receipt *types.Receipt) {}

View file

@ -23,6 +23,7 @@ import (
"sync/atomic" "sync/atomic"
"github.com/ethereum/go-ethereum/common" "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/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
) )
@ -47,6 +48,7 @@ func init() {
// } // }
type fourByteTracer struct { type fourByteTracer struct {
tracers.NoopTracer tracers.NoopTracer
env *vm.EVM
ids map[string]int // ids aggregates the 4byte ids found ids map[string]int // ids aggregates the 4byte ids found
interrupt atomic.Bool // Atomic flag to signal execution interruption interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption reason error // Textual reason for the interruption
@ -78,13 +80,16 @@ func (t *fourByteTracer) store(id []byte, size int) {
t.ids[key] += 1 t.ids[key] += 1
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (t *fourByteTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { t.env = env
// Update list of precompiles based on current block // 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) 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 { if len(input) >= 4 {
t.store(input[0:4], len(input)-4) t.store(input[0:4], len(input)-4)
} }

View file

@ -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. // 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 toCopy := to
t.callstack[0] = callFrame{ t.callstack[0] = callFrame{
Type: vm.CALL, 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) 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() t.gasLimit = tx.Gas()
} }

View file

@ -146,11 +146,8 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. // 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) { func (t *flatCallTracer) CaptureStart(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) t.tracer.CaptureStart(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)
} }
// CaptureEnd is called after the call finishes to finalize the tracing. // 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) { func (t *flatCallTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
t.tracer.CaptureTxStart(tx) 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) { func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt) {

View file

@ -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. // 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 { 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 { for _, t := range t.tracers {
t.CaptureTxStart(tx) t.CaptureTxStart(env, tx)
} }
} }

View file

@ -19,6 +19,7 @@ package native
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
@ -61,7 +62,6 @@ type prestateTracer struct {
post state post state
create bool create bool
to common.Address to common.Address
gasLimit uint64 // Amount of gas bought for the whole tx
config prestateTracerConfig config prestateTracerConfig
interrupt atomic.Bool // Atomic flag to signal execution interruption interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the 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. // 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) { func (t *prestateTracer) CaptureStart(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
}
} }
// CaptureEnd is called after the call finishes to finalize the tracing. // 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) { func (t *prestateTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
t.gasLimit = tx.Gas() 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) { func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt) {

View file

@ -39,7 +39,7 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (Tracer, error) {
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. // 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. // 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 (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) {} func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt) {}

View file

@ -16,7 +16,7 @@ func NewPrinter() *Printer {
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. // 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) 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) 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) fmt.Printf("CaptureTxStart: tx=%v\n", tx)
} }