fix(core/txpool): fix nonce assignment in local tracker #31496 (#2183)

This commit is contained in:
Daniel Liu 2026-03-18 14:11:47 +08:00 committed by GitHub
parent 508680055b
commit 8be617c17a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 53 additions and 5 deletions

View file

@ -57,7 +57,7 @@ type testEnv struct {
func newTestEnv(t *testing.T, n int, gasTip uint64, journal string) *testEnv {
genDb, blocks, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), n, func(i int, gen *core.BlockGen) {
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, gen.BaseFee(), nil), signer, key)
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, big.NewInt(params.GWei), nil), signer, key)
if err != nil {
panic(err)
}
@ -107,11 +107,24 @@ func (env *testEnv) makeTx(nonce uint64, gasPrice *big.Int) *types.Transaction {
return tx
}
func (env *testEnv) makeTxs(n int) []*types.Transaction {
head := env.chain.CurrentHeader()
state, _ := env.chain.StateAt(head.Root)
nonce := state.GetNonce(address)
var txs []*types.Transaction
for i := 0; i < n; i++ {
tx, _ := types.SignTx(types.NewTransaction(nonce+uint64(i), common.Address{0x00}, big.NewInt(1000), params.TxGas, big.NewInt(params.GWei), nil), signer, key)
txs = append(txs, tx)
}
return txs
}
func (env *testEnv) commit() {
head := env.chain.CurrentBlock()
block := env.chain.GetBlock(head.Hash(), head.Number.Uint64())
blocks, _ := core.GenerateChain(env.chain.Config(), block, ethash.NewFaker(), env.genDb, 1, func(i int, gen *core.BlockGen) {
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, gen.BaseFee(), nil), signer, key)
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, big.NewInt(params.GWei), nil), signer, key)
if err != nil {
panic(err)
}
@ -122,3 +135,29 @@ func (env *testEnv) commit() {
panic(err)
}
}
func TestResubmit(t *testing.T) {
env := newTestEnv(t, 10, 0, "")
defer env.close()
txs := env.makeTxs(10)
txsA := txs[:len(txs)/2]
txsB := txs[len(txs)/2:]
env.pool.Add(txsA, true)
pending, queued := env.pool.ContentFrom(address)
if len(pending) != len(txsA) || len(queued) != 0 {
t.Fatalf("Unexpected txpool content: %d, %d", len(pending), len(queued))
}
env.tracker.TrackAll(txs)
resubmit, all := env.tracker.recheck(true)
if len(resubmit) != len(txsB) {
t.Fatalf("Unexpected transactions to resubmit, got: %d, want: %d", len(resubmit), len(txsB))
}
if len(all) == 0 || len(all[address]) == 0 {
t.Fatalf("Unexpected transactions being tracked, got: %d, want: %d", 0, len(txs))
}
if len(all[address]) != len(txs) {
t.Fatalf("Unexpected transactions being tracked, got: %d, want: %d", len(all[address]), len(txs))
}
}

View file

@ -400,9 +400,9 @@ func (p *TxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool)
return p.subs.Track(event.JoinSubscriptions(subs...))
}
// Nonce returns the next nonce of an account, with all transactions executable
// PoolNonce returns the next nonce of an account, with all transactions executable
// by the pool already applied on top.
func (p *TxPool) Nonce(addr common.Address) uint64 {
func (p *TxPool) PoolNonce(addr common.Address) uint64 {
// Since (for now) accounts are unique to subpools, only one pool will have
// (at max) a non-state nonce. To avoid stateful lookups, just return the
// highest nonce for now.
@ -415,6 +415,15 @@ func (p *TxPool) Nonce(addr common.Address) uint64 {
return nonce
}
// Nonce returns the next nonce of an account at the current chain head. Unlike
// PoolNonce, this function does not account for pending executable transactions.
func (p *TxPool) Nonce(addr common.Address) uint64 {
p.stateLock.RLock()
defer p.stateLock.RUnlock()
return p.state.GetNonce(addr)
}
// Stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (p *TxPool) Stats() (int, int) {

View file

@ -349,7 +349,7 @@ func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash)
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
return b.eth.txPool.Nonce(addr), nil
return b.eth.txPool.PoolNonce(addr), nil
}
func (b *EthAPIBackend) Stats() (runnable int, blocked int) {