@@ -582,6 +582,15 @@ class PeerManagerImpl final : public PeerManager
582582 */
583583 bool MaybeDiscourageAndDisconnect (CNode& pnode, Peer& peer);
584584
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+
585594 /* * Handle a transaction whose result was MempoolAcceptResult::ResultType::VALID.
586595 * Updates m_txrequest, m_orphanage, and vExtraTxnForCompact. Also queues the tx for relay. */
587596 void ProcessValidTx (NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)
@@ -3037,6 +3046,63 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
30373046 return ;
30383047}
30393048
3049+ void PeerManagerImpl::ProcessInvalidTx (NodeId nodeid, const CTransactionRef& ptx, const TxValidationState& state,
3050+ bool maybe_add_extra_compact_tx)
3051+ {
3052+ AssertLockNotHeld (m_peer_mutex);
3053+ AssertLockHeld (g_msgproc_mutex);
3054+ AssertLockHeld (cs_main);
3055+
3056+ LogDebug (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
3057+ ptx->GetHash ().ToString (),
3058+ ptx->GetWitnessHash ().ToString (),
3059+ nodeid,
3060+ state.ToString ());
3061+
3062+ if (state.GetResult () == TxValidationResult::TX_MISSING_INPUTS) {
3063+ return ;
3064+ } else if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3065+ // We can add the wtxid of this transaction to our reject filter.
3066+ // Do not add txids of witness transactions or witness-stripped
3067+ // transactions to the filter, as they can have been malleated;
3068+ // adding such txids to the reject filter would potentially
3069+ // interfere with relay of valid transactions from peers that
3070+ // do not support wtxid-based relay. See
3071+ // https://github.com/bitcoin/bitcoin/issues/8279 for details.
3072+ // We can remove this restriction (and always add wtxids to
3073+ // the filter even for witness stripped transactions) once
3074+ // wtxid-based relay is broadly deployed.
3075+ // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
3076+ // for concerns around weakening security of unupgraded nodes
3077+ // if we start doing this too early.
3078+ m_recent_rejects.insert (ptx->GetWitnessHash ().ToUint256 ());
3079+ m_txrequest.ForgetTxHash (ptx->GetWitnessHash ());
3080+ // If the transaction failed for TX_INPUTS_NOT_STANDARD,
3081+ // then we know that the witness was irrelevant to the policy
3082+ // failure, since this check depends only on the txid
3083+ // (the scriptPubKey being spent is covered by the txid).
3084+ // Add the txid to the reject filter to prevent repeated
3085+ // processing of this transaction in the event that child
3086+ // transactions are later received (resulting in
3087+ // parent-fetching by txid via the orphan-handling logic).
3088+ if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && ptx->HasWitness ()) {
3089+ m_recent_rejects.insert (ptx->GetHash ().ToUint256 ());
3090+ m_txrequest.ForgetTxHash (ptx->GetHash ());
3091+ }
3092+ if (maybe_add_extra_compact_tx && RecursiveDynamicUsage (*ptx) < 100000 ) {
3093+ AddToCompactExtraTransactions (ptx);
3094+ }
3095+ }
3096+
3097+ MaybePunishNodeForTx (nodeid, state);
3098+
3099+ // If the tx failed in ProcessOrphanTx, it should be removed from the orphanage unless the
3100+ // tx was still missing inputs. If the tx was not in the orphanage, EraseTx does nothing and returns 0.
3101+ if (Assume (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) && m_orphanage.EraseTx (ptx->GetHash ()) > 0 ) {
3102+ LogDebug (BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n " , ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ());
3103+ }
3104+ }
3105+
30403106void PeerManagerImpl::ProcessValidTx (NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)
30413107{
30423108 AssertLockNotHeld (m_peer_mutex);
@@ -3085,53 +3151,18 @@ bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
30853151 ProcessValidTx (peer.m_id , porphanTx, result.m_replaced_transactions .value_or (empty_replacement_list));
30863152 return true ;
30873153 } else if (state.GetResult () != TxValidationResult::TX_MISSING_INPUTS) {
3088- if (state.IsInvalid ()) {
3089- LogPrint (BCLog::TXPACKAGES, " invalid orphan tx %s (wtxid=%s) from peer=%d. %s\n " ,
3090- orphanHash.ToString (),
3091- orphan_wtxid.ToString (),
3092- peer.m_id ,
3093- state.ToString ());
3094- LogPrint (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
3095- orphanHash.ToString (),
3096- orphan_wtxid.ToString (),
3097- peer.m_id ,
3098- state.ToString ());
3099- // Maybe punish peer that gave us an invalid orphan tx
3100- MaybePunishNodeForTx (peer.m_id , state);
3101- }
3102- // Has inputs but not accepted to mempool
3103- // Probably non-standard or insufficient fee
3104- LogPrint (BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n " , orphanHash.ToString (), orphan_wtxid.ToString ());
3105- if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
3106- // We can add the wtxid of this transaction to our reject filter.
3107- // Do not add txids of witness transactions or witness-stripped
3108- // transactions to the filter, as they can have been malleated;
3109- // adding such txids to the reject filter would potentially
3110- // interfere with relay of valid transactions from peers that
3111- // do not support wtxid-based relay. See
3112- // https://github.com/bitcoin/bitcoin/issues/8279 for details.
3113- // We can remove this restriction (and always add wtxids to
3114- // the filter even for witness stripped transactions) once
3115- // wtxid-based relay is broadly deployed.
3116- // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
3117- // for concerns around weakening security of unupgraded nodes
3118- // if we start doing this too early.
3119- m_recent_rejects.insert (porphanTx->GetWitnessHash ().ToUint256 ());
3120- // If the transaction failed for TX_INPUTS_NOT_STANDARD,
3121- // then we know that the witness was irrelevant to the policy
3122- // failure, since this check depends only on the txid
3123- // (the scriptPubKey being spent is covered by the txid).
3124- // Add the txid to the reject filter to prevent repeated
3125- // processing of this transaction in the event that child
3126- // transactions are later received (resulting in
3127- // parent-fetching by txid via the orphan-handling logic).
3128- if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && porphanTx->HasWitness ()) {
3129- // We only add the txid if it differs from the wtxid, to
3130- // avoid wasting entries in the rolling bloom filter.
3131- m_recent_rejects.insert (porphanTx->GetHash ().ToUint256 ());
3132- }
3154+ LogPrint (BCLog::TXPACKAGES, " invalid orphan tx %s (wtxid=%s) from peer=%d. %s\n " ,
3155+ orphanHash.ToString (),
3156+ orphan_wtxid.ToString (),
3157+ peer.m_id ,
3158+ state.ToString ());
3159+
3160+ if (Assume (state.IsInvalid () &&
3161+ state.GetResult () != TxValidationResult::TX_UNKNOWN &&
3162+ state.GetResult () != TxValidationResult::TX_NO_MEMPOOL &&
3163+ state.GetResult () != TxValidationResult::TX_RESULT_UNSET)) {
3164+ ProcessInvalidTx (peer.m_id , porphanTx, state, /* maybe_add_extra_compact_tx=*/ false );
31333165 }
3134- m_orphanage.EraseTx (orphanHash);
31353166 return true ;
31363167 }
31373168 }
@@ -4363,48 +4394,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43634394 m_txrequest.ForgetTxHash (tx.GetHash ());
43644395 m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
43654396 }
4366- } else {
4367- if (state.GetResult () != TxValidationResult::TX_WITNESS_STRIPPED) {
4368- // We can add the wtxid of this transaction to our reject filter.
4369- // Do not add txids of witness transactions or witness-stripped
4370- // transactions to the filter, as they can have been malleated;
4371- // adding such txids to the reject filter would potentially
4372- // interfere with relay of valid transactions from peers that
4373- // do not support wtxid-based relay. See
4374- // https://github.com/bitcoin/bitcoin/issues/8279 for details.
4375- // We can remove this restriction (and always add wtxids to
4376- // the filter even for witness stripped transactions) once
4377- // wtxid-based relay is broadly deployed.
4378- // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
4379- // for concerns around weakening security of unupgraded nodes
4380- // if we start doing this too early.
4381- m_recent_rejects.insert (tx.GetWitnessHash ().ToUint256 ());
4382- m_txrequest.ForgetTxHash (tx.GetWitnessHash ());
4383- // If the transaction failed for TX_INPUTS_NOT_STANDARD,
4384- // then we know that the witness was irrelevant to the policy
4385- // failure, since this check depends only on the txid
4386- // (the scriptPubKey being spent is covered by the txid).
4387- // Add the txid to the reject filter to prevent repeated
4388- // processing of this transaction in the event that child
4389- // transactions are later received (resulting in
4390- // parent-fetching by txid via the orphan-handling logic).
4391- if (state.GetResult () == TxValidationResult::TX_INPUTS_NOT_STANDARD && tx.HasWitness ()) {
4392- m_recent_rejects.insert (tx.GetHash ().ToUint256 ());
4393- m_txrequest.ForgetTxHash (tx.GetHash ());
4394- }
4395- if (RecursiveDynamicUsage (*ptx) < 100000 ) {
4396- AddToCompactExtraTransactions (ptx);
4397- }
4398- }
43994397 }
4400-
44014398 if (state.IsInvalid ()) {
4402- LogPrint (BCLog::MEMPOOLREJ, " %s (wtxid=%s) from peer=%d was not accepted: %s\n " ,
4403- tx.GetHash ().ToString (),
4404- tx.GetWitnessHash ().ToString (),
4405- pfrom.GetId (),
4406- state.ToString ());
4407- MaybePunishNodeForTx (pfrom.GetId (), state);
4399+ ProcessInvalidTx (pfrom.GetId (), ptx, state, /* maybe_add_extra_compact_tx=*/ true );
44084400 }
44094401 return ;
44104402 }
0 commit comments