clear address reservations inside subpools, with explanation for why it's not done at the TxPool level.

This commit is contained in:
Jared Wasinger 2024-10-02 16:30:44 +07:00 committed by Felix Lange
parent 5842b1db62
commit 8d241f0475
2 changed files with 39 additions and 0 deletions

View file

@ -1729,6 +1729,23 @@ func (p *BlobPool) Clear() {
log.Warn("failed to delete blob tx from backing store", "err", err) log.Warn("failed to delete blob tx from backing store", "err", err)
} }
} }
// unreserve each tracked account. Ideally, we could just clear the
// reservation map in the parent txpool context. However, if we clear in
// parent context, to avoid exposing the subpool lock, we have to lock the
// reservations and then lock each subpool.
//
// This creates the potential for a deadlock situation:
//
// * TxPool.Clear locks the reservations
// * a new transaction is received which locks the subpool mutex
// * TxPool.Clear attempts to lock subpool mutex
//
// The transaction addition may attempt to reserve the sender addr which
// can't happen until Clear releases the reservation lock. Clear cannot
// acquire the subpool lock until the transaction addition is completed.
for acct, _ := range p.index {
p.reserve(acct, false)
}
p.lookup = make(map[common.Hash]uint64) p.lookup = make(map[common.Hash]uint64)
p.index = make(map[common.Address][]*blobTxMeta) p.index = make(map[common.Address][]*blobTxMeta)
p.spent = make(map[common.Address]*uint256.Int) p.spent = make(map[common.Address]*uint256.Int)

View file

@ -1968,6 +1968,28 @@ func (p *LegacyPool) Clear() {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
// unreserve each tracked account. Ideally, we could just clear the
// reservation map in the parent txpool context. However, if we clear in
// parent context, to avoid exposing the subpool lock, we have to lock the
// reservations and then lock each subpool.
//
// This creates the potential for a deadlock situation:
//
// * TxPool.Clear locks the reservations
// * a new transaction is received which locks the subpool mutex
// * TxPool.Clear attempts to lock subpool mutex
//
// The transaction addition may attempt to reserve the sender addr which
// can't happen until Clear releases the reservation lock. Clear cannot
// acquire the subpool lock until the transaction addition is completed.
for _, tx := range p.all.remotes {
senderAddr, _ := types.Sender(p.signer, tx)
p.reserve(senderAddr, false)
}
for localSender, _ := range p.locals.accounts {
p.reserve(localSender, false)
}
p.all = newLookup() p.all = newLookup()
p.priced = newPricedList(p.all) p.priced = newPricedList(p.all)
p.pending = make(map[common.Address]*list) p.pending = make(map[common.Address]*list)