diff options
-rw-r--r-- | src/bench/rpc_mempool.cpp | 2 | ||||
-rw-r--r-- | src/net.cpp | 2 | ||||
-rw-r--r-- | src/net_processing.cpp | 2 | ||||
-rw-r--r-- | src/netaddress.h | 6 | ||||
-rw-r--r-- | src/qt/test/test_main.cpp | 2 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 2 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 4 | ||||
-rw-r--r-- | src/span.h | 8 | ||||
-rw-r--r-- | src/test/denialofservice_tests.cpp | 24 | ||||
-rw-r--r-- | src/test/fuzz/tx_pool.cpp | 2 | ||||
-rw-r--r-- | src/test/txpackage_tests.cpp | 16 | ||||
-rw-r--r-- | src/test/validation_block_tests.cpp | 2 | ||||
-rw-r--r-- | src/util/syscall_sandbox.cpp | 3 | ||||
-rwxr-xr-x | test/functional/feature_nulldummy.py | 30 | ||||
-rwxr-xr-x | test/functional/rpc_decodescript.py | 65 | ||||
-rwxr-xr-x | test/functional/rpc_generateblock.py | 34 | ||||
-rw-r--r-- | test/sanitizer_suppressions/ubsan | 1 |
17 files changed, 115 insertions, 90 deletions
diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index f1eeef8885..67c827d0d3 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -12,7 +12,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { LockPoints lp; - pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCost */ 4, lp)); + pool.addUnchecked(CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); } static void RpcMempool(benchmark::Bench& bench) diff --git a/src/net.cpp b/src/net.cpp index 82e55d4189..d1f1b54007 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3024,7 +3024,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg) size_t nMessageSize = msg.data.size(); LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId()); if (gArgs.GetBoolArg("-capturemessages", false)) { - CaptureMessage(pnode->addr, msg.m_type, msg.data, /* incoming */ false); + CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false); } TRACE6(net, outbound_message, diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2185ccc700..a896bb76ae 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -4105,7 +4105,7 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt ); if (gArgs.GetBoolArg("-capturemessages", false)) { - CaptureMessage(pfrom->addr, msg.m_command, MakeUCharSpan(msg.m_recv), /* incoming */ true); + CaptureMessage(pfrom->addr, msg.m_command, MakeUCharSpan(msg.m_recv), /*is_incoming=*/true); } msg.SetVersion(pfrom->GetCommonVersion()); diff --git a/src/netaddress.h b/src/netaddress.h index b0b1c5ca9e..a5b74eb35b 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -385,6 +385,12 @@ private: /** * Unserialize from a pre-ADDRv2/BIP155 format from an array. + * + * This function is only called from UnserializeV1Stream() and is a wrapper + * for SetLegacyIPv6(); however, we keep it for symmetry with + * SerializeV1Array() to have pairs of ser/unser functions and to make clear + * that if one is altered, a corresponding reverse modification should be + * applied to the other. */ void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) { diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index b26cddf4ae..e7a3d724bb 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -69,7 +69,7 @@ int main(int argc, char* argv[]) #if defined(WIN32) if (getenv("QT_QPA_PLATFORM") == nullptr) _putenv_s("QT_QPA_PLATFORM", "minimal"); #else - setenv("QT_QPA_PLATFORM", "minimal", /* overwrite */ 0); + setenv("QT_QPA_PLATFORM", "minimal", 0 /* overwrite */); #endif // Don't remove this, it's needed to access diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 518c41d12a..9e2b1ab07e 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1010,7 +1010,7 @@ static RPCHelpMan submitblock() bool new_block; auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash()); RegisterSharedValidationInterface(sc); - bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block); + bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /*force_processing=*/true, /*new_block=*/&new_block); UnregisterSharedValidationInterface(sc); if (!new_block && accepted) { return "duplicate"; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 89f2309cb7..2dd121c6f6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1619,7 +1619,7 @@ static RPCHelpMan utxoupdatepsbt() } } // We don't actually need private keys further on; hide them as a precaution. - HidingSigningProvider public_provider(&provider, /* nosign */ true, /* nobip32derivs */ false); + HidingSigningProvider public_provider(&provider, /*hide_secret=*/true, /*hide_origin=*/false); // Fetch previous transactions (inputs): CCoinsView viewDummy; @@ -1658,7 +1658,7 @@ static RPCHelpMan utxoupdatepsbt() // Update script/keypath information using descriptor data. // Note that SignPSBTInput does a lot more than just constructing ECDSA signatures // we don't actually care about those here, in fact. - SignPSBTInput(public_provider, psbtx, i, &txdata, /* sighash_type */ 1); + SignPSBTInput(public_provider, psbtx, i, &txdata, /*sighash=*/1); } // Update script/keypath information using descriptor data. diff --git a/src/span.h b/src/span.h index 168162e309..1e347846d8 100644 --- a/src/span.h +++ b/src/span.h @@ -30,7 +30,11 @@ /** A Span is an object that can refer to a contiguous sequence of objects. * - * It implements a subset of C++20's std::span. + * This file implements a subset of C++20's std::span. It can be considered + * temporary compatibility code until C++20 and is designed to be a + * self-contained abstraction without depending on other project files. For this + * reason, Clang lifetimebound is defined here instead of including + * <attributes.h>, which also defines it. * * Things to be aware of when writing code that deals with Spans: * @@ -60,7 +64,7 @@ * types that expose a data() and size() member function), functions that * accept a Span as input parameter can be called with any compatible * range-like object. For example, this works: -* + * * void Foo(Span<const int> arg); * * Foo(std::vector<int>{1, 2, 3}); // Works diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 668ff150ee..765663e0ef 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr1, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "", ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false); + CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr1, /*nKeyedNetGroupIn=*/0, /*nLocalHostNonceIn=*/0, CAddress(), /*addrNameIn=*/"", ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false); dummyNode1.SetCommonVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode1); @@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) static void AddRandomOutboundPeer(std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman) { CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE); - vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "", ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false)); + vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr, /*nKeyedNetGroupIn=*/0, /*nLocalHostNonceIn=*/0, CAddress(), /*addrNameIn=*/"", ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false)); CNode &node = *vNodes.back(); node.SetCommonVersion(PROTOCOL_VERSION); @@ -212,9 +212,9 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) std::array<CNode*, 3> nodes; banman->ClearBanned(); - nodes[0] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[0], /* nKeyedNetGroupIn */ 0, - /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "", - ConnectionType::INBOUND, /* inbound_onion */ false}; + nodes[0] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[0], /*nKeyedNetGroupIn=*/0, + /*nLocalHostNonceIn */ 0, CAddress(), /*addrNameIn=*/"", + ConnectionType::INBOUND, /*inbound_onion=*/false}; nodes[0]->SetCommonVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(nodes[0]); nodes[0]->fSuccessfullyConnected = true; @@ -228,9 +228,9 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) BOOST_CHECK(nodes[0]->fDisconnect); BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged - nodes[1] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[1], /* nKeyedNetGroupIn */ 1, - /* nLocalHostNonceIn */ 1, CAddress(), /* pszDest */ "", - ConnectionType::INBOUND, /* inbound_onion */ false}; + nodes[1] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[1], /*nKeyedNetGroupIn=*/1, + /*nLocalHostNonceIn */ 1, CAddress(), /*addrNameIn=*/"", + ConnectionType::INBOUND, /*inbound_onion=*/false}; nodes[1]->SetCommonVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(nodes[1]); nodes[1]->fSuccessfullyConnected = true; @@ -259,9 +259,9 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) // Make sure non-IP peers are discouraged and disconnected properly. - nodes[2] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[2], /* nKeyedNetGroupIn */ 1, - /* nLocalHostNonceIn */ 1, CAddress(), /* pszDest */ "", - ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false}; + nodes[2] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[2], /*nKeyedNetGroupIn=*/1, + /*nLocalHostNonceIn */ 1, CAddress(), /*addrNameIn=*/"", + ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false}; nodes[2]->SetCommonVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(nodes[2]); nodes[2]->fSuccessfullyConnected = true; @@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 4, /* nLocalHostNonceIn */ 4, CAddress(), /* pszDest */ "", ConnectionType::INBOUND, /* inbound_onion */ false); + CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, /*nKeyedNetGroupIn=*/4, /*nLocalHostNonceIn=*/4, CAddress(), /*addrNameIn=*/"", ConnectionType::INBOUND, /*inbound_onion=*/false); dummyNode.SetCommonVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode); dummyNode.fSuccessfullyConnected = true; diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp index 17b5ef88b9..752e882608 100644 --- a/src/test/fuzz/tx_pool.cpp +++ b/src/test/fuzz/tx_pool.cpp @@ -93,7 +93,7 @@ void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, CCh const auto info_all = tx_pool.infoAll(); if (!info_all.empty()) { const auto& tx_to_remove = *PickValue(fuzzed_data_provider, info_all).tx; - WITH_LOCK(tx_pool.cs, tx_pool.removeRecursive(tx_to_remove, /* dummy */ MemPoolRemovalReason::BLOCK)); + WITH_LOCK(tx_pool.cs, tx_pool.removeRecursive(tx_to_remove, MemPoolRemovalReason::BLOCK /* dummy */)); std::vector<uint256> all_txids; tx_pool.queryHashes(all_txids); assert(all_txids.size() < info_all.size()); diff --git a/src/test/txpackage_tests.cpp b/src/test/txpackage_tests.cpp index 537a6ccea1..8d92bee221 100644 --- a/src/test/txpackage_tests.cpp +++ b/src/test/txpackage_tests.cpp @@ -73,19 +73,19 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup) CKey parent_key; parent_key.MakeNewKey(true); CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey())); - auto mtx_parent = CreateValidMempoolTransaction(/* input_transaction */ m_coinbase_txns[0], /* vout */ 0, - /* input_height */ 0, /* input_signing_key */ coinbaseKey, - /* output_destination */ parent_locking_script, - /* output_amount */ CAmount(49 * COIN), /* submit */ false); + auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/ m_coinbase_txns[0], /*input_vout=*/0, + /*input_height=*/ 0, /*input_signing_key=*/coinbaseKey, + /*output_destination=*/ parent_locking_script, + /*output_amount=*/ CAmount(49 * COIN), /*submit=*/false); CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); CKey child_key; child_key.MakeNewKey(true); CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey())); - auto mtx_child = CreateValidMempoolTransaction(/* input_transaction */ tx_parent, /* vout */ 0, - /* input_height */ 101, /* input_signing_key */ parent_key, - /* output_destination */ child_locking_script, - /* output_amount */ CAmount(48 * COIN), /* submit */ false); + auto mtx_child = CreateValidMempoolTransaction(/*input_transaction=*/ tx_parent, /*input_vout=*/0, + /*input_height=*/ 101, /*input_signing_key=*/parent_key, + /*output_destination */ child_locking_script, + /*output_amount=*/ CAmount(48 * COIN), /*submit=*/false); CTransactionRef tx_child = MakeTransactionRef(mtx_child); const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {tx_parent, tx_child}, /* test_accept */ true); BOOST_CHECK_MESSAGE(result_parent_child.m_state.IsValid(), diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 8a48d539f8..54873ce6fa 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) { bool ignored; auto ProcessBlock = [&](std::shared_ptr<const CBlock> block) -> bool { - return Assert(m_node.chainman)->ProcessNewBlock(Params(), block, /* fForceProcessing */ true, /* fNewBlock */ &ignored); + return Assert(m_node.chainman)->ProcessNewBlock(Params(), block, /*force_processing=*/true, /*new_block=*/&ignored); }; // Process all mined blocks diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp index bc69df44f4..6e1cc9b457 100644 --- a/src/util/syscall_sandbox.cpp +++ b/src/util/syscall_sandbox.cpp @@ -581,7 +581,7 @@ public: allowed_syscalls.insert(__NR_fdatasync); // synchronize a file's in-core state with storage device allowed_syscalls.insert(__NR_flock); // apply or remove an advisory lock on an open file allowed_syscalls.insert(__NR_fstat); // get file status - allowed_syscalls.insert(__NR_newfstatat); // get file status + allowed_syscalls.insert(__NR_fstatfs); // get file system status allowed_syscalls.insert(__NR_fsync); // synchronize a file's in-core state with storage device allowed_syscalls.insert(__NR_ftruncate); // truncate a file to a specified length allowed_syscalls.insert(__NR_getcwd); // get current working directory @@ -589,6 +589,7 @@ public: allowed_syscalls.insert(__NR_getdents64); // get directory entries allowed_syscalls.insert(__NR_lstat); // get file status allowed_syscalls.insert(__NR_mkdir); // create a directory + allowed_syscalls.insert(__NR_newfstatat); // get file status allowed_syscalls.insert(__NR_open); // open and possibly create a file allowed_syscalls.insert(__NR_openat); // open and possibly create a file allowed_syscalls.insert(__NR_readlink); // read value of a symbolic link diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 4d59d5a07d..7a84098a83 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -22,7 +22,10 @@ from test_framework.blocktools import ( create_transaction, ) from test_framework.messages import CTransaction -from test_framework.script import CScript +from test_framework.script import ( + OP_0, + OP_TRUE, +) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -32,16 +35,11 @@ from test_framework.util import ( NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" -def trueDummy(tx): - scriptSig = CScript(tx.vin[0].scriptSig) - newscript = [] - for i in scriptSig: - if len(newscript) == 0: - assert len(i) == 0 - newscript.append(b'\x51') - else: - newscript.append(i) - tx.vin[0].scriptSig = CScript(newscript) +def invalidate_nulldummy_tx(tx): + """Transform a NULLDUMMY compliant tx (i.e. scriptSig starts with OP_0) + to be non-NULLDUMMY compliant by replacing the dummy with OP_TRUE""" + assert_equal(tx.vin[0].scriptSig[0], OP_0) + tx.vin[0].scriptSig = bytes([OP_TRUE]) + tx.vin[0].scriptSig[1:] tx.rehash() @@ -94,7 +92,7 @@ class NULLDUMMYTest(BitcoinTestFramework): self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47) - trueDummy(test2tx) + invalidate_nulldummy_tx(test2tx) assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test2tx.serialize_with_witness().hex(), 0) self.log.info(f"Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [{COINBASE_MATURITY + 4}]") @@ -103,7 +101,7 @@ class NULLDUMMYTest(BitcoinTestFramework): self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46) test6txs = [CTransaction(test4tx)] - trueDummy(test4tx) + invalidate_nulldummy_tx(test4tx) assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test4tx.serialize_with_witness().hex(), 0) self.block_submit(self.nodes[0], [test4tx], accept=False) @@ -123,11 +121,7 @@ class NULLDUMMYTest(BitcoinTestFramework): tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS) assert_equal(tmpl['previousblockhash'], self.lastblockhash) assert_equal(tmpl['height'], self.lastblockheight + 1) - block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1) - for tx in txs: - tx.rehash() - block.vtx.append(tx) - block.hashMerkleRoot = block.calc_merkle_root() + block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1, txlist=txs) if with_witness: add_witness_commitment(block) block.solve() diff --git a/test/functional/rpc_decodescript.py b/test/functional/rpc_decodescript.py index 58432c3dae..8c0f48129a 100755 --- a/test/functional/rpc_decodescript.py +++ b/test/functional/rpc_decodescript.py @@ -27,29 +27,29 @@ class DecodeScriptTest(BitcoinTestFramework): # below are test cases for all of the standard transaction types - # 1) P2PK scriptSig + self.log.info("- P2PK") # the scriptSig of a public key scriptPubKey simply pushes a signature onto the stack rpc_result = self.nodes[0].decodescript(push_signature) assert_equal(signature, rpc_result['asm']) - # 2) P2PKH scriptSig + self.log.info("- P2PKH") rpc_result = self.nodes[0].decodescript(push_signature + push_public_key) assert_equal(signature + ' ' + public_key, rpc_result['asm']) - # 3) multisig scriptSig + self.log.info("- multisig") # this also tests the leading portion of a P2SH multisig scriptSig # OP_0 <A sig> <B sig> rpc_result = self.nodes[0].decodescript('00' + push_signature + push_signature) assert_equal('0 ' + signature + ' ' + signature, rpc_result['asm']) - # 4) P2SH scriptSig + self.log.info("- P2SH") # an empty P2SH redeemScript is valid and makes for a very simple test case. # thus, such a spending scriptSig would just need to pass the outer redeemScript # hash test and leave true on the top of the stack. rpc_result = self.nodes[0].decodescript('5100') assert_equal('1 0', rpc_result['asm']) - # 5) null data scriptSig - no such thing because null data scripts can not be spent. + # null data scriptSig - no such thing because null data scripts can not be spent. # thus, no test case for that standard transaction type is here. def decodescript_script_pub_key(self): @@ -63,50 +63,58 @@ class DecodeScriptTest(BitcoinTestFramework): # below are test cases for all of the standard transaction types - # 1) P2PK scriptPubKey + self.log.info("- P2PK") # <pubkey> OP_CHECKSIG rpc_result = self.nodes[0].decodescript(push_public_key + 'ac') assert_equal(public_key + ' OP_CHECKSIG', rpc_result['asm']) + assert_equal('pubkey', rpc_result['type']) # P2PK is translated to P2WPKH assert_equal('0 ' + public_key_hash, rpc_result['segwit']['asm']) - # 2) P2PKH scriptPubKey + self.log.info("- P2PKH") # OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG rpc_result = self.nodes[0].decodescript('76a9' + push_public_key_hash + '88ac') + assert_equal('pubkeyhash', rpc_result['type']) assert_equal('OP_DUP OP_HASH160 ' + public_key_hash + ' OP_EQUALVERIFY OP_CHECKSIG', rpc_result['asm']) # P2PKH is translated to P2WPKH + assert_equal('witness_v0_keyhash', rpc_result['segwit']['type']) assert_equal('0 ' + public_key_hash, rpc_result['segwit']['asm']) - # 3) multisig scriptPubKey + self.log.info("- multisig") # <m> <A pubkey> <B pubkey> <C pubkey> <n> OP_CHECKMULTISIG # just imagine that the pub keys used below are different. # for our purposes here it does not matter that they are the same even though it is unrealistic. multisig_script = '52' + push_public_key + push_public_key + push_public_key + '53ae' rpc_result = self.nodes[0].decodescript(multisig_script) + assert_equal('multisig', rpc_result['type']) assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm']) # multisig in P2WSH multisig_script_hash = sha256(bytes.fromhex(multisig_script)).hex() + assert_equal('witness_v0_scripthash', rpc_result['segwit']['type']) assert_equal('0 ' + multisig_script_hash, rpc_result['segwit']['asm']) - # 4) P2SH scriptPubKey + self.log.info ("- P2SH") # OP_HASH160 <Hash160(redeemScript)> OP_EQUAL. # push_public_key_hash here should actually be the hash of a redeem script. # but this works the same for purposes of this test. rpc_result = self.nodes[0].decodescript('a9' + push_public_key_hash + '87') + assert_equal('scripthash', rpc_result['type']) assert_equal('OP_HASH160 ' + public_key_hash + ' OP_EQUAL', rpc_result['asm']) # P2SH does not work in segwit secripts. decodescript should not return a result for it. assert 'segwit' not in rpc_result - # 5) null data scriptPubKey + self.log.info("- null data") # use a signature look-alike here to make sure that we do not decode random data as a signature. # this matters if/when signature sighash decoding comes along. # would want to make sure that no such decoding takes place in this case. signature_imposter = '48304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001' # OP_RETURN <data> rpc_result = self.nodes[0].decodescript('6a' + signature_imposter) + assert_equal('nulldata', rpc_result['type']) assert_equal('OP_RETURN ' + signature_imposter[2:], rpc_result['asm']) - # 6) a CLTV redeem script. redeem scripts are in-effect scriptPubKey scripts, so adding a test here. + self.log.info("- CLTV redeem script") + # redeem scripts are in-effect scriptPubKey scripts, so adding a test here. # OP_NOP2 is also known as OP_CHECKLOCKTIMEVERIFY. # just imagine that the pub keys used below are different. # for our purposes here it does not matter that they are the same even though it is unrealistic. @@ -121,55 +129,69 @@ class DecodeScriptTest(BitcoinTestFramework): # lock until block 500,000 cltv_script = '63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac' rpc_result = self.nodes[0].decodescript(cltv_script) + assert_equal('nonstandard', rpc_result['type']) assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm']) # CLTV script in P2WSH cltv_script_hash = sha256(bytes.fromhex(cltv_script)).hex() assert_equal('0 ' + cltv_script_hash, rpc_result['segwit']['asm']) - # 7) P2PK scriptPubKey + self.log.info("- P2PK with uncompressed pubkey") # <pubkey> OP_CHECKSIG rpc_result = self.nodes[0].decodescript(push_uncompressed_public_key + 'ac') + assert_equal('pubkey', rpc_result['type']) assert_equal(uncompressed_public_key + ' OP_CHECKSIG', rpc_result['asm']) # uncompressed pubkeys are invalid for checksigs in segwit scripts. # decodescript should not return a P2WPKH equivalent. assert 'segwit' not in rpc_result - # 8) multisig scriptPubKey with an uncompressed pubkey + self.log.info("- multisig with uncompressed pubkey") # <m> <A pubkey> <B pubkey> <n> OP_CHECKMULTISIG # just imagine that the pub keys used below are different. # the purpose of this test is to check that a segwit script is not returned for bare multisig scripts # with an uncompressed pubkey in them. rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_uncompressed_public_key +'52ae') + assert_equal('multisig', rpc_result['type']) assert_equal('2 ' + public_key + ' ' + uncompressed_public_key + ' 2 OP_CHECKMULTISIG', rpc_result['asm']) # uncompressed pubkeys are invalid for checksigs in segwit scripts. # decodescript should not return a P2WPKH equivalent. assert 'segwit' not in rpc_result - # 9) P2WPKH scriptpubkey + self.log.info("- P2WPKH") # 0 <PubKeyHash> rpc_result = self.nodes[0].decodescript('00' + push_public_key_hash) + assert_equal('witness_v0_keyhash', rpc_result['type']) assert_equal('0 ' + public_key_hash, rpc_result['asm']) # segwit scripts do not work nested into each other. # a nested segwit script should not be returned in the results. assert 'segwit' not in rpc_result - # 10) P2WSH scriptpubkey + self.log.info("- P2WSH") # 0 <ScriptHash> # even though this hash is of a P2PK script which is better used as bare P2WPKH, it should not matter # for the purpose of this test. rpc_result = self.nodes[0].decodescript('0020' + p2wsh_p2pk_script_hash) + assert_equal('witness_v0_scripthash', rpc_result['type']) assert_equal('0 ' + p2wsh_p2pk_script_hash, rpc_result['asm']) # segwit scripts do not work nested into each other. # a nested segwit script should not be returned in the results. assert 'segwit' not in rpc_result + self.log.info("- P2TR") + # 1 <x-only pubkey> + xonly_public_key = '01'*32 # first ever P2TR output on mainnet + rpc_result = self.nodes[0].decodescript('5120' + xonly_public_key) + assert_equal('witness_v1_taproot', rpc_result['type']) + assert_equal('1 ' + xonly_public_key, rpc_result['asm']) + assert 'segwit' not in rpc_result + def decoderawtransaction_asm_sighashtype(self): """Test decoding scripts via RPC command "decoderawtransaction". This test is in with the "decodescript" tests because they are testing the same "asm" script decodes. """ - # this test case uses a random plain vanilla mainnet transaction with a single P2PKH input and output + self.log.info("- various mainnet txs") + # this test case uses a mainnet transaction that has a P2SH input and both P2PKH and P2SH outputs. tx = '0100000001696a20784a2c70143f634e95227dbdfdf0ecd51647052e70854512235f5986ca010000008a47304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb014104d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536ffffffff0100e1f505000000001976a914eb6c6e0cdb2d256a32d97b8df1fc75d1920d9bca88ac00000000' rpc_result = self.nodes[0].decoderawtransaction(tx) assert_equal('304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb[ALL] 04d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536', rpc_result['vin'][0]['scriptSig']['asm']) @@ -185,11 +207,13 @@ class DecodeScriptTest(BitcoinTestFramework): assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm']) txSave = tx_from_hex(tx) + self.log.info("- tx not passing DER signature checks") # make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000' rpc_result = self.nodes[0].decoderawtransaction(tx) assert_equal('OP_RETURN 300602010002010001', rpc_result['vout'][0]['scriptPubKey']['asm']) + self.log.info("- tx passing DER signature checks") # verify that we have not altered scriptPubKey processing even of a specially crafted P2PKH pubkeyhash and P2SH redeem script hash that is made to pass the der signature checks tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914301102070101010101010102060101010101010188acee2a02000000000017a91430110207010101010101010206010101010101018700000000' rpc_result = self.nodes[0].decoderawtransaction(tx) @@ -207,7 +231,7 @@ class DecodeScriptTest(BitcoinTestFramework): push_signature_2 = '48' + signature_2 signature_2_sighash_decoded = der_signature + '[NONE|ANYONECANPAY]' - # 1) P2PK scriptSig + self.log.info("- P2PK scriptSig") txSave.vin[0].scriptSig = bytes.fromhex(push_signature) rpc_result = self.nodes[0].decoderawtransaction(txSave.serialize().hex()) assert_equal(signature_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) @@ -217,20 +241,23 @@ class DecodeScriptTest(BitcoinTestFramework): rpc_result = self.nodes[0].decoderawtransaction(txSave.serialize().hex()) assert_equal(signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) - # 2) multisig scriptSig + self.log.info("- multisig scriptSig") txSave.vin[0].scriptSig = bytes.fromhex('00' + push_signature + push_signature_2) rpc_result = self.nodes[0].decoderawtransaction(txSave.serialize().hex()) assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) - # 3) test a scriptSig that contains more than push operations. + self.log.info("- scriptSig that contains more than push operations") # in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it. txSave.vin[0].scriptSig = bytes.fromhex('6a143011020701010101010101020601010101010101') rpc_result = self.nodes[0].decoderawtransaction(txSave.serialize().hex()) assert_equal('OP_RETURN 3011020701010101010101020601010101010101', rpc_result['vin'][0]['scriptSig']['asm']) def run_test(self): + self.log.info("Test decoding of standard input scripts [scriptSig]") self.decodescript_script_sig() + self.log.info("Test decoding of standard output scripts [scriptPubKey]") self.decodescript_script_pub_key() + self.log.info("Test 'asm' script decoding of transactions") self.decoderawtransaction_asm_sighashtype() if __name__ == '__main__': diff --git a/test/functional/rpc_generateblock.py b/test/functional/rpc_generateblock.py index 4dc5c63ff3..7aede0e947 100755 --- a/test/functional/rpc_generateblock.py +++ b/test/functional/rpc_generateblock.py @@ -6,6 +6,7 @@ ''' from test_framework.test_framework import BitcoinTestFramework +from test_framework.wallet import MiniWallet from test_framework.util import ( assert_equal, assert_raises_rpc_error, @@ -16,14 +17,13 @@ class GenerateBlockTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() - def run_test(self): node = self.nodes[0] + miniwallet = MiniWallet(node) + miniwallet.rescan_utxos() self.log.info('Generate an empty block to address') - address = node.getnewaddress() + address = miniwallet.get_address() hash = self.generateblock(node, output=address, transactions=[])['hash'] block = node.getblock(blockhash=hash, verbose=2) assert_equal(len(block['tx']), 1) @@ -51,37 +51,31 @@ class GenerateBlockTest(BitcoinTestFramework): assert_equal(len(block['tx']), 1) assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address) - # Generate 110 blocks to spend - self.generatetoaddress(node, 110, address) - # Generate some extra mempool transactions to verify they don't get mined for _ in range(10): - node.sendtoaddress(address, 0.001) + miniwallet.send_self_transfer(from_node=node) self.log.info('Generate block with txid') - txid = node.sendtoaddress(address, 1) + txid = miniwallet.send_self_transfer(from_node=node)['txid'] hash = self.generateblock(node, address, [txid])['hash'] block = node.getblock(hash, 1) assert_equal(len(block['tx']), 2) assert_equal(block['tx'][1], txid) self.log.info('Generate block with raw tx') - utxos = node.listunspent(addresses=[address]) - raw = node.createrawtransaction([{'txid':utxos[0]['txid'], 'vout':utxos[0]['vout']}],[{address:1}]) - signed_raw = node.signrawtransactionwithwallet(raw)['hex'] - hash = self.generateblock(node, address, [signed_raw])['hash'] + rawtx = miniwallet.create_self_transfer(from_node=node)['hex'] + hash = self.generateblock(node, address, [rawtx])['hash'] + block = node.getblock(hash, 1) assert_equal(len(block['tx']), 2) txid = block['tx'][1] - assert_equal(node.gettransaction(txid)['hex'], signed_raw) + assert_equal(node.getrawtransaction(txid=txid, verbose=False, blockhash=hash), rawtx) self.log.info('Fail to generate block with out of order txs') - raw1 = node.createrawtransaction([{'txid':txid, 'vout':0}],[{address:0.9999}]) - signed_raw1 = node.signrawtransactionwithwallet(raw1)['hex'] - txid1 = node.sendrawtransaction(signed_raw1) - raw2 = node.createrawtransaction([{'txid':txid1, 'vout':0}],[{address:0.999}]) - signed_raw2 = node.signrawtransactionwithwallet(raw2)['hex'] - assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [signed_raw2, txid1]) + txid1 = miniwallet.send_self_transfer(from_node=node)['txid'] + utxo1 = miniwallet.get_utxo(txid=txid1) + rawtx2 = miniwallet.create_self_transfer(from_node=node, utxo_to_spend=utxo1)['hex'] + assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [rawtx2, txid1]) self.log.info('Fail to generate block with txid not in mempool') missing_txid = '0000000000000000000000000000000000000000000000000000000000000000' diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index 2a729c66d9..79a4eba1fc 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -91,7 +91,6 @@ implicit-signed-integer-truncation:leveldb/ implicit-signed-integer-truncation:miner.cpp implicit-signed-integer-truncation:net.cpp implicit-signed-integer-truncation:net_processing.cpp -implicit-signed-integer-truncation:netaddress.cpp implicit-signed-integer-truncation:streams.h implicit-signed-integer-truncation:test/arith_uint256_tests.cpp implicit-signed-integer-truncation:test/skiplist_tests.cpp |