@@ -3006,8 +3006,11 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3006
3006
AssertLockHeld (g_msgproc_mutex);
3007
3007
AssertLockHeld (m_tx_download_mutex);
3008
3008
3009
+ PeerRef peer{GetPeerRef (nodeid)};
3010
+
3009
3011
auto & m_orphanage = m_txdownloadman.GetOrphanageRef ();
3010
3012
auto & m_txrequest = m_txdownloadman.GetTxRequestRef ();
3013
+ const CTransaction& tx{*ptx};
3011
3014
3012
3015
LogDebug (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
3013
3016
ptx->GetHash ().ToString (),
@@ -3016,6 +3019,84 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3016
3019
state.ToString ());
3017
3020
3018
3021
if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS) {
3022
+ // Only process a new orphan if this is a first time failure, as otherwise it must be either
3023
+ // already in orphanage or from 1p1c processing.
3024
+ if (first_time_failure) {
3025
+ bool fRejectedParents = false ; // It may be the case that the orphans parents have all been rejected
3026
+
3027
+ // Deduplicate parent txids, so that we don't have to loop over
3028
+ // the same parent txid more than once down below.
3029
+ std::vector<uint256> unique_parents;
3030
+ unique_parents.reserve (tx.vin .size ());
3031
+ for (const CTxIn& txin : tx.vin ) {
3032
+ // We start with all parents, and then remove duplicates below.
3033
+ unique_parents.push_back (txin.prevout .hash );
3034
+ }
3035
+ std::sort (unique_parents.begin (), unique_parents.end ());
3036
+ unique_parents.erase (std::unique (unique_parents.begin (), unique_parents.end ()), unique_parents.end ());
3037
+
3038
+ // Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable.
3039
+ // We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
3040
+ // submit 1p1c packages. However, fail immediately if any are in m_lazy_recent_rejects.
3041
+ std::optional<uint256> rejected_parent_reconsiderable;
3042
+ for (const uint256& parent_txid : unique_parents) {
3043
+ if (RecentRejectsFilter ().contains (parent_txid)) {
3044
+ fRejectedParents = true ;
3045
+ break ;
3046
+ } else if (RecentRejectsReconsiderableFilter ().contains (parent_txid) && !m_mempool.exists (GenTxid::Txid (parent_txid))) {
3047
+ // More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
3048
+ // sufficient to accept this package, so just give up here.
3049
+ if (rejected_parent_reconsiderable.has_value ()) {
3050
+ fRejectedParents = true ;
3051
+ break ;
3052
+ }
3053
+ rejected_parent_reconsiderable = parent_txid;
3054
+ }
3055
+ }
3056
+ if (!fRejectedParents ) {
3057
+ const auto current_time{GetTime<std::chrono::microseconds>()};
3058
+
3059
+ for (const uint256& parent_txid : unique_parents) {
3060
+ // Here, we only have the txid (and not wtxid) of the
3061
+ // inputs, so we only request in txid mode, even for
3062
+ // wtxidrelay peers.
3063
+ // Eventually we should replace this with an improved
3064
+ // protocol for getting all unconfirmed parents.
3065
+ const auto gtxid{GenTxid::Txid (parent_txid)};
3066
+ if (peer) AddKnownTx (*peer, parent_txid);
3067
+ // Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
3068
+ // previously rejected for being too low feerate. This orphan might CPFP it.
3069
+ if (!m_txdownloadman.AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
3070
+ m_txdownloadman.AddTxAnnouncement (nodeid, gtxid, current_time, /* p2p_inv=*/ false );
3071
+ }
3072
+ }
3073
+
3074
+ if (m_orphanage.AddTx (ptx, nodeid)) {
3075
+ AddToCompactExtraTransactions (ptx);
3076
+ }
3077
+
3078
+ // Once added to the orphan pool, a tx is considered AlreadyHave, and we shouldn't request it anymore.
3079
+ m_txrequest.ForgetTxHash (tx.GetHash ());
3080
+ m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
3081
+
3082
+ // DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789)
3083
+ m_orphanage.LimitOrphans (m_opts.max_orphan_txs , m_rng);
3084
+ } else {
3085
+ LogDebug (BCLog::MEMPOOL, " not keeping orphan with rejected parents %s (wtxid=%s)\n " ,
3086
+ tx.GetHash ().ToString (),
3087
+ tx.GetWitnessHash ().ToString ());
3088
+ // We will continue to reject this tx since it has rejected
3089
+ // parents so avoid re-requesting it from other peers.
3090
+ // Here we add both the txid and the wtxid, as we know that
3091
+ // regardless of what witness is provided, we will not accept
3092
+ // this, so we don't need to allow for redownload of this txid
3093
+ // from any of our non-wtxidrelay peers.
3094
+ RecentRejectsFilter ().insert (tx.GetHash ().ToUint256 ());
3095
+ RecentRejectsFilter ().insert (tx.GetWitnessHash ().ToUint256 ());
3096
+ m_txrequest.ForgetTxHash (tx.GetHash ());
3097
+ m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
3098
+ }
3099
+ }
3019
3100
return ;
3020
3101
} else if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3021
3102
// We can add the wtxid of this transaction to our reject filter.
@@ -4375,7 +4456,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4375
4456
LOCK2 (cs_main, m_tx_download_mutex);
4376
4457
4377
4458
auto & m_txrequest = m_txdownloadman.GetTxRequestRef ();
4378
- auto & m_orphanage = m_txdownloadman.GetOrphanageRef ();
4379
4459
4380
4460
m_txrequest.ReceivedResponse (pfrom.GetId (), txid);
4381
4461
if (tx.HasWitness ()) m_txrequest.ReceivedResponse (pfrom.GetId (), wtxid);
@@ -4445,83 +4525,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4445
4525
ProcessValidTx (pfrom.GetId (), ptx, result.m_replaced_transactions );
4446
4526
pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
4447
4527
}
4448
- else if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS)
4449
- {
4450
- bool fRejectedParents = false ; // It may be the case that the orphans parents have all been rejected
4451
-
4452
- // Deduplicate parent txids, so that we don't have to loop over
4453
- // the same parent txid more than once down below.
4454
- std::vector<uint256> unique_parents;
4455
- unique_parents.reserve (tx.vin .size ());
4456
- for (const CTxIn& txin : tx.vin ) {
4457
- // We start with all parents, and then remove duplicates below.
4458
- unique_parents.push_back (txin.prevout .hash );
4459
- }
4460
- std::sort (unique_parents.begin (), unique_parents.end ());
4461
- unique_parents.erase (std::unique (unique_parents.begin (), unique_parents.end ()), unique_parents.end ());
4462
-
4463
- // Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable.
4464
- // We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
4465
- // submit 1p1c packages. However, fail immediately if any are in m_lazy_recent_rejects.
4466
- std::optional<uint256> rejected_parent_reconsiderable;
4467
- for (const uint256& parent_txid : unique_parents) {
4468
- if (RecentRejectsFilter ().contains (parent_txid)) {
4469
- fRejectedParents = true ;
4470
- break ;
4471
- } else if (RecentRejectsReconsiderableFilter ().contains (parent_txid) && !m_mempool.exists (GenTxid::Txid (parent_txid))) {
4472
- // More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
4473
- // sufficient to accept this package, so just give up here.
4474
- if (rejected_parent_reconsiderable.has_value ()) {
4475
- fRejectedParents = true ;
4476
- break ;
4477
- }
4478
- rejected_parent_reconsiderable = parent_txid;
4479
- }
4480
- }
4481
- if (!fRejectedParents ) {
4482
- const auto current_time{GetTime<std::chrono::microseconds>()};
4483
-
4484
- for (const uint256& parent_txid : unique_parents) {
4485
- // Here, we only have the txid (and not wtxid) of the
4486
- // inputs, so we only request in txid mode, even for
4487
- // wtxidrelay peers.
4488
- // Eventually we should replace this with an improved
4489
- // protocol for getting all unconfirmed parents.
4490
- const auto gtxid{GenTxid::Txid (parent_txid)};
4491
- AddKnownTx (*peer, parent_txid);
4492
- // Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
4493
- // previously rejected for being too low feerate. This orphan might CPFP it.
4494
- if (!m_txdownloadman.AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
4495
- m_txdownloadman.AddTxAnnouncement (pfrom.GetId (), gtxid, current_time, /* p2p_inv=*/ false );
4496
- }
4497
- }
4498
-
4499
- if (m_orphanage.AddTx (ptx, pfrom.GetId ())) {
4500
- AddToCompactExtraTransactions (ptx);
4501
- }
4502
-
4503
- // Once added to the orphan pool, a tx is considered AlreadyHave, and we shouldn't request it anymore.
4504
- m_txrequest.ForgetTxHash (tx.GetHash ());
4505
- m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4506
-
4507
- // DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789)
4508
- m_orphanage.LimitOrphans (m_opts.max_orphan_txs , m_rng);
4509
- } else {
4510
- LogDebug (BCLog::MEMPOOL, " not keeping orphan with rejected parents %s (wtxid=%s)\n " ,
4511
- tx.GetHash ().ToString (),
4512
- tx.GetWitnessHash ().ToString ());
4513
- // We will continue to reject this tx since it has rejected
4514
- // parents so avoid re-requesting it from other peers.
4515
- // Here we add both the txid and the wtxid, as we know that
4516
- // regardless of what witness is provided, we will not accept
4517
- // this, so we don't need to allow for redownload of this txid
4518
- // from any of our non-wtxidrelay peers.
4519
- RecentRejectsFilter ().insert (tx.GetHash ().ToUint256 ());
4520
- RecentRejectsFilter ().insert (tx.GetWitnessHash ().ToUint256 ());
4521
- m_txrequest.ForgetTxHash (tx.GetHash ());
4522
- m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4523
- }
4524
- }
4525
4528
if (state.IsInvalid ()) {
4526
4529
ProcessInvalidTx (pfrom.GetId (), ptx, state, /* first_time_failure=*/ true );
4527
4530
}
0 commit comments