@@ -278,37 +278,36 @@ func New(config Config, chain BlockChain) *LegacyPool {
278278 // Sanitize the input to ensure no vulnerable gas prices are set
279279 config = (& config ).sanitize ()
280280
281- // Create the transaction pool with its initial settings
282- pool := & LegacyPool {
283- config : config ,
284- chain : chain ,
285- chainconfig : chain .Config (),
286- signer : types .LatestSigner (chain .Config ()),
287- pending : make (map [common.Address ]* list ),
288- cached : make (map [common.Address ]* list ),
289- queue : make (map [common.Address ]* list ),
290- beats : make (map [common.Address ]time.Time ),
291- all : newLookup (),
292- reqResetCh : make (chan * txpoolResetRequest ),
293- reqPromoteCh : make (chan * accountSet ),
294- queueTxEventCh : make (chan * types.Transaction ),
295- reorgDoneCh : make (chan chan struct {}),
296- reorgShutdownCh : make (chan struct {}),
297- initDoneCh : make (chan struct {}),
298- }
299- pool .locals = newAccountSet (pool .signer )
300- for _ , addr := range config .Locals {
301- log .Info ("Setting new local account" , "address" , addr )
302- pool .locals .add (addr )
303- }
304- pool .priced = newPricedList (pool .all )
305-
281+ // Create the transaction pool and its channels
282+ pool := NewStatic (config , chain )
283+ pool .reqResetCh = make (chan * txpoolResetRequest )
284+ pool .reqPromoteCh = make (chan * accountSet )
285+ pool .queueTxEventCh = make (chan * types.Transaction )
286+ pool .reorgDoneCh = make (chan chan struct {})
287+ pool .reorgShutdownCh = make (chan struct {})
288+ pool .initDoneCh = make (chan struct {})
306289 if ! config .NoLocals && config .Journal != "" {
307290 pool .journal = newTxJournal (config .Journal )
308291 }
309292 return pool
310293}
311294
295+ // NewStatic creates a new transaction pool without any channel
296+ // and journal. A pool created in this way should only be inited
297+ // with InitStatic.
298+ func NewStatic (config Config , chain BlockChain ) * LegacyPool {
299+ // Create the transaction pool with its initial settings
300+ pool := & LegacyPool {
301+ config : config ,
302+ chain : chain ,
303+ chainconfig : chain .Config (),
304+ signer : types .LatestSigner (chain .Config ()),
305+ }
306+ pool .setEmptyLists ()
307+ pool .setInitialLocals ()
308+ return pool
309+ }
310+
312311// Filter returns whether the given transaction can be consumed by the legacy
313312// pool, specifically, whether it is a Legacy, AccessList or Dynamic transaction.
314313func (pool * LegacyPool ) Filter (tx * types.Transaction ) bool {
@@ -325,6 +324,32 @@ func (pool *LegacyPool) Filter(tx *types.Transaction) bool {
325324// from disk and filtered based on the provided starting settings. The internal
326325// goroutines will be spun up and the pool deemed operational afterwards.
327326func (pool * LegacyPool ) Init (gasTip uint64 , head * types.Header , reserve txpool.AddressReserver ) error {
327+ // Do basic initializations about reserver, gas price and state
328+ pool .InitStatic (gasTip , head , reserve )
329+
330+ // Start the reorg loop early, so it can handle requests generated during
331+ // journal loading.
332+ pool .wg .Add (1 )
333+ go pool .scheduleReorgLoop ()
334+
335+ // If local transactions and journaling is enabled, load from disk
336+ if pool .journal != nil {
337+ if err := pool .journal .load (pool .addLocals ); err != nil {
338+ log .Warn ("Failed to load transaction journal" , "err" , err )
339+ }
340+ if err := pool .journal .rotate (pool .local ()); err != nil {
341+ log .Warn ("Failed to rotate transaction journal" , "err" , err )
342+ }
343+ }
344+ pool .wg .Add (1 )
345+ go pool .loop ()
346+ return nil
347+ }
348+
349+ // InitStatic sets the gas price needed to keep a transaction in the pool
350+ // and the chain head to allow balance / nonce checks. This method doesn't
351+ // start loops or load journals, so the pool can be released automatically.
352+ func (pool * LegacyPool ) InitStatic (gasTip uint64 , head * types.Header , reserve txpool.AddressReserver ) error {
328353 // Set the address reserver to request exclusive access to pooled accounts
329354 pool .reserve = reserve
330355
@@ -344,24 +369,34 @@ func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.A
344369 pool .currentHead .Store (head )
345370 pool .currentState = statedb
346371 pool .pendingNonces = newNoncer (statedb )
372+ return nil
373+ }
347374
348- // Start the reorg loop early, so it can handle requests generated during
349- // journal loading.
350- pool .wg .Add (1 )
351- go pool .scheduleReorgLoop ()
375+ // ResetStatic reverts any transaction insertion to a pool created by NewStatic
376+ // and inited by InitStatic, so that the pool can be reused as only initialized.
377+ func (pool * LegacyPool ) ResetStatic () {
378+ pool .setEmptyLists ()
379+ pool .setInitialLocals ()
380+ pool .pendingNonces = newNoncer (pool .currentState )
381+ }
352382
353- // If local transactions and journaling is enabled, load from disk
354- if pool .journal != nil {
355- if err := pool .journal .load (pool .addLocals ); err != nil {
356- log .Warn ("Failed to load transaction journal" , "err" , err )
357- }
358- if err := pool .journal .rotate (pool .local ()); err != nil {
359- log .Warn ("Failed to rotate transaction journal" , "err" , err )
360- }
383+ // setEmptyLists sets all transaction records of the pool to empty.
384+ func (pool * LegacyPool ) setEmptyLists () {
385+ pool .pending = make (map [common.Address ]* list )
386+ pool .cached = make (map [common.Address ]* list )
387+ pool .queue = make (map [common.Address ]* list )
388+ pool .beats = make (map [common.Address ]time.Time )
389+ pool .all = newLookup ()
390+ pool .priced = newPricedList (pool .all )
391+ }
392+
393+ // setInitialLocals resets the local accounts of the pool to initially configured.
394+ func (pool * LegacyPool ) setInitialLocals () {
395+ pool .locals = newAccountSet (pool .signer )
396+ for _ , addr := range pool .config .Locals {
397+ log .Info ("Setting new local account" , "address" , addr )
398+ pool .locals .add (addr )
361399 }
362- pool .wg .Add (1 )
363- go pool .loop ()
364- return nil
365400}
366401
367402// loop is the transaction pool's main event loop, waiting for and reacting to
@@ -475,21 +510,16 @@ func (pool *LegacyPool) loop() {
475510 }
476511}
477512
478- // CloseSilently is the same as Close(), but doesn't log. Intended to be used
479- // for short-lived verification pools (not the main node tx pool) .
480- func (pool * LegacyPool ) CloseSilently () {
513+ // Close terminates the transaction pool. If the pool is created through NewStatic
514+ // and inited through InitStatic, then this operation is not necessary .
515+ func (pool * LegacyPool ) Close () error {
481516 // Terminate the pool reorger and return
482517 close (pool .reorgShutdownCh )
483518 pool .wg .Wait ()
484519
485520 if pool .journal != nil {
486521 pool .journal .close ()
487522 }
488- }
489-
490- // Close terminates the transaction pool.
491- func (pool * LegacyPool ) Close () error {
492- pool .CloseSilently ()
493523 log .Info ("Transaction pool stopped" )
494524 return nil
495525}
@@ -1185,6 +1215,10 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, local, sync bool) []error
11851215 errs [nilSlot ] = err
11861216 nilSlot ++
11871217 }
1218+ // Return if no channel is initialized, ref NewStatic and InitStatic
1219+ if pool .reqPromoteCh == nil {
1220+ return errs
1221+ }
11881222 // Reorg the pool internals if needed and return
11891223 done := pool .requestPromoteExecutables (dirtyAddrs )
11901224 if sync {
0 commit comments