Skip to content

Commit 71b32b4

Browse files
jwasingerfjl
authored andcommitted
core/txpool, eth/catalyst: clear transaction pool in Rollback (#30534)
This adds an API method `DropTransactions` to legacy pool, blob pool and txpool interface. This method removes all txs currently tracked in the pools. It modifies the simulated beacon to use the new method in `Rollback` which removes previous hacky implementation that also erroneously reset the gas tip to 1 gwei. --------- Co-authored-by: Felix Lange <[email protected]>
1 parent 9e959db commit 71b32b4

File tree

5 files changed

+102
-8
lines changed

5 files changed

+102
-8
lines changed

core/txpool/blobpool/blobpool.go

+50
Original file line numberDiff line numberDiff line change
@@ -1714,3 +1714,53 @@ func (p *BlobPool) Status(hash common.Hash) txpool.TxStatus {
17141714
}
17151715
return txpool.TxStatusUnknown
17161716
}
1717+
1718+
// Clear implements txpool.SubPool, removing all tracked transactions
1719+
// from the blob pool and persistent store.
1720+
func (p *BlobPool) Clear() {
1721+
p.lock.Lock()
1722+
defer p.lock.Unlock()
1723+
1724+
// manually iterating and deleting every entry is super sub-optimal
1725+
// However, Clear is not currently used in production so
1726+
// performance is not critical at the moment.
1727+
for hash := range p.lookup.txIndex {
1728+
id, _ := p.lookup.storeidOfTx(hash)
1729+
if err := p.store.Delete(id); err != nil {
1730+
log.Warn("failed to delete blob tx from backing store", "err", err)
1731+
}
1732+
}
1733+
for hash := range p.lookup.blobIndex {
1734+
id, _ := p.lookup.storeidOfBlob(hash)
1735+
if err := p.store.Delete(id); err != nil {
1736+
log.Warn("failed to delete blob from backing store", "err", err)
1737+
}
1738+
}
1739+
1740+
// unreserve each tracked account. Ideally, we could just clear the
1741+
// reservation map in the parent txpool context. However, if we clear in
1742+
// parent context, to avoid exposing the subpool lock, we have to lock the
1743+
// reservations and then lock each subpool.
1744+
//
1745+
// This creates the potential for a deadlock situation:
1746+
//
1747+
// * TxPool.Clear locks the reservations
1748+
// * a new transaction is received which locks the subpool mutex
1749+
// * TxPool.Clear attempts to lock subpool mutex
1750+
//
1751+
// The transaction addition may attempt to reserve the sender addr which
1752+
// can't happen until Clear releases the reservation lock. Clear cannot
1753+
// acquire the subpool lock until the transaction addition is completed.
1754+
for acct, _ := range p.index {
1755+
p.reserve(acct, false)
1756+
}
1757+
p.lookup = newLookup()
1758+
p.index = make(map[common.Address][]*blobTxMeta)
1759+
p.spent = make(map[common.Address]*uint256.Int)
1760+
1761+
var (
1762+
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head))
1763+
blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
1764+
)
1765+
p.evict = newPriceHeap(basefee, blobfee, p.index)
1766+
}

core/txpool/legacypool/legacypool.go

+41
Original file line numberDiff line numberDiff line change
@@ -1961,3 +1961,44 @@ func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
19611961
func numSlots(tx *types.Transaction) int {
19621962
return int((tx.Size() + txSlotSize - 1) / txSlotSize)
19631963
}
1964+
1965+
// Clear implements txpool.SubPool, removing all tracked txs from the pool
1966+
// and rotating the journal.
1967+
func (pool *LegacyPool) Clear() {
1968+
pool.mu.Lock()
1969+
defer pool.mu.Unlock()
1970+
1971+
// unreserve each tracked account. Ideally, we could just clear the
1972+
// reservation map in the parent txpool context. However, if we clear in
1973+
// parent context, to avoid exposing the subpool lock, we have to lock the
1974+
// reservations and then lock each subpool.
1975+
//
1976+
// This creates the potential for a deadlock situation:
1977+
//
1978+
// * TxPool.Clear locks the reservations
1979+
// * a new transaction is received which locks the subpool mutex
1980+
// * TxPool.Clear attempts to lock subpool mutex
1981+
//
1982+
// The transaction addition may attempt to reserve the sender addr which
1983+
// can't happen until Clear releases the reservation lock. Clear cannot
1984+
// acquire the subpool lock until the transaction addition is completed.
1985+
for _, tx := range pool.all.remotes {
1986+
senderAddr, _ := types.Sender(pool.signer, tx)
1987+
pool.reserve(senderAddr, false)
1988+
}
1989+
for localSender, _ := range pool.locals.accounts {
1990+
pool.reserve(localSender, false)
1991+
}
1992+
1993+
pool.all = newLookup()
1994+
pool.priced = newPricedList(pool.all)
1995+
pool.pending = make(map[common.Address]*list)
1996+
pool.queue = make(map[common.Address]*list)
1997+
1998+
if !pool.config.NoLocals && pool.config.Journal != "" {
1999+
pool.journal = newTxJournal(pool.config.Journal)
2000+
if err := pool.journal.rotate(pool.local()); err != nil {
2001+
log.Warn("Failed to rotate transaction journal", "err", err)
2002+
}
2003+
}
2004+
}

core/txpool/subpool.go

+3
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,7 @@ type SubPool interface {
168168
// Status returns the known status (unknown/pending/queued) of a transaction
169169
// identified by their hashes.
170170
Status(hash common.Hash) TxStatus
171+
172+
// Clear removes all tracked transactions from the pool
173+
Clear()
171174
}

core/txpool/txpool.go

+7
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,10 @@ func (p *TxPool) Sync() error {
497497
return errors.New("pool already terminated")
498498
}
499499
}
500+
501+
// Clear removes all tracked txs from the subpools.
502+
func (p *TxPool) Clear() {
503+
for _, subpool := range p.subpools {
504+
subpool.Clear()
505+
}
506+
}

eth/catalyst/simulated_beacon.go

+1-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"crypto/sha256"
2222
"errors"
2323
"fmt"
24-
"math/big"
2524
"sync"
2625
"time"
2726

@@ -34,7 +33,6 @@ import (
3433
"github.com/ethereum/go-ethereum/event"
3534
"github.com/ethereum/go-ethereum/log"
3635
"github.com/ethereum/go-ethereum/node"
37-
"github.com/ethereum/go-ethereum/params"
3836
"github.com/ethereum/go-ethereum/rpc"
3937
)
4038

@@ -287,12 +285,7 @@ func (c *SimulatedBeacon) Commit() common.Hash {
287285

288286
// Rollback un-sends previously added transactions.
289287
func (c *SimulatedBeacon) Rollback() {
290-
// Flush all transactions from the transaction pools
291-
maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
292-
c.eth.TxPool().SetGasTip(maxUint256)
293-
// Set the gas tip back to accept new transactions
294-
// TODO (Marius van der Wijden): set gas tip to parameter passed by config
295-
c.eth.TxPool().SetGasTip(big.NewInt(params.GWei))
288+
c.eth.TxPool().Clear()
296289
}
297290

298291
// Fork sets the head to the provided hash.

0 commit comments

Comments
 (0)