Skip to content

Commit 4eb5155

Browse files
committed
Make TX_WITNESS_STRIPPED its own rejection reason
Previously, TX_WITNESS_MUTATED could be returned during transaction validation for either transactions that had a witness that was non-standard, or for transactions that had no witness but were invalid due to segwit validation rules. However, for txid/wtxid-relay considerations, net_processing distinguishes the witness stripped case separately, because it affects whether a wtxid should be able to be added to the reject filter. It is safe to add the wtxid of a witness-mutated transaction to the filter (as that wtxid shouldn't collide with the txid, and hence it wouldn't interfere with transaction relay from txid-relay peers), but it is not safe to add the wtxid (== txid) of a witness-stripped transaction to the filter, because that would interfere with relay of another transaction with the same txid (but different wtxid) when relaying from txid-relay peers. Also updates the comment explaining this logic, and explaining that we can get rid of this complexity once there's a sufficient deployment of wtxid-relaying peers on the network.
1 parent 97141ca commit 4eb5155

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

src/consensus/validation.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ enum class TxValidationResult {
3030
TX_MISSING_INPUTS, //!< transaction was missing some of its inputs
3131
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
3232
/**
33-
* Transaction might be missing a witness, have a witness prior to SegWit
33+
* Transaction might have a witness prior to SegWit
3434
* activation, or witness may have been malleated (which includes
3535
* non-standard witnesses).
3636
*/
3737
TX_WITNESS_MUTATED,
38+
/**
39+
* Transaction is missing a witness.
40+
*/
41+
TX_WITNESS_STRIPPED,
3842
/**
3943
* Tx already in mempool or conflicts with a tx in the chain
4044
* (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)

src/net_processing.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,7 @@ static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state,
11601160
case TxValidationResult::TX_MISSING_INPUTS:
11611161
case TxValidationResult::TX_PREMATURE_SPEND:
11621162
case TxValidationResult::TX_WITNESS_MUTATED:
1163+
case TxValidationResult::TX_WITNESS_STRIPPED:
11631164
case TxValidationResult::TX_CONFLICT:
11641165
case TxValidationResult::TX_MEMPOOL_POLICY:
11651166
break;
@@ -2031,10 +2032,19 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
20312032
// Has inputs but not accepted to mempool
20322033
// Probably non-standard or insufficient fee
20332034
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
2034-
if (orphanTx.HasWitness() || orphan_state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
2035-
// Do not use rejection cache for witness transactions or
2036-
// witness-stripped transactions, as they can have been malleated.
2037-
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
2035+
if (orphan_state.GetResult() != TxValidationResult::TX_WITNESS_STRIPPED) {
2036+
// Do not add txids of witness transactions or witness-stripped
2037+
// transactions to the filter, as they can have been malleated;
2038+
// adding such txids to the reject filter would potentially
2039+
// interfere with relay of valid transactions from peers that
2040+
// do not support wtxid-based relay. See
2041+
// https://github.com/bitcoin/bitcoin/issues/8279 for details.
2042+
// We can remove this restriction (and always add wtxids to
2043+
// the filter even for witness stripped transactions) once
2044+
// wtxid-based relay is broadly deployed.
2045+
// See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
2046+
// for concerns around weakening security of unupgraded nodes
2047+
// if we start doing this too early.
20382048
assert(recentRejects);
20392049
recentRejects->insert(orphanTx.GetWitnessHash());
20402050
}
@@ -2992,10 +3002,19 @@ void ProcessMessage(
29923002
recentRejects->insert(tx.GetWitnessHash());
29933003
}
29943004
} else {
2995-
if (tx.HasWitness() || state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
2996-
// Do not use rejection cache for witness transactions or
2997-
// witness-stripped transactions, as they can have been malleated.
2998-
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
3005+
if (state.GetResult() != TxValidationResult::TX_WITNESS_STRIPPED) {
3006+
// Do not add txids of witness transactions or witness-stripped
3007+
// transactions to the filter, as they can have been malleated;
3008+
// adding such txids to the reject filter would potentially
3009+
// interfere with relay of valid transactions from peers that
3010+
// do not support wtxid-based relay. See
3011+
// https://github.com/bitcoin/bitcoin/issues/8279 for details.
3012+
// We can remove this restriction (and always add wtxids to
3013+
// the filter even for witness stripped transactions) once
3014+
// wtxid-based relay is broadly deployed.
3015+
// See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
3016+
// for concerns around weakening security of unupgraded nodes
3017+
// if we start doing this too early.
29993018
assert(recentRejects);
30003019
recentRejects->insert(tx.GetWitnessHash());
30013020
if (RecursiveDynamicUsage(*ptx) < 100000) {

src/validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, Precompute
939939
if (!tx.HasWitness() && CheckInputScripts(tx, state_dummy, m_view, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, false, txdata) &&
940940
!CheckInputScripts(tx, state_dummy, m_view, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, false, txdata)) {
941941
// Only the witness is missing, so the transaction itself may be fine.
942-
state.Invalid(TxValidationResult::TX_WITNESS_MUTATED,
942+
state.Invalid(TxValidationResult::TX_WITNESS_STRIPPED,
943943
state.GetRejectReason(), state.GetDebugMessage());
944944
}
945945
return false; // state filled in by CheckInputScripts

0 commit comments

Comments
 (0)