Skip to content

Commit d9f8dc6

Browse files
committed
Merge bitcoin/bitcoin#31097: validation: Improve input script check error reporting
86e2a6b [test] A non-standard transaction which is also consensus-invalid should return the consensus error (Antoine Poinsot) f859ff8 [validation] Improve script check error reporting (dergoegge) Pull request description: An input script might be invalid for multiple reasons. For example, it might fail both a standardness check and a consensus check, which can lead to a `mandatory-script-verify-flag-failed` error being reported that includes the script error string from the standardness failure (e.g. `mandatory-script-verify-flag-failed (Using OP_CODESEPARATOR in non-witness script)`), which is confusing. ACKs for top commit: darosior: re-ACK 86e2a6b ariard: Re-Code Review ACK 86e2a6b instagibbs: ACK 86e2a6b Tree-SHA512: 053939107c0bcd6643e9006b2518ddc3a6de47d2c6c66af71a04e8af5cf9ec207f19e54583b7a056efd77571edf5fd4f36c31ebe80d1f0777219c756c055eb42
2 parents 563c4d2 + 86e2a6b commit d9f8dc6

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-2
lines changed

src/validation.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,8 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
21792179
if (pvChecks) {
21802180
pvChecks->emplace_back(std::move(check));
21812181
} else if (!check()) {
2182+
ScriptError error{check.GetScriptError()};
2183+
21822184
if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {
21832185
// Check whether the failure was caused by a
21842186
// non-mandatory script verification check, such as
@@ -2192,6 +2194,14 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
21922194
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
21932195
if (check2())
21942196
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
2197+
2198+
// If the second check failed, it failed due to a mandatory script verification
2199+
// flag, but the first check might have failed on a non-mandatory script
2200+
// verification flag.
2201+
//
2202+
// Avoid reporting a mandatory script check failure with a non-mandatory error
2203+
// string by reporting the error from the second check.
2204+
error = check2.GetScriptError();
21952205
}
21962206
// MANDATORY flag failures correspond to
21972207
// TxValidationResult::TX_CONSENSUS. Because CONSENSUS
@@ -2202,7 +2212,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
22022212
// support, to avoid splitting the network (but this
22032213
// depends on the details of how net_processing handles
22042214
// such errors).
2205-
return state.Invalid(TxValidationResult::TX_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
2215+
return state.Invalid(TxValidationResult::TX_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(error)));
22062216
}
22072217
}
22082218

test/functional/data/invalid_txs.py

+11
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,17 @@ def get_tx(self):
263263
'valid_in_block' : True
264264
})
265265

266+
class NonStandardAndInvalid(BadTxTemplate):
267+
"""A non-standard transaction which is also consensus-invalid should return the consensus error."""
268+
reject_reason = "mandatory-script-verify-flag-failed (OP_RETURN was encountered)"
269+
expect_disconnect = True
270+
valid_in_block = False
271+
272+
def get_tx(self):
273+
return create_tx_with_script(
274+
self.spend_tx, 0, script_sig=b'\x00' * 3 + b'\xab\x6a',
275+
amount=(self.spend_avail // 2))
276+
266277
# Disabled opcode tx templates (CVE-2010-5137)
267278
DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [
268279
OP_CAT,

test/functional/feature_block.py

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def set_test_params(self):
8888
self.extra_args = [[
8989
'-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
9090
'-testactivationheight=bip34@2',
91+
'-par=1', # Until https://github.com/bitcoin/bitcoin/issues/30960 is fixed
9192
]]
9293

9394
def run_test(self):

test/functional/p2p_invalid_tx.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def run_test(self):
165165
node.p2ps[0].send_txs_and_test([rejected_parent], node, success=False)
166166

167167
self.log.info('Test that a peer disconnection causes erase its transactions from the orphan pool')
168-
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=25']):
168+
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=26']):
169169
self.reconnect_p2p(num_connections=1)
170170

171171
self.log.info('Test that a transaction in the orphan pool is included in a new tip block causes erase this transaction from the orphan pool')

0 commit comments

Comments
 (0)