Use nonce reason in journal

This commit is contained in:
Sina Mahmoodi 2025-02-04 18:19:40 +01:00
parent 459c50f793
commit 6f5e74b717
20 changed files with 124 additions and 56 deletions

View file

@ -430,7 +430,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
statedb, _ := state.New(types.EmptyRootHash, sdb) statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) 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) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance)
for k, v := range a.Storage { for k, v := range a.Storage {
statedb.SetState(addr, k, v) statedb.SetState(addr, k, v)

View file

@ -137,7 +137,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance) statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
} }
statedb.SetCode(addr, account.Code) statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce) statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
for key, value := range account.Storage { for key, value := range account.Storage {
statedb.SetState(addr, key, value) 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.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
} }
statedb.SetCode(addr, account.Code) statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce) statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
for key, value := range account.Storage { for key, value := range account.Storage {
statedb.SetState(addr, key, value) statedb.SetState(addr, key, value)
} }

View file

@ -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) stateObject := s.getOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetNonce(nonce) stateObject.SetNonce(nonce)

View file

@ -69,7 +69,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction
{ {
name: "SetNonce", name: "SetNonce",
fn: func(a testAction, s *StateDB) { 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), args: make([]int64, 1),
}, },

View file

@ -175,10 +175,13 @@ func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, rea
return prev return prev
} }
func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) { func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tracing.NonceChangeReason) {
s.inner.SetNonce(address, nonce) prev := s.inner.GetNonce(address)
if s.hooks.OnNonceChange != nil { s.inner.SetNonce(address, nonce, reason)
s.hooks.OnNonceChange(address, nonce-1, nonce) if s.hooks.OnNonceChangeV2 != nil {
s.hooks.OnNonceChangeV2(address, prev, nonce, reason)
} else if s.hooks.OnNonceChange != nil {
s.hooks.OnNonceChange(address, prev, nonce)
} }
} }

View file

@ -113,7 +113,7 @@ func TestHooks(t *testing.T) {
}) })
sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified) sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer) 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.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("0x11"))
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22")) sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22"))

View file

@ -60,7 +60,7 @@ func TestUpdateLeaks(t *testing.T) {
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
addr := common.BytesToAddress([]byte{i}) addr := common.BytesToAddress([]byte{i})
state.AddBalance(addr, uint256.NewInt(uint64(11*i)), tracing.BalanceChangeUnspecified) 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 { if i%2 == 0 {
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 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) { modify := func(state *StateDB, addr common.Address, i, tweak byte) {
state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified) 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 { if i%2 == 0 {
state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 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}) 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", name: "SetNonce",
fn: func(a testAction, s *StateDB) { 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), args: make([]int64, 1),
}, },

View file

@ -464,7 +464,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value)
} else { } else {
// Increment the nonce for the next transaction. // 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. // Apply EIP-7702 authorizations.
if msg.AuthList != nil { if msg.AuthList != nil {
@ -572,7 +572,7 @@ func (st *stateTransition) applyAuthorization(msg *Message, auth *types.Authoriz
} }
// Update nonce and account code. // 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{}) { if auth.Address == (common.Address{}) {
// Delegation to zero address means clear. // Delegation to zero address means clear.
st.state.SetCode(authority, nil) st.state.SetCode(authority, nil)

View file

@ -9,11 +9,17 @@ The tracing interface has been extended with backwards-compatible changes to sup
### Deprecated methods ### Deprecated methods
- `OnSystemCallStart()`: This hook is deprecated in favor of `OnSystemCallStartV2(vm *VMContext)`. - `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 ### New methods
- `OnBlockHashRead(blockNum uint64, hash common.Hash)`: This hook is called when a block hash is read by EVM. - `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`. - `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 ### Modified types
@ -39,7 +45,7 @@ func init() {
The state changes that are covered by the journaling library are: The state changes that are covered by the journaling library are:
- `OnBalanceChange`. Note that `OnBalanceChange` will carry the `BalanceChangeRevert` reason. - `OnBalanceChange`. Note that `OnBalanceChange` will carry the `BalanceChangeRevert` reason.
- `OnNonceChange` - `OnNonceChange`, `OnNonceChangeV2`
- `OnCodeChange` - `OnCodeChange`
- `OnStorageChange` - `OnStorageChange`

View file

@ -164,6 +164,9 @@ type (
// NonceChangeHook is called when the nonce of an account changes. // NonceChangeHook is called when the nonce of an account changes.
NonceChangeHook = func(addr common.Address, prev, new uint64) 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 is called when the code of an account changes.
CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte)
@ -199,6 +202,7 @@ type Hooks struct {
// State events // State events
OnBalanceChange BalanceChangeHook OnBalanceChange BalanceChangeHook
OnNonceChange NonceChangeHook OnNonceChange NonceChangeHook
OnNonceChangeV2 NonceChangeHookV2
OnCodeChange CodeChangeHook OnCodeChange CodeChangeHook
OnStorageChange StorageChangeHook OnStorageChange StorageChangeHook
OnLog LogHook OnLog LogHook
@ -336,3 +340,29 @@ const (
// it will be "manually" tracked by a direct emit of the gas change event. // it will be "manually" tracked by a direct emit of the gas change event.
GasChangeIgnored GasChangeReason = 0xFF 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
)

View file

@ -38,9 +38,8 @@ type revision struct {
// journal is a state change journal to be wrapped around a tracer. // 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. // It will emit the state change hooks with reverse values when a call reverts.
type journal struct { type journal struct {
entries []entry entries []entry
hooks *Hooks hooks *Hooks
lastCreator *common.Address // Account that initiated the last contract creation
validRevisions []revision validRevisions []revision
nextRevisionId int nextRevisionId int
@ -57,9 +56,12 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
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 // 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 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 // Create a new Hooks instance and copy all hooks
wrapped := hooks.copy() wrapped := hooks.copy()
@ -73,8 +75,12 @@ 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 { if hooks.OnNonceChange != nil || hooks.OnNonceChangeV2 != nil {
wrapped.OnNonceChange = j.OnNonceChange // 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 { if hooks.OnCodeChange != nil {
wrapped.OnCodeChange = j.OnCodeChange 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) { 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()) j.revIds = append(j.revIds, j.snapshot())
if typ == CREATE || typ == CREATE2 {
j.lastCreator = &from
}
if j.hooks.OnEnter != nil { if j.hooks.OnEnter != nil {
j.hooks.OnEnter(depth, typ, from, to, input, gas, value) j.hooks.OnEnter(depth, typ, from, to, input, gas, value)
} }
} }
func (j *journal) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { 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] revId := j.revIds[len(j.revIds)-1]
j.revIds = j.revIds[:len(j.revIds)-1] j.revIds = j.revIds[:len(j.revIds)-1]
if reverted { 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. // When a contract is created, the nonce of the creator is incremented.
// This change is not reverted when the creation fails. // This change is not reverted when the creation fails.
if j.lastCreator != nil && *j.lastCreator == addr { if reason != NonceChangeContractCreator {
// Skip only the first nonce change.
j.lastCreator = nil
} else {
j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new}) 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) j.hooks.OnNonceChange(addr, prev, new)
} }
} }
@ -241,7 +240,9 @@ func (b balanceChange) revert(hooks *Hooks) {
} }
func (n nonceChange) 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) hooks.OnNonceChange(n.addr, n.new, n.prev)
} }
} }

