Skip to content

Commit aaaf01d

Browse files
s1nafjl
andauthored
core/tracing: state journal wrapper (#30441)
Here we add some more changes for live tracing API v1.1: - Hook `OnSystemCallStartV2` was introduced with `VMContext` as parameter. - Hook `OnBlockHashRead` was introduced. - `GetCodeHash` was added to the state interface - The new `WrapWithJournal` construction helps with tracking EVM reverts in the tracer. --------- Co-authored-by: Felix Lange <[email protected]>
1 parent ed1d46b commit aaaf01d

23 files changed

+709
-32
lines changed

cmd/evm/internal/t8ntool/execution.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
419419
statedb, _ := state.New(types.EmptyRootHash, sdb)
420420
for addr, a := range accounts {
421421
statedb.SetCode(addr, a.Code)
422-
statedb.SetNonce(addr, a.Nonce)
422+
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
423423
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance)
424424
for k, v := range a.Storage {
425425
statedb.SetState(addr, k, v)

core/genesis.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
154154
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
155155
}
156156
statedb.SetCode(addr, account.Code)
157-
statedb.SetNonce(addr, account.Nonce)
157+
statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
158158
for key, value := range account.Storage {
159159
statedb.SetState(addr, key, value)
160160
}
@@ -180,7 +180,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, e
180180
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
181181
}
182182
statedb.SetCode(addr, account.Code)
183-
statedb.SetNonce(addr, account.Nonce)
183+
statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
184184
for key, value := range account.Storage {
185185
statedb.SetState(addr, key, value)
186186
}

core/state/statedb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int, reason tr
432432
}
433433
}
434434

435-
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
435+
func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.NonceChangeReason) {
436436
stateObject := s.getOrNewStateObject(addr)
437437
if stateObject != nil {
438438
stateObject.SetNonce(nonce)

core/state/statedb_fuzz_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction
6969
{
7070
name: "SetNonce",
7171
fn: func(a testAction, s *StateDB) {
72-
s.SetNonce(addr, uint64(a.args[0]))
72+
s.SetNonce(addr, uint64(a.args[0]), tracing.NonceChangeUnspecified)
7373
},
7474
args: make([]int64, 1),
7575
},

core/state/statedb_hooked.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,13 @@ func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, rea
179179
return prev
180180
}
181181

182-
func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) {
183-
s.inner.SetNonce(address, nonce)
184-
if s.hooks.OnNonceChange != nil {
185-
s.hooks.OnNonceChange(address, nonce-1, nonce)
182+
func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tracing.NonceChangeReason) {
183+
prev := s.inner.GetNonce(address)
184+
s.inner.SetNonce(address, nonce, reason)
185+
if s.hooks.OnNonceChangeV2 != nil {
186+
s.hooks.OnNonceChangeV2(address, prev, nonce, reason)
187+
} else if s.hooks.OnNonceChange != nil {
188+
s.hooks.OnNonceChange(address, prev, nonce)
186189
}
187190
}
188191

core/state/statedb_hooked_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func TestHooks(t *testing.T) {
8585
var wants = []string{
8686
"0xaa00000000000000000000000000000000000000.balance: 0->100 (BalanceChangeUnspecified)",
8787
"0xaa00000000000000000000000000000000000000.balance: 100->50 (BalanceChangeTransfer)",
88-
"0xaa00000000000000000000000000000000000000.nonce: 1336->1337",
88+
"0xaa00000000000000000000000000000000000000.nonce: 0->1337",
8989
"0xaa00000000000000000000000000000000000000.code: (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470) ->0x1325 (0xa12ae05590de0c93a00bc7ac773c2fdb621e44f814985e72194f921c0050f728)",
9090
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000000 ->0x0000000000000000000000000000000000000000000000000000000000000011",
9191
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000011 ->0x0000000000000000000000000000000000000000000000000000000000000022",
@@ -113,7 +113,7 @@ func TestHooks(t *testing.T) {
113113
})
114114
sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
115115
sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer)
116-
sdb.SetNonce(common.Address{0xaa}, 1337)
116+
sdb.SetNonce(common.Address{0xaa}, 1337, tracing.NonceChangeGenesis)
117117
sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37})
118118
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11"))
119119
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22"))

