diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 42e26b3b38..513600be35 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -121,8 +121,8 @@ func (pool *TxPool) resetState() { if addr, err := tx.From(); err == nil { // Set the nonce. Transaction nonce can never be lower // than the state nonce; validatePool took care of that. - if pool.pendingState.GetNonce(addr) < tx.Nonce() { - pool.pendingState.SetNonce(addr, tx.Nonce()) + if pool.pendingState.GetNonce(addr) <= tx.Nonce() { + pool.pendingState.SetNonce(addr, tx.Nonce()+1) } } } diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go index 7d09847401..d9267cc435 100644 --- a/core/transaction_pool_test.go +++ b/core/transaction_pool_test.go @@ -219,3 +219,22 @@ func TestMissingNonce(t *testing.T) { t.Error("expected 1 queued transaction, got", len(pool.queue[addr])) } } + +func TestNonceRecovery(t *testing.T) { + const n = 10 + pool, key := setupTxPool() + addr := crypto.PubkeyToAddress(key.PublicKey) + pool.currentState().SetNonce(addr, n) + pool.currentState().AddBalance(addr, big.NewInt(100000000000000)) + pool.resetState() + tx := transaction(n, big.NewInt(100000), key) + if err := pool.Add(tx); err != nil { + t.Error(err) + } + // simulate some weird re-order of transactions and missing nonce(s) + pool.currentState().SetNonce(addr, n-1) + pool.resetState() + if fn := pool.pendingState.GetNonce(addr); fn != n+1 { + t.Errorf("expected nonce to be %d, got %d", n+1, fn) + } +}