Skip to content

Commit f526798

Browse files
rjl493456442jakub-freebit
authored andcommitted
core/txpool: fix nonce assignment in local tracker (ethereum#31496)
Fixes ethereum#31494
1 parent c4d4218 commit f526798

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

core/txpool/locals/tx_tracker_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ func (env *testEnv) makeTx(nonce uint64, gasPrice *big.Int) *types.Transaction {
108108
return tx
109109
}
110110

111+
func (env *testEnv) makeTxs(n int) []*types.Transaction {
112+
head := env.chain.CurrentHeader()
113+
state, _ := env.chain.StateAt(head.Root)
114+
nonce := state.GetNonce(address)
115+
116+
var txs []*types.Transaction
117+
for i := 0; i < n; i++ {
118+
tx, _ := types.SignTx(types.NewTransaction(nonce+uint64(i), common.Address{0x00}, big.NewInt(1000), params.TxGas, big.NewInt(params.GWei), nil), signer, key)
119+
txs = append(txs, tx)
120+
}
121+
return txs
122+
}
123+
111124
func (env *testEnv) commit() {
112125
head := env.chain.CurrentBlock()
113126
block := env.chain.GetBlock(head.Hash(), head.Number.Uint64())
@@ -177,3 +190,29 @@ func TestRejectInvalids(t *testing.T) {
177190
}
178191
}
179192
}
193+
194+
func TestResubmit(t *testing.T) {
195+
env := newTestEnv(t, 10, 0, "")
196+
defer env.close()
197+
198+
txs := env.makeTxs(10)
199+
txsA := txs[:len(txs)/2]
200+
txsB := txs[len(txs)/2:]
201+
env.pool.Add(txsA, true)
202+
pending, queued := env.pool.ContentFrom(address)
203+
if len(pending) != len(txsA) || len(queued) != 0 {
204+
t.Fatalf("Unexpected txpool content: %d, %d", len(pending), len(queued))
205+
}
206+
env.tracker.TrackAll(txs)
207+
208+
resubmit, all := env.tracker.recheck(true)
209+
if len(resubmit) != len(txsB) {
210+
t.Fatalf("Unexpected transactions to resubmit, got: %d, want: %d", len(resubmit), len(txsB))
211+
}
212+
if len(all) == 0 || len(all[address]) == 0 {
213+
t.Fatalf("Unexpected transactions being tracked, got: %d, want: %d", 0, len(txs))
214+
}
215+
if len(all[address]) != len(txs) {
216+
t.Fatalf("Unexpected transactions being tracked, got: %d, want: %d", len(all[address]), len(txs))
217+
}
218+
}

core/txpool/txpool.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,9 @@ func (p *TxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool)
466466
return p.subs.Track(event.JoinSubscriptions(subs...))
467467
}
468468

469-
// Nonce returns the next nonce of an account, with all transactions executable
469+
// PoolNonce returns the next nonce of an account, with all transactions executable
470470
// by the pool already applied on top.
471-
func (p *TxPool) Nonce(addr common.Address) uint64 {
471+
func (p *TxPool) PoolNonce(addr common.Address) uint64 {
472472
// Since (for now) accounts are unique to subpools, only one pool will have
473473
// (at max) a non-state nonce. To avoid stateful lookups, just return the
474474
// highest nonce for now.
@@ -481,6 +481,15 @@ func (p *TxPool) Nonce(addr common.Address) uint64 {
481481
return nonce
482482
}
483483

484+
// Nonce returns the next nonce of an account at the current chain head. Unlike
485+
// PoolNonce, this function does not account for pending executable transactions.
486+
func (p *TxPool) Nonce(addr common.Address) uint64 {
487+
p.stateLock.RLock()
488+
defer p.stateLock.RUnlock()
489+
490+
return p.state.GetNonce(addr)
491+
}
492+
484493
// Stats retrieves the current pool stats, namely the number of pending and the
485494
// number of queued (non-executable) transactions.
486495
func (p *TxPool) Stats() (int, int) {

eth/api_backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash)
327327
}
328328

329329
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
330-
return b.eth.txPool.Nonce(addr), nil
330+
return b.eth.txPool.PoolNonce(addr), nil
331331
}
332332

333333
func (b *EthAPIBackend) Stats() (runnable int, blocked int) {

0 commit comments

Comments
 (0)