Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/test/txvalidationcache_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
// validated going into the memory pool does not allow
// double-spends in blocks to pass validation when they should not.

CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CScript scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));

const auto ToMemPool = [this](const CMutableTransaction& tx) {
LOCK(cs_main);
Expand All @@ -62,7 +63,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)

// Sign:
std::vector<unsigned char> vchSig;
uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
uint256 hash = SignatureHash(p2pk_scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL);
spends[i].vin[0].scriptSig << vchSig;
Expand Down
6 changes: 3 additions & 3 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1079,9 +1079,9 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
std::vector<std::string> comments2;
comments2.emplace_back("comment1");
comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/"));
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
BOOST_CHECK(FormatSubVersion("Test", 99900, std::vector<std::string>()).starts_with("/Test:9.99.0/"));
BOOST_CHECK(FormatSubVersion("Test", 99900, comments).starts_with("/Test:9.99.0(comment1)/"));
BOOST_CHECK(FormatSubVersion("Test", 99900, comments2).starts_with("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
}

BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
Expand Down
38 changes: 19 additions & 19 deletions src/wallet/test/wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Cap last block file size, and mine new block in a new block file.
CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE);
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())));
CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());

// Verify ScanForWalletTransactions fails to read an unknown start block.
Expand Down Expand Up @@ -200,7 +200,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// Cap last block file size, and mine new block in a new block file.
CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE);
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())));
CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());

// Prune the older block file.
Expand All @@ -226,7 +226,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
keys.setArray();
UniValue key;
key.setObject();
key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey())));
key.pushKV("scriptPubKey", HexStr(GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))));
key.pushKV("timestamp", 0);
key.pushKV("internal", UniValue(true));
keys.push_back(key);
Expand Down Expand Up @@ -266,14 +266,14 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// will pick up both blocks, not just the first.
const int64_t BLOCK_TIME = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5);
SetMockTime(BLOCK_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);

// Set key birthday to block time increased by the timestamp window, so
// rescan will start at the block time.
const int64_t KEY_TIME = BLOCK_TIME + TIMESTAMP_WINDOW;
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);

std::string backup_file = fs::PathToString(m_args.GetDataDirNet() / "wallet.backup");

Expand Down Expand Up @@ -581,7 +581,7 @@ class ListCoinsTestingSetup : public TestChain100Setup
public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())));
wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), coinbaseKey);
}

Expand All @@ -605,7 +605,7 @@ class ListCoinsTestingSetup : public TestChain100Setup
LOCK(wallet->cs_wallet);
blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
}
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())));

LOCK(wallet->cs_wallet);
LOCK(Assert(m_node.chainman)->GetMutex());
Expand Down Expand Up @@ -854,10 +854,10 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
promise.get_future().wait();
});
std::string error;
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));


Expand Down Expand Up @@ -896,10 +896,10 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
addtx_count = 0;
auto handler = HandleLoadWallet(context, [&](std::unique_ptr<interfaces::Wallet> wallet) {
BOOST_CHECK(rescan_completed);
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
m_node.validation_signals->SyncWithValidationInterfaceQueue();
});
Expand Down Expand Up @@ -937,9 +937,9 @@ BOOST_FIXTURE_TEST_CASE(RemoveTxs, TestChain100Setup)
AddKey(*wallet, key);

std::string error;
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()))).vtx[0]);
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
CreateAndProcessBlock({block_tx}, GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())));

m_node.validation_signals->SyncWithValidationInterfaceQueue();

Expand Down
3 changes: 3 additions & 0 deletions test/functional/feature_includeconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def run_test(self):
self.log.info("-includeconf works from config file. subversion should end with 'main; relative)/'")

subversion = self.nodes[0].getnetworkinfo()["subversion"]
subversion = "/" + subversion.split("/")[1] + "/"
assert subversion.endswith("main; relative)/")

self.log.info("-includeconf cannot be used as command-line arg")
Expand All @@ -55,6 +56,7 @@ def run_test(self):
self.start_node(0)

