@@ -272,14 +272,7 @@ HerderImpl::shutdown()
272
272
" Shutdown interrupting quorum transitive closure analysis." );
273
273
mLastQuorumMapIntersectionState .mInterruptFlag = true ;
274
274
}
275
- if (mTransactionQueue )
276
- {
277
- mTransactionQueue ->shutdown ();
278
- }
279
- if (mSorobanTransactionQueue )
280
- {
281
- mSorobanTransactionQueue ->shutdown ();
282
- }
275
+ mTransactionQueues ->shutdown ();
283
276
284
277
mTxSetGarbageCollectTimer .cancel ();
285
278
}
@@ -589,22 +582,35 @@ HerderImpl::emitEnvelope(SCPEnvelope const& envelope)
589
582
broadcast (envelope);
590
583
}
591
584
585
+ // TODO: Move to Herder.cpp?
592
586
TransactionQueue::AddResult
593
- HerderImpl::recvTransaction (TransactionFrameBasePtr tx, bool submittedFromSelf)
587
+ Herder::recvTransaction (TransactionQueuesPtr txQueues,
588
+ TransactionFrameBasePtr tx, bool submittedFromSelf)
594
589
{
595
590
ZoneScoped;
591
+ ClassicTransactionQueue& classicTxQueue =
592
+ txQueues->getClassicTransactionQueue ();
596
593
TransactionQueue::AddResult result (
597
594
TransactionQueue::AddResultCode::ADD_STATUS_COUNT);
598
595
599
596
// Allow txs of the same kind to reach the tx queue in case it can be
600
597
// replaced by fee
598
+ // TODO: Is there a potential TOCTOU issue here as sourceAccountPending
599
+ // could change before adding? I think no because the other competing thread
600
+ // would be whatever is handling ledger close. However, that will only
601
+ // decrease the sourceAccountPending value, which means this erroneously
602
+ // rejects (which is safe). I guess it's possible for a user-submitted
603
+ // transaction to come in and conflict with the overlay thread, but that
604
+ // would require them to be simultaneously running two clients and
605
+ // submitting from both of them. Still, it might be safest to use some kind
606
+ // of atomic function that handles both this check AND the add.
601
607
bool hasSoroban =
602
- mSorobanTransactionQueue &&
603
- mSorobanTransactionQueue ->sourceAccountPending (tx->getSourceID ()) &&
608
+ txQueues->hasSorobanTransactionQueue () &&
609
+ txQueues->getSorobanTransactionQueue ().sourceAccountPending (
610
+ tx->getSourceID ()) &&
604
611
!tx->isSoroban ();
605
- bool hasClassic =
606
- mTransactionQueue ->sourceAccountPending (tx->getSourceID ()) &&
607
- tx->isSoroban ();
612
+ bool hasClassic = classicTxQueue.sourceAccountPending (tx->getSourceID ()) &&
613
+ tx->isSoroban ();
608
614
if (hasSoroban || hasClassic)
609
615
{
610
616
CLOG_DEBUG (Herder,
@@ -617,31 +623,12 @@ HerderImpl::recvTransaction(TransactionFrameBasePtr tx, bool submittedFromSelf)
617
623
}
618
624
else if (!tx->isSoroban ())
619
625
{
620
- if (mApp .getConfig ().BACKGROUND_TX_QUEUE && !submittedFromSelf)
621
- {
622
- mApp .postOnOverlayThread (
623
- [this , tx]() { mTransactionQueue ->tryAdd (tx, false ); },
624
- " try add tx" );
625
- result.code = TransactionQueue::AddResultCode::ADD_STATUS_UNKNOWN;
626
- }
627
- else
628
- {
629
- result = mTransactionQueue ->tryAdd (tx, submittedFromSelf);
630
- }
626
+ result = classicTxQueue.tryAdd (tx, submittedFromSelf);
631
627
}
632
- else if (mSorobanTransactionQueue )
628
+ else if (txQueues-> hasSorobanTransactionQueue () )
633
629
{
634
- if (mApp .getConfig ().BACKGROUND_TX_QUEUE && !submittedFromSelf)
635
- {
636
- mApp .postOnOverlayThread (
637
- [this , tx]() { mSorobanTransactionQueue ->tryAdd (tx, false ); },
638
- " try add tx" );
639
- result.code = TransactionQueue::AddResultCode::ADD_STATUS_UNKNOWN;
640
- }
641
- else
642
- {
643
- result = mSorobanTransactionQueue ->tryAdd (tx, submittedFromSelf);
644
- }
630
+ result = txQueues->getSorobanTransactionQueue ().tryAdd (
631
+ tx, submittedFromSelf);
645
632
}
646
633
else
647
634
{
@@ -661,6 +648,13 @@ HerderImpl::recvTransaction(TransactionFrameBasePtr tx, bool submittedFromSelf)
661
648
return result;
662
649
}
663
650
651
+ TransactionQueue::AddResult
652
+ HerderImpl::recvTransaction (TransactionFrameBasePtr tx, bool submittedFromSelf)
653
+ {
654
+ ZoneScoped;
655
+ return Herder::recvTransaction (mTransactionQueues , tx, submittedFromSelf);
656
+ }
657
+
664
658
bool
665
659
HerderImpl::checkCloseTime (SCPEnvelope const & envelope, bool enforceRecent)
666
660
{
@@ -943,13 +937,7 @@ HerderImpl::externalizeValue(TxSetXDRFrameConstPtr txSet, uint32_t ledgerSeq,
943
937
bool
944
938
HerderImpl::sourceAccountPending (AccountID const & accountID) const
945
939
{
946
- bool accPending = mTransactionQueue ->sourceAccountPending (accountID);
947
- if (mSorobanTransactionQueue )
948
- {
949
- accPending = accPending ||
950
- mSorobanTransactionQueue ->sourceAccountPending (accountID);
951
- }
952
- return accPending;
940
+ return mTransactionQueues ->sourceAccountPending (accountID);
953
941
}
954
942
955
943
#endif
@@ -1112,13 +1100,12 @@ HerderImpl::getPendingEnvelopes()
1112
1100
ClassicTransactionQueue&
1113
1101
HerderImpl::getTransactionQueue ()
1114
1102
{
1115
- return * mTransactionQueue ;
1103
+ return mTransactionQueues -> getClassicTransactionQueue () ;
1116
1104
}
1117
1105
SorobanTransactionQueue&
1118
1106
HerderImpl::getSorobanTransactionQueue ()
1119
1107
{
1120
- releaseAssert (mSorobanTransactionQueue );
1121
- return *mSorobanTransactionQueue ;
1108
+ return mTransactionQueues ->getSorobanTransactionQueue ();
1122
1109
}
1123
1110
#endif
1124
1111
@@ -1411,14 +1398,16 @@ HerderImpl::triggerNextLedger(uint32_t ledgerSeqToTrigger,
1411
1398
// it's guaranteed to be up-to-date
1412
1399
auto const & lcl = mLedgerManager .getLastClosedLedgerHeader ();
1413
1400
PerPhaseTransactionList txPhases;
1414
- txPhases.emplace_back (mTransactionQueue ->getTransactions (lcl.header ));
1401
+ txPhases.emplace_back (
1402
+ mTransactionQueues ->getClassicTransactionQueue ().getTransactions (
1403
+ lcl.header ));
1415
1404
1416
1405
if (protocolVersionStartsFrom (lcl.header .ledgerVersion ,
1417
1406
SOROBAN_PROTOCOL_VERSION))
1418
1407
{
1419
- releaseAssert (mSorobanTransactionQueue );
1420
1408
txPhases.emplace_back (
1421
- mSorobanTransactionQueue ->getTransactions (lcl.header ));
1409
+ mTransactionQueues ->getSorobanTransactionQueue ().getTransactions (
1410
+ lcl.header ));
1422
1411
}
1423
1412
1424
1413
// We pick as next close time the current time unless it's before the last
@@ -1485,12 +1474,11 @@ HerderImpl::triggerNextLedger(uint32_t ledgerSeqToTrigger,
1485
1474
if (protocolVersionStartsFrom (lcl.header .ledgerVersion ,
1486
1475
SOROBAN_PROTOCOL_VERSION))
1487
1476
{
1488
- releaseAssert (mSorobanTransactionQueue );
1489
- mSorobanTransactionQueue ->ban (
1477
+ mTransactionQueues ->getSorobanTransactionQueue ().ban (
1490
1478
invalidTxPhases[static_cast <size_t >(TxSetPhase::SOROBAN)]);
1491
1479
}
1492
1480
1493
- mTransactionQueue -> ban (
1481
+ mTransactionQueues -> getClassicTransactionQueue (). ban (
1494
1482
invalidTxPhases[static_cast <size_t >(TxSetPhase::CLASSIC)]);
1495
1483
1496
1484
auto txSetHash = proposedSet->getContentsHash ();
@@ -2190,18 +2178,18 @@ HerderImpl::maybeSetupSorobanQueue(uint32_t protocolVersion)
2190
2178
{
2191
2179
if (protocolVersionStartsFrom (protocolVersion, SOROBAN_PROTOCOL_VERSION))
2192
2180
{
2193
- if (!mSorobanTransactionQueue )
2181
+ if (!mTransactionQueues -> hasSorobanTransactionQueue () )
2194
2182
{
2195
2183
releaseAssert (mTxQueueBucketSnapshot );
2196
- mSorobanTransactionQueue =
2184
+ mTransactionQueues -> setSorobanTransactionQueue (
2197
2185
std::make_unique<SorobanTransactionQueue>(
2198
2186
mApp , mTxQueueBucketSnapshot ,
2199
2187
TRANSACTION_QUEUE_TIMEOUT_LEDGERS,
2200
2188
TRANSACTION_QUEUE_BAN_LEDGERS,
2201
- SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER);
2189
+ SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER)) ;
2202
2190
}
2203
2191
}
2204
- else if (mSorobanTransactionQueue )
2192
+ else if (mTransactionQueues -> hasSorobanTransactionQueue () )
2205
2193
{
2206
2194
throw std::runtime_error (
2207
2195
" Invalid state: Soroban queue initialized before v20" );
@@ -2215,10 +2203,10 @@ HerderImpl::start()
2215
2203
mTxQueueBucketSnapshot = mApp .getBucketManager ()
2216
2204
.getBucketSnapshotManager ()
2217
2205
.copySearchableLiveBucketListSnapshot ();
2218
- releaseAssert (! mTransactionQueue );
2219
- mTransactionQueue = std::make_unique<ClassicTransactionQueue>(
2220
- mApp , mTxQueueBucketSnapshot , TRANSACTION_QUEUE_TIMEOUT_LEDGERS,
2221
- TRANSACTION_QUEUE_BAN_LEDGERS, TRANSACTION_QUEUE_SIZE_MULTIPLIER);
2206
+ mTransactionQueues -> setClassicTransactionQueue (
2207
+ std::make_unique<ClassicTransactionQueue>(
2208
+ mApp , mTxQueueBucketSnapshot , TRANSACTION_QUEUE_TIMEOUT_LEDGERS,
2209
+ TRANSACTION_QUEUE_BAN_LEDGERS, TRANSACTION_QUEUE_SIZE_MULTIPLIER) );
2222
2210
2223
2211
mMaxTxSize = mApp .getHerder ().getMaxClassicTxSize ();
2224
2212
{
@@ -2378,18 +2366,18 @@ HerderImpl::updateTransactionQueue(TxSetXDRFrameConstPtr externalizedTxSet)
2378
2366
.maybeCopySearchableBucketListSnapshot (mTxQueueBucketSnapshot );
2379
2367
if (txsPerPhase.size () > static_cast <size_t >(TxSetPhase::CLASSIC))
2380
2368
{
2381
- mTransactionQueue -> update (
2369
+ mTransactionQueues -> getClassicTransactionQueue (). update (
2382
2370
txsPerPhase[static_cast <size_t >(TxSetPhase::CLASSIC)], lhhe.header ,
2383
2371
mTxQueueBucketSnapshot , filterInvalidTxs);
2384
2372
}
2385
2373
2386
2374
// Even if we're in protocol 20, still check for number of phases, in case
2387
2375
// we're dealing with the upgrade ledger that contains old-style transaction
2388
2376
// set
2389
- if (mSorobanTransactionQueue != nullptr &&
2377
+ if (mTransactionQueues -> hasSorobanTransactionQueue () &&
2390
2378
txsPerPhase.size () > static_cast <size_t >(TxSetPhase::SOROBAN))
2391
2379
{
2392
- mSorobanTransactionQueue -> update (
2380
+ mTransactionQueues -> getSorobanTransactionQueue (). update (
2393
2381
txsPerPhase[static_cast <size_t >(TxSetPhase::SOROBAN)], lhhe.header ,
2394
2382
mTxQueueBucketSnapshot , filterInvalidTxs);
2395
2383
}
@@ -2508,37 +2496,34 @@ HerderImpl::isNewerNominationOrBallotSt(SCPStatement const& oldSt,
2508
2496
size_t
2509
2497
HerderImpl::getMaxQueueSizeOps () const
2510
2498
{
2511
- return mTransactionQueue ->getMaxQueueSizeOps ();
2499
+ return mTransactionQueues ->getClassicTransactionQueue ()
2500
+ .getMaxQueueSizeOps ();
2512
2501
}
2513
2502
2514
2503
size_t
2515
2504
HerderImpl::getMaxQueueSizeSorobanOps () const
2516
2505
{
2517
- return mSorobanTransactionQueue
2518
- ? mSorobanTransactionQueue ->getMaxQueueSizeOps ()
2506
+ return mTransactionQueues ->hasSorobanTransactionQueue ()
2507
+ ? mTransactionQueues ->getSorobanTransactionQueue ()
2508
+ .getMaxQueueSizeOps ()
2519
2509
: 0 ;
2520
2510
}
2521
2511
2522
2512
bool
2523
2513
HerderImpl::isBannedTx (Hash const & hash) const
2524
2514
{
2525
- auto banned = mTransactionQueue ->isBanned (hash);
2526
- if (mSorobanTransactionQueue )
2527
- {
2528
- banned = banned || mSorobanTransactionQueue ->isBanned (hash);
2529
- }
2530
- return banned;
2515
+ return mTransactionQueues ->isBanned (hash);
2531
2516
}
2532
2517
2533
2518
TransactionFrameBaseConstPtr
2534
2519
HerderImpl::getTx (Hash const & hash) const
2535
2520
{
2536
- auto classic = mTransactionQueue ->getTx (hash);
2537
- if (!classic && mSorobanTransactionQueue )
2538
- {
2539
- return mSorobanTransactionQueue -> getTx (hash);
2540
- }
2541
- return classic ;
2521
+ return mTransactionQueues ->getTx (hash);
2522
+ }
2523
+
2524
+ TransactionQueuesPtr HerderImpl::getTransactionQueues () const {
2525
+ releaseAssert ( mTransactionQueues );
2526
+ return mTransactionQueues ;
2542
2527
}
2543
2528
2544
2529
}
0 commit comments