@@ -584,7 +584,7 @@ class PeerManagerImpl final : public PeerManager
584
584
* @param[in] maybe_add_extra_compact_tx Whether this tx should be added to vExtraTxnForCompact.
585
585
* Set to false if the tx has already been rejected before,
586
586
* e.g. is an orphan, to avoid adding duplicate entries.
587
- * Updates m_txrequest, m_recent_rejects, m_recent_rejects_reconsiderable , m_orphanage, and vExtraTxnForCompact. */
587
+ * Updates m_txrequest, m_lazy_recent_rejects, m_lazy_recent_rejects_reconsiderable , m_orphanage, and vExtraTxnForCompact. */
588
588
void ProcessInvalidTx (NodeId nodeid, const CTransactionRef& tx, const TxValidationState& result,
589
589
bool maybe_add_extra_compact_tx)
590
590
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, m_tx_download_mutex);
@@ -776,9 +776,9 @@ class PeerManagerImpl final : public PeerManager
776
776
/* * Synchronizes tx download including TxRequestTracker, rejection filters, and TxOrphanage.
777
777
* Lock invariants:
778
778
* - A txhash (txid or wtxid) in m_txrequest is not also in m_orphanage.
779
- * - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_rejects .
780
- * - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_rejects_reconsiderable .
781
- * - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_confirmed_transactions .
779
+ * - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_rejects .
780
+ * - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_rejects_reconsiderable .
781
+ * - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_confirmed_transactions .
782
782
* - Each data structure's limits hold (m_orphanage max size, m_txrequest per-peer limits, etc).
783
783
*/
784
784
Mutex m_tx_download_mutex ACQUIRED_BEFORE (m_mempool.cs);
@@ -856,9 +856,9 @@ class PeerManagerImpl final : public PeerManager
856
856
/* * Check whether we already have this gtxid in:
857
857
* - mempool
858
858
* - orphanage
859
- * - m_recent_rejects
860
- * - m_recent_rejects_reconsiderable (if include_reconsiderable = true)
861
- * - m_recent_confirmed_transactions
859
+ * - m_lazy_recent_rejects
860
+ * - m_lazy_recent_rejects_reconsiderable (if include_reconsiderable = true)
861
+ * - m_lazy_recent_confirmed_transactions
862
862
* */
863
863
bool AlreadyHaveTx (const GenTxid& gtxid, bool include_reconsiderable)
864
864
EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex);
@@ -897,15 +897,26 @@ class PeerManagerImpl final : public PeerManager
897
897
*
898
898
* Memory used: 1.3 MB
899
899
*/
900
- CRollingBloomFilter m_recent_rejects GUARDED_BY (m_tx_download_mutex){120'000 , 0.000'001 };
900
+ std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects GUARDED_BY (m_tx_download_mutex){nullptr };
901
+
902
+ CRollingBloomFilter& RecentRejectsFilter () EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex)
903
+ {
904
+ AssertLockHeld (m_tx_download_mutex);
905
+
906
+ if (!m_lazy_recent_rejects) {
907
+ m_lazy_recent_rejects = std::make_unique<CRollingBloomFilter>(120'000 , 0.000'001 );
908
+ }
909
+
910
+ return *m_lazy_recent_rejects;
911
+ }
901
912
902
913
/* *
903
914
* Filter for:
904
915
* (1) wtxids of transactions that were recently rejected by the mempool but are
905
916
* eligible for reconsideration if submitted with other transactions.
906
917
* (2) packages (see GetPackageHash) we have already rejected before and should not retry.
907
918
*
908
- * Similar to m_recent_rejects , this filter is used to save bandwidth when e.g. all of our peers
919
+ * Similar to m_lazy_recent_rejects , this filter is used to save bandwidth when e.g. all of our peers
909
920
* have larger mempools and thus lower minimum feerates than us.
910
921
*
911
922
* When a transaction's error is TxValidationResult::TX_RECONSIDERABLE (in a package or by
@@ -917,9 +928,20 @@ class PeerManagerImpl final : public PeerManager
917
928
*
918
929
* Reset this filter when the chain tip changes.
919
930
*
920
- * Parameters are picked to be the same as m_recent_rejects , with the same rationale.
931
+ * Parameters are picked to be the same as m_lazy_recent_rejects , with the same rationale.
921
932
*/
922
- CRollingBloomFilter m_recent_rejects_reconsiderable GUARDED_BY (m_tx_download_mutex){120'000 , 0.000'001 };
933
+ std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects_reconsiderable GUARDED_BY (m_tx_download_mutex){nullptr };
934
+
935
+ CRollingBloomFilter& RecentRejectsReconsiderableFilter () EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex)
936
+ {
937
+ AssertLockHeld (m_tx_download_mutex);
938
+
939
+ if (!m_lazy_recent_rejects_reconsiderable) {
940
+ m_lazy_recent_rejects_reconsiderable = std::make_unique<CRollingBloomFilter>(120'000 , 0.000'001 );
941
+ }
942
+
943
+ return *m_lazy_recent_rejects_reconsiderable;
944
+ }
923
945
924
946
/*
925
947
* Filter for transactions that have been recently confirmed.
@@ -936,7 +958,18 @@ class PeerManagerImpl final : public PeerManager
936
958
* transaction per day that would be inadvertently ignored (which is the
937
959
* same probability that we have in the reject filter).
938
960
*/
939
- CRollingBloomFilter m_recent_confirmed_transactions GUARDED_BY (m_tx_download_mutex){48'000 , 0.000'001 };
961
+ std::unique_ptr<CRollingBloomFilter> m_lazy_recent_confirmed_transactions GUARDED_BY (m_tx_download_mutex){nullptr };
962
+
963
+ CRollingBloomFilter& RecentConfirmedTransactionsFilter () EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex)
964
+ {
965
+ AssertLockHeld (m_tx_download_mutex);
966
+
967
+ if (!m_lazy_recent_confirmed_transactions) {
968
+ m_lazy_recent_confirmed_transactions = std::make_unique<CRollingBloomFilter>(48'000 , 0.000'001 );
969
+ }
970
+
971
+ return *m_lazy_recent_confirmed_transactions;
972
+ }
940
973
941
974
/* *
942
975
* For sending `inv`s to inbound peers, we use a single (exponentially
@@ -2080,8 +2113,8 @@ void PeerManagerImpl::ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd)
2080
2113
// If the chain tip has changed, previously rejected transactions might now be valid, e.g. due
2081
2114
// to a timelock. Reset the rejection filters to give those transactions another chance if we
2082
2115
// see them again.
2083
- m_recent_rejects .reset ();
2084
- m_recent_rejects_reconsiderable .reset ();
2116
+ RecentRejectsFilter () .reset ();
2117
+ RecentRejectsReconsiderableFilter () .reset ();
2085
2118
}
2086
2119
}
2087
2120
@@ -2119,9 +2152,9 @@ void PeerManagerImpl::BlockConnected(
2119
2152
m_orphanage.EraseForBlock (*pblock);
2120
2153
2121
2154
for (const auto & ptx : pblock->vtx ) {
2122
- m_recent_confirmed_transactions .insert (ptx->GetHash ().ToUint256 ());
2155
+ RecentConfirmedTransactionsFilter () .insert (ptx->GetHash ().ToUint256 ());
2123
2156
if (ptx->HasWitness ()) {
2124
- m_recent_confirmed_transactions .insert (ptx->GetWitnessHash ().ToUint256 ());
2157
+ RecentConfirmedTransactionsFilter () .insert (ptx->GetWitnessHash ().ToUint256 ());
2125
2158
}
2126
2159
m_txrequest.ForgetTxHash (ptx->GetHash ());
2127
2160
m_txrequest.ForgetTxHash (ptx->GetWitnessHash ());
@@ -2139,7 +2172,7 @@ void PeerManagerImpl::BlockDisconnected(const std::shared_ptr<const CBlock> &blo
2139
2172
// presumably the most common case of relaying a confirmed transaction
2140
2173
// should be just after a new block containing it is found.
2141
2174
LOCK (m_tx_download_mutex);
2142
- m_recent_confirmed_transactions .reset ();
2175
+ RecentConfirmedTransactionsFilter () .reset ();
2143
2176
}
2144
2177
2145
2178
/* *
@@ -2300,11 +2333,11 @@ bool PeerManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconside
2300
2333
if (m_orphanage.HaveTx (Wtxid::FromUint256 (hash))) return true ;
2301
2334
}
2302
2335
2303
- if (include_reconsiderable && m_recent_rejects_reconsiderable .contains (hash)) return true ;
2336
+ if (include_reconsiderable && RecentRejectsReconsiderableFilter () .contains (hash)) return true ;
2304
2337
2305
- if (m_recent_confirmed_transactions .contains (hash)) return true ;
2338
+ if (RecentConfirmedTransactionsFilter () .contains (hash)) return true ;
2306
2339
2307
- return m_recent_rejects .contains (hash) || m_mempool.exists (gtxid);
2340
+ return RecentRejectsFilter () .contains (hash) || m_mempool.exists (gtxid);
2308
2341
}
2309
2342
2310
2343
bool PeerManagerImpl::AlreadyHaveBlock (const uint256& block_hash)
@@ -3192,12 +3225,12 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3192
3225
// for concerns around weakening security of unupgraded nodes
3193
3226
// if we start doing this too early.
3194
3227
if (state.GetResult () == TxValidationResult::TX_RECONSIDERABLE) {
3195
- // If the result is TX_RECONSIDERABLE, add it to m_recent_rejects_reconsiderable
3228
+ // If the result is TX_RECONSIDERABLE, add it to m_lazy_recent_rejects_reconsiderable
3196
3229
// because we should not download or submit this transaction by itself again, but may
3197
3230
// submit it as part of a package later.
3198
- m_recent_rejects_reconsiderable .insert (ptx->GetWitnessHash ().ToUint256 ());
3231
+ RecentRejectsReconsiderableFilter () .insert (ptx->GetWitnessHash ().ToUint256 ());
3199
3232
} else {
3200
- m_recent_rejects .insert (ptx->GetWitnessHash ().ToUint256 ());
3233
+ RecentRejectsFilter () .insert (ptx->GetWitnessHash ().ToUint256 ());
3201
3234
}
3202
3235
m_txrequest.ForgetTxHash (ptx->GetWitnessHash ());
3203
3236
// If the transaction failed for TX_INPUTS_NOT_STANDARD,
@@ -3211,7 +3244,7 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3211
3244
// We only add the txid if it differs from the wtxid, to avoid wasting entries in the
3212
3245
// rolling bloom filter.
3213
3246
if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && ptx->HasWitness ()) {
3214
- m_recent_rejects .insert (ptx->GetHash ().ToUint256 ());
3247
+ RecentRejectsFilter () .insert (ptx->GetHash ().ToUint256 ());
3215
3248
m_txrequest.ForgetTxHash (ptx->GetHash ());
3216
3249
}
3217
3250
if (maybe_add_extra_compact_tx && RecursiveDynamicUsage (*ptx) < 100000 ) {
@@ -3266,7 +3299,7 @@ void PeerManagerImpl::ProcessPackageResult(const PackageToValidate& package_to_v
3266
3299
const auto & senders = package_to_validate.m_senders ;
3267
3300
3268
3301
if (package_result.m_state .IsInvalid ()) {
3269
- m_recent_rejects_reconsiderable .insert (GetPackageHash (package));
3302
+ RecentRejectsReconsiderableFilter () .insert (GetPackageHash (package));
3270
3303
}
3271
3304
// We currently only expect to process 1-parent-1-child packages. Remove if this changes.
3272
3305
if (!Assume (package.size () == 2 )) return ;
@@ -3320,7 +3353,7 @@ std::optional<PeerManagerImpl::PackageToValidate> PeerManagerImpl::Find1P1CPacka
3320
3353
3321
3354
const auto & parent_wtxid{ptx->GetWitnessHash ()};
3322
3355
3323
- Assume (m_recent_rejects_reconsiderable .contains (parent_wtxid.ToUint256 ()));
3356
+ Assume (RecentRejectsReconsiderableFilter () .contains (parent_wtxid.ToUint256 ()));
3324
3357
3325
3358
// Prefer children from this peer. This helps prevent censorship attempts in which an attacker
3326
3359
// sends lots of fake children for the parent, and we (unluckily) keep selecting the fake
@@ -3332,7 +3365,7 @@ std::optional<PeerManagerImpl::PackageToValidate> PeerManagerImpl::Find1P1CPacka
3332
3365
// most recent) one efficiently.
3333
3366
for (const auto & child : cpfp_candidates_same_peer) {
3334
3367
Package maybe_cpfp_package{ptx, child};
3335
- if (!m_recent_rejects_reconsiderable .contains (GetPackageHash (maybe_cpfp_package))) {
3368
+ if (!RecentRejectsReconsiderableFilter () .contains (GetPackageHash (maybe_cpfp_package))) {
3336
3369
return PeerManagerImpl::PackageToValidate{ptx, child, nodeid, nodeid};
3337
3370
}
3338
3371
}
@@ -3356,10 +3389,10 @@ std::optional<PeerManagerImpl::PackageToValidate> PeerManagerImpl::Find1P1CPacka
3356
3389
3357
3390
for (const auto index : tx_indices) {
3358
3391
// If we already tried a package and failed for any reason, the combined hash was
3359
- // cached in m_recent_rejects_reconsiderable .
3392
+ // cached in m_lazy_recent_rejects_reconsiderable .
3360
3393
const auto [child_tx, child_sender] = cpfp_candidates_different_peer.at (index);
3361
3394
Package maybe_cpfp_package{ptx, child_tx};
3362
- if (!m_recent_rejects_reconsiderable .contains (GetPackageHash (maybe_cpfp_package))) {
3395
+ if (!RecentRejectsReconsiderableFilter () .contains (GetPackageHash (maybe_cpfp_package))) {
3363
3396
return PeerManagerImpl::PackageToValidate{ptx, child_tx, nodeid, child_sender};
3364
3397
}
3365
3398
}
@@ -4551,8 +4584,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4551
4584
}
4552
4585
}
4553
4586
4554
- if (m_recent_rejects_reconsiderable .contains (wtxid)) {
4555
- // When a transaction is already in m_recent_rejects_reconsiderable , we shouldn't submit
4587
+ if (RecentRejectsReconsiderableFilter () .contains (wtxid)) {
4588
+ // When a transaction is already in m_lazy_recent_rejects_reconsiderable , we shouldn't submit
4556
4589
// it by itself again. However, look for a matching child in the orphanage, as it is
4557
4590
// possible that they succeed as a package.
4558
4591
LogPrint (BCLog::TXPACKAGES, " found tx %s (wtxid=%s) in reconsiderable rejects, looking for child in orphanage\n " ,
@@ -4564,20 +4597,20 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4564
4597
ProcessPackageResult (package_to_validate.value (), package_result);
4565
4598
}
4566
4599
}
4567
- // If a tx is detected by m_recent_rejects it is ignored. Because we haven't
4600
+ // If a tx is detected by m_lazy_recent_rejects it is ignored. Because we haven't
4568
4601
// submitted the tx to our mempool, we won't have computed a DoS
4569
4602
// score for it or determined exactly why we consider it invalid.
4570
4603
//
4571
4604
// This means we won't penalize any peer subsequently relaying a DoSy
4572
4605
// tx (even if we penalized the first peer who gave it to us) because
4573
- // we have to account for m_recent_rejects showing false positives. In
4606
+ // we have to account for m_lazy_recent_rejects showing false positives. In
4574
4607
// other words, we shouldn't penalize a peer if we aren't *sure* they
4575
4608
// submitted a DoSy tx.
4576
4609
//
4577
- // Note that m_recent_rejects doesn't just record DoSy or invalid
4610
+ // Note that m_lazy_recent_rejects doesn't just record DoSy or invalid
4578
4611
// transactions, but any tx not accepted by the mempool, which may be
4579
4612
// due to node policy (vs. consensus). So we can't blanket penalize a
4580
- // peer simply for relaying a tx that our m_recent_rejects has caught,
4613
+ // peer simply for relaying a tx that our m_lazy_recent_rejects has caught,
4581
4614
// regardless of false positives.
4582
4615
return ;
4583
4616
}
@@ -4604,16 +4637,16 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4604
4637
std::sort (unique_parents.begin (), unique_parents.end ());
4605
4638
unique_parents.erase (std::unique (unique_parents.begin (), unique_parents.end ()), unique_parents.end ());
4606
4639
4607
- // Distinguish between parents in m_recent_rejects and m_recent_rejects_reconsiderable .
4608
- // We can tolerate having up to 1 parent in m_recent_rejects_reconsiderable since we
4609
- // submit 1p1c packages. However, fail immediately if any are in m_recent_rejects .
4640
+ // Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable .
4641
+ // We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
4642
+ // submit 1p1c packages. However, fail immediately if any are in m_lazy_recent_rejects .
4610
4643
std::optional<uint256> rejected_parent_reconsiderable;
4611
4644
for (const uint256& parent_txid : unique_parents) {
4612
- if (m_recent_rejects .contains (parent_txid)) {
4645
+ if (RecentRejectsFilter () .contains (parent_txid)) {
4613
4646
fRejectedParents = true ;
4614
4647
break ;
4615
- } else if (m_recent_rejects_reconsiderable .contains (parent_txid) && !m_mempool.exists (GenTxid::Txid (parent_txid))) {
4616
- // More than 1 parent in m_recent_rejects_reconsiderable : 1p1c will not be
4648
+ } else if (RecentRejectsReconsiderableFilter () .contains (parent_txid) && !m_mempool.exists (GenTxid::Txid (parent_txid))) {
4649
+ // More than 1 parent in m_lazy_recent_rejects_reconsiderable : 1p1c will not be
4617
4650
// sufficient to accept this package, so just give up here.
4618
4651
if (rejected_parent_reconsiderable.has_value ()) {
4619
4652
fRejectedParents = true ;
@@ -4633,7 +4666,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4633
4666
// protocol for getting all unconfirmed parents.
4634
4667
const auto gtxid{GenTxid::Txid (parent_txid)};
4635
4668
AddKnownTx (*peer, parent_txid);
4636
- // Exclude m_recent_rejects_reconsiderable : the missing parent may have been
4669
+ // Exclude m_lazy_recent_rejects_reconsiderable : the missing parent may have been
4637
4670
// previously rejected for being too low feerate. This orphan might CPFP it.
4638
4671
if (!AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) AddTxAnnouncement (pfrom, gtxid, current_time);
4639
4672
}
@@ -4658,8 +4691,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4658
4691
// regardless of what witness is provided, we will not accept
4659
4692
// this, so we don't need to allow for redownload of this txid
4660
4693
// from any of our non-wtxidrelay peers.
4661
- m_recent_rejects .insert (tx.GetHash ().ToUint256 ());
4662
- m_recent_rejects .insert (tx.GetWitnessHash ().ToUint256 ());
4694
+ RecentRejectsFilter () .insert (tx.GetHash ().ToUint256 ());
4695
+ RecentRejectsFilter () .insert (tx.GetWitnessHash ().ToUint256 ());
4663
4696
m_txrequest.ForgetTxHash (tx.GetHash ());
4664
4697
m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4665
4698
}
@@ -6306,7 +6339,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
6306
6339
entry.second .GetHash ().ToString (), entry.first );
6307
6340
}
6308
6341
for (const GenTxid& gtxid : requestable) {
6309
- // Exclude m_recent_rejects_reconsiderable : we may be requesting a missing parent
6342
+ // Exclude m_lazy_recent_rejects_reconsiderable : we may be requesting a missing parent
6310
6343
// that was previously rejected for being too low feerate.
6311
6344
if (!AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
6312
6345
LogPrint (BCLog::NET, " Requesting %s %s peer=%d\n " , gtxid.IsWtxid () ? " wtx" : " tx" ,
0 commit comments