attempt at making txpool Add sync param work

This commit is contained in:
Jared Wasinger 2025-04-04 12:35:48 +02:00
parent a7f24c26c0
commit c5055a88b3
4 changed files with 66 additions and 14 deletions

View file

@ -19,6 +19,7 @@ package legacypool
import ( import (
"errors" "errors"
"fmt"
"maps" "maps"
"math" "math"
"math/big" "math/big"
@ -246,7 +247,7 @@ type LegacyPool struct {
priced *pricedList // All transactions sorted by price priced *pricedList // All transactions sorted by price
reqResetCh chan *txpoolResetRequest reqResetCh chan *txpoolResetRequest
reqPromoteCh chan *accountSet reqPromoteCh chan *reqPromote
queueTxEventCh chan *types.Transaction queueTxEventCh chan *types.Transaction
reorgDoneCh chan chan struct{} reorgDoneCh chan chan struct{}
reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop
@ -258,6 +259,7 @@ type LegacyPool struct {
type txpoolResetRequest struct { type txpoolResetRequest struct {
oldHead, newHead *types.Header oldHead, newHead *types.Header
done chan struct{}
} }
// New creates a new transaction pool to gather, sort and filter inbound // New creates a new transaction pool to gather, sort and filter inbound
@ -277,7 +279,7 @@ func New(config Config, chain BlockChain) *LegacyPool {
beats: make(map[common.Address]time.Time), beats: make(map[common.Address]time.Time),
all: newLookup(), all: newLookup(),
reqResetCh: make(chan *txpoolResetRequest), reqResetCh: make(chan *txpoolResetRequest),
reqPromoteCh: make(chan *accountSet), reqPromoteCh: make(chan *reqPromote),
queueTxEventCh: make(chan *types.Transaction), queueTxEventCh: make(chan *types.Transaction),
reorgDoneCh: make(chan chan struct{}), reorgDoneCh: make(chan chan struct{}),
reorgShutdownCh: make(chan struct{}), reorgShutdownCh: make(chan struct{}),
@ -962,6 +964,9 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
pool.mu.Lock() pool.mu.Lock()
newErrs, dirtyAddrs := pool.addTxsLocked(news) newErrs, dirtyAddrs := pool.addTxsLocked(news)
pool.mu.Unlock() pool.mu.Unlock()
for _, new := range news {
fmt.Printf("prepare tx for queue %x\n", new.Hash())
}
var nilSlot = 0 var nilSlot = 0
for _, err := range newErrs { for _, err := range newErrs {
@ -972,9 +977,11 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
nilSlot++ nilSlot++
} }
// Reorg the pool internals if needed and return // Reorg the pool internals if needed and return
done := pool.requestPromoteExecutables(dirtyAddrs) req := &reqPromote{dirtyAddrs, make(chan struct{})}
pool.requestPromoteExecutables(req)
if sync { if sync {
<-done <-req.done
fmt.Printf("done adding txs %v\n", txs[0])
} }
return errs return errs
} }
@ -1140,9 +1147,10 @@ func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bo
// requestReset requests a pool reset to the new head block. // requestReset requests a pool reset to the new head block.
// The returned channel is closed when the reset has occurred. // The returned channel is closed when the reset has occurred.
func (pool *LegacyPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} { func (pool *LegacyPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} {
req := &txpoolResetRequest{oldHead, newHead, make(chan struct{})}
select { select {
case pool.reqResetCh <- &txpoolResetRequest{oldHead, newHead}: case pool.reqResetCh <- req:
return <-pool.reorgDoneCh return req.done
case <-pool.reorgShutdownCh: case <-pool.reorgShutdownCh:
return pool.reorgShutdownCh return pool.reorgShutdownCh
} }
@ -1150,10 +1158,10 @@ func (pool *LegacyPool) requestReset(oldHead *types.Header, newHead *types.Heade
// requestPromoteExecutables requests transaction promotion checks for the given addresses. // requestPromoteExecutables requests transaction promotion checks for the given addresses.
// The returned channel is closed when the promotion checks have occurred. // The returned channel is closed when the promotion checks have occurred.
func (pool *LegacyPool) requestPromoteExecutables(set *accountSet) chan struct{} { func (pool *LegacyPool) requestPromoteExecutables(req *reqPromote) chan struct{} {
select { select {
case pool.reqPromoteCh <- set: case pool.reqPromoteCh <- req:
return <-pool.reorgDoneCh return req.done
case <-pool.reorgShutdownCh: case <-pool.reorgShutdownCh:
return pool.reorgShutdownCh return pool.reorgShutdownCh
} }
@ -1174,6 +1182,8 @@ func (pool *LegacyPool) scheduleReorgLoop() {
defer pool.wg.Done() defer pool.wg.Done()
var ( var (
curDones []chan struct{}
nextDones []chan struct{}
curDone chan struct{} // non-nil while runReorg is active curDone chan struct{} // non-nil while runReorg is active
nextDone = make(chan struct{}) nextDone = make(chan struct{})
launchNextRun bool launchNextRun bool
@ -1184,11 +1194,15 @@ func (pool *LegacyPool) scheduleReorgLoop() {
for { for {
// Launch next background reorg if needed // Launch next background reorg if needed
if curDone == nil && launchNextRun { if curDone == nil && launchNextRun {
fmt.Printf("initiating reorg with dones %v\n", nextDones)
fmt.Printf("initiating reorg with dirty accounts: %v\n", dirtyAccounts)
// Run the background reorg and announcements // Run the background reorg and announcements
go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents) go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents)
// Prepare everything for the next round of reorg // Prepare everything for the next round of reorg
curDone, nextDone = nextDone, make(chan struct{}) curDone, nextDone = nextDone, make(chan struct{})
curDones, nextDones = nextDones, []chan struct{}{}
launchNextRun = false launchNextRun = false
reset, dirtyAccounts = nil, nil reset, dirtyAccounts = nil, nil
@ -1203,20 +1217,37 @@ func (pool *LegacyPool) scheduleReorgLoop() {
} else { } else {
reset.newHead = req.newHead reset.newHead = req.newHead
} }
fmt.Printf("reset: appending to next dones %v\n", req.done)
nextDones = append(nextDones, req.done)
launchNextRun = true launchNextRun = true
pool.reorgDoneCh <- nextDone //pool.reorgDoneCh <- nextDone
case req := <-pool.reqPromoteCh: case req := <-pool.reqPromoteCh:
select {
case tx := <-pool.queueTxEventCh:
fmt.Printf("queue tx %x\n", tx.Hash())
// Queue up the event, but don't schedule a reorg. It's up to the caller to
// request one later if they want the events sent.
addr, _ := types.Sender(pool.signer, tx)
if _, ok := queuedEvents[addr]; !ok {
queuedEvents[addr] = NewSortedMap()
}
queuedEvents[addr].Put(tx)
default:
}
// Promote request: update address set if request is already pending. // Promote request: update address set if request is already pending.
if dirtyAccounts == nil { if dirtyAccounts == nil {
dirtyAccounts = req dirtyAccounts = req.set
} else { } else {
dirtyAccounts.merge(req) dirtyAccounts.merge(req.set)
} }
fmt.Printf("promote executables: appending to next dones %v\n", req.done)
nextDones = append(nextDones, req.done)
launchNextRun = true launchNextRun = true
pool.reorgDoneCh <- nextDone //pool.reorgDoneCh <- nextDone
case tx := <-pool.queueTxEventCh: case tx := <-pool.queueTxEventCh:
fmt.Printf("queue tx %x\n", tx.Hash())
// Queue up the event, but don't schedule a reorg. It's up to the caller to // Queue up the event, but don't schedule a reorg. It's up to the caller to
// request one later if they want the events sent. // request one later if they want the events sent.
addr, _ := types.Sender(pool.signer, tx) addr, _ := types.Sender(pool.signer, tx)
@ -1226,12 +1257,24 @@ func (pool *LegacyPool) scheduleReorgLoop() {
queuedEvents[addr].Put(tx) queuedEvents[addr].Put(tx)
case <-curDone: case <-curDone:
fmt.Println("reorg done")
for _, ch := range curDones {
fmt.Println(ch)
close(ch)
}
fmt.Println("end reorg done")
curDone = nil curDone = nil
case <-pool.reorgShutdownCh: case <-pool.reorgShutdownCh:
// Wait for current run to finish. // Wait for current run to finish.
if curDone != nil { if curDone != nil {
fmt.Println("shutdown reorg done")
<-curDone <-curDone
for _, ch := range curDones {
fmt.Println(ch)
close(ch)
}
fmt.Println("end reorg done")
} }
close(nextDone) close(nextDone)
return return
@ -1309,6 +1352,7 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest,
if _, ok := events[addr]; !ok { if _, ok := events[addr]; !ok {
events[addr] = NewSortedMap() events[addr] = NewSortedMap()
} }
fmt.Printf("promoted tx %v\n", tx.Hash())
events[addr].Put(tx) events[addr].Put(tx)
} }
if len(events) > 0 { if len(events) > 0 {
@ -1429,6 +1473,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T
// Iterate over all accounts and promote any executable transactions // Iterate over all accounts and promote any executable transactions
gasLimit := pool.currentHead.Load().GasLimit gasLimit := pool.currentHead.Load().GasLimit
for _, addr := range accounts { for _, addr := range accounts {
fmt.Printf("promoteExecutables %x\n", addr)
list := pool.queue[addr] list := pool.queue[addr]
if list == nil { if list == nil {
continue // Just in case someone calls with a non existing account continue // Just in case someone calls with a non existing account
@ -1687,6 +1732,11 @@ type accountSet struct {
cache []common.Address cache []common.Address
} }
type reqPromote struct {
set *accountSet
done chan struct{}
}
// newAccountSet creates a new address set with an associated signer for sender // newAccountSet creates a new address set with an associated signer for sender
// derivations. // derivations.
func newAccountSet(signer types.Signer, addrs ...common.Address) *accountSet { func newAccountSet(signer types.Signer, addrs ...common.Address) *accountSet {

View file

@ -361,6 +361,7 @@ func (p *TxPool) Add(txs []*types.Transaction, sync bool) []error {
splits := make([]int, len(txs)) splits := make([]int, len(txs))
for i, tx := range txs { for i, tx := range txs {
fmt.Printf("txpool attempting to add %v\n", tx.Hash())
// Mark this transaction belonging to no-subpool // Mark this transaction belonging to no-subpool
splits[i] = -1 splits[i] = -1

View file

@ -119,6 +119,7 @@ func TestEth2AssembleBlock(t *testing.T) {
t.Fatalf("error signing transaction, err=%v", err) t.Fatalf("error signing transaction, err=%v", err)
} }
ethservice.TxPool().Add([]*types.Transaction{tx}, true) ethservice.TxPool().Add([]*types.Transaction{tx}, true)
fmt.Println("in test: added txs")
blockParams := engine.PayloadAttributes{ blockParams := engine.PayloadAttributes{
Timestamp: blocks[9].Time() + 5, Timestamp: blocks[9].Time() + 5,
} }

@ -1 +1 @@
Subproject commit 81862e4848585a438d64f911a19b3825f0f4cd95 Subproject commit faf33b471465d3c6cdc3d04fbd690895f78d33f2