Skip to content

Commit cba3302

Browse files
committed
core: only reorg changed account, not all
1 parent 9702bad commit cba3302

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

core/tx_pool.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func (pool *TxPool) resetState() {
251251
}
252252
// Check the queue and move transactions over to the pending if possible
253253
// or remove those that have become invalid
254-
pool.promoteExecutables(currentState)
254+
pool.promoteExecutables(currentState, nil)
255255
}
256256

257257
// Stop terminates the transaction pool.
@@ -546,7 +546,8 @@ func (pool *TxPool) Add(tx *types.Transaction) error {
546546
if err != nil {
547547
return err
548548
}
549-
pool.promoteExecutables(state)
549+
from, _ := types.Sender(pool.signer, tx) // already validated
550+
pool.promoteExecutables(state, []common.Address{from})
550551
}
551552
return nil
552553
}
@@ -557,24 +558,26 @@ func (pool *TxPool) AddBatch(txs []*types.Transaction) error {
557558
defer pool.mu.Unlock()
558559

559560
// Add the batch of transaction, tracking the accepted ones
560-
replaced, added := true, 0
561+
dirty := make(map[common.Address]struct{})
561562
for _, tx := range txs {
562563
if replace, err := pool.add(tx); err == nil {
563-
added++
564564
if !replace {
565-
replaced = false
565+
from, _ := types.Sender(pool.signer, tx) // already validated
566+
dirty[from] = struct{}{}
566567
}
567568
}
568569
}
569570
// Only reprocess the internal state if something was actually added
570-
if added > 0 {
571-
if !replaced {
572-
state, err := pool.currentState()
573-
if err != nil {
574-
return err
575-
}
576-
pool.promoteExecutables(state)
571+
if len(dirty) > 0 {
572+
state, err := pool.currentState()
573+
if err != nil {
574+
return err
575+
}
576+
addrs := make([]common.Address, 0, len(dirty))
577+
for addr, _ := range dirty {
578+
addrs = append(addrs, addr)
577579
}
580+
pool.promoteExecutables(state, addrs)
578581
}
579582
return nil
580583
}
@@ -651,12 +654,23 @@ func (pool *TxPool) removeTx(hash common.Hash) {
651654
// promoteExecutables moves transactions that have become processable from the
652655
// future queue to the set of pending transactions. During this process, all
653656
// invalidated transactions (low nonce, low balance) are deleted.
654-
func (pool *TxPool) promoteExecutables(state *state.StateDB) {
657+
func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.Address) {
655658
gaslimit := pool.gasLimit()
656659

660+
// Gather all the accounts potentially needing updates
661+
if accounts == nil {
662+
accounts = make([]common.Address, 0, len(pool.queue))
663+
for addr, _ := range pool.queue {
664+
accounts = append(accounts, addr)
665+
}
666+
}
657667
// Iterate over all accounts and promote any executable transactions
658668
queued := uint64(0)
659-
for addr, list := range pool.queue {
669+
for _, addr := range accounts {
670+
list := pool.queue[addr]
671+
if list == nil {
672+
continue // Just in case someone calls with a non existing account
673+
}
660674
// Drop all transactions that are deemed too old (low nonce)
661675
for _, tx := range list.Forward(state.GetNonce(addr)) {
662676
hash := tx.Hash()

core/tx_pool_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func TestTransactionQueue(t *testing.T) {
175175
pool.resetState()
176176
pool.enqueueTx(tx.Hash(), tx)
177177

178-
pool.promoteExecutables(currentState)
178+
pool.promoteExecutables(currentState, []common.Address{from})
179179
if len(pool.pending) != 1 {
180180
t.Error("expected valid txs to be 1 is", len(pool.pending))
181181
}
@@ -184,7 +184,7 @@ func TestTransactionQueue(t *testing.T) {
184184
from, _ = deriveSender(tx)
185185
currentState.SetNonce(from, 2)
186186
pool.enqueueTx(tx.Hash(), tx)
187-
pool.promoteExecutables(currentState)
187+
pool.promoteExecutables(currentState, []common.Address{from})
188188
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
189189
t.Error("expected transaction to be in tx pool")
190190
}
@@ -206,7 +206,7 @@ func TestTransactionQueue(t *testing.T) {
206206
pool.enqueueTx(tx2.Hash(), tx2)
207207
pool.enqueueTx(tx3.Hash(), tx3)
208208

209-
pool.promoteExecutables(currentState)
209+
pool.promoteExecutables(currentState, []common.Address{from})
210210

211211
if len(pool.pending) != 1 {
212212
t.Error("expected tx pool to be 1, got", len(pool.pending))
@@ -304,16 +304,16 @@ func TestTransactionDoubleNonce(t *testing.T) {
304304
t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
305305
}
306306
state, _ := pool.currentState()
307-
pool.promoteExecutables(state)
307+
pool.promoteExecutables(state, []common.Address{addr})
308308
if pool.pending[addr].Len() != 1 {
309309
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
310310
}
311311
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
312312
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
313313
}
314-
// Add the thid transaction and ensure it's not saved (smaller price)
314+
// Add the third transaction and ensure it's not saved (smaller price)
315315
pool.add(tx3)
316-
pool.promoteExecutables(state)
316+
pool.promoteExecutables(state, []common.Address{addr})
317317
if pool.pending[addr].Len() != 1 {
318318
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
319319
}
@@ -1087,7 +1087,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
10871087
// Benchmark the speed of pool validation
10881088
b.ResetTimer()
10891089
for i := 0; i < b.N; i++ {
1090-
pool.promoteExecutables(state)
1090+
pool.promoteExecutables(state, nil)
10911091
}
10921092
}
10931093

0 commit comments

Comments
 (0)