diff --git a/core/tx_pool.go b/core/tx_pool.go index 17904ee2da09..aed6e9f3b7b5 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -1231,32 +1231,6 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { } } - // for AA we need to re-validate accounts that were included - // split into separate function - // This introduces some basic race conditions, so this needs to be refactored - for _, tx := range included { - var account = tx.To() - if account != nil && tx.IsAA() { - if pool.Has(tx.Hash()) { - pool.removeTx(tx.Hash(), true) - } else { - if pending := pool.pending[*account]; pending != nil { - pending_tx := pending.txs.Flatten()[0] - pool.removeTx(pending_tx.Hash(), true) - // ignore locals for now - pool.add(pending_tx, false) - } - - if queued := pool.queue[*account]; queued != nil { - queued_tx := queued.txs.Flatten()[0] - pool.removeTx(queued_tx.Hash(), true) - // ignore locals for now - pool.add(queued_tx, false) - } - } - } - } - // Initialize the internal state to the current head if newHead == nil { newHead = pool.chain.CurrentBlock().Header() // Special case during testing @@ -1270,6 +1244,15 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.pendingNonces = newTxNoncer(statedb) pool.currentMaxGas = newHead.GasLimit + // re-validate aa transactions for accounts where a transaction was included + if oldHead != nil && oldHead.Hash() == newHead.ParentHash { + includedTransactions := pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()).Transactions() + pool.validateAAExecutables(includedTransactions) + } + + // for AA we need to re-validate accounts that were included after forking + pool.validateAAExecutables(included) + // Inject any transactions discarded due to reorgs log.Debug("Reinjecting stale transactions", "count", len(reinject)) senderCacher.recover(pool.signer, reinject) @@ -1280,6 +1263,28 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.istanbul = pool.chainconfig.IsIstanbul(next) } +// This re-validates accounts which have been touched in a recent block +func (pool *TxPool) validateAAExecutables(txs []*types.Transaction) { + for _, tx := range txs { + var account = tx.To() + if account != nil && tx.IsAA() { + if pool.Has(tx.Hash()) { + pool.removeTx(tx.Hash(), true) + } else if pending := pool.pending[*account]; pending != nil { + pending_tx := pending.txs.Flatten()[0] + pool.removeTx(pending_tx.Hash(), true) + // ignore locals for now + pool.add(pending_tx, false) + } else if queued := pool.queue[*account]; queued != nil { + queued_tx := queued.txs.Flatten()[0] + pool.removeTx(queued_tx.Hash(), true) + // ignore locals for now + pool.add(queued_tx, false) + } + } + } +} + // 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.