@@ -582,6 +582,20 @@ class PeerManagerImpl final : public PeerManager
582
582
*/
583
583
bool MaybeDiscourageAndDisconnect (CNode& pnode, Peer& peer);
584
584
585
+ /* * Handle a transaction whose result was not MempoolAcceptResult::ResultType::VALID.
586
+ * @param[in] maybe_add_extra_compact_tx Whether this tx should be added to vExtraTxnForCompact.
587
+ * Set to false if the tx has already been rejected before,
588
+ * e.g. is an orphan, to avoid adding duplicate entries.
589
+ * Updates m_txrequest, m_recent_rejects, m_orphanage, and vExtraTxnForCompact. */
590
+ void ProcessInvalidTx (NodeId nodeid, const CTransactionRef& tx, const TxValidationState& result,
591
+ bool maybe_add_extra_compact_tx)
592
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
593
+
594
+ /* * Handle a transaction whose result was MempoolAcceptResult::ResultType::VALID.
595
+ * Updates m_txrequest, m_orphanage, and vExtraTxnForCompact. Also queues the tx for relay. */
596
+ void ProcessValidTx (NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)
597
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
598
+
585
599
/* *
586
600
* Reconsider orphan transactions after a parent has been accepted to the mempool.
587
601
*
@@ -3054,6 +3068,91 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
3054
3068
return ;
3055
3069
}
3056
3070
3071
+ void PeerManagerImpl::ProcessInvalidTx (NodeId nodeid, const CTransactionRef& ptx, const TxValidationState& state,
3072
+ bool maybe_add_extra_compact_tx)
3073
+ {
3074
+ AssertLockNotHeld (m_peer_mutex);
3075
+ AssertLockHeld (g_msgproc_mutex);
3076
+ AssertLockHeld (cs_main);
3077
+
3078
+ LogDebug (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
3079
+ ptx->GetHash ().ToString (),
3080
+ ptx->GetWitnessHash ().ToString (),
3081
+ nodeid,
3082
+ state.ToString ());
3083
+
3084
+ if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS) {
3085
+ return ;
3086
+ } else if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3087
+ // We can add the wtxid of this transaction to our reject filter.
3088
+ // Do not add txids of witness transactions or witness-stripped
3089
+ // transactions to the filter, as they can have been malleated;
3090
+ // adding such txids to the reject filter would potentially
3091
+ // interfere with relay of valid transactions from peers that
3092
+ // do not support wtxid-based relay. See
3093
+ // https://github.com/bitcoin/bitcoin/issues/8279 for details.
3094
+ // We can remove this restriction (and always add wtxids to
3095
+ // the filter even for witness stripped transactions) once
3096
+ // wtxid-based relay is broadly deployed.
3097
+ // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
3098
+ // for concerns around weakening security of unupgraded nodes
3099
+ // if we start doing this too early.
3100
+ m_recent_rejects.insert (ptx->GetWitnessHash ().ToUint256 ());
3101
+ m_txrequest.ForgetTxHash (ptx->GetWitnessHash ());
3102
+ // If the transaction failed for TX_INPUTS_NOT_STANDARD,
3103
+ // then we know that the witness was irrelevant to the policy
3104
+ // failure, since this check depends only on the txid
3105
+ // (the scriptPubKey being spent is covered by the txid).
3106
+ // Add the txid to the reject filter to prevent repeated
3107
+ // processing of this transaction in the event that child
3108
+ // transactions are later received (resulting in
3109
+ // parent-fetching by txid via the orphan-handling logic).
3110
+ if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && ptx->HasWitness ()) {
3111
+ m_recent_rejects.insert (ptx->GetHash ().ToUint256 ());
3112
+ m_txrequest.ForgetTxHash (ptx->GetHash ());
3113
+ }
3114
+ if (maybe_add_extra_compact_tx && RecursiveDynamicUsage (*ptx) < 100000 ) {
3115
+ AddToCompactExtraTransactions (ptx);
3116
+ }
3117
+ }
3118
+
3119
+ MaybePunishNodeForTx (nodeid, state);
3120
+
3121
+ // If the tx failed in ProcessOrphanTx, it should be removed from the orphanage unless the
3122
+ // tx was still missing inputs. If the tx was not in the orphanage, EraseTx does nothing and returns 0.
3123
+ if (Assume (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) && m_orphanage.EraseTx (ptx->GetHash ()) > 0 ) {
3124
+ LogDebug (BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n " , ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ());
3125
+ }
3126
+ }
3127
+
3128
+ void PeerManagerImpl::ProcessValidTx (NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)
3129
+ {
3130
+ AssertLockNotHeld (m_peer_mutex);
3131
+ AssertLockHeld (g_msgproc_mutex);
3132
+ AssertLockHeld (cs_main);
3133
+
3134
+ // As this version of the transaction was acceptable, we can forget about any requests for it.
3135
+ // No-op if the tx is not in txrequest.
3136
+ m_txrequest.ForgetTxHash (tx->GetHash ());
3137
+ m_txrequest.ForgetTxHash (tx->GetWitnessHash ());
3138
+
3139
+ m_orphanage.AddChildrenToWorkSet (*tx);
3140
+ // If it came from the orphanage, remove it. No-op if the tx is not in txorphanage.
3141
+ m_orphanage.EraseTx (tx->GetHash ());
3142
+
3143
+ LogDebug (BCLog::MEMPOOL, " AcceptToMemoryPool: peer=%d: accepted %s (wtxid=%s) (poolsz %u txn, %u kB)\n " ,
3144
+ nodeid,
3145
+ tx->GetHash ().ToString (),
3146
+ tx->GetWitnessHash ().ToString (),
3147
+ m_mempool.size (), m_mempool.DynamicMemoryUsage () / 1000 );
3148
+
3149
+ RelayTransaction (tx->GetHash (), tx->GetWitnessHash ());
3150
+
3151
+ for (const CTransactionRef& removedTx : replaced_transactions) {
3152
+ AddToCompactExtraTransactions (removedTx);
3153
+ }
3154
+ }
3155
+
3057
3156
bool PeerManagerImpl::ProcessOrphanTx (Peer& peer)
3058
3157
{
3059
3158
AssertLockHeld (g_msgproc_mutex);
@@ -3069,66 +3168,23 @@ bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3069
3168
3070
3169
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
3071
3170
LogPrint (BCLog::TXPACKAGES, " accepted orphan tx %s (wtxid=%s)\n " , orphanHash.ToString (), orphan_wtxid.ToString ());
3072
- LogPrint (BCLog::MEMPOOL, " AcceptToMemoryPool: peer=%d: accepted %s (wtxid=%s) (poolsz %u txn, %u kB)\n " ,
3073
- peer.m_id ,
3074
- orphanHash.ToString (),
3075
- orphan_wtxid.ToString (),
3076
- m_mempool.size (), m_mempool.DynamicMemoryUsage () / 1000 );
3077
- RelayTransaction (orphanHash, porphanTx->GetWitnessHash ());
3078
- m_orphanage.AddChildrenToWorkSet (*porphanTx);
3079
- m_orphanage.EraseTx (orphanHash);
3080
- for (const CTransactionRef& removedTx : result.m_replaced_transactions .value ()) {
3081
- AddToCompactExtraTransactions (removedTx);
3082
- }
3171
+ Assume (result.m_replaced_transactions .has_value ());
3172
+ std::list<CTransactionRef> empty_replacement_list;
3173
+ ProcessValidTx (peer.m_id , porphanTx, result.m_replaced_transactions .value_or (empty_replacement_list));
3083
3174
return true ;
3084
3175
} else if (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) {
3085
- if (state.IsInvalid ()) {
3086
- LogPrint (BCLog::TXPACKAGES, " invalid orphan tx %s (wtxid=%s) from peer=%d. %s\n " ,
3087
- orphanHash.ToString (),
3088
- orphan_wtxid.ToString (),
3089
- peer.m_id ,
3090
- state.ToString ());
3091
- LogPrint (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
3092
- orphanHash.ToString (),
3093
- orphan_wtxid.ToString (),
3094
- peer.m_id ,
3095
- state.ToString ());
3096
- // Maybe punish peer that gave us an invalid orphan tx
3097
- MaybePunishNodeForTx (peer.m_id , state);
3098
- }
3099
- // Has inputs but not accepted to mempool
3100
- // Probably non-standard or insufficient fee
3101
- LogPrint (BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n " , orphanHash.ToString (), orphan_wtxid.ToString ());
3102
- if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3103
- // We can add the wtxid of this transaction to our reject filter.
3104
- // Do not add txids of witness transactions or witness-stripped
3105
- // transactions to the filter, as they can have been malleated;
3106
- // adding such txids to the reject filter would potentially
3107
- // interfere with relay of valid transactions from peers that
3108
- // do not support wtxid-based relay. See
3109
- // https://github.com/bitcoin/bitcoin/issues/8279 for details.
3110
- // We can remove this restriction (and always add wtxids to
3111
- // the filter even for witness stripped transactions) once
3112
- // wtxid-based relay is broadly deployed.
3113
- // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
3114
- // for concerns around weakening security of unupgraded nodes
3115
- // if we start doing this too early.
3116
- m_recent_rejects.insert (porphanTx->GetWitnessHash ().ToUint256 ());
3117
- // If the transaction failed for TX_INPUTS_NOT_STANDARD,
3118
- // then we know that the witness was irrelevant to the policy
3119
- // failure, since this check depends only on the txid
3120
- // (the scriptPubKey being spent is covered by the txid).
3121
- // Add the txid to the reject filter to prevent repeated
3122
- // processing of this transaction in the event that child
3123
- // transactions are later received (resulting in
3124
- // parent-fetching by txid via the orphan-handling logic).
3125
- if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && porphanTx->HasWitness ()) {
3126
- // We only add the txid if it differs from the wtxid, to
3127
- // avoid wasting entries in the rolling bloom filter.
3128
- m_recent_rejects.insert (porphanTx->GetHash ().ToUint256 ());
3129
- }
3176
+ LogPrint (BCLog::TXPACKAGES, " invalid orphan tx %s (wtxid=%s) from peer=%d. %s\n " ,
3177
+ orphanHash.ToString (),
3178
+ orphan_wtxid.ToString (),
3179
+ peer.m_id ,
3180
+ state.ToString ());
3181
+
3182
+ if (Assume (state.IsInvalid () &&
3183
+ state.GetResult () != TxValidationResult::TX_UNKNOWN &&
3184
+ state.GetResult () != TxValidationResult::TX_NO_MEMPOOL &&
3185
+ state.GetResult () != TxValidationResult::TX_RESULT_UNSET)) {
3186
+ ProcessInvalidTx (peer.m_id , porphanTx, state, /* maybe_add_extra_compact_tx=*/ false );
3130
3187
}
3131
- m_orphanage.EraseTx (orphanHash);
3132
3188
return true ;
3133
3189
}
3134
3190
}
@@ -4298,24 +4354,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4298
4354
const TxValidationState& state = result.m_state ;
4299
4355
4300
4356
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
4301
- // As this version of the transaction was acceptable, we can forget about any
4302
- // requests for it.
4303
- m_txrequest.ForgetTxHash (tx.GetHash ());
4304
- m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4305
- RelayTransaction (tx.GetHash (), tx.GetWitnessHash ());
4306
- m_orphanage.AddChildrenToWorkSet (tx);
4307
-
4357
+ ProcessValidTx (pfrom.GetId (), ptx, result.m_replaced_transactions .value ());
4308
4358
pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
4309
-
4310
- LogPrint (BCLog::MEMPOOL, " AcceptToMemoryPool: peer=%d: accepted %s (wtxid=%s) (poolsz %u txn, %u kB)\n " ,
4311
- pfrom.GetId (),
4312
- tx.GetHash ().ToString (),
4313
- tx.GetWitnessHash ().ToString (),
4314
- m_mempool.size (), m_mempool.DynamicMemoryUsage () / 1000 );
4315
-
4316
- for (const CTransactionRef& removedTx : result.m_replaced_transactions .value ()) {
4317
- AddToCompactExtraTransactions (removedTx);
4318
- }
4319
4359
}
4320
4360
else if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS)
4321
4361
{
@@ -4376,48 +4416,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4376
4416
m_txrequest.ForgetTxHash (tx.GetHash ());
4377
4417
m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4378
4418
}
4379
- } else {
4380
- if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
4381
- // We can add the wtxid of this transaction to our reject filter.
4382
- // Do not add txids of witness transactions or witness-stripped
4383
- // transactions to the filter, as they can have been malleated;
4384
- // adding such txids to the reject filter would potentially
4385
- // interfere with relay of valid transactions from peers that
4386
- // do not support wtxid-based relay. See
4387
- // https://github.com/bitcoin/bitcoin/issues/8279 for details.
4388
- // We can remove this restriction (and always add wtxids to
4389
- // the filter even for witness stripped transactions) once
4390
- // wtxid-based relay is broadly deployed.
4391
- // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
4392
- // for concerns around weakening security of unupgraded nodes
4393
- // if we start doing this too early.
4394
- m_recent_rejects.insert (tx.GetWitnessHash ().ToUint256 ());
4395
- m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4396
- // If the transaction failed for TX_INPUTS_NOT_STANDARD,
4397
- // then we know that the witness was irrelevant to the policy
4398
- // failure, since this check depends only on the txid
4399
- // (the scriptPubKey being spent is covered by the txid).
4400
- // Add the txid to the reject filter to prevent repeated
4401
- // processing of this transaction in the event that child
4402
- // transactions are later received (resulting in
4403
- // parent-fetching by txid via the orphan-handling logic).
4404
- if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && tx.HasWitness ()) {
4405
- m_recent_rejects.insert (tx.GetHash ().ToUint256 ());
4406
- m_txrequest.ForgetTxHash (tx.GetHash ());
4407
- }
4408
- if (RecursiveDynamicUsage (*ptx) < 100000 ) {
4409
- AddToCompactExtraTransactions (ptx);
4410
- }
4411
- }
4412
4419
}
4413
-
4414
4420
if (state.IsInvalid ()) {
4415
- LogPrint (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
4416
- tx.GetHash ().ToString (),
4417
- tx.GetWitnessHash ().ToString (),
4418
- pfrom.GetId (),
4419
- state.ToString ());
4420
- MaybePunishNodeForTx (pfrom.GetId (), state);
4421
+ ProcessInvalidTx (pfrom.GetId (), ptx, state, /* maybe_add_extra_compact_tx=*/ true );
4421
4422
}
4422
4423
return ;
4423
4424
}
0 commit comments