View file

@ -40,6 +40,10 @@ func (t *testTracer) OnNonceChange(addr common.Address, prev uint64, new uint64)
t.nonce = new 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) { func (t *testTracer) OnCodeChange(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
t.code = code 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.OnCodeChange(addr, common.Hash{}, nil, common.Hash{}, []byte{1, 2, 3})
wr.OnStorageChange(addr, common.Hash{1}, common.Hash{}, common.Hash{2}) wr.OnStorageChange(addr, common.Hash{1}, common.Hash{}, common.Hash{2})
wr.OnEnter(1, 0, addr, addr, nil, 1000, big.NewInt(0)) 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(100), big.NewInt(200), BalanceChangeUnspecified)
wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified)
wr.OnStorageChange(addr, common.Hash{1}, common.Hash{2}, common.Hash{3}) 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.OnEnter(0, 0, addr, addr, nil, 1000, big.NewInt(0))
wr.OnBalanceChange(addr, big.NewInt(0), big.NewInt(100), BalanceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(0), big.NewInt(100), BalanceChangeUnspecified)
wr.OnEnter(1, 0, addr, addr, nil, 1000, big.NewInt(0)) 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(100), big.NewInt(200), BalanceChangeUnspecified)
wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified) wr.OnBalanceChange(addr, big.NewInt(200), big.NewInt(250), BalanceChangeUnspecified)
wr.OnExit(0, nil, 100, errors.New("revert"), true) wr.OnExit(0, nil, 100, errors.New("revert"), true)
@ -150,13 +154,28 @@ func TestNonceIncOnCreate(t *testing.T) {
} }
addr := common.HexToAddress("0x1234") addr := common.HexToAddress("0x1234")
wr.OnEnter(0, CREATE, addr, addr, nil, 1000, big.NewInt(0)) 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) wr.OnExit(0, nil, 100, errors.New("revert"), true)
if tr.nonce != 1 { if tr.nonce != 1 {
t.Fatalf("unexpected nonce: %v", tr.nonce) 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) { func TestAllHooksCalled(t *testing.T) {
tracer := newTracerAllHooks() tracer := newTracerAllHooks()
hooks := tracer.hooks() hooks := tracer.hooks()
@ -182,6 +201,10 @@ func TestAllHooksCalled(t *testing.T) {
if field.Name == "copy" { if field.Name == "copy" {
continue continue
} }
// Skip if field is not set
if wrappedValue.Field(i).IsNil() {
continue
}
// Get the method // Get the method
method := wrappedValue.Field(i) method := wrappedValue.Field(i)
@ -218,6 +241,7 @@ 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
} }
delete(t.hooksCalled, "OnNonceChange")
return t return t
} }
@ -242,6 +266,9 @@ 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)
if field.Name == "OnNonceChange" {
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

View file

@ -640,9 +640,9 @@ func TestOpenDrops(t *testing.T) {
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) 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(dangler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(filler.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.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(underpayer.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(outpricer.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) 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 // Seed the state database with this account
statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance), tracing.BalanceChangeUnspecified) 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 // Sign the seed transactions and store them in the data store
for _, tx := range seed.txs { for _, tx := range seed.txs {
@ -1439,7 +1439,7 @@ func TestAdd(t *testing.T) {
// Apply the nonce updates to the state db // Apply the nonce updates to the state db
for _, tx := range txs { for _, tx := range txs {
sender, _ := types.Sender(types.LatestSigner(params.MainnetChainConfig), tx) 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) pool.Reset(chain.CurrentBlock(), header)
verifyPoolInternals(t, pool) verifyPoolInternals(t, pool)

View file

@ -252,7 +252,7 @@ func (c *testChain) State() (*state.StateDB, error) {
if *c.trigger { if *c.trigger {
c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
// simulate that the new head block included tx0 and tx1 // 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.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether), tracing.BalanceChangeUnspecified)
*c.trigger = false *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) { func testSetNonce(pool *LegacyPool, addr common.Address, nonce uint64) {
pool.mu.Lock() pool.mu.Lock()
pool.currentState.SetNonce(addr, nonce) pool.currentState.SetNonce(addr, nonce, tracing.NonceChangeUnspecified)
pool.mu.Unlock() 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 // remove current transactions and increase nonce to prepare for a reset and cleanup
statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2) statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2, tracing.NonceChangeUnspecified)
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2, tracing.NonceChangeUnspecified)
<-pool.requestReset(nil, nil) <-pool.requestReset(nil, nil)
// make sure queue, pending are cleared // 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 // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
pool.Close() 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)) blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
pool = New(config, blockchain) pool = New(config, blockchain)
@ -2428,12 +2428,12 @@ func testJournaling(t *testing.T, nolocals bool) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Bump the nonce temporarily and ensure the newly invalidated transaction is removed // 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) <-pool.requestReset(nil, nil)
time.Sleep(2 * config.Rejournal) time.Sleep(2 * config.Rejournal)
pool.Close() 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)) blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
pool = New(config, blockchain) pool = New(config, blockchain)
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "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/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -218,7 +219,7 @@ func TestProcessParentBlockHash(t *testing.T) {
// block 2 parent hash is 0x0200.... // block 2 parent hash is 0x0200....
// etc // etc
checkBlockHashes := func(statedb *state.StateDB) { checkBlockHashes := func(statedb *state.StateDB) {
statedb.SetNonce(params.HistoryStorageAddress, 1) statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified)
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode) statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
// Process n blocks, from 1 .. num // Process n blocks, from 1 .. num
var num = 2 var num = 2

View file

@ -439,7 +439,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if nonce+1 < nonce { if nonce+1 < nonce {
return nil, common.Address{}, gas, ErrNonceUintOverflow 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 // Charge the contract creation init gas in verkle mode
if evm.chainRules.IsEIP4762 { if evm.chainRules.IsEIP4762 {
@ -487,7 +487,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
evm.StateDB.CreateContract(address) evm.StateDB.CreateContract(address)
if evm.chainRules.IsEIP158 { 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 // Charge the contract creation init gas in verkle mode
if evm.chainRules.IsEIP4762 { if evm.chainRules.IsEIP4762 {

View file

@ -38,7 +38,7 @@ type StateDB interface {
GetBalance(common.Address) *uint256.Int GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64 GetNonce(common.Address) uint64
SetNonce(common.Address, uint64) SetNonce(common.Address, uint64, tracing.NonceChangeReason)
GetCodeHash(common.Address) common.Hash GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte GetCode(common.Address) []byte

View file

@ -410,7 +410,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
eoa := common.HexToAddress("E0") eoa := common.HexToAddress("E0")
{ {
cfg.State.CreateAccount(eoa) cfg.State.CreateAccount(eoa)
cfg.State.SetNonce(eoa, 100) cfg.State.SetNonce(eoa, 100, tracing.NonceChangeUnspecified)
} }
reverting := common.HexToAddress("EE") reverting := common.HexToAddress("EE")
{ {

View file

@ -86,7 +86,7 @@ func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.Precompi
} }
// Override account nonce. // Override account nonce.
if account.Nonce != nil { if account.Nonce != nil {
statedb.SetNonce(addr, uint64(*account.Nonce)) statedb.SetNonce(addr, uint64(*account.Nonce), tracing.NonceChangeUnspecified)
} }
// Override account(contract) code. // Override account(contract) code.
if account.Code != nil { if account.Code != nil {

View file

@ -505,7 +505,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
statedb, _ := state.New(types.EmptyRootHash, sdb) statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) 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) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified)
for k, v := range a.Storage { for k, v := range a.Storage {
statedb.SetState(addr, k, v) statedb.SetState(addr, k, v)