mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-16 13:06: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 names parameter associates a label with each tracer, used as keys in
|
||||||
// the aggregated JSON result returned by GetResult.
|
// 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) {
|
func NewMuxTracer(names []string, objects []*tracers.Tracer) (*tracers.Tracer, error) {
|
||||||
t := &muxTracer{names: names, tracers: objects}
|
t := &muxTracer{names: names, tracers: objects}
|
||||||
return &tracers.Tracer{
|
return &tracers.Tracer{
|
||||||
|
|
@ -75,8 +81,8 @@ func NewMuxTracer(names []string, objects []*tracers.Tracer) (*tracers.Tracer, e
|
||||||
OnFault: t.OnFault,
|
OnFault: t.OnFault,
|
||||||
OnGasChange: t.OnGasChange,
|
OnGasChange: t.OnGasChange,
|
||||||
OnBalanceChange: t.OnBalanceChange,
|
OnBalanceChange: t.OnBalanceChange,
|
||||||
OnNonceChange: t.OnNonceChange,
|
OnNonceChangeV2: t.OnNonceChangeV2,
|
||||||
OnCodeChange: t.OnCodeChange,
|
OnCodeChangeV2: t.OnCodeChangeV2,
|
||||||
OnStorageChange: t.OnStorageChange,
|
OnStorageChange: t.OnStorageChange,
|
||||||
OnLog: t.OnLog,
|
OnLog: t.OnLog,
|
||||||
OnSystemCallStartV2: t.OnSystemCallStart,
|
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 {
|
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)
|
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) {
|
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 {
|
for _, t := range t.tracers {
|
||||||
if t.OnCodeChangeV2 != nil {
|
if t.OnCodeChangeV2 != nil {
|
||||||
t.OnCodeChangeV2(a, prevCodeHash, prev, codeHash, code, reason)
|
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