core/state/statedb_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func TestUpdateLeaks(t *testing.T) {
6060
for i := byte(0); i < 255; i++ {
6161
addr := common.BytesToAddress([]byte{i})
6262
state.AddBalance(addr, uint256.NewInt(uint64(11*i)), tracing.BalanceChangeUnspecified)
63-
state.SetNonce(addr, uint64(42*i))
63+
state.SetNonce(addr, uint64(42*i), tracing.NonceChangeUnspecified)
6464
if i%2 == 0 {
6565
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
6666
}
@@ -95,7 +95,7 @@ func TestIntermediateLeaks(t *testing.T) {
9595

9696
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
9797
state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified)
98-
state.SetNonce(addr, uint64(42*i+tweak))
98+
state.SetNonce(addr, uint64(42*i+tweak), tracing.NonceChangeUnspecified)
9999
if i%2 == 0 {
100100
state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{})
101101
state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
@@ -357,7 +357,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
357357
{
358358
name: "SetNonce",
359359
fn: func(a testAction, s *StateDB) {
360-
s.SetNonce(addr, uint64(a.args[0]))
360+
s.SetNonce(addr, uint64(a.args[0]), tracing.NonceChangeUnspecified)
361361
},
362362
args: make([]int64, 1),
363363
},

core/state_transition.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
487487
ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value)
488488
} else {
489489
// Increment the nonce for the next transaction.
490-
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1)
490+
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall)
491491

492492
// Apply EIP-7702 authorizations.
493493
if msg.SetCodeAuthorizations != nil {
@@ -602,7 +602,7 @@ func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization)
602602
}
603603

604604
// Update nonce and account code.
605-
st.state.SetNonce(authority, auth.Nonce+1)
605+
st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization)
606606
if auth.Address == (common.Address{}) {
607607
// Delegation to zero address means clear.
608608
st.state.SetCode(authority, nil)

core/tracing/CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,53 @@ All notable changes to the tracing interface will be documented in this file.
44

55
## [Unreleased]
66

7+
The tracing interface has been extended with backwards-compatible changes to support more use-cases and simplify tracer code. The most notable change is a state journaling library which emits reverse events when a call is reverted.
8+
9+
### Deprecated methods
10+
11+
- `OnSystemCallStart()`: This hook is deprecated in favor of `OnSystemCallStartV2(vm *VMContext)`.
12+
- `OnNonceChange(addr common.Address, prev, new uint64)`: This hook is deprecated in favor of `OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason)`.
13+
14+
### New methods
15+
16+
- `OnBlockHashRead(blockNum uint64, hash common.Hash)`: This hook is called when a block hash is read by EVM.
17+
- `OnSystemCallStartV2(vm *VMContext)`. This allows access to EVM context during system calls. It is a successor to `OnSystemCallStart`.
18+
- `OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason)`: This hook is called when a nonce change occurs. It is a successor to `OnNonceChange`.
19+
20+
### New types
21+
22+
- `NonceChangeReason` is a new type used to provide a reason for nonce changes. Notably it includes `NonceChangeRevert` which will be emitted by the state journaling library when a nonce change is due to a revert.
23+
24+
### Modified types
25+
26+
- `VMContext.StateDB` has been extended with `GetCodeHash(addr common.Address) common.Hash` method used to retrieve the code hash an account.
27+
- `BalanceChangeReason` has been extended with the `BalanceChangeRevert` reason. More on that below.
28+
29+
### State journaling
30+
31+
Tracers receive state changes events from the node. The tracer was so far expected to keep track of modified accounts and slots and revert those changes when a call frame failed. Now a utility tracer wrapper is provided which will emit "reverse change" events when a call frame fails. To use this feature the hooks have to be wrapped prior to registering the tracer. The following example demonstrates how to use the state journaling library:
32+
33+
```go
34+
func init() {
35+
tracers.LiveDirectory.Register("test", func (cfg json.RawMessage) (*tracing.Hooks, error) {
36+
hooks, err := newTestTracer(cfg)
37+
if err != nil {
38+
return nil, err
39+
}
40+
return tracing.WrapWithJournal(hooks)
41+
})
42+
}
43+
```
44+
45+
The state changes that are covered by the journaling library are:
46+
47+
- `OnBalanceChange`. Note that `OnBalanceChange` will carry the `BalanceChangeRevert` reason.
48+
- `OnNonceChange`, `OnNonceChangeV2`
49+
- `OnCodeChange`
50+
- `OnStorageChange`
51+
52+
## [v1.14.9](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.9)
53+
754
### Modified types
855

956
- `GasChangeReason` has been extended with the following reasons which will be enabled only post-Verkle. There shouldn't be any gas changes with those reasons prior to the fork.

core/tracing/gen_balance_change_reason_stringer.go

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)