mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
core/tracing: auto upgrade deprecated hooks
This commit is contained in:
parent
aaaf01d712
commit
6ade175b11
8 changed files with 78 additions and 17 deletions
|
|
@ -184,8 +184,6 @@ func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tr
|
||||||
s.inner.SetNonce(address, nonce, reason)
|
s.inner.SetNonce(address, nonce, reason)
|
||||||
if s.hooks.OnNonceChangeV2 != nil {
|
if s.hooks.OnNonceChangeV2 != nil {
|
||||||
s.hooks.OnNonceChangeV2(address, prev, nonce, reason)
|
s.hooks.OnNonceChangeV2(address, prev, nonce, reason)
|
||||||
} else if s.hooks.OnNonceChange != nil {
|
|
||||||
s.hooks.OnNonceChange(address, prev, nonce)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ func TestHooks(t *testing.T) {
|
||||||
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
||||||
emitF("%v.balance: %v->%v (%v)", addr, prev, new, reason)
|
emitF("%v.balance: %v->%v (%v)", addr, prev, new, reason)
|
||||||
},
|
},
|
||||||
OnNonceChange: func(addr common.Address, prev, new uint64) {
|
OnNonceChangeV2: func(addr common.Address, prev, new uint64, reason tracing.NonceChangeReason) {
|
||||||
emitF("%v.nonce: %v->%v", addr, prev, new)
|
emitF("%v.nonce: %v->%v", addr, prev, new)
|
||||||
},
|
},
|
||||||
OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
|
OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
package tracing
|
package tracing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -33,6 +34,11 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrHookConflict is returned when conflicting hooks are exposed.
|
||||||
|
ErrHookConflict = errors.New("hook conflict")
|
||||||
|
)
|
||||||
|
|
||||||
// OpContext provides the context at which the opcode is being
|
// OpContext provides the context at which the opcode is being
|
||||||
// executed in, including the memory, stack and various contract-level information.
|
// executed in, including the memory, stack and various contract-level information.
|
||||||
type OpContext interface {
|
type OpContext interface {
|
||||||
|
|
@ -217,6 +223,36 @@ type Hooks struct {
|
||||||
OnBlockHashRead BlockHashReadHook
|
OnBlockHashRead BlockHashReadHook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upgrade will upgrade the methods to their most recent versions
|
||||||
|
// when possible, e.g. use `OnNonceChangeV2` instead of `OnNonceChange`.
|
||||||
|
func Upgrade(hooks *Hooks) (*Hooks, error) {
|
||||||
|
if hooks == nil {
|
||||||
|
return &Hooks{}, nil
|
||||||
|
}
|
||||||
|
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
|
||||||
|
return nil, ErrHookConflict
|
||||||
|
}
|
||||||
|
if hooks.OnSystemCallStart != nil && hooks.OnSystemCallStartV2 != nil {
|
||||||
|
return nil, ErrHookConflict
|
||||||
|
}
|
||||||
|
// Shallow copy
|
||||||
|
tmp := *hooks
|
||||||
|
internal := &tmp
|
||||||
|
if hooks.OnNonceChange != nil {
|
||||||
|
hooks.OnNonceChangeV2 = func(addr common.Address, prev, new uint64, reason NonceChangeReason) {
|
||||||
|
internal.OnNonceChange(addr, prev, new)
|
||||||
|
}
|
||||||
|
hooks.OnNonceChange = nil
|
||||||
|
}
|
||||||
|
if hooks.OnSystemCallStart != nil {
|
||||||
|
hooks.OnSystemCallStartV2 = func(vm *VMContext) {
|
||||||
|
internal.OnSystemCallStart()
|
||||||
|
}
|
||||||
|
hooks.OnSystemCallStart = nil
|
||||||
|
}
|
||||||
|
return hooks, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BalanceChangeReason is used to indicate the reason for a balance change, useful
|
// BalanceChangeReason is used to indicate the reason for a balance change, useful
|
||||||
// for tracing and reporting.
|
// for tracing and reporting.
|
||||||
type BalanceChangeReason byte
|
type BalanceChangeReason byte
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,17 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
||||||
if hooks == nil {
|
if hooks == nil {
|
||||||
return nil, fmt.Errorf("wrapping nil tracer")
|
return nil, fmt.Errorf("wrapping nil tracer")
|
||||||
}
|
}
|
||||||
// No state change to journal, return the wrapped hooks as is
|
|
||||||
if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil {
|
// Upgrade hooks so we don't have to bother with old versions.
|
||||||
return hooks, nil
|
var err error
|
||||||
|
hooks, err = Upgrade(hooks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
|
|
||||||
return nil, fmt.Errorf("cannot have both OnNonceChange and OnNonceChangeV2")
|
// No state change to journal, return the wrapped hooks as is
|
||||||
|
if hooks.OnBalanceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil {
|
||||||
|
return hooks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Hooks instance and copy all hooks
|
// Create a new Hooks instance and copy all hooks
|
||||||
|
|
@ -62,12 +67,10 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
||||||
if hooks.OnBalanceChange != nil {
|
if hooks.OnBalanceChange != nil {
|
||||||
wrapped.OnBalanceChange = j.OnBalanceChange
|
wrapped.OnBalanceChange = j.OnBalanceChange
|
||||||
}
|
}
|
||||||
if hooks.OnNonceChange != nil || hooks.OnNonceChangeV2 != nil {
|
if hooks.OnNonceChangeV2 != nil {
|
||||||
// Regardless of which hook version is used in the tracer,
|
// Regardless of which hook version is used in the tracer,
|
||||||
// the journal will want to capture the nonce change reason.
|
// the journal will want to capture the nonce change reason.
|
||||||
wrapped.OnNonceChangeV2 = j.OnNonceChangeV2
|
wrapped.OnNonceChangeV2 = j.OnNonceChangeV2
|
||||||
// A precaution to ensure EVM doesn't call both hooks.
|
|
||||||
wrapped.OnNonceChange = nil
|
|
||||||
}
|
}
|
||||||
if hooks.OnCodeChange != nil {
|
if hooks.OnCodeChange != nil {
|
||||||
wrapped.OnCodeChange = j.OnCodeChange
|
wrapped.OnCodeChange = j.OnCodeChange
|
||||||
|
|
@ -156,8 +159,6 @@ func (j *journal) OnNonceChangeV2(addr common.Address, prev, new uint64, reason
|
||||||
}
|
}
|
||||||
if j.hooks.OnNonceChangeV2 != nil {
|
if j.hooks.OnNonceChangeV2 != nil {
|
||||||
j.hooks.OnNonceChangeV2(addr, prev, new, reason)
|
j.hooks.OnNonceChangeV2(addr, prev, new, reason)
|
||||||
} else if j.hooks.OnNonceChange != nil {
|
|
||||||
j.hooks.OnNonceChange(addr, prev, new)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,8 +220,6 @@ func (b balanceChange) revert(hooks *Hooks) {
|
||||||
func (n nonceChange) revert(hooks *Hooks) {
|
func (n nonceChange) revert(hooks *Hooks) {
|
||||||
if hooks.OnNonceChangeV2 != nil {
|
if hooks.OnNonceChangeV2 != nil {
|
||||||
hooks.OnNonceChangeV2(n.addr, n.new, n.prev, NonceChangeRevert)
|
hooks.OnNonceChangeV2(n.addr, n.new, n.prev, NonceChangeRevert)
|
||||||
} else if hooks.OnNonceChange != nil {
|
|
||||||
hooks.OnNonceChange(n.addr, n.new, n.prev)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,9 @@ func newTracerAllHooks() *tracerAllHooks {
|
||||||
for i := 0; i < hooksType.NumField(); i++ {
|
for i := 0; i < hooksType.NumField(); i++ {
|
||||||
t.hooksCalled[hooksType.Field(i).Name] = false
|
t.hooksCalled[hooksType.Field(i).Name] = false
|
||||||
}
|
}
|
||||||
|
// Deprecated methods
|
||||||
delete(t.hooksCalled, "OnNonceChange")
|
delete(t.hooksCalled, "OnNonceChange")
|
||||||
|
delete(t.hooksCalled, "OnSystemCallStart")
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,9 +324,13 @@ func (t *tracerAllHooks) hooks() *Hooks {
|
||||||
hooksValue := reflect.ValueOf(h).Elem()
|
hooksValue := reflect.ValueOf(h).Elem()
|
||||||
for i := 0; i < hooksValue.NumField(); i++ {
|
for i := 0; i < hooksValue.NumField(); i++ {
|
||||||
field := hooksValue.Type().Field(i)
|
field := hooksValue.Type().Field(i)
|
||||||
|
// Skip deprecated methods
|
||||||
if field.Name == "OnNonceChange" {
|
if field.Name == "OnNonceChange" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if field.Name == "OnSystemCallStart" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
hookMethod := reflect.MakeFunc(field.Type, func(args []reflect.Value) []reflect.Value {
|
hookMethod := reflect.MakeFunc(field.Type, func(args []reflect.Value) []reflect.Value {
|
||||||
t.hooksCalled[field.Name] = true
|
t.hooksCalled[field.Name] = true
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ type Tracer struct {
|
||||||
Stop func(err error)
|
Stop func(err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tracer) upgrade() (*Tracer, error) {
|
||||||
|
upgraded, err := tracing.Upgrade(t.Hooks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Tracer{Hooks: upgraded, GetResult: t.GetResult, Stop: t.Stop}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type ctorFn func(*Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
|
type ctorFn func(*Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
|
||||||
type jsCtorFn func(string, *Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
|
type jsCtorFn func(string, *Context, json.RawMessage, *params.ChainConfig) (*Tracer, error)
|
||||||
|
|
||||||
|
|
@ -84,7 +92,11 @@ func (d *directory) New(name string, ctx *Context, cfg json.RawMessage, chainCon
|
||||||
cfg = json.RawMessage("{}")
|
cfg = json.RawMessage("{}")
|
||||||
}
|
}
|
||||||
if elem, ok := d.elems[name]; ok {
|
if elem, ok := d.elems[name]; ok {
|
||||||
return elem.ctor(ctx, cfg, chainConfig)
|
t, err := elem.ctor(ctx, cfg, chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t.upgrade()
|
||||||
}
|
}
|
||||||
// Assume JS code
|
// Assume JS code
|
||||||
return d.jsEval(name, ctx, cfg, chainConfig)
|
return d.jsEval(name, ctx, cfg, chainConfig)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package tracers
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
)
|
)
|
||||||
|
|
@ -36,6 +37,7 @@ type liveDirectory struct {
|
||||||
// Register registers a tracer constructor by name.
|
// Register registers a tracer constructor by name.
|
||||||
func (d *liveDirectory) Register(name string, f ctorFunc) {
|
func (d *liveDirectory) Register(name string, f ctorFunc) {
|
||||||
d.elems[name] = f
|
d.elems[name] = f
|
||||||
|
fmt.Printf("Registered tracer %q\n", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a tracer by name.
|
// New instantiates a tracer by name.
|
||||||
|
|
@ -44,7 +46,11 @@ func (d *liveDirectory) New(name string, config json.RawMessage) (*tracing.Hooks
|
||||||
config = json.RawMessage("{}")
|
config = json.RawMessage("{}")
|
||||||
}
|
}
|
||||||
if f, ok := d.elems[name]; ok {
|
if f, ok := d.elems[name]; ok {
|
||||||
return f(config)
|
hooks, err := f(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tracing.Upgrade(hooks)
|
||||||
}
|
}
|
||||||
return nil, errors.New("not found")
|
return nil, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ func newSupplyTracer(cfg json.RawMessage) (*tracing.Hooks, error) {
|
||||||
OnGenesisBlock: t.onGenesisBlock,
|
OnGenesisBlock: t.onGenesisBlock,
|
||||||
OnTxStart: t.onTxStart,
|
OnTxStart: t.onTxStart,
|
||||||
OnBalanceChange: t.onBalanceChange,
|
OnBalanceChange: t.onBalanceChange,
|
||||||
|
OnNonceChange: t.onNonceChange,
|
||||||
OnEnter: t.onEnter,
|
OnEnter: t.onEnter,
|
||||||
OnExit: t.onExit,
|
OnExit: t.onExit,
|
||||||
OnClose: t.onClose,
|
OnClose: t.onClose,
|
||||||
|
|
@ -326,3 +327,6 @@ func (s *supplyTracer) write(data any) {
|
||||||
log.Warn("failed to write to supply tracer log file", "error", err)
|
log.Warn("failed to write to supply tracer log file", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (t *supplyTracer) onNonceChange(addr common.Address, prev, new uint64) {
|
||||||
|
fmt.Printf("Nonce change for %s: %d -> %d\n", addr, prev, new)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue