move chainConfig to ctor instead of txStart

This commit is contained in:
Sina Mahmoodi 2024-10-04 19:10:33 +02:00
parent 6cf0b434e0
commit 026bc17278
16 changed files with 71 additions and 56 deletions

View file

@ -54,9 +54,8 @@ type VMContext struct {
Time uint64 Time uint64
Random *common.Hash Random *common.Hash
// Effective tx gas price // Effective tx gas price
GasPrice *big.Int GasPrice *big.Int
ChainConfig *params.ChainConfig StateDB StateDB
StateDB StateDB
} }
// BlockEvent is emitted upon tracing an incoming block. // BlockEvent is emitted upon tracing an incoming block.

View file

@ -613,7 +613,6 @@ func (evm *EVM) GetVMContext() *tracing.VMContext {
Time: evm.Context.Time, Time: evm.Context.Time,
Random: evm.Context.Random, Random: evm.Context.Random,
GasPrice: evm.TxContext.GasPrice, GasPrice: evm.TxContext.GasPrice,
ChainConfig: evm.ChainConfig(),
StateDB: evm.StateDB, StateDB: evm.StateDB,
} }
} }

View file

@ -1009,7 +1009,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
Stop: logger.Stop, Stop: logger.Stop,
} }
} else { } else {
tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig) tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig, api.backend.ChainConfig())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/params"
) )
// Context contains some contextual infos for a transaction execution that is not // Context contains some contextual infos for a transaction execution that is not
@ -44,8 +45,8 @@ type Tracer struct {
Stop func(err error) Stop func(err error)
} }
type ctorFn func(*Context, json.RawMessage) (*Tracer, error) type ctorFn func(*Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
type jsCtorFn func(string, *Context, json.RawMessage) (*Tracer, error) type jsCtorFn func(string, *Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
type elem struct { type elem struct {
ctor ctorFn ctor ctorFn
@ -78,12 +79,12 @@ func (d *directory) RegisterJSEval(f jsCtorFn) {
// New returns a new instance of a tracer, by iterating through the // New returns a new instance of a tracer, by iterating through the
// registered lookups. Name is either name of an existing tracer // registered lookups. Name is either name of an existing tracer
// or an arbitrary JS code. // or an arbitrary JS code.
func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (*Tracer, error) { func (d *directory) New(name string, ctx *Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*Tracer, error) {
if elem, ok := d.elems[name]; ok { if elem, ok := d.elems[name]; ok {
return elem.ctor(ctx, cfg) return elem.ctor(ctx, cfg, chainConfig)
} }
// Assume JS code // Assume JS code
return d.jsEval(name, ctx, cfg) return d.jsEval(name, ctx, cfg, chainConfig)
} }
// IsJS will return true if the given tracer will evaluate // IsJS will return true if the given tracer will evaluate

View file

@ -121,7 +121,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
) )
state.Close() state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
if err != nil { if err != nil {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }
@ -229,7 +229,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config)
if err != nil { if err != nil {
b.Fatalf("failed to create call tracer: %v", err) b.Fatalf("failed to create call tracer: %v", err)
} }
@ -266,7 +266,7 @@ func TestInternals(t *testing.T) {
} }
) )
mkTracer := func(name string, cfg json.RawMessage) *tracers.Tracer { mkTracer := func(name string, cfg json.RawMessage) *tracers.Tracer {
tr, err := tracers.DefaultDirectory.New(name, nil, cfg) tr, err := tracers.DefaultDirectory.New(name, nil, cfg, config)
if err != nil { if err != nil {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }

View file

@ -89,7 +89,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
defer state.Close() defer state.Close()
// Create the tracer, the EVM environment and run it // Create the tracer, the EVM environment and run it
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
if err != nil { if err != nil {
return fmt.Errorf("failed to create call tracer: %v", err) return fmt.Errorf("failed to create call tracer: %v", err)
} }

View file

@ -98,7 +98,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
) )
defer state.Close() defer state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
if err != nil { if err != nil {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/internal" "github.com/ethereum/go-ethereum/eth/tracers/internal"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -46,10 +47,10 @@ func init() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
type ctorFn = func(*tracers.Context, json.RawMessage) (*tracers.Tracer, error) type ctorFn = func(*tracers.Context, json.RawMessage, *params.ChainConfig) (*tracers.Tracer, error)
lookup := func(code string) ctorFn { lookup := func(code string) ctorFn {
return func(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { return func(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
return newJsTracer(code, ctx, cfg) return newJsTracer(code, ctx, cfg, chainConfig)
} }
} }
for name, code := range assetTracers { for name, code := range assetTracers {
@ -102,6 +103,7 @@ func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString b
type jsTracer struct { type jsTracer struct {
vm *goja.Runtime vm *goja.Runtime
env *tracing.VMContext env *tracing.VMContext
chainConfig *params.ChainConfig
toBig toBigFn // Converts a hex string into a JS bigint toBig toBigFn // Converts a hex string into a JS bigint
toBuf toBufFn // Converts a []byte into a JS buffer toBuf toBufFn // Converts a []byte into a JS buffer
fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte
@ -138,13 +140,14 @@ type jsTracer struct {
// The methods `result` and `fault` are required to be present. // The methods `result` and `fault` are required to be present.
// The methods `step`, `enter`, and `exit` are optional, but note that // The methods `step`, `enter`, and `exit` are optional, but note that
// `enter` and `exit` always go together. // `enter` and `exit` always go together.
func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
vm := goja.New() vm := goja.New()
// By default field names are exported to JS as is, i.e. capitalized. // By default field names are exported to JS as is, i.e. capitalized.
vm.SetFieldNameMapper(goja.UncapFieldNameMapper()) vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
t := &jsTracer{ t := &jsTracer{
vm: vm, vm: vm,
ctx: make(map[string]goja.Value), ctx: make(map[string]goja.Value),
chainConfig: chainConfig,
} }
t.setTypeConverters() t.setTypeConverters()
@ -244,7 +247,7 @@ func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
t.dbValue = db.setupObject() t.dbValue = db.setupObject()
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) rules := t.chainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(rules)
t.ctx["block"] = t.vm.ToValue(t.env.BlockNumber.Uint64()) t.ctx["block"] = t.vm.ToValue(t.env.BlockNumber.Uint64())
t.ctx["gas"] = t.vm.ToValue(tx.Gas()) t.ctx["gas"] = t.vm.ToValue(tx.Gas())

View file

@ -90,11 +90,12 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
func TestTracer(t *testing.T) { func TestTracer(t *testing.T) {
execTracer := func(code string, contract []byte) ([]byte, string) { execTracer := func(code string, contract []byte) ([]byte, string) {
t.Helper() t.Helper()
tracer, err := newJsTracer(code, nil, nil) chainConfig := params.TestChainConfig
tracer, err := newJsTracer(code, nil, nil, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
ret, err := runTrace(tracer, testCtx(), params.TestChainConfig, contract) ret, err := runTrace(tracer, testCtx(), chainConfig, contract)
if err != nil { if err != nil {
return nil, err.Error() // Stringify to allow comparison without nil checks return nil, err.Error() // Stringify to allow comparison without nil checks
} }
@ -167,7 +168,8 @@ func TestTracer(t *testing.T) {
func TestHalt(t *testing.T) { func TestHalt(t *testing.T) {
timeout := errors.New("stahp") timeout := errors.New("stahp")
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil) chainConfig := params.TestChainConfig
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -175,20 +177,21 @@ func TestHalt(t *testing.T) {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
tracer.Stop(timeout) tracer.Stop(timeout)
}() }()
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig, nil); !strings.Contains(err.Error(), "stahp") { if _, err = runTrace(tracer, testCtx(), chainConfig, nil); !strings.Contains(err.Error(), "stahp") {
t.Errorf("Expected timeout error, got %v", err) t.Errorf("Expected timeout error, got %v", err)
} }
} }
func TestHaltBetweenSteps(t *testing.T) { func TestHaltBetweenSteps(t *testing.T) {
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil) chainConfig := params.TestChainConfig
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
scope := &vm.ScopeContext{ scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
} }
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{}) tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0)) tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil) tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
@ -206,11 +209,12 @@ func TestHaltBetweenSteps(t *testing.T) {
func TestNoStepExec(t *testing.T) { func TestNoStepExec(t *testing.T) {
execTracer := func(code string) []byte { execTracer := func(code string) []byte {
t.Helper() t.Helper()
tracer, err := newJsTracer(code, nil, nil) chainConfig := params.TestChainConfig
tracer, err := newJsTracer(code, nil, nil, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{}) tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0)) tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
tracer.OnExit(0, nil, 0, nil, false) tracer.OnExit(0, nil, 0, nil, false)
@ -241,7 +245,7 @@ func TestIsPrecompile(t *testing.T) {
chaincfg.IstanbulBlock = big.NewInt(200) chaincfg.IstanbulBlock = big.NewInt(200)
chaincfg.BerlinBlock = big.NewInt(300) chaincfg.BerlinBlock = big.NewInt(300)
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)} txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil, chaincfg)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -255,7 +259,7 @@ func TestIsPrecompile(t *testing.T) {
t.Errorf("tracer should not consider blake2f as precompile in byzantium") t.Errorf("tracer should not consider blake2f as precompile in byzantium")
} }
tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil, chaincfg)
blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)} blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)}
res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil)
if err != nil { if err != nil {
@ -267,15 +271,16 @@ func TestIsPrecompile(t *testing.T) {
} }
func TestEnterExit(t *testing.T) { func TestEnterExit(t *testing.T) {
chainConfig := params.TestChainConfig
// test that either both or none of enter() and exit() are defined // test that either both or none of enter() and exit() are defined
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil); err == nil { if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil, chainConfig); err == nil {
t.Fatal("tracer creation should've failed without exit() definition") t.Fatal("tracer creation should've failed without exit() definition")
} }
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil); err != nil { if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil, chainConfig); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// test that the enter and exit method are correctly invoked and the values passed // test that the enter and exit method are correctly invoked and the values passed
tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context), nil) tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context), nil, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -297,7 +302,8 @@ func TestEnterExit(t *testing.T) {
func TestSetup(t *testing.T) { func TestSetup(t *testing.T) {
// Test empty config // Test empty config
_, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil) chainConfig := params.TestChainConfig
_, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil, chainConfig)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -307,12 +313,12 @@ func TestSetup(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// Test no setup func // Test no setup func
_, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg) _, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Test config value // Test config value
tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", new(tracers.Context), cfg) tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", new(tracers.Context), cfg, chainConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params"
) )
func init() { func init() {
@ -48,17 +49,19 @@ func init() {
// 0xc281d19e-0: 1 // 0xc281d19e-0: 1
// } // }
type fourByteTracer struct { type fourByteTracer struct {
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
chainConfig *params.ChainConfig
activePrecompiles []common.Address // Updated on tx start based on given rules activePrecompiles []common.Address // Updated on tx start based on given rules
} }
// newFourByteTracer returns a native go tracer which collects // newFourByteTracer returns a native go tracer which collects
// 4 byte-identifiers of a tx, and implements vm.EVMLogger. // 4 byte-identifiers of a tx, and implements vm.EVMLogger.
func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, error) { func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
t := &fourByteTracer{ t := &fourByteTracer{
ids: make(map[string]int), ids: make(map[string]int),
chainConfig: chainConfig,
} }
return &tracers.Tracer{ return &tracers.Tracer{
Hooks: &tracing.Hooks{ Hooks: &tracing.Hooks{
@ -88,7 +91,7 @@ func (t *fourByteTracer) store(id []byte, size int) {
func (t *fourByteTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { func (t *fourByteTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) rules := t.chainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(rules)
} }

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params"
) )
//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go //go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go
@ -125,7 +126,7 @@ type callTracerConfig struct {
// newCallTracer returns a native go tracer which tracks // newCallTracer returns a native go tracer which tracks
// call frames of a tx, and implements vm.EVMLogger. // call frames of a tx, and implements vm.EVMLogger.
func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { func newCallTracer(ctx *tracers.Context, cfg json.RawMessage, _ *params.ChainConfig) (*tracers.Tracer, error) {
t, err := newCallTracerObject(ctx, cfg) t, err := newCallTracerObject(ctx, cfg)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params"
) )
//go:generate go run github.com/fjl/gencodec -type flatCallAction -field-override flatCallActionMarshaling -out gen_flatcallaction_json.go //go:generate go run github.com/fjl/gencodec -type flatCallAction -field-override flatCallActionMarshaling -out gen_flatcallaction_json.go
@ -114,6 +115,7 @@ type flatCallResultMarshaling struct {
type flatCallTracer struct { type flatCallTracer struct {
tracer *callTracer tracer *callTracer
config flatCallTracerConfig config flatCallTracerConfig
chainConfig *params.ChainConfig
ctx *tracers.Context // Holds tracer context data ctx *tracers.Context // Holds tracer context data
interrupt atomic.Bool // Atomic flag to signal execution interruption interrupt atomic.Bool // Atomic flag to signal execution interruption
activePrecompiles []common.Address // Updated on tx start based on given rules activePrecompiles []common.Address // Updated on tx start based on given rules
@ -125,7 +127,7 @@ type flatCallTracerConfig struct {
} }
// newFlatCallTracer returns a new flatCallTracer. // newFlatCallTracer returns a new flatCallTracer.
func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
var config flatCallTracerConfig var config flatCallTracerConfig
if cfg != nil { if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil { if err := json.Unmarshal(cfg, &config); err != nil {
@ -140,7 +142,7 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Trac
return nil, err return nil, err
} }
ft := &flatCallTracer{tracer: t, ctx: ctx, config: config} ft := &flatCallTracer{tracer: t, ctx: ctx, config: config, chainConfig: chainConfig}
return &tracers.Tracer{ return &tracers.Tracer{
Hooks: &tracing.Hooks{ Hooks: &tracing.Hooks{
OnTxStart: ft.OnTxStart, OnTxStart: ft.OnTxStart,
@ -206,7 +208,7 @@ func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction
} }
t.tracer.OnTxStart(env, tx, from) t.tracer.OnTxStart(env, tx, from)
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) rules := t.chainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(rules)
} }

View file

@ -31,7 +31,7 @@ import (
) )
func TestCallFlatStop(t *testing.T) { func TestCallFlatStop(t *testing.T) {
tracer, err := tracers.DefaultDirectory.New("flatCallTracer", &tracers.Context{}, nil) tracer, err := tracers.DefaultDirectory.New("flatCallTracer", &tracers.Context{}, nil, params.MainnetChainConfig)
require.NoError(t, err) require.NoError(t, err)
// this error should be returned by GetResult // this error should be returned by GetResult
@ -47,9 +47,7 @@ func TestCallFlatStop(t *testing.T) {
Data: nil, Data: nil,
}) })
tracer.OnTxStart(&tracing.VMContext{ tracer.OnTxStart(&tracing.VMContext{}, tx, common.Address{})
ChainConfig: params.MainnetChainConfig,
}, tx, common.Address{})
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, nil, 0, big.NewInt(0)) tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, nil, 0, big.NewInt(0))

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
) )
func init() { func init() {
@ -38,7 +39,7 @@ type muxTracer struct {
} }
// newMuxTracer returns a new mux tracer. // newMuxTracer returns a new mux tracer.
func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
var config map[string]json.RawMessage var config map[string]json.RawMessage
if cfg != nil { if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil { if err := json.Unmarshal(cfg, &config); err != nil {
@ -48,7 +49,7 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, e
objects := make([]*tracers.Tracer, 0, len(config)) objects := make([]*tracers.Tracer, 0, len(config))
names := make([]string, 0, len(config)) names := make([]string, 0, len(config))
for k, v := range config { for k, v := range config {
t, err := tracers.DefaultDirectory.New(k, ctx, v) t, err := tracers.DefaultDirectory.New(k, ctx, v, chainConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
) )
func init() { func init() {
@ -35,7 +36,7 @@ func init() {
type noopTracer struct{} type noopTracer struct{}
// newNoopTracer returns a new noop tracer. // newNoopTracer returns a new noop tracer.
func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, error) { func newNoopTracer(ctx *tracers.Context, _ json.RawMessage, _ *params.ChainConfig) (*tracers.Tracer, error) {
t := &noopTracer{} t := &noopTracer{}
return &tracers.Tracer{ return &tracers.Tracer{
Hooks: &tracing.Hooks{ Hooks: &tracing.Hooks{

View file

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/internal" "github.com/ethereum/go-ethereum/eth/tracers/internal"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
) )
//go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go //go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go
@ -74,7 +75,7 @@ type prestateTracerConfig struct {
DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications
} }
func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) { func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, _ *params.ChainConfig) (*tracers.Tracer, error) {
var config prestateTracerConfig var config prestateTracerConfig
if cfg != nil { if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil { if err := json.Unmarshal(cfg, &config); err != nil {