@@ -98,8 +98,8 @@ type TransactionPool struct {
9898 // exceed the txPoolMaxSize. This flag is reset to false OnNewBlock
9999 stateproofOverflowed bool
100100
101- testEvalCtx * testEvalContext
102- testEvalCtxMu deadlock.RWMutex
101+ testBlockEvaluator * eval. TestBlockEvaluator
102+ testBlockEvaluatorMu deadlock.RWMutex
103103
104104 // shutdown is set to true when the pool is being shut down. It is checked in exported methods
105105 // to prevent pool operations like remember and recomputing the block evaluator
@@ -109,7 +109,6 @@ type TransactionPool struct {
109109
110110// BlockEvaluator defines the block evaluator interface exposed by the ledger package.
111111type BlockEvaluator interface {
112- TestTransactionGroup (txgroup []transactions.SignedTxn ) error
113112 Round () basics.Round
114113 PaySetSize () int
115114 TransactionGroup (txads []transactions.SignedTxnWithAD ) error
@@ -118,30 +117,33 @@ type BlockEvaluator interface {
118117 ResetTxnBytes ()
119118}
120119
121- // testEvalContext implements the eval.TestEvalContext interface.
120+ // testEvalContext implements the eval.TestEvalContext interface. It allows for concurrent
121+ // calls to TestTransactionGroup for candidate transactions calling transactionPool.Test.
122122type testEvalContext struct {
123123 ledger * ledger.Ledger
124124 block bookkeeping.Block
125125 proto config.ConsensusParams
126126 specials transactions.SpecialAddresses
127127}
128128
129- func newTestEvalCtx (ledger * ledger.Ledger , block bookkeeping.Block ) * testEvalContext {
130- return & testEvalContext {
131- ledger : ledger ,
132- block : block ,
133- proto : config .Consensus [block .CurrentProtocol ],
134- specials : transactions.SpecialAddresses {
135- FeeSink : block .FeeSink ,
136- RewardsPool : block .RewardsPool ,
137- },
138- }
129+ func newTestBlockEvaluator (ledger * ledger.Ledger , block bookkeeping.Block ) * eval.TestBlockEvaluator {
130+ return & eval.TestBlockEvaluator {
131+ TestEvalContext : & testEvalContext {
132+ ledger : ledger ,
133+ block : block ,
134+ proto : config .Consensus [block .CurrentProtocol ],
135+ specials : transactions.SpecialAddresses {
136+ FeeSink : block .FeeSink ,
137+ RewardsPool : block .RewardsPool ,
138+ },
139+ }}
139140}
140141
141142func (c * testEvalContext ) Proto () config.ConsensusParams { return c .proto }
142143func (c * testEvalContext ) Specials () transactions.SpecialAddresses { return c .specials }
143144func (c * testEvalContext ) TxnContext () transactions.TxnContext { return c .block }
144145func (c * testEvalContext ) CheckDup (firstValid , lastValid basics.Round , txid transactions.Txid , txl ledgercore.Txlease ) error {
146+ // will call txTail.checkDup, which uses an RLock for concurrent access.
145147 return c .ledger .CheckDup (c .proto , c .block .BlockHeader .Round , firstValid , lastValid , txid , txl )
146148}
147149
@@ -421,19 +423,20 @@ func (pool *TransactionPool) checkSufficientFee(txgroup []transactions.SignedTxn
421423
422424// Test performs basic duplicate detection and well-formedness checks
423425// on a transaction group without storing the group.
426+ // It may be called concurrently.
424427func (pool * TransactionPool ) Test (txgroup []transactions.SignedTxn ) error {
425428 if err := pool .checkPendingQueueSize (txgroup ); err != nil {
426429 return err
427430 }
428431
429- pool .testEvalCtxMu .RLock ()
430- defer pool .testEvalCtxMu .RUnlock ()
432+ pool .testBlockEvaluatorMu .RLock ()
433+ defer pool .testBlockEvaluatorMu .RUnlock ()
431434
432- if pool .testEvalCtx == nil {
435+ if pool .testBlockEvaluator == nil {
433436 return fmt .Errorf ("Test: testEvalCtx is nil" )
434437 }
435438
436- return eval . TestTransactionGroup (pool . testEvalCtx , txgroup )
439+ return pool . testBlockEvaluator . TestTransactionGroup (txgroup )
437440}
438441
439442type poolIngestParams struct {
@@ -780,9 +783,9 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIDs map[transact
780783 return
781784 }
782785
783- pool .testEvalCtxMu .Lock ()
784- pool .testEvalCtx = newTestEvalCtx (pool .ledger , next )
785- pool .testEvalCtxMu .Unlock ()
786+ pool .testBlockEvaluatorMu .Lock ()
787+ pool .testBlockEvaluator = newTestBlockEvaluator (pool .ledger , next )
788+ pool .testBlockEvaluatorMu .Unlock ()
786789
787790 var asmStats telemetryspec.AssembleBlockMetrics
788791 asmStats .StartCount = len (txgroups )
0 commit comments