@@ -565,8 +565,8 @@ class PeerManagerImpl final : public PeerManager
565
565
bool MaybeDiscourageAndDisconnect (CNode& pnode, Peer& peer);
566
566
567
567
struct PackageToValidate {
568
- const Package m_txns;
569
- const std::vector<NodeId> m_senders;
568
+ Package m_txns;
569
+ std::vector<NodeId> m_senders;
570
570
/* * Construct a 1-parent-1-child package. */
571
571
explicit PackageToValidate (const CTransactionRef& parent,
572
572
const CTransactionRef& child,
@@ -576,6 +576,16 @@ class PeerManagerImpl final : public PeerManager
576
576
m_senders {parent_sender, child_sender}
577
577
{}
578
578
579
+ // Move ctor
580
+ PackageToValidate (PackageToValidate&& other) : m_txns{std::move (other.m_txns )}, m_senders{std::move (other.m_senders )} {}
581
+
582
+ // Move assignment
583
+ PackageToValidate& operator =(PackageToValidate&& other) {
584
+ this ->m_txns = std::move (other.m_txns );
585
+ this ->m_senders = std::move (other.m_senders );
586
+ return *this ;
587
+ }
588
+
579
589
std::string ToString () const {
580
590
Assume (m_txns.size () == 2 );
581
591
return strprintf (" parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)" ,
@@ -589,11 +599,17 @@ class PeerManagerImpl final : public PeerManager
589
599
};
590
600
591
601
/* * Handle a transaction whose result was not MempoolAcceptResult::ResultType::VALID.
592
- * @param[in] first_time_failure Whether this tx should be added to vExtraTxnForCompact.
602
+ * @param[in] first_time_failure Whether we should consider inserting into vExtraTxnForCompact, adding
603
+ * a new orphan to resolve, or looking for a package to submit.
604
+ * Set to true for transactions just received over p2p.
593
605
* Set to false if the tx has already been rejected before,
594
- * e.g. is an orphan, to avoid adding duplicate entries.
595
- * Updates m_txrequest, m_lazy_recent_rejects, m_lazy_recent_rejects_reconsiderable, m_orphanage, and vExtraTxnForCompact. */
596
- void ProcessInvalidTx (NodeId nodeid, const CTransactionRef& tx, const TxValidationState& result,
606
+ * e.g. is already in the orphanage, to avoid adding duplicate entries.
607
+ * Updates m_txrequest, m_lazy_recent_rejects, m_lazy_recent_rejects_reconsiderable, m_orphanage, and vExtraTxnForCompact.
608
+ *
609
+ * @returns a PackageToValidate if this transaction has a reconsiderable failure and an eligible package was found,
610
+ * or std::nullopt otherwise.
611
+ */
612
+ std::optional<PackageToValidate> ProcessInvalidTx (NodeId nodeid, const CTransactionRef& tx, const TxValidationState& result,
597
613
bool first_time_failure)
598
614
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, m_tx_download_mutex);
599
615
@@ -2999,7 +3015,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
2999
3015
return ;
3000
3016
}
3001
3017
3002
- void PeerManagerImpl::ProcessInvalidTx (NodeId nodeid, const CTransactionRef& ptx, const TxValidationState& state,
3018
+ std::optional<PeerManagerImpl::PackageToValidate> PeerManagerImpl::ProcessInvalidTx (NodeId nodeid, const CTransactionRef& ptx, const TxValidationState& state,
3003
3019
bool first_time_failure)
3004
3020
{
3005
3021
AssertLockNotHeld (m_peer_mutex);
@@ -3017,6 +3033,8 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3017
3033
ptx->GetWitnessHash ().ToString (),
3018
3034
nodeid,
3019
3035
state.ToString ());
3036
+ // Populated if failure is reconsiderable and eligible package is found.
3037
+ std::optional<PackageToValidate> package_to_validate;
3020
3038
3021
3039
if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS) {
3022
3040
// Only process a new orphan if this is a first time failure, as otherwise it must be either
@@ -3097,7 +3115,7 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3097
3115
m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
3098
3116
}
3099
3117
}
3100
- return ;
3118
+ return std::nullopt ;
3101
3119
} else if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3102
3120
// We can add the wtxid of this transaction to our reject filter.
3103
3121
// Do not add txids of witness transactions or witness-stripped
@@ -3117,6 +3135,14 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3117
3135
// because we should not download or submit this transaction by itself again, but may
3118
3136
// submit it as part of a package later.
3119
3137
RecentRejectsReconsiderableFilter ().insert (ptx->GetWitnessHash ().ToUint256 ());
3138
+
3139
+ if (first_time_failure) {
3140
+ // When a transaction fails for TX_RECONSIDERABLE, look for a matching child in the
3141
+ // orphanage, as it is possible that they succeed as a package.
3142
+ LogDebug (BCLog::TXPACKAGES, " tx %s (wtxid=%s) failed but reconsiderable, looking for child in orphanage\n " ,
3143
+ ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ());
3144
+ package_to_validate = Find1P1CPackage (ptx, nodeid);
3145
+ }
3120
3146
} else {
3121
3147
RecentRejectsFilter ().insert (ptx->GetWitnessHash ().ToUint256 ());
3122
3148
}
@@ -3147,6 +3173,8 @@ void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx
3147
3173
if (Assume (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) && m_orphanage.EraseTx (ptx->GetWitnessHash ()) > 0 ) {
3148
3174
LogDebug (BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n " , ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ());
3149
3175
}
3176
+
3177
+ return package_to_validate;
3150
3178
}
3151
3179
3152
3180
void PeerManagerImpl::ProcessValidTx (NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)
@@ -4526,14 +4554,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4526
4554
pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
4527
4555
}
4528
4556
if (state.IsInvalid ()) {
4529
- ProcessInvalidTx (pfrom.GetId (), ptx, state, /* first_time_failure=*/ true );
4530
- }
4531
- // When a transaction fails for TX_RECONSIDERABLE, look for a matching child in the
4532
- // orphanage, as it is possible that they succeed as a package.
4533
- if (state.GetResult () == TxValidationResult::TX_RECONSIDERABLE) {
4534
- LogDebug (BCLog::TXPACKAGES, " tx %s (wtxid=%s) failed but reconsiderable, looking for child in orphanage\n " ,
4535
- txid.ToString (), wtxid.ToString ());
4536
- if (auto package_to_validate{Find1P1CPackage (ptx, pfrom.GetId ())}) {
4557
+ if (auto package_to_validate{ProcessInvalidTx (pfrom.GetId (), ptx, state, /* first_time_failure=*/ true )}) {
4537
4558
const auto package_result{ProcessNewPackage (m_chainman.ActiveChainstate (), m_mempool, package_to_validate->m_txns , /* test_accept=*/ false , /* client_maxfeerate=*/ std::nullopt)};
4538
4559
LogDebug (BCLog::TXPACKAGES, " package evaluation for %s: %s\n " , package_to_validate->ToString (),
4539
4560
package_result.m_state .IsValid () ? " package accepted" : " package rejected" );
0 commit comments