mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
[validation] Make script error messages uniform for parallel/single validation
This makes the debug output mostly the same for -par=1 and parallel validation runs. Of course, parallel validation is non-deterministic in what error it may encounter first if there are multiple issues. Also, the way certain script-related and non-script-related checks are performed differs between the two modes still, which may result in discrepancies.
This commit is contained in:
parent
1ac1c33f3f
commit
146a3d5426
9 changed files with 11 additions and 19 deletions
|
@ -403,8 +403,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
|
||||||
tx.vout[0].nValue -= LOWFEE;
|
tx.vout[0].nValue -= LOWFEE;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
|
||||||
// Should throw block-validation-failed
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("mandatory-script-verify-flag-failed"));
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
|
|
||||||
|
|
||||||
// Delete the dummy blocks again.
|
// Delete the dummy blocks again.
|
||||||
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
|
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
|
||||||
|
|
|
@ -2688,8 +2688,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||||
// Any transaction validation failure in ConnectBlock is a block consensus failure
|
// Any transaction validation failure in ConnectBlock is a block consensus failure
|
||||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
|
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
|
||||||
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
|
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
|
||||||
LogError("ConnectBlock(): CheckInputScripts on %s failed with %s\n",
|
LogInfo("Script validation error in block: %s\n", tx_state.GetRejectReason());
|
||||||
tx.GetHash().ToString(), state.ToString());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
control.Add(std::move(vChecks));
|
control.Add(std::move(vChecks));
|
||||||
|
@ -2717,8 +2716,9 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||||
|
|
||||||
auto parallel_result = control.Complete();
|
auto parallel_result = control.Complete();
|
||||||
if (parallel_result.has_value()) {
|
if (parallel_result.has_value()) {
|
||||||
LogPrintf("ERROR: %s: CheckQueue failed\n", __func__);
|
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(*parallel_result)));
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "block-validation-failed");
|
LogInfo("Script validation error in block: %s", state.GetRejectReason());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
const auto time_4{SteadyClock::now()};
|
const auto time_4{SteadyClock::now()};
|
||||||
m_chainman.time_verify += time_4 - time_2;
|
m_chainman.time_verify += time_4 - time_2;
|
||||||
|
|
|
@ -88,7 +88,6 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
self.extra_args = [[
|
self.extra_args = [[
|
||||||
'-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
|
'-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
|
||||||
'-testactivationheight=bip34@2',
|
'-testactivationheight=bip34@2',
|
||||||
'-par=1', # Until https://github.com/bitcoin/bitcoin/issues/30960 is fixed
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
|
|
@ -87,7 +87,6 @@ class BIP65Test(BitcoinTestFramework):
|
||||||
self.noban_tx_relay = True
|
self.noban_tx_relay = True
|
||||||
self.extra_args = [[
|
self.extra_args = [[
|
||||||
f'-testactivationheight=cltv@{CLTV_HEIGHT}',
|
f'-testactivationheight=cltv@{CLTV_HEIGHT}',
|
||||||
'-par=1', # Use only one script thread to get the exact reject reason for testing
|
|
||||||
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
|
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
|
||||||
]]
|
]]
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
@ -175,7 +174,7 @@ class BIP65Test(BitcoinTestFramework):
|
||||||
block.hashMerkleRoot = block.calc_merkle_root()
|
block.hashMerkleRoot = block.calc_merkle_root()
|
||||||
block.solve()
|
block.solve()
|
||||||
|
|
||||||
with self.nodes[0].assert_debug_log(expected_msgs=[f'CheckInputScripts on {block.vtx[-1].hash} failed with {expected_cltv_reject_reason}']):
|
with self.nodes[0].assert_debug_log(expected_msgs=[f'Script validation error in block: {expected_cltv_reject_reason}']):
|
||||||
peer.send_and_ping(msg_block(block))
|
peer.send_and_ping(msg_block(block))
|
||||||
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
|
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
|
||||||
peer.sync_with_ping()
|
peer.sync_with_ping()
|
||||||
|
|
|
@ -99,7 +99,6 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
||||||
self.noban_tx_relay = True
|
self.noban_tx_relay = True
|
||||||
self.extra_args = [[
|
self.extra_args = [[
|
||||||
f'-testactivationheight=csv@{CSV_ACTIVATION_HEIGHT}',
|
f'-testactivationheight=csv@{CSV_ACTIVATION_HEIGHT}',
|
||||||
'-par=1', # Use only one script thread to get the exact reject reason for testing
|
|
||||||
]]
|
]]
|
||||||
self.supports_cli = False
|
self.supports_cli = False
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ class BIP66Test(BitcoinTestFramework):
|
||||||
self.noban_tx_relay = True
|
self.noban_tx_relay = True
|
||||||
self.extra_args = [[
|
self.extra_args = [[
|
||||||
f'-testactivationheight=dersig@{DERSIG_HEIGHT}',
|
f'-testactivationheight=dersig@{DERSIG_HEIGHT}',
|
||||||
'-par=1', # Use only one script thread to get the exact log msg for testing
|
|
||||||
]]
|
]]
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
self.rpc_timeout = 240
|
self.rpc_timeout = 240
|
||||||
|
@ -131,7 +130,7 @@ class BIP66Test(BitcoinTestFramework):
|
||||||
block.hashMerkleRoot = block.calc_merkle_root()
|
block.hashMerkleRoot = block.calc_merkle_root()
|
||||||
block.solve()
|
block.solve()
|
||||||
|
|
||||||
with self.nodes[0].assert_debug_log(expected_msgs=[f'CheckInputScripts on {block.vtx[-1].hash} failed with mandatory-script-verify-flag-failed (Non-canonical DER signature)']):
|
with self.nodes[0].assert_debug_log(expected_msgs=[f'Script validation error in block: mandatory-script-verify-flag-failed (Non-canonical DER signature)']):
|
||||||
peer.send_and_ping(msg_block(block))
|
peer.send_and_ping(msg_block(block))
|
||||||
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
|
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
|
||||||
peer.sync_with_ping()
|
peer.sync_with_ping()
|
||||||
|
|
|
@ -57,7 +57,6 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
||||||
self.extra_args = [[
|
self.extra_args = [[
|
||||||
f'-testactivationheight=segwit@{COINBASE_MATURITY + 5}',
|
f'-testactivationheight=segwit@{COINBASE_MATURITY + 5}',
|
||||||
'-addresstype=legacy',
|
'-addresstype=legacy',
|
||||||
'-par=1', # Use only one script thread to get the exact reject reason for testing
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
def create_transaction(self, *, txid, input_details=None, addr, amount, privkey):
|
def create_transaction(self, *, txid, input_details=None, addr, amount, privkey):
|
||||||
|
|
|
@ -1285,7 +1285,6 @@ class TaprootTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 1
|
self.num_nodes = 1
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
self.extra_args = [["-par=1"]]
|
|
||||||
|
|
||||||
def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False):
|
def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False):
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,9 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.noban_tx_relay = True
|
self.noban_tx_relay = True
|
||||||
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
|
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
|
||||||
self.extra_args = [
|
self.extra_args = [
|
||||||
|
# -par=1 should not affect validation outcome or logging/reported failures. It is kept
|
||||||
|
# here to exercise the code path still (as it is distinct for multithread script
|
||||||
|
# validation).
|
||||||
["-acceptnonstdtxn=1", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}", "-par=1"],
|
["-acceptnonstdtxn=1", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}", "-par=1"],
|
||||||
["-acceptnonstdtxn=0", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}"],
|
["-acceptnonstdtxn=0", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}"],
|
||||||
]
|
]
|
||||||
|
@ -507,10 +510,6 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# When the block is serialized without witness, validation fails because the transaction is
|
# When the block is serialized without witness, validation fails because the transaction is
|
||||||
# invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction
|
# invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction
|
||||||
# without a witness is invalid).
|
# without a witness is invalid).
|
||||||
# Note: The reject reason for this failure could be
|
|
||||||
# 'block-validation-failed' (if script check threads > 1) or
|
|
||||||
# 'mandatory-script-verify-flag-failed (Witness program was passed an
|
|
||||||
# empty witness)' (otherwise).
|
|
||||||
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False,
|
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False,
|
||||||
reason='mandatory-script-verify-flag-failed (Witness program was passed an empty witness)')
|
reason='mandatory-script-verify-flag-failed (Witness program was passed an empty witness)')
|
||||||
|
|
||||||
|
@ -1015,7 +1014,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
|
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
|
||||||
tx2.wit.vtxinwit.extend([CTxInWitness(), CTxInWitness()])
|
tx2.wit.vtxinwit.extend([CTxInWitness(), CTxInWitness()])
|
||||||
tx2.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_script]
|
tx2.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_script]
|
||||||
tx2.wit.vtxinwit[1].scriptWitness.stack = [CScript([OP_TRUE])]
|
tx2.wit.vtxinwit[1].scriptWitness.stack = []
|
||||||
|
|
||||||
block = self.build_next_block()
|
block = self.build_next_block()
|
||||||
self.update_witness_block_with_transactions(block, [tx2])
|
self.update_witness_block_with_transactions(block, [tx2])
|
||||||
|
|
Loading…
Add table
Reference in a new issue