diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index aef497885e..54c9b46174 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -430,7 +430,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB statedb, _ := state.New(types.EmptyRootHash, sdb) for addr, a := range accounts { statedb.SetCode(addr, a.Code) - statedb.SetNonce(addr, a.Nonce) + statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance) for k, v := range a.Storage { statedb.SetState(addr, k, v) diff --git a/core/genesis.go b/core/genesis.go index 85ef049ba6..c668ed13a6 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -137,7 +137,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance) } statedb.SetCode(addr, account.Code) - statedb.SetNonce(addr, account.Nonce) + statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis) for key, value := range account.Storage { statedb.SetState(addr, key, value) } @@ -159,7 +159,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, e statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance) } statedb.SetCode(addr, account.Code) - statedb.SetNonce(addr, account.Nonce) + statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis) for key, value := range account.Storage { statedb.SetState(addr, key, value) } diff --git a/core/state/statedb.go b/core/state/statedb.go index d279ccfdfe..9bb749468c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -432,7 +432,7 @@ func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int, reason tr } } -func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { +func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.NonceChangeReason) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { stateObject.SetNonce(nonce) diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go index 7cbfd9b9d7..77a40dc26d 100644 --- a/core/state/statedb_fuzz_test.go +++ b/core/state/statedb_fuzz_test.go @@ -69,7 +69,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction { name: "SetNonce", fn: func(a testAction, s *StateDB) { - s.SetNonce(addr, uint64(a.args[0])) + s.SetNonce(addr, uint64(a.args[0]), tracing.NonceChangeUnspecified) }, args: make([]int64, 1), }, diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 31bdd06b46..e21feb1ae9 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -175,10 +175,13 @@ func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, rea return prev } -func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) { - s.inner.SetNonce(address, nonce) - if s.hooks.OnNonceChange != nil { - s.hooks.OnNonceChange(address, nonce-1, nonce) +func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tracing.NonceChangeReason) { + prev := s.inner.GetNonce(address) + s.inner.SetNonce(address, nonce, reason) + if s.hooks.OnNonceChangeV2 != nil { + s.hooks.OnNonceChangeV2(address, prev, nonce, reason) + } else if s.hooks.OnNonceChange != nil { + s.hooks.OnNonceChange(address, prev, nonce) } } diff --git a/core/state/statedb_hooked_test.go b/core/state/statedb_hooked_test.go index 5f82ed06d0..1580679ad3 100644 --- a/core/state/statedb_hooked_test.go +++ b/core/state/statedb_hooked_test.go @@ -113,7 +113,7 @@ func TestHooks(t *testing.T) { }) sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified) sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer) - sdb.SetNonce(common.Address{0xaa}, 1337) + sdb.SetNonce(common.Address{0xaa}, 1337, tracing.NonceChangeUnspecified) sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37}) sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11")) sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22")) diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 37141e90b0..f9cdcdbf49 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -60,7 +60,7 @@ func TestUpdateLeaks(t *testing.T) { for i := byte(0); i < 255; i++ { addr := common.BytesToAddress([]byte{i}) state.AddBalance(addr, uint256.NewInt(uint64(11*i)), tracing.BalanceChangeUnspecified) - state.SetNonce(addr, uint64(42*i)) + state.SetNonce(addr, uint64(42*i), tracing.NonceChangeUnspecified) if i%2 == 0 { state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) } @@ -95,7 +95,7 @@ func TestIntermediateLeaks(t *testing.T) { modify := func(state *StateDB, addr common.Address, i, tweak byte) { state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified) - state.SetNonce(addr, uint64(42*i+tweak)) + state.SetNonce(addr, uint64(42*i+tweak), tracing.NonceChangeUnspecified) if i%2 == 0 { state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 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 { { name: "SetNonce", fn: func(a testAction, s *StateDB) { - s.SetNonce(addr, uint64(a.args[0])) + s.SetNonce(addr, uint64(a.args[0]), tracing.NonceChangeUnspecified) }, args: make([]int64, 1), }, diff --git a/core/state_transition.go b/core/state_transition.go index 58728e470e..8600407d5b 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -464,7 +464,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) } else { // Increment the nonce for the next transaction. - st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1) + st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall) // Apply EIP-7702 authorizations. if msg.AuthList != nil { @@ -572,7 +572,7 @@ func (st *stateTransition) applyAuthorization(msg *Message, auth *types.Authoriz } // Update nonce and account code. - st.state.SetNonce(authority, auth.Nonce+1) + st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization) if auth.Address == (common.Address{}) { // Delegation to zero address means clear. st.state.SetCode(authority, nil) diff --git a/core/tracing/CHANGELOG.md b/core/tracing/CHANGELOG.md index b9f08bc65f..1e539fb1ff 100644 --- a/core/tracing/CHANGELOG.md +++ b/core/tracing/CHANGELOG.md @@ -9,11 +9,17 @@ The tracing interface has been extended with backwards-compatible changes to sup ### Deprecated methods - `OnSystemCallStart()`: This hook is deprecated in favor of `OnSystemCallStartV2(vm *VMContext)`. +- `OnNonceChange(addr common.Address, prev, new uint64)`: This hook is deprecated in favor of `OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason)`. ### New methods - `OnBlockHashRead(blockNum uint64, hash common.Hash)`: This hook is called when a block hash is read by EVM. - `OnSystemCallStartV2(vm *VMContext)`. This allows access to EVM context during system calls. It is a successor to `OnSystemCallStart`. +- `OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason)`: This hook is called when a nonce change occurs. It is a successor to `OnNonceChange`. + +### New types + +- `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. ### Modified types @@ -39,7 +45,7 @@ func init() { The state changes that are covered by the journaling library are: - `OnBalanceChange`. Note that `OnBalanceChange` will carry the `BalanceChangeRevert` reason. -- `OnNonceChange` +- `OnNonceChange`, `OnNonceChangeV2` - `OnCodeChange` - `OnStorageChange` diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index 26d4578577..c39e09aca1 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -164,6 +164,9 @@ type ( // NonceChangeHook is called when the nonce of an account changes. NonceChangeHook = func(addr common.Address, prev, new uint64) + // NonceChangeHookV2 is called when the nonce of an account changes. + NonceChangeHookV2 = func(addr common.Address, prev, new uint64, reason NonceChangeReason) + // CodeChangeHook is called when the code of an account changes. CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) @@ -199,6 +202,7 @@ type Hooks struct { // State events OnBalanceChange BalanceChangeHook OnNonceChange NonceChangeHook + OnNonceChangeV2 NonceChangeHookV2 OnCodeChange CodeChangeHook OnStorageChange StorageChangeHook OnLog LogHook @@ -336,3 +340,29 @@ const ( // it will be "manually" tracked by a direct emit of the gas change event. GasChangeIgnored GasChangeReason = 0xFF ) + +// NonceChangeReason is used to indicate the reason for a nonce change. +type NonceChangeReason byte + +const ( + NonceChangeUnspecified NonceChangeReason = 0 + + // NonceChangeGenesis is the nonce allocated to accounts at genesis. + NonceChangeGenesis NonceChangeReason = 1 + + // NonceChangeEoACall is the nonce change due to an EoA call. + NonceChangeEoACall NonceChangeReason = 2 + + // NonceChangeContractCreator is the nonce change of an account creating a contract. + NonceChangeContractCreator NonceChangeReason = 3 + + // NonceChangeNewContract is the nonce change of a newly created contract. + NonceChangeNewContract NonceChangeReason = 4 + + // NonceChangeTransaction is the nonce change due to a EIP-7702 authorization. + NonceChangeAuthorization NonceChangeReason = 5 + + // NonceChangeRevert is emitted when the nonce is reverted back to a previous value due to call failure. + // It is only emitted when the tracer has opted in to use the journaling wrapper. + NonceChangeRevert NonceChangeReason = 6 +) diff --git a/core/tracing/journal.go b/core/tracing/journal.go index 6f386efda5..e32b03ce7f 100644 --- a/core/tracing/journal.go +++ b/core/tracing/journal.go @@ -38,9 +38,8 @@ type revision struct { // journal is a state change journal to be wrapped around a tracer. // It will emit the state change hooks with reverse values when a call reverts. type journal struct { - entries []entry - hooks *Hooks - lastCreator *common.Address // Account that initiated the last contract creation + entries []entry + hooks *Hooks validRevisions []revision nextRevisionId int @@ -57,9 +56,12 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) { 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.OnCodeChange == nil && hooks.OnStorageChange == nil { + if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil { return hooks, nil } + if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil { + return nil, fmt.Errorf("cannot have both OnNonceChange and OnNonceChangeV2") + } // Create a new Hooks instance and copy all hooks wrapped := hooks.copy() @@ -73,8 +75,12 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) { if hooks.OnBalanceChange != nil { wrapped.OnBalanceChange = j.OnBalanceChange } - if hooks.OnNonceChange != nil { - wrapped.OnNonceChange = j.OnNonceChange + if hooks.OnNonceChange != nil || hooks.OnNonceChangeV2 != nil { + // Regardless of which hook version is used in the tracer, + // the journal will want to capture the nonce change reason. + wrapped.OnNonceChangeV2 = j.OnNonceChangeV2 + // A precaution to ensure EVM doesn't call both hooks. + wrapped.OnNonceChange = nil } if hooks.OnCodeChange != nil { wrapped.OnCodeChange = j.OnCodeChange @@ -142,18 +148,12 @@ func (j *journal) OnTxEnd(receipt *types.Receipt, err error) { func (j *journal) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { j.revIds = append(j.revIds, j.snapshot()) - if typ == CREATE || typ == CREATE2 { - j.lastCreator = &from - } if j.hooks.OnEnter != nil { j.hooks.OnEnter(depth, typ, from, to, input, gas, value) } } func (j *journal) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { - if j.lastCreator != nil { - j.lastCreator = nil - } revId := j.revIds[len(j.revIds)-1] j.revIds = j.revIds[:len(j.revIds)-1] if reverted { @@ -171,16 +171,15 @@ func (j *journal) OnBalanceChange(addr common.Address, prev, new *big.Int, reaso } } -func (j *journal) OnNonceChange(addr common.Address, prev, new uint64) { +func (j *journal) OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason) { // When a contract is created, the nonce of the creator is incremented. // This change is not reverted when the creation fails. - if j.lastCreator != nil && *j.lastCreator == addr { - // Skip only the first nonce change. - j.lastCreator = nil - } else { + if reason != NonceChangeContractCreator { j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new}) } - if j.hooks.OnNonceChange != nil { + if j.hooks.OnNonceChangeV2 != nil { + j.hooks.OnNonceChangeV2(addr, prev, new, reason) + } else if j.hooks.OnNonceChange != nil { j.hooks.OnNonceChange(addr, prev, new) } } @@ -241,7 +240,9 @@ func (b balanceChange) revert(hooks *Hooks) { } func (n nonceChange) revert(hooks *Hooks) { - if hooks.OnNonceChange != nil { + if hooks.OnNonceChangeV2 != nil { + hooks.OnNonceChangeV2(n.addr, n.new, n.prev, NonceChangeRevert) + } else if hooks.OnNonceChange != nil { hooks.OnNonceChange(n.addr, n.new, n.prev) } } diff --git a/core/tracing/journal_test.go b/core/tracing/journal_test.go index 7ea28bb75e..64cdbe03a8 100644 --- a/core/tracing/journal_test.go +++ b/core/tracing/journal_test.go @@ -40,6 +40,10 @@ func (t *testTracer) OnNonceChange(addr common.Address, prev uint64, new uint64) t.nonce = new } +func (t *testTracer) OnNonceChangeV2(addr common.Address, prev uint64, new uint64, reason NonceChangeReason) { + t.nonce = new +} + func (t *testTracer) OnCodeChange(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) { t.code = code } @@ -67,7 +71,7 @@ func TestJournalIntegration(t *testing.T) { wr.OnCodeChange(addr, common.Hash{}, nil, common.Hash{}, []byte{1, 2, 3}) wr.OnStorageChange(addr, common.Hash{1}, common.Hash{}, common.Hash{2}) wr.OnEnter(1, 0, addr, addr, nil, 1000, big.NewInt(0)) - wr.OnNonceChange(addr, 0, 1) + wr.OnNonceChangeV2(addr, 0, 1, NonceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(100), big.NewInt(200), BalanceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified) wr.OnStorageChange(addr, common.Hash{1}, common.Hash{2}, common.Hash{3}) @@ -101,7 +105,7 @@ func TestJournalTopRevert(t *testing.T) { wr.OnEnter(0, 0, addr, addr, nil, 1000, big.NewInt(0)) wr.OnBalanceChange(addr, big.NewInt(0), big.NewInt(100), BalanceChangeUnspecified) wr.OnEnter(1, 0, addr, addr, nil, 1000, big.NewInt(0)) - wr.OnNonceChange(addr, 0, 1) + wr.OnNonceChangeV2(addr, 0, 1, NonceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(100), big.NewInt(200), BalanceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified) wr.OnExit(0, nil, 100, errors.New("revert"), true) @@ -150,13 +154,28 @@ func TestNonceIncOnCreate(t *testing.T) { } addr := common.HexToAddress("0x1234") wr.OnEnter(0, CREATE, addr, addr, nil, 1000, big.NewInt(0)) - wr.OnNonceChange(addr, 0, 1) + wr.OnNonceChangeV2(addr, 0, 1, NonceChangeContractCreator) wr.OnExit(0, nil, 100, errors.New("revert"), true) if tr.nonce != 1 { t.Fatalf("unexpected nonce: %v", tr.nonce) } } +func TestOnNonceChangeV2(t *testing.T) { + tr := &testTracer{} + wr, err := WrapWithJournal(&Hooks{OnNonceChangeV2: tr.OnNonceChangeV2}) + if err != nil { + t.Fatalf("failed to wrap test tracer: %v", err) + } + addr := common.HexToAddress("0x1234") + wr.OnEnter(2, 0, addr, addr, nil, 1000, big.NewInt(0)) + wr.OnNonceChangeV2(addr, 0, 1, NonceChangeEoACall) + wr.OnExit(2, nil, 100, nil, true) + if tr.nonce != 0 { + t.Fatalf("unexpected nonce: %v", tr.nonce) + } +} + func TestAllHooksCalled(t *testing.T) { tracer := newTracerAllHooks() hooks := tracer.hooks() @@ -182,6 +201,10 @@ func TestAllHooksCalled(t *testing.T) { if field.Name == "copy" { continue } + // Skip if field is not set + if wrappedValue.Field(i).IsNil() { + continue + } // Get the method method := wrappedValue.Field(i) @@ -218,6 +241,7 @@ func newTracerAllHooks() *tracerAllHooks { for i := 0; i < hooksType.NumField(); i++ { t.hooksCalled[hooksType.Field(i).Name] = false } + delete(t.hooksCalled, "OnNonceChange") return t } @@ -242,6 +266,9 @@ func (t *tracerAllHooks) hooks() *Hooks { hooksValue := reflect.ValueOf(h).Elem() for i := 0; i < hooksValue.NumField(); i++ { field := hooksValue.Type().Field(i) + if field.Name == "OnNonceChange" { + continue + } hookMethod := reflect.MakeFunc(field.Type, func(args []reflect.Value) []reflect.Value { t.hooksCalled[field.Name] = true return nil diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index e4441bec5d..4a96ba640a 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -640,9 +640,9 @@ func TestOpenDrops(t *testing.T) { statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) - statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3) + statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3, tracing.NonceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) - statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2) + statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2, tracing.NonceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) @@ -1384,7 +1384,7 @@ func TestAdd(t *testing.T) { // Seed the state database with this account statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance), tracing.BalanceChangeUnspecified) - statedb.SetNonce(addrs[acc], seed.nonce) + statedb.SetNonce(addrs[acc], seed.nonce, tracing.NonceChangeUnspecified) // Sign the seed transactions and store them in the data store for _, tx := range seed.txs { @@ -1439,7 +1439,7 @@ func TestAdd(t *testing.T) { // Apply the nonce updates to the state db for _, tx := range txs { sender, _ := types.Sender(types.LatestSigner(params.MainnetChainConfig), tx) - chain.statedb.SetNonce(sender, tx.Nonce()+1) + chain.statedb.SetNonce(sender, tx.Nonce()+1, tracing.NonceChangeUnspecified) } pool.Reset(chain.CurrentBlock(), header) verifyPoolInternals(t, pool) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 39673d176d..f5d834101c 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -252,7 +252,7 @@ func (c *testChain) State() (*state.StateDB, error) { if *c.trigger { c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) // simulate that the new head block included tx0 and tx1 - c.statedb.SetNonce(c.address, 2) + c.statedb.SetNonce(c.address, 2, tracing.NonceChangeUnspecified) c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether), tracing.BalanceChangeUnspecified) *c.trigger = false } @@ -313,7 +313,7 @@ func testAddBalance(pool *LegacyPool, addr common.Address, amount *big.Int) { func testSetNonce(pool *LegacyPool, addr common.Address, nonce uint64) { pool.mu.Lock() - pool.currentState.SetNonce(addr, nonce) + pool.currentState.SetNonce(addr, nonce, tracing.NonceChangeUnspecified) pool.mu.Unlock() } @@ -1074,8 +1074,8 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { } // remove current transactions and increase nonce to prepare for a reset and cleanup - statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2) - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) + statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2, tracing.NonceChangeUnspecified) + statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2, tracing.NonceChangeUnspecified) <-pool.requestReset(nil, nil) // make sure queue, pending are cleared @@ -2405,7 +2405,7 @@ func testJournaling(t *testing.T, nolocals bool) { } // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive pool.Close() - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) + statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1, tracing.NonceChangeUnspecified) blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool = New(config, blockchain) @@ -2428,12 +2428,12 @@ func testJournaling(t *testing.T, nolocals bool) { t.Fatalf("pool internal state corrupted: %v", err) } // Bump the nonce temporarily and ensure the newly invalidated transaction is removed - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) + statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2, tracing.NonceChangeUnspecified) <-pool.requestReset(nil, nil) time.Sleep(2 * config.Rejournal) pool.Close() - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) + statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1, tracing.NonceChangeUnspecified) blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool = New(config, blockchain) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go index 5088231207..d20bad85bf 100644 --- a/core/verkle_witness_test.go +++ b/core/verkle_witness_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -218,7 +219,7 @@ func TestProcessParentBlockHash(t *testing.T) { // block 2 parent hash is 0x0200.... // etc checkBlockHashes := func(statedb *state.StateDB) { - statedb.SetNonce(params.HistoryStorageAddress, 1) + statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified) statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode) // Process n blocks, from 1 .. num var num = 2 diff --git a/core/vm/evm.go b/core/vm/evm.go index 1a0215459c..3be0a3b067 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -439,7 +439,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if nonce+1 < nonce { return nil, common.Address{}, gas, ErrNonceUintOverflow } - evm.StateDB.SetNonce(caller.Address(), nonce+1) + evm.StateDB.SetNonce(caller.Address(), nonce+1, tracing.NonceChangeContractCreator) // Charge the contract creation init gas in verkle mode if evm.chainRules.IsEIP4762 { @@ -487,7 +487,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, evm.StateDB.CreateContract(address) if evm.chainRules.IsEIP158 { - evm.StateDB.SetNonce(address, 1) + evm.StateDB.SetNonce(address, 1, tracing.NonceChangeNewContract) } // Charge the contract creation init gas in verkle mode if evm.chainRules.IsEIP4762 { diff --git a/core/vm/interface.go b/core/vm/interface.go index 011541dde3..2596a7d9bb 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -38,7 +38,7 @@ type StateDB interface { GetBalance(common.Address) *uint256.Int GetNonce(common.Address) uint64 - SetNonce(common.Address, uint64) + SetNonce(common.Address, uint64, tracing.NonceChangeReason) GetCodeHash(common.Address) common.Hash GetCode(common.Address) []byte diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 6074e9a096..760c26c6db 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -410,7 +410,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode eoa := common.HexToAddress("E0") { cfg.State.CreateAccount(eoa) - cfg.State.SetNonce(eoa, 100) + cfg.State.SetNonce(eoa, 100, tracing.NonceChangeUnspecified) } reverting := common.HexToAddress("EE") { diff --git a/internal/ethapi/override/override.go b/internal/ethapi/override/override.go index 70b6210275..f6a8a94ffd 100644 --- a/internal/ethapi/override/override.go +++ b/internal/ethapi/override/override.go @@ -86,7 +86,7 @@ func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.Precompi } // Override account nonce. if account.Nonce != nil { - statedb.SetNonce(addr, uint64(*account.Nonce)) + statedb.SetNonce(addr, uint64(*account.Nonce), tracing.NonceChangeUnspecified) } // Override account(contract) code. if account.Code != nil { diff --git a/tests/state_test_util.go b/tests/state_test_util.go index e735ce2fb8..bb76b527c0 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -505,7 +505,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo statedb, _ := state.New(types.EmptyRootHash, sdb) for addr, a := range accounts { statedb.SetCode(addr, a.Code) - statedb.SetNonce(addr, a.Nonce) + statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeUnspecified) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified) for k, v := range a.Storage { statedb.SetState(addr, k, v)