Skip to content

Commit b60a276

Browse files
committed
core: transaction nonce recovery fix
When the transaction state recovery kicked in it assigned the last (incorrect) nonce to the pending state which caused transactions with the same nonce to occur. Added test for nonce recovery
1 parent 985b5f2 commit b60a276

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

core/transaction_pool.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ func (pool *TxPool) resetState() {
121121
if addr, err := tx.From(); err == nil {
122122
// Set the nonce. Transaction nonce can never be lower
123123
// than the state nonce; validatePool took care of that.
124-
if pool.pendingState.GetNonce(addr) < tx.Nonce() {
125-
pool.pendingState.SetNonce(addr, tx.Nonce())
124+
if pool.pendingState.GetNonce(addr) <= tx.Nonce() {
125+
pool.pendingState.SetNonce(addr, tx.Nonce()+1)
126126
}
127127
}
128128
}

core/transaction_pool_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,22 @@ func TestMissingNonce(t *testing.T) {
219219
t.Error("expected 1 queued transaction, got", len(pool.queue[addr]))
220220
}
221221
}
222+
223+
func TestNonceRecovery(t *testing.T) {
224+
const n = 10
225+
pool, key := setupTxPool()
226+
addr := crypto.PubkeyToAddress(key.PublicKey)
227+
pool.currentState().SetNonce(addr, n)
228+
pool.currentState().AddBalance(addr, big.NewInt(100000000000000))
229+
pool.resetState()
230+
tx := transaction(n, big.NewInt(100000), key)
231+
if err := pool.Add(tx); err != nil {
232+
t.Error(err)
233+
}
234+
// simulate some weird re-order of transactions and missing nonce(s)
235+
pool.currentState().SetNonce(addr, n-1)
236+
pool.resetState()
237+
if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
238+
t.Errorf("expected nonce to be %d, got %d", n+1, fn)
239+
}
240+
}

0 commit comments

Comments
 (0)