mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Merge bitcoin/bitcoin#29862: test: Validate oversized transactions or without inputs
969e047cfb
Replace hard-coded constant in test (Lőrinc)327a31d1a4
Validate oversized transaction (Lőrinc)1984187840
Validate transaction without inputs (Lőrinc)c3a8843189
Use SCRIPT_VERIFY_NONE instead of hard-coded 0 in transaction_tests (Lőrinc) Pull request description: Based on https://maflcko.github.io/b-c-cov/test_bitcoin.coverage/src/consensus/tx_check.cpp.gcov.html empty inputs and oversized transactions weren't covered by Boost unit tests (though they're covered by [python](https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_accept.py#L231) [tests](https://github.com/bitcoin/bitcoin/blob/master/test/functional/data/invalid_txs.py#L102)). <img alt="image" src="https://github.com/bitcoin/bitcoin/assets/1841944/57a74ff5-5466-401f-a4fe-d79e36964adf"> I have tried including the empty transaction into [tx_invalid.json](https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_invalid.json#L34-L36), but it failed for another reason, so I added a separate test case for it in the end. The oversized tx data is on the failure threshold now (lower threshold fails for a different reason, but I guess that's fine, we're testing the boundary here). ACKs for top commit: achow101: ACK969e047cfb
tdb3: ACK969e047cfb
pending `MSan, depends` CI failure. glozow: utACK969e047cfb
Tree-SHA512: 2a472690eabfdacc276b7e0414d3a4ebc75c227405b202c9fe3c8befad875f6e4d9b40c056fb05971ad3ae479c8f53edebb2eeeb700088856caf5cf58bfca0c1
This commit is contained in:
commit
21656e99b5
@ -72,17 +72,16 @@ static std::map<std::string, unsigned int> mapFlagNames = {
|
||||
|
||||
unsigned int ParseScriptFlags(std::string strFlags)
|
||||
{
|
||||
if (strFlags.empty() || strFlags == "NONE") return 0;
|
||||
unsigned int flags = 0;
|
||||
std::vector<std::string> words = SplitString(strFlags, ',');
|
||||
unsigned int flags = SCRIPT_VERIFY_NONE;
|
||||
if (strFlags.empty() || strFlags == "NONE") return flags;
|
||||
|
||||
std::vector<std::string> words = SplitString(strFlags, ',');
|
||||
for (const std::string& word : words)
|
||||
{
|
||||
if (!mapFlagNames.count(word))
|
||||
BOOST_ERROR("Bad test: unknown verification flag '" << word << "'");
|
||||
flags |= mapFlagNames[word];
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ bool CheckMapFlagNames()
|
||||
|
||||
std::string FormatScriptFlags(unsigned int flags)
|
||||
{
|
||||
if (flags == 0) {
|
||||
if (flags == SCRIPT_VERIFY_NONE) {
|
||||
return "";
|
||||
}
|
||||
std::string ret;
|
||||
@ -370,6 +369,41 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_no_inputs)
|
||||
{
|
||||
CMutableTransaction empty;
|
||||
|
||||
TxValidationState state;
|
||||
BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(empty), state), "Transaction with no inputs should be invalid.");
|
||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vin-empty");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_oversized)
|
||||
{
|
||||
auto createTransaction =[](size_t payloadSize) {
|
||||
CMutableTransaction tx;
|
||||
tx.vin.resize(1);
|
||||
tx.vout.emplace_back(1, CScript() << OP_RETURN << std::vector<unsigned char>(payloadSize));
|
||||
return CTransaction(tx);
|
||||
};
|
||||
const auto maxTransactionSize = MAX_BLOCK_WEIGHT / WITNESS_SCALE_FACTOR;
|
||||
const auto oversizedTransactionBaseSize = ::GetSerializeSize(TX_NO_WITNESS(createTransaction(maxTransactionSize))) - maxTransactionSize;
|
||||
|
||||
auto maxPayloadSize = maxTransactionSize - oversizedTransactionBaseSize;
|
||||
{
|
||||
TxValidationState state;
|
||||
CheckTransaction(createTransaction(maxPayloadSize), state);
|
||||
BOOST_CHECK(state.GetRejectReason() != "bad-txns-oversize");
|
||||
}
|
||||
|
||||
maxPayloadSize += 1;
|
||||
{
|
||||
TxValidationState state;
|
||||
BOOST_CHECK_MESSAGE(!CheckTransaction(createTransaction(maxPayloadSize), state), "Oversized transaction should be invalid");
|
||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-oversize");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
||||
{
|
||||
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
|
||||
@ -615,11 +649,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
// Normal pay-to-compressed-pubkey.
|
||||
CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1);
|
||||
CreateCreditAndSpend(keystore, scriptPubkey2, output2, input2);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -628,11 +662,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1)), output1, input1);
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2)), output2, input2);
|
||||
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -640,11 +674,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
// Witness pay-to-compressed-pubkey (v0).
|
||||
CreateCreditAndSpend(keystore, destination_script_1, output1, input1);
|
||||
CreateCreditAndSpend(keystore, destination_script_2, output2, input2);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -653,11 +687,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(destination_script_1)), output1, input1);
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(destination_script_2)), output2, input2);
|
||||
ReplaceRedeemScript(input2.vin[0].scriptSig, destination_script_1);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -665,11 +699,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
// Normal pay-to-uncompressed-pubkey.
|
||||
CreateCreditAndSpend(keystore, scriptPubkey1L, output1, input1);
|
||||
CreateCreditAndSpend(keystore, scriptPubkey2L, output2, input2);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -678,11 +712,11 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1L)), output1, input1);
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2L)), output2, input2);
|
||||
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
CheckWithFlag(output1, input2, 0, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
|
||||
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
|
||||
@ -697,19 +731,19 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
|
||||
// Normal 2-of-2 multisig
|
||||
CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
|
||||
CheckWithFlag(output1, input1, 0, false);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, false);
|
||||
CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
|
||||
CheckWithFlag(output2, input2, 0, false);
|
||||
CheckWithFlag(output2, input2, SCRIPT_VERIFY_NONE, false);
|
||||
BOOST_CHECK(*output1 == *output2);
|
||||
UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
|
||||
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
|
||||
|
||||
// P2SH 2-of-2 multisig
|
||||
CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptMulti)), output1, input1, false);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false);
|
||||
CreateCreditAndSpend(keystore2, GetScriptForDestination(ScriptHash(scriptMulti)), output2, input2, false);
|
||||
CheckWithFlag(output2, input2, 0, true);
|
||||
CheckWithFlag(output2, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
|
||||
BOOST_CHECK(*output1 == *output2);
|
||||
UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
|
||||
@ -718,10 +752,10 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
|
||||
// Witness 2-of-2 multisig
|
||||
CreateCreditAndSpend(keystore, destination_script_multi, output1, input1, false);
|
||||
CheckWithFlag(output1, input1, 0, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
|
||||
CreateCreditAndSpend(keystore2, destination_script_multi, output2, input2, false);
|
||||
CheckWithFlag(output2, input2, 0, true);
|
||||
CheckWithFlag(output2, input2, SCRIPT_VERIFY_NONE, true);
|
||||
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
|
||||
BOOST_CHECK(*output1 == *output2);
|
||||
UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
|
||||
|
@ -18,6 +18,7 @@ from test_framework.messages import (
|
||||
CTxInWitness,
|
||||
CTxOut,
|
||||
MAX_BLOCK_WEIGHT,
|
||||
WITNESS_SCALE_FACTOR,
|
||||
MAX_MONEY,
|
||||
SEQUENCE_FINAL,
|
||||
tx_from_hex,
|
||||
@ -228,7 +229,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
|
||||
self.log.info('A really large transaction')
|
||||
tx = tx_from_hex(raw_tx_reference)
|
||||
tx.vin = [tx.vin[0]] * math.ceil(MAX_BLOCK_WEIGHT // 4 / len(tx.vin[0].serialize()))
|
||||
tx.vin = [tx.vin[0]] * math.ceil((MAX_BLOCK_WEIGHT // WITNESS_SCALE_FACTOR) / len(tx.vin[0].serialize()))
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-oversize'}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
|
Loading…
Reference in New Issue
Block a user