mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-09 09:36:40 +00:00
eth/tracers: forward V2 state hooks through mux tracer (#34869)
Fixes the muxTracer to correctly forward events to v2 state hooks, i.e. `OnCodeChangeV2` and `OnNonceChangeV2`.
This commit is contained in:
parent
f0b21fa110
commit
efd6cdcff1
2 changed files with 101 additions and 12 deletions
|
|
@ -63,6 +63,12 @@ func newMuxTracerFromConfig(ctx *tracers.Context, cfg json.RawMessage, chainConf
|
|||
//
|
||||
// The names parameter associates a label with each tracer, used as keys in
|
||||
// the aggregated JSON result returned by GetResult.
|
||||
//
|
||||
// For hooks that have both a V1 and V2 form (OnCodeChange / OnCodeChangeV2,
|
||||
// OnNonceChange / OnNonceChangeV2, OnSystemCallStart / OnSystemCallStartV2),
|
||||
// the mux exposes only the V2 variant upward. The fanout then prefers each
|
||||
// child's V2 hook and falls back to V1 if only V1 is set, mirroring the
|
||||
// precedence already used in core/state_processor.go.
|
||||
func NewMuxTracer(names []string, objects []*tracers.Tracer) (*tracers.Tracer, error) {
|
||||
t := &muxTracer{names: names, tracers: objects}
|
||||
return &tracers.Tracer{
|
||||
|
|
@ -75,8 +81,8 @@ func NewMuxTracer(names []string, objects []*tracers.Tracer) (*tracers.Tracer, e
|
|||
OnFault: t.OnFault,
|
||||
OnGasChange: t.OnGasChange,
|
||||
OnBalanceChange: t.OnBalanceChange,
|
||||
OnNonceChange: t.OnNonceChange,
|
||||
OnCodeChange: t.OnCodeChange,
|
||||
OnNonceChangeV2: t.OnNonceChangeV2,
|
||||
OnCodeChangeV2: t.OnCodeChangeV2,
|
||||
OnStorageChange: t.OnStorageChange,
|
||||
OnLog: t.OnLog,
|
||||
OnSystemCallStartV2: t.OnSystemCallStart,
|
||||
|
|
@ -151,26 +157,22 @@ func (t *muxTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason
|
|||
}
|
||||
}
|
||||
|
||||
func (t *muxTracer) OnNonceChange(a common.Address, prev, new uint64) {
|
||||
func (t *muxTracer) OnNonceChangeV2(a common.Address, prev, new uint64, reason tracing.NonceChangeReason) {
|
||||
for _, t := range t.tracers {
|
||||
if t.OnNonceChange != nil {
|
||||
if t.OnNonceChangeV2 != nil {
|
||||
t.OnNonceChangeV2(a, prev, new, reason)
|
||||
} else if t.OnNonceChange != nil {
|
||||
t.OnNonceChange(a, prev, new)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *muxTracer) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte) {
|
||||
for _, t := range t.tracers {
|
||||
if t.OnCodeChange != nil {
|
||||
t.OnCodeChange(a, prevCodeHash, prev, codeHash, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *muxTracer) OnCodeChangeV2(a common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte, reason tracing.CodeChangeReason) {
|
||||
for _, t := range t.tracers {
|
||||
if t.OnCodeChangeV2 != nil {
|
||||
t.OnCodeChangeV2(a, prevCodeHash, prev, codeHash, code, reason)
|
||||
} else if t.OnCodeChange != nil {
|
||||
t.OnCodeChange(a, prevCodeHash, prev, codeHash, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
87
eth/tracers/native/mux_test.go
Normal file
87
eth/tracers/native/mux_test.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
)
|
||||
|
||||
// TestMuxForwardsV2StateHooks verifies that the mux tracer fans out the V2
|
||||
// variants of state-change hooks to child tracers. A child tracer that only
|
||||
// implements OnCodeChangeV2 / OnNonceChangeV2 must still receive events when
|
||||
// wrapped behind the mux. The mux must also fall back to the V1 hook when a
|
||||
// child only implements V1, mirroring the precedence used in
|
||||
// core/state_processor.go.
|
||||
func TestMuxForwardsV2StateHooks(t *testing.T) {
|
||||
var (
|
||||
codeV2Calls int
|
||||
nonceV2Calls int
|
||||
codeV1Calls int
|
||||
nonceV1Calls int
|
||||
)
|
||||
v2Child := &tracers.Tracer{
|
||||
Hooks: &tracing.Hooks{
|
||||
OnCodeChangeV2: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason tracing.CodeChangeReason) {
|
||||
codeV2Calls++
|
||||
},
|
||||
OnNonceChangeV2: func(addr common.Address, prev, new uint64, reason tracing.NonceChangeReason) {
|
||||
nonceV2Calls++
|
||||
},
|
||||
},
|
||||
}
|
||||
v1Child := &tracers.Tracer{
|
||||
Hooks: &tracing.Hooks{
|
||||
OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
|
||||
codeV1Calls++
|
||||
},
|
||||
OnNonceChange: func(addr common.Address, prev, new uint64) {
|
||||
nonceV1Calls++
|
||||
},
|
||||
},
|
||||
}
|
||||
mux, err := NewMuxTracer([]string{"v2", "v1"}, []*tracers.Tracer{v2Child, v1Child})
|
||||
if err != nil {
|
||||
t.Fatalf("NewMuxTracer: %v", err)
|
||||
}
|
||||
|
||||
if mux.Hooks.OnCodeChangeV2 == nil {
|
||||
t.Fatal("mux does not expose OnCodeChangeV2; V2-only child tracers will miss code changes")
|
||||
}
|
||||
if mux.Hooks.OnNonceChangeV2 == nil {
|
||||
t.Fatal("mux does not expose OnNonceChangeV2; V2-only child tracers will miss nonce changes")
|
||||
}
|
||||
|
||||
mux.Hooks.OnCodeChangeV2(common.Address{}, common.Hash{}, nil, common.Hash{}, nil, tracing.CodeChangeContractCreation)
|
||||
mux.Hooks.OnNonceChangeV2(common.Address{}, 0, 1, tracing.NonceChangeEoACall)
|
||||
|
||||
if codeV2Calls != 1 {
|
||||
t.Fatalf("V2 child OnCodeChangeV2 got %d calls, want 1", codeV2Calls)
|
||||
}
|
||||
if nonceV2Calls != 1 {
|
||||
t.Fatalf("V2 child OnNonceChangeV2 got %d calls, want 1", nonceV2Calls)
|
||||
}
|
||||
if codeV1Calls != 1 {
|
||||
t.Fatalf("V1 child OnCodeChange got %d calls, want 1 (mux should fall back from V2 to V1)", codeV1Calls)
|
||||
}
|
||||
if nonceV1Calls != 1 {
|
||||
t.Fatalf("V1 child OnNonceChange got %d calls, want 1 (mux should fall back from V2 to V1)", nonceV1Calls)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue