aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2015-09-18 17:59:21 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-09-18 17:59:21 +0800
commitb60a27627b32dd0e76269732b834ece1fe7d5c3a (patch)
treee43414be9c8c3aa122ba9934cfece0ef4e730eb6
parent985b5f29ed18eac6a36d569edbde6dcfde8d1ab0 (diff)
downloadgo-tangerine-b60a27627b32dd0e76269732b834ece1fe7d5c3a.tar.gz
go-tangerine-b60a27627b32dd0e76269732b834ece1fe7d5c3a.tar.zst
go-tangerine-b60a27627b32dd0e76269732b834ece1fe7d5c3a.zip
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
-rw-r--r--core/transaction_pool.go4
-rw-r--r--core/transaction_pool_test.go19
2 files changed, 21 insertions, 2 deletions
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 42e26b3b3..513600be3 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 7d0984740..d9267cc43 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)
+ }
+}