subversion = self.nodes[0].getnetworkinfo()["subversion"]
subversion = "/" + subversion.split("/")[1] + "/"
assert subversion.endswith("main; relative)/")
self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf")

Expand All @@ -80,6 +82,7 @@ def run_test(self):
self.start_node(0)

subversion = self.nodes[0].getnetworkinfo()["subversion"]
subversion = "/" + subversion.split("/")[1] + "/"
assert subversion.endswith("main; relative; relative2)/")

if __name__ == '__main__':
Expand Down
10 changes: 6 additions & 4 deletions test/functional/feature_uacomment.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ def set_test_params(self):

def run_test(self):
self.log.info("test multiple -uacomment")
test_uacomment = self.nodes[0].getnetworkinfo()["subversion"][-12:-1]
assert_equal(test_uacomment, "(testnode0)")
subversion = self.nodes[0].getnetworkinfo()["subversion"]
subversion = "/" + subversion.split("/")[1] + "/"
assert_equal(subversion[-12:-1], "(testnode0)")

self.restart_node(0, ["-uacomment=foo"])
foo_uacomment = self.nodes[0].getnetworkinfo()["subversion"][-17:-1]
assert_equal(foo_uacomment, "(testnode0; foo)")
subversion = self.nodes[0].getnetworkinfo()["subversion"]
subversion = "/" + subversion.split("/")[1] + "/"
assert_equal(subversion[-17:-1], "(testnode0; foo)")

self.log.info("test -uacomment max length")
self.stop_node(0)
Expand Down
56 changes: 0 additions & 56 deletions test/functional/feature_uasf_reduced_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,61 +716,6 @@ def test_op_if_notif_rejection(self):
assert_equal(result_notif['allowed'], False)
self.log.info(f" ✓ Tapscript with OP_NOTIF: REJECTED ({result_notif['reject-reason']})")

def test_mandatory_flags_cannot_be_bypassed(self):
"""Test that REDUCED_DATA consensus-mandatory flags cannot be bypassed via ignore_rejects.

This test verifies that even though PolicyScriptChecks can be bypassed via ignore_rejects,
the subsequent ConsensusScriptChecks enforces consensus rules and prevents invalid transactions
from entering the mempool.
"""
self.log.info("Testing that REDUCED_DATA rules are enforced despite ignore_rejects...")
node = self.nodes[0]

# Test case: Create a witness script with a 257-byte PUSHDATA (violates REDUCED_DATA)
self.log.info(" Test: 257-byte PUSHDATA in witness script")

# Create a P2WSH output with a witness script containing 257-byte data push
witness_script_257 = CScript([b'\x00' * 257, OP_DROP, OP_TRUE])
script_pubkey_257 = script_to_p2wsh_script(witness_script_257)

# Create and fund the output
funding_tx_257 = self.create_test_transaction(script_pubkey_257)
txid_257 = node.sendrawtransaction(funding_tx_257.serialize().hex())
self.generate(node, 1)
output_value_257 = funding_tx_257.vout[0].nValue

# Create spending transaction that reveals the 257-byte PUSHDATA
spending_tx_257 = CTransaction()
spending_tx_257.vin = [CTxIn(COutPoint(int(txid_257, 16), 0))]
# Add padding to output to ensure tx meets minimum size requirements (82 bytes non-witness)
spending_tx_257.vout = [CTxOut(output_value_257 - 1000, CScript([OP_TRUE, OP_DROP] + [OP_TRUE] * 30))]
spending_tx_257.wit.vtxinwit.append(CTxInWitness())
spending_tx_257.wit.vtxinwit[0].scriptWitness.stack = [witness_script_257]
spending_tx_257.rehash()

# Test 1: Normal testmempoolaccept should reject
self.log.info(" Test 1a: Normal testmempoolaccept (should reject)")
result_normal = node.testmempoolaccept([spending_tx_257.serialize().hex()])[0]
assert_equal(result_normal['allowed'], False)
assert 'mempool-script-verify-flag' in result_normal['reject-reason']
self.log.info(f" ✓ Normal testmempoolaccept correctly rejected: {result_normal['reject-reason']}")

