Skip to content

Commit 9e96b30

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 4bf5a1b commit 9e96b30

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-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: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,7 @@ static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state,
11021102
case TxValidationResult::TX_MISSING_INPUTS:
11031103
case TxValidationResult::TX_PREMATURE_SPEND:
11041104
case TxValidationResult::TX_WITNESS_MUTATED:
1105+
case TxValidationResult::TX_WITNESS_STRIPPED:
11051106
case TxValidationResult::TX_CONFLICT:
11061107
case TxValidationResult::TX_MEMPOOL_POLICY:
11071108
break;
@@ -1942,10 +1943,16 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
19421943
// Has inputs but not accepted to mempool
19431944
// Probably non-standard or insufficient fee
19441945
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
1945-
if (orphanTx.HasWitness() || orphan_state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
1946-
// Do not use rejection cache for witness transactions or
1947-
// witness-stripped transactions, as they can have been malleated.
1948-
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
1946+
if (orphanTx.HasWitness() || orphan_state.GetResult() != TxValidationResult::TX_WITNESS_STRIPPED) {
1947+
// Do not add txids of witness transactions or witness-stripped
1948+
// transactions to the filter, as they can have been malleated;
1949+
// adding such txids to the reject filter would potentially
1950+
// interfere with relay of valid transactions from peers that
1951+
// do not support wtxid-based relay. See
1952+
// https://github.com/bitcoin/bitcoin/issues/8279 for details.
1953+
// We can remove this restriction (and always add wtxids to
1954+
// the filter even for witness tripped transactions) once
1955+
// wtxid-based relay is broadly deployed.
19491956
assert(recentRejects);
19501957
recentRejects->insert(orphanTx.GetWitnessHash());
19511958
}
@@ -2681,10 +2688,16 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
26812688
recentRejects->insert(tx.GetWitnessHash());
26822689
}
26832690
} else {
2684-
if (tx.HasWitness() || state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
2685-
// Do not use rejection cache for witness transactions or
2686-
// witness-stripped transactions, as they can have been malleated.
2687-
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
2691+
if (tx.HasWitness() || state.GetResult() != TxValidationResult::TX_WITNESS_STRIPPED) {
2692+
// Do not add txids of witness transactions or witness-stripped
2693+
// transactions to the filter, as they can have been malleated;
2694+
// adding such txids to the reject filter would potentially
2695+
// interfere with relay of valid transactions from peers that
2696+
// do not support wtxid-based relay. See
2697+
// https://github.com/bitcoin/bitcoin/issues/8279 for details.
2698+
// We can remove this restriction (and always add wtxids to
2699+
// the filter even for witness tripped transactions) once
2700+
// wtxid-based relay is broadly deployed.
26882701
assert(recentRejects);
26892702
recentRejects->insert(tx.GetWitnessHash());
26902703
if (RecursiveDynamicUsage(*ptx) < 100000) {

src/validation.cpp

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

0 commit comments

Comments
 (0)