|
|
@@ -251,7 +251,7 @@ func (pool *TxPool) resetState() {
|
|
|
}
|
|
|
// Check the queue and move transactions over to the pending if possible
|
|
|
// or remove those that have become invalid
|
|
|
- pool.promoteExecutables(currentState)
|
|
|
+ pool.promoteExecutables(currentState, nil)
|
|
|
}
|
|
|
|
|
|
// Stop terminates the transaction pool.
|
|
|
@@ -546,7 +546,8 @@ func (pool *TxPool) Add(tx *types.Transaction) error {
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- pool.promoteExecutables(state)
|
|
|
+ from, _ := types.Sender(pool.signer, tx) // already validated
|
|
|
+ pool.promoteExecutables(state, []common.Address{from})
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
@@ -557,24 +558,26 @@ func (pool *TxPool) AddBatch(txs []*types.Transaction) error {
|
|
|
defer pool.mu.Unlock()
|
|
|
|
|
|
// Add the batch of transaction, tracking the accepted ones
|
|
|
- replaced, added := true, 0
|
|
|
+ dirty := make(map[common.Address]struct{})
|
|
|
for _, tx := range txs {
|
|
|
if replace, err := pool.add(tx); err == nil {
|
|
|
- added++
|
|
|
if !replace {
|
|
|
- replaced = false
|
|
|
+ from, _ := types.Sender(pool.signer, tx) // already validated
|
|
|
+ dirty[from] = struct{}{}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// Only reprocess the internal state if something was actually added
|
|
|
- if added > 0 {
|
|
|
- if !replaced {
|
|
|
- state, err := pool.currentState()
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- pool.promoteExecutables(state)
|
|
|
+ if len(dirty) > 0 {
|
|
|
+ state, err := pool.currentState()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ addrs := make([]common.Address, 0, len(dirty))
|
|
|
+ for addr, _ := range dirty {
|
|
|
+ addrs = append(addrs, addr)
|
|
|
}
|
|
|
+ pool.promoteExecutables(state, addrs)
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
@@ -651,12 +654,23 @@ func (pool *TxPool) removeTx(hash common.Hash) {
|
|
|
// promoteExecutables moves transactions that have become processable from the
|
|
|
// future queue to the set of pending transactions. During this process, all
|
|
|
// invalidated transactions (low nonce, low balance) are deleted.
|
|
|
-func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
|
|
+func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.Address) {
|
|
|
gaslimit := pool.gasLimit()
|
|
|
|
|
|
+ // Gather all the accounts potentially needing updates
|
|
|
+ if accounts == nil {
|
|
|
+ accounts = make([]common.Address, 0, len(pool.queue))
|
|
|
+ for addr, _ := range pool.queue {
|
|
|
+ accounts = append(accounts, addr)
|
|
|
+ }
|
|
|
+ }
|
|
|
// Iterate over all accounts and promote any executable transactions
|
|
|
queued := uint64(0)
|
|
|
- for addr, list := range pool.queue {
|
|
|
+ for _, addr := range accounts {
|
|
|
+ list := pool.queue[addr]
|
|
|
+ if list == nil {
|
|
|
+ continue // Just in case someone calls with a non existing account
|
|
|
+ }
|
|
|
// Drop all transactions that are deemed too old (low nonce)
|
|
|
for _, tx := range list.Forward(state.GetNonce(addr)) {
|
|
|
hash := tx.Hash()
|