# Test 2: Try to bypass with ignore_rejects=["non-mandatory-script-verify-flag"]
# Expected: Transaction is STILL REJECTED because ConsensusScriptChecks enforces consensus rules
self.log.info(" Test 1b: testmempoolaccept with ignore_rejects")
self.log.info(" This bypasses PolicyScriptChecks but NOT ConsensusScriptChecks")
result_bypass = node.testmempoolaccept(
rawtxs=[spending_tx_257.serialize().hex()],
ignore_rejects=["mempool-script-verify-flag-failed"]
)[0]

# The transaction should still be rejected because ConsensusScriptChecks
# uses GetBlockScriptFlags() which includes REDUCED_DATA consensus rules
self.log.info(f" Result: allowed={result_bypass['allowed']}")
assert_equal(result_bypass['allowed'], False)
self.log.info(f" ✓ Transaction correctly rejected: {result_bypass['reject-reason']}")
self.log.info(" ✓ ConsensusScriptChecks prevents bypass of REDUCED_DATA consensus rules")

def test_generation_output_size_limit(self):
"""Test that generation tx outputs are also subject to output size limits."""
self.log.info("Testing generation tx output scriptPubKey size limits...")
Expand Down Expand Up @@ -928,7 +873,6 @@ def run_test(self):
self.test_taproot_control_block_size()
self.test_op_success_rejection()
self.test_op_if_notif_rejection()
self.test_mandatory_flags_cannot_be_bypassed()
self.test_p2a_witness_rejected()

self.log.info("All UASF-ReducedData tests completed")
Expand Down
8 changes: 4 additions & 4 deletions test/functional/mempool_sigoplimit.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
class BytesPerSigOpTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
# allow large datacarrier output to pad transactions
self.extra_args = [['-datacarriersize=100000']]
# multi-OP_RETURN padding outputs are non-standard
self.extra_args = [['-acceptnonstdtxn=1']]

def create_p2wsh_spending_tx(self, witness_script, output_script):
"""Create a 1-input-1-output P2WSH spending transaction with only the
Expand Down Expand Up @@ -303,8 +303,8 @@ def test_sigops_package(self):
def test_legacy_sigops_stdness(self):
self.log.info("Test a transaction with too many legacy sigops in its inputs is non-standard.")

# Restart with the default settings
self.restart_node(0)
# Restart without -acceptnonstdtxn to enable standardness checks
self.restart_node(0, extra_args=[])

# Create a P2SH script with 15 sigops.
_, dummy_pubkey = generate_keypair()
Expand Down
1 change: 1 addition & 0 deletions test/functional/rpc_getdescriptoractivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def test_receive_then_spend(self, node, wallet):
[blockhash_1, blockhash_2, blockhash_2], [wallet.get_descriptor()], True))

def test_no_address(self, node, wallet):
self.restart_node(0, extra_args=["-acceptnonstdtxn=1"])
raw_wallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_OP_TRUE)
self.generate(raw_wallet, 100)

Expand Down
2 changes: 1 addition & 1 deletion test/functional/rpc_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def assert_net_servicesnames(servicesflag, servicenames):
"""
servicesflag_generated = 0
for servicename in servicenames:
servicesflag_generated |= getattr(test_framework.messages, 'NODE_' + servicename)
servicesflag_generated |= getattr(test_framework.messages, 'NODE_' + servicename.rstrip('?'))
assert servicesflag_generated == servicesflag


Expand Down
2 changes: 0 additions & 2 deletions test/functional/test_framework/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,6 @@ def create_self_transfer(
return tx

def sendrawtransaction(self, *, from_node, tx_hex, maxfeerate=0, **kwargs):
if self._mode == MiniWalletMode.RAW_OP_TRUE and 'ignore_rejects' not in kwargs:
kwargs['ignore_rejects'] = ('scriptsig-not-pushonly', 'scriptpubkey', 'bad-txns-input-script-unknown')
txid = from_node.sendrawtransaction(hexstring=tx_hex, maxfeerate=maxfeerate, **kwargs)
self.scan_tx(from_node.decoderawtransaction(tx_hex))
return txid
Expand Down
Loading