diff options
41 files changed, 188 insertions, 177 deletions
diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index 230288bc6c..76cde42161 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -42,7 +42,7 @@ if [ -n "$PIP_PACKAGES" ]; then fi if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then - git clone --depth=1 https://github.com/llvm/llvm-project -b llvmorg-16.0.5 "${BASE_SCRATCH_DIR}"/msan/llvm-project + git clone --depth=1 https://github.com/llvm/llvm-project -b llvmorg-16.0.6 "${BASE_SCRATCH_DIR}"/msan/llvm-project cmake -G Ninja -B "${BASE_SCRATCH_DIR}"/msan/clang_build/ -DLLVM_ENABLE_PROJECTS="clang" \ -DCMAKE_BUILD_TYPE=Release \ @@ -55,6 +55,7 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then update-alternatives --install /usr/bin/clang++ clang++ "${BASE_SCRATCH_DIR}"/msan/clang_build/bin/clang++ 100 update-alternatives --install /usr/bin/clang clang "${BASE_SCRATCH_DIR}"/msan/clang_build/bin/clang 100 + update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer "${BASE_SCRATCH_DIR}"/msan/clang_build/bin/llvm-symbolizer 100 cmake -G Ninja -B "${BASE_SCRATCH_DIR}"/msan/cxx_build/ -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' \ -DCMAKE_BUILD_TYPE=Release \ diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh index 1e086a9f13..0b10ebd44b 100755 --- a/ci/test/06_script_b.sh +++ b/ci/test/06_script_b.sh @@ -170,5 +170,5 @@ if [ "${RUN_TIDY}" = "true" ]; then fi if [ "$RUN_FUZZ_TESTS" = "true" ]; then - bash -c "LD_LIBRARY_PATH=${DEPENDS_DIR}/${HOST}/lib test/fuzz/test_runner.py ${FUZZ_TESTS_CONFIG} $MAKEJOBS -l DEBUG ${DIR_FUZZ_IN}" + bash -c "LD_LIBRARY_PATH=${DEPENDS_DIR}/${HOST}/lib test/fuzz/test_runner.py ${FUZZ_TESTS_CONFIG} $MAKEJOBS -l DEBUG ${DIR_FUZZ_IN} --empty_min_time=60" fi diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 9187f242eb..5761e8b321 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -115,7 +115,7 @@ bool WriteSettings(const fs::path& path, { SettingsValue out(SettingsValue::VOBJ); for (const auto& value : values) { - out.__pushKV(value.first, value.second); + out.pushKVEnd(value.first, value.second); } std::ofstream file; file.open(path); diff --git a/src/kernel/mempool_entry.h b/src/kernel/mempool_entry.h index 969ddcd1ce..886e1e1b3a 100644 --- a/src/kernel/mempool_entry.h +++ b/src/kernel/mempool_entry.h @@ -57,7 +57,7 @@ struct CompareIteratorByHash { * ("descendant" transactions). * * When a new entry is added to the mempool, we update the descendant state - * (nCountWithDescendants, nSizeWithDescendants, and nModFeesWithDescendants) for + * (m_count_with_descendants, nSizeWithDescendants, and nModFeesWithDescendants) for * all ancestors of the newly added transaction. * */ @@ -87,13 +87,13 @@ private: // Information about descendants of this transaction that are in the // mempool; if we remove this transaction we must remove all of these // descendants as well. - uint64_t nCountWithDescendants{1}; //!< number of descendant transactions + int64_t m_count_with_descendants{1}; //!< number of descendant transactions // Using int64_t instead of int32_t to avoid signed integer overflow issues. int64_t nSizeWithDescendants; //!< ... and size CAmount nModFeesWithDescendants; //!< ... and total fees (all including us) // Analogous statistics for ancestor transactions - uint64_t nCountWithAncestors{1}; + int64_t m_count_with_ancestors{1}; // Using int64_t instead of int32_t to avoid signed integer overflow issues. int64_t nSizeWithAncestors; CAmount nModFeesWithAncestors; @@ -153,13 +153,13 @@ public: lockPoints = lp; } - uint64_t GetCountWithDescendants() const { return nCountWithDescendants; } + uint64_t GetCountWithDescendants() const { return m_count_with_descendants; } int64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; } bool GetSpendsCoinbase() const { return spendsCoinbase; } - uint64_t GetCountWithAncestors() const { return nCountWithAncestors; } + uint64_t GetCountWithAncestors() const { return m_count_with_ancestors; } int64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index edc0fb05d7..5f58eef1db 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -371,10 +371,10 @@ UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<s } if (!positional_args.empty()) { - // Use __pushKV instead of pushKV to avoid overwriting an explicit + // Use pushKVEnd instead of pushKV to avoid overwriting an explicit // "args" value with an implicit one. Let the RPC server handle the // request as given. - params.__pushKV("args", positional_args); + params.pushKVEnd("args", positional_args); } return params; diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 89c403b6f5..11d2874961 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -351,8 +351,8 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempoo entryToJSON(pool, info, e); // Mempool has unique entries so there is no advantage in using // UniValue::pushKV, which checks if the key already exists in O(N). - // UniValue::__pushKV is used instead which currently is O(1). - o.__pushKV(hash.ToString(), info); + // UniValue::pushKVEnd is used instead which currently is O(1). + o.pushKVEnd(hash.ToString(), info); } return o; } else { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index d39efcb245..daf751111f 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -437,7 +437,7 @@ static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, c if (options.exists(fr->first)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter " + fr->first + " specified multiple times"); } - options.__pushKV(fr->first, *fr->second); + options.pushKVEnd(fr->first, *fr->second); argsIn.erase(fr); } continue; diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index a0918bf463..b2076bea07 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -32,9 +32,9 @@ struct secure_allocator : public std::allocator<T> { { } ~secure_allocator() noexcept {} - template <typename _Other> + template <typename Other> struct rebind { - typedef secure_allocator<_Other> other; + typedef secure_allocator<Other> other; }; T* allocate(std::size_t n, const void* hint = nullptr) diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h index 795eea3bc0..2dc644c242 100644 --- a/src/support/allocators/zeroafterfree.h +++ b/src/support/allocators/zeroafterfree.h @@ -27,9 +27,9 @@ struct zero_after_free_allocator : public std::allocator<T> { { } ~zero_after_free_allocator() noexcept {} - template <typename _Other> + template <typename Other> struct rebind { - typedef zero_after_free_allocator<_Other> other; + typedef zero_after_free_allocator<Other> other; }; void deallocate(T* p, std::size_t n) diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 7035c53d13..c561675d1a 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -101,7 +101,14 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction) (void)AreInputsStandard(tx, coins_view_cache); (void)IsWitnessStandard(tx, coins_view_cache); - UniValue u(UniValue::VOBJ); - TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u); - TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u); + if (tx.GetTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding + { + UniValue u{UniValue::VOBJ}; + TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u); + } + { + UniValue u{UniValue::VOBJ}; + TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u); + } + } } diff --git a/src/test/settings_tests.cpp b/src/test/settings_tests.cpp index c24921bf9b..eb11df0497 100644 --- a/src/test/settings_tests.cpp +++ b/src/test/settings_tests.cpp @@ -35,7 +35,7 @@ inline std::ostream& operator<<(std::ostream& os, const common::SettingsValue& v inline std::ostream& operator<<(std::ostream& os, const std::pair<std::string, common::SettingsValue>& kv) { common::SettingsValue out(common::SettingsValue::VOBJ); - out.__pushKV(kv.first, kv.second); + out.pushKVEnd(kv.first, kv.second); os << out.write(); return os; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 1286eba035..845fbdb66e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -370,8 +370,8 @@ void CTxMemPoolEntry::UpdateDescendantState(int32_t modifySize, CAmount modifyFe nSizeWithDescendants += modifySize; assert(nSizeWithDescendants > 0); nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, modifyFee); - nCountWithDescendants += uint64_t(modifyCount); - assert(int64_t(nCountWithDescendants) > 0); + m_count_with_descendants += modifyCount; + assert(m_count_with_descendants > 0); } void CTxMemPoolEntry::UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps) @@ -379,8 +379,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int32_t modifySize, CAmount modifyFee, nSizeWithAncestors += modifySize; assert(nSizeWithAncestors > 0); nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, modifyFee); - nCountWithAncestors += uint64_t(modifyCount); - assert(int64_t(nCountWithAncestors) > 0); + m_count_with_ancestors += modifyCount; + assert(m_count_with_ancestors > 0); nSigOpCostWithAncestors += modifySigOps; assert(int(nSigOpCostWithAncestors) >= 0); } diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp index 19f9fae998..af86baa8ac 100644 --- a/src/txorphanage.cpp +++ b/src/txorphanage.cpp @@ -55,10 +55,10 @@ bool TxOrphanage::AddTx(const CTransactionRef& tx, NodeId peer) int TxOrphanage::EraseTx(const uint256& txid) { LOCK(m_mutex); - return _EraseTx(txid); + return EraseTxNoLock(txid); } -int TxOrphanage::_EraseTx(const uint256& txid) +int TxOrphanage::EraseTxNoLock(const uint256& txid) { AssertLockHeld(m_mutex); std::map<uint256, OrphanTx>::iterator it = m_orphans.find(txid); @@ -103,7 +103,7 @@ void TxOrphanage::EraseForPeer(NodeId peer) std::map<uint256, OrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid if (maybeErase->second.fromPeer == peer) { - nErased += _EraseTx(maybeErase->second.tx->GetHash()); + nErased += EraseTxNoLock(maybeErase->second.tx->GetHash()); } } if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer=%d\n", nErased, peer); @@ -125,7 +125,7 @@ void TxOrphanage::LimitOrphans(unsigned int max_orphans) { std::map<uint256, OrphanTx>::iterator maybeErase = iter++; if (maybeErase->second.nTimeExpire <= nNow) { - nErased += _EraseTx(maybeErase->second.tx->GetHash()); + nErased += EraseTxNoLock(maybeErase->second.tx->GetHash()); } else { nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime); } @@ -139,7 +139,7 @@ void TxOrphanage::LimitOrphans(unsigned int max_orphans) { // Evict a random orphan: size_t randompos = rng.randrange(m_orphan_list.size()); - _EraseTx(m_orphan_list[randompos]->first); + EraseTxNoLock(m_orphan_list[randompos]->first); ++nEvicted; } if (nEvicted > 0) LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted); @@ -231,7 +231,7 @@ void TxOrphanage::EraseForBlock(const CBlock& block) if (vOrphanErase.size()) { int nErased = 0; for (const uint256& orphanHash : vOrphanErase) { - nErased += _EraseTx(orphanHash); + nErased += EraseTxNoLock(orphanHash); } LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased); } diff --git a/src/txorphanage.h b/src/txorphanage.h index 45276c6c98..a4705bf382 100644 --- a/src/txorphanage.h +++ b/src/txorphanage.h @@ -99,7 +99,7 @@ protected: std::map<uint256, OrphanMap::iterator> m_wtxid_to_orphan_it GUARDED_BY(m_mutex); /** Erase an orphan by txid */ - int _EraseTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(m_mutex); + int EraseTxNoLock(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(m_mutex); }; #endif // BITCOIN_TXORPHANAGE_H diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 004135ef97..94f80f9c27 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -87,7 +87,7 @@ public: template <class It> void push_backV(It first, It last); - void __pushKV(std::string key, UniValue val); + void pushKVEnd(std::string key, UniValue val); void pushKV(std::string key, UniValue val); void pushKVs(UniValue obj); diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index c3d19caae0..656d2e8203 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -115,7 +115,7 @@ void UniValue::push_backV(const std::vector<UniValue>& vec) values.insert(values.end(), vec.begin(), vec.end()); } -void UniValue::__pushKV(std::string key, UniValue val) +void UniValue::pushKVEnd(std::string key, UniValue val) { checkType(VOBJ); @@ -131,7 +131,7 @@ void UniValue::pushKV(std::string key, UniValue val) if (findKey(key, idx)) values[idx] = std::move(val); else - __pushKV(std::move(key), std::move(val)); + pushKVEnd(std::move(key), std::move(val)); } void UniValue::pushKVs(UniValue obj) @@ -140,7 +140,7 @@ void UniValue::pushKVs(UniValue obj) obj.checkType(VOBJ); for (size_t i = 0; i < obj.keys.size(); i++) - __pushKV(std::move(obj.keys.at(i)), std::move(obj.values.at(i))); + pushKVEnd(std::move(obj.keys.at(i)), std::move(obj.values.at(i))); } void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index 5fb973c67b..8b90448b36 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -86,7 +86,7 @@ void univalue_push_throw() UniValue j; BOOST_CHECK_THROW(j.push_back(1), std::runtime_error); BOOST_CHECK_THROW(j.push_backV({1}), std::runtime_error); - BOOST_CHECK_THROW(j.__pushKV("k", 1), std::runtime_error); + BOOST_CHECK_THROW(j.pushKVEnd("k", 1), std::runtime_error); BOOST_CHECK_THROW(j.pushKV("k", 1), std::runtime_error); BOOST_CHECK_THROW(j.pushKVs({}), std::runtime_error); } @@ -364,7 +364,7 @@ void univalue_object() obj.setObject(); UniValue uv; uv.setInt(42); - obj.__pushKV("age", uv); + obj.pushKVEnd("age", uv); BOOST_CHECK_EQUAL(obj.size(), 1); BOOST_CHECK_EQUAL(obj["age"].getValStr(), "42"); diff --git a/src/validation.cpp b/src/validation.cpp index d9a0fce34f..542c1060a9 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2914,6 +2914,7 @@ CBlockIndex* Chainstate::FindMostWorkChain() while (pindexTest != pindexFailed) { if (fFailedChain) { pindexFailed->nStatus |= BLOCK_FAILED_CHILD; + m_blockman.m_dirty_blockindex.insert(pindexFailed); } else if (fMissingData) { // If we're missing data, then add back to m_blocks_unlinked, // so that if the block arrives in the future we can try adding diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp index 0bd6a9670c..a8ef0a5731 100644 --- a/src/wallet/rpc/addresses.cpp +++ b/src/wallet/rpc/addresses.cpp @@ -677,11 +677,11 @@ RPCHelpMan getaddressesbylabel() CHECK_NONFATAL(unique); // UniValue::pushKV checks if the key exists in O(N) // and since duplicate addresses are unexpected (checked with - // std::set in O(log(N))), UniValue::__pushKV is used instead, + // std::set in O(log(N))), UniValue::pushKVEnd is used instead, // which currently is O(1). UniValue value(UniValue::VOBJ); value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown"); - ret.__pushKV(address, value); + ret.pushKVEnd(address, value); } }); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 62f0f53b01..ba11933b91 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3856,16 +3856,19 @@ bool CWallet::MigrateToSQLite(bilingual_str& error) // Close this database and delete the file fs::path db_path = fs::PathFromString(m_database->Filename()); - fs::path db_dir = db_path.parent_path(); m_database->Close(); fs::remove(db_path); + // Generate the path for the location of the migrated wallet + // Wallets that are plain files rather than wallet directories will be migrated to be wallet directories. + const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(m_name)); + // Make new DB DatabaseOptions opts; opts.require_create = true; opts.require_format = DatabaseFormat::SQLITE; DatabaseStatus db_status; - std::unique_ptr<WalletDatabase> new_db = MakeDatabase(db_dir, opts, db_status, error); + std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error); assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists. m_database.reset(); m_database = std::move(new_db); diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py index 36ee79dab9..613d2eab14 100755 --- a/test/functional/feature_assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -35,7 +35,6 @@ from test_framework.blocktools import ( create_block, create_coinbase, ) -from test_framework.key import ECKey from test_framework.messages import ( CBlockHeader, COutPoint, @@ -46,9 +45,13 @@ from test_framework.messages import ( msg_headers, ) from test_framework.p2p import P2PInterface -from test_framework.script import (CScript, OP_TRUE) +from test_framework.script import ( + CScript, + OP_TRUE, +) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal +from test_framework.wallet_util import generate_keypair class BaseNode(P2PInterface): @@ -90,9 +93,7 @@ class AssumeValidTest(BitcoinTestFramework): self.blocks = [] # Get a pubkey for the coinbase TXO - coinbase_key = ECKey() - coinbase_key.generate() - coinbase_pubkey = coinbase_key.get_pubkey().get_bytes() + _, coinbase_pubkey = generate_keypair() # Create the first block with a coinbase output to our key height = 1 diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 1080e77c40..765db97445 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -14,7 +14,6 @@ from test_framework.blocktools import ( get_legacy_sigopcount_block, MAX_BLOCK_SIGOPS, ) -from test_framework.key import ECKey from test_framework.messages import ( CBlock, COIN, @@ -55,6 +54,7 @@ from test_framework.util import ( assert_equal, assert_greater_than, ) +from test_framework.wallet_util import generate_keypair from data import invalid_txs @@ -98,9 +98,7 @@ class FullBlockTest(BitcoinTestFramework): self.bootstrap_p2p() # Add one p2p connection to the node self.block_heights = {} - self.coinbase_key = ECKey() - self.coinbase_key.generate() - self.coinbase_pubkey = self.coinbase_key.get_pubkey().get_bytes() + self.coinbase_key, self.coinbase_pubkey = generate_keypair() self.tip = None self.blocks = {} self.genesis_hash = int(self.nodes[0].getbestblockhash(), 16) diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index c95657dbbb..7b2a29bdb4 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -35,8 +35,7 @@ from test_framework.util import ( assert_raises_rpc_error, ) from test_framework.wallet import getnewdestination -from test_framework.key import ECKey -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" @@ -71,12 +70,9 @@ class NULLDUMMYTest(BitcoinTestFramework): return tx_from_hex(signedtx["hex"]) def run_test(self): - eckey = ECKey() - eckey.generate() - self.privkey = bytes_to_wif(eckey.get_bytes()) - self.pubkey = eckey.get_pubkey().get_bytes().hex() - cms = self.nodes[0].createmultisig(1, [self.pubkey]) - wms = self.nodes[0].createmultisig(1, [self.pubkey], 'p2sh-segwit') + self.privkey, self.pubkey = generate_keypair(wif=True) + cms = self.nodes[0].createmultisig(1, [self.pubkey.hex()]) + wms = self.nodes[0].createmultisig(1, [self.pubkey.hex()], 'p2sh-segwit') self.ms_address = cms["address"] ms_unlock_details = {"scriptPubKey": address_to_scriptpubkey(self.ms_address).hex(), "redeemScript": cms["redeemScript"]} diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py index 8be2040d91..b37bfd28ae 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -97,6 +97,7 @@ from test_framework.util import ( assert_equal, random_bytes, ) +from test_framework.wallet_util import generate_keypair from test_framework.key import ( generate_privkey, compute_xonly_pubkey, @@ -1186,11 +1187,8 @@ def spenders_taproot_active(): # Also add a few legacy spends into the mix, so that transactions which combine taproot and pre-taproot spends get tested too. for compressed in [False, True]: - eckey1 = ECKey() - eckey1.set(generate_privkey(), compressed) - pubkey1 = eckey1.get_pubkey().get_bytes() - eckey2 = ECKey() - eckey2.set(generate_privkey(), compressed) + eckey1, pubkey1 = generate_keypair(compressed=compressed) + eckey2, _ = generate_keypair(compressed=compressed) for p2sh in [False, True]: for witv0 in [False, True]: for hashtype in VALID_SIGHASHES_ECDSA + [random.randrange(0x04, 0x80), random.randrange(0x84, 0x100)]: diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index 737a8d0a2e..8f3aec96a7 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -9,7 +9,6 @@ from decimal import Decimal import math from test_framework.test_framework import BitcoinTestFramework -from test_framework.key import ECKey from test_framework.messages import ( MAX_BIP125_RBF_SEQUENCE, COIN, @@ -44,6 +43,7 @@ from test_framework.util import ( assert_raises_rpc_error, ) from test_framework.wallet import MiniWallet +from test_framework.wallet_util import generate_keypair class MempoolAcceptanceTest(BitcoinTestFramework): @@ -283,9 +283,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): rawtxs=[tx.serialize().hex()], ) tx = tx_from_hex(raw_tx_reference) - key = ECKey() - key.generate() - pubkey = key.get_pubkey().get_bytes() + _, pubkey = generate_keypair() tx.vout[0].scriptPubKey = keys_to_multisig_script([pubkey] * 3, k=2) # Some bare multisig script (2-of-3) self.check_mempool_result( result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bare-multisig'}], diff --git a/test/functional/mempool_dust.py b/test/functional/mempool_dust.py index 41a26e82da..f4e385a112 100755 --- a/test/functional/mempool_dust.py +++ b/test/functional/mempool_dust.py @@ -5,7 +5,6 @@ """Test dust limit mempool policy (`-dustrelayfee` parameter)""" from decimal import Decimal -from test_framework.key import ECKey from test_framework.messages import ( COIN, CTxOut, @@ -32,6 +31,7 @@ from test_framework.util import ( get_fee, ) from test_framework.wallet import MiniWallet +from test_framework.wallet_util import generate_keypair DUST_RELAY_TX_FEE = 3000 # default setting [sat/kvB] @@ -74,11 +74,8 @@ class DustRelayFeeTest(BitcoinTestFramework): self.wallet = MiniWallet(self.nodes[0]) # prepare output scripts of each standard type - key = ECKey() - key.generate(compressed=False) - uncompressed_pubkey = key.get_pubkey().get_bytes() - key.generate(compressed=True) - pubkey = key.get_pubkey().get_bytes() + _, uncompressed_pubkey = generate_keypair(compressed=False) + _, pubkey = generate_keypair(compressed=True) output_scripts = ( (key_to_p2pk_script(uncompressed_pubkey), "P2PK (uncompressed)"), diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index b0900e49b8..bfae190c66 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -14,7 +14,6 @@ from test_framework.blocktools import ( create_block, create_coinbase, ) -from test_framework.key import ECKey from test_framework.messages import ( MAX_BIP125_RBF_SEQUENCE, CBlockHeader, @@ -89,6 +88,7 @@ from test_framework.util import ( assert_raises_rpc_error, ) from test_framework.wallet import MiniWallet +from test_framework.wallet_util import generate_keypair MAX_SIGOP_COST = 80000 @@ -1448,9 +1448,7 @@ class SegWitTest(BitcoinTestFramework): # Segwit transactions using uncompressed pubkeys are not accepted # under default policy, but should still pass consensus. - key = ECKey() - key.generate(False) - pubkey = key.get_pubkey().get_bytes() + key, pubkey = generate_keypair(compressed=False) assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey utxo = self.utxo.pop(0) @@ -1544,11 +1542,7 @@ class SegWitTest(BitcoinTestFramework): @subtest def test_signature_version_1(self): - - key = ECKey() - key.generate() - pubkey = key.get_pubkey().get_bytes() - + key, pubkey = generate_keypair() witness_script = key_to_p2pk_script(pubkey) script_pubkey = script_to_p2wsh_script(witness_script) diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py index 279fb01a57..34e60d70f0 100755 --- a/test/functional/rpc_createmultisig.py +++ b/test/functional/rpc_createmultisig.py @@ -12,13 +12,13 @@ from test_framework.address import address_to_scriptpubkey from test_framework.blocktools import COINBASE_MATURITY from test_framework.authproxy import JSONRPCException from test_framework.descriptors import descsum_create, drop_origins -from test_framework.key import ECPubKey, ECKey +from test_framework.key import ECPubKey from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_raises_rpc_error, assert_equal, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair from test_framework.wallet import ( MiniWallet, getnewdestination, @@ -38,10 +38,9 @@ class RpcCreateMultiSigTest(BitcoinTestFramework): self.priv = [] node0, node1, node2 = self.nodes for _ in range(self.nkeys): - k = ECKey() - k.generate() - self.pub.append(k.get_pubkey().get_bytes().hex()) - self.priv.append(bytes_to_wif(k.get_bytes(), k.is_compressed)) + privkey, pubkey = generate_keypair(wif=True) + self.pub.append(pubkey.hex()) + self.priv.append(privkey) if self.is_bdb_compiled(): self.final = node2.getnewaddress() else: diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index e2fb4673ea..c4ed4da0f2 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -8,7 +8,7 @@ from decimal import Decimal from itertools import product from test_framework.descriptors import descsum_create -from test_framework.key import ECKey, H_POINT +from test_framework.key import H_POINT from test_framework.messages import ( COutPoint, CTransaction, @@ -43,8 +43,8 @@ from test_framework.util import ( random_bytes, ) from test_framework.wallet_util import ( - bytes_to_wif, - get_generate_key + generate_keypair, + get_generate_key, ) import json @@ -710,9 +710,7 @@ class PSBTTest(BitcoinTestFramework): self.log.info("Test that we can fund psbts with external inputs specified") - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) + privkey, _ = generate_keypair(wif=True) self.nodes[1].createwallet("extfund") wallet = self.nodes[1].get_wallet_rpc("extfund") @@ -825,11 +823,9 @@ class PSBTTest(BitcoinTestFramework): self.nodes[1].createwallet(wallet_name="scriptwatchonly", disable_private_keys=True) watchonly = self.nodes[1].get_wallet_rpc("scriptwatchonly") - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) + privkey, pubkey = generate_keypair(wif=True) - desc = descsum_create("wsh(pkh({}))".format(eckey.get_pubkey().get_bytes().hex())) + desc = descsum_create("wsh(pkh({}))".format(pubkey.hex())) if self.options.descriptors: res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}]) else: @@ -846,11 +842,9 @@ class PSBTTest(BitcoinTestFramework): # Same test but for taproot if self.options.descriptors: - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) + privkey, pubkey = generate_keypair(wif=True) - desc = descsum_create("tr({},pk({}))".format(H_POINT, eckey.get_pubkey().get_bytes().hex())) + desc = descsum_create("tr({},pk({}))".format(H_POINT, pubkey.hex())) res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}]) assert res[0]["success"] addr = self.nodes[0].deriveaddresses(desc)[0] diff --git a/test/functional/rpc_signrawtransactionwithkey.py b/test/functional/rpc_signrawtransactionwithkey.py index 580f63063d..ac7a86704f 100755 --- a/test/functional/rpc_signrawtransactionwithkey.py +++ b/test/functional/rpc_signrawtransactionwithkey.py @@ -11,7 +11,6 @@ from test_framework.address import ( address_to_scriptpubkey, script_to_p2sh, ) -from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -23,16 +22,16 @@ from test_framework.script_util import ( script_to_p2sh_p2wsh_script, script_to_p2wsh_script, ) +from test_framework.wallet import ( + getnewdestination, +) from test_framework.wallet_util import ( - bytes_to_wif, + generate_keypair, ) from decimal import ( Decimal, ) -from test_framework.wallet import ( - getnewdestination, -) class SignRawTransactionWithKeyTest(BitcoinTestFramework): @@ -80,11 +79,8 @@ class SignRawTransactionWithKeyTest(BitcoinTestFramework): def witness_script_test(self): self.log.info("Test signing transaction to P2SH-P2WSH addresses without wallet") # Create a new P2SH-P2WSH 1-of-1 multisig address: - eckey = ECKey() - eckey.generate() - embedded_privkey = bytes_to_wif(eckey.get_bytes()) - embedded_pubkey = eckey.get_pubkey().get_bytes().hex() - p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey], "p2sh-segwit") + embedded_privkey, embedded_pubkey = generate_keypair(wif=True) + p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey.hex()], "p2sh-segwit") # send transaction to P2SH-P2WSH 1-of-1 multisig address self.block_hash = self.generate(self.nodes[0], COINBASE_MATURITY + 1) self.blk_idx = 0 @@ -109,10 +105,7 @@ class SignRawTransactionWithKeyTest(BitcoinTestFramework): def verify_txn_with_witness_script(self, tx_type): self.log.info("Test with a {} script as the witnessScript".format(tx_type)) - eckey = ECKey() - eckey.generate() - embedded_privkey = bytes_to_wif(eckey.get_bytes()) - embedded_pubkey = eckey.get_pubkey().get_bytes().hex() + embedded_privkey, embedded_pubkey = generate_keypair(wif=True) witness_script = { 'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(), 'P2PK': key_to_p2pk_script(embedded_pubkey).hex() diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index 1d546e12bd..271095ea21 100644 --- a/test/functional/test_framework/wallet.py +++ b/test/functional/test_framework/wallet.py @@ -20,6 +20,7 @@ from test_framework.address import ( key_to_p2wpkh, output_key_to_p2tr, ) +from test_framework.blocktools import COINBASE_MATURITY from test_framework.descriptors import descsum_create from test_framework.key import ( ECKey, @@ -53,7 +54,7 @@ from test_framework.util import ( assert_equal, assert_greater_than_or_equal, ) -from test_framework.blocktools import COINBASE_MATURITY +from test_framework.wallet_util import generate_keypair DEFAULT_FEE = Decimal("0.0001") @@ -395,9 +396,7 @@ def getnewdestination(address_type='bech32m'): 'legacy', 'p2sh-segwit', 'bech32' and 'bech32m'. Can be used when a random destination is needed, but no compiled wallet is available (e.g. as replacement to the getnewaddress/getaddressinfo RPCs).""" - key = ECKey() - key.generate() - pubkey = key.get_pubkey().get_bytes() + key, pubkey = generate_keypair() if address_type == 'legacy': scriptpubkey = key_to_p2pkh_script(pubkey) address = key_to_p2pkh(pubkey) diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py index 410d85cd8c..319f120297 100755 --- a/test/functional/test_framework/wallet_util.py +++ b/test/functional/test_framework/wallet_util.py @@ -63,12 +63,9 @@ def get_generate_key(): """Generate a fresh key Returns a named tuple of privkey, pubkey and all address and scripts.""" - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) - pubkey = eckey.get_pubkey().get_bytes().hex() + privkey, pubkey = generate_keypair(wif=True) return Key(privkey=privkey, - pubkey=pubkey, + pubkey=pubkey.hex(), p2pkh_script=key_to_p2pkh_script(pubkey).hex(), p2pkh_addr=key_to_p2pkh(pubkey), p2wpkh_script=key_to_p2wpkh_script(pubkey).hex(), @@ -114,8 +111,14 @@ def bytes_to_wif(b, compressed=True): b += b'\x01' return byte_to_base58(b, 239) -def generate_wif_key(): - # Makes a WIF privkey for imports - k = ECKey() - k.generate() - return bytes_to_wif(k.get_bytes(), k.is_compressed) +def generate_keypair(compressed=True, wif=False): + """Generate a new random keypair and return the corresponding ECKey / + bytes objects. The private key can also be provided as WIF (wallet + import format) string instead, which is often useful for wallet RPC + interaction.""" + privkey = ECKey() + privkey.generate(compressed) + pubkey = privkey.get_pubkey().get_bytes() + if wif: + privkey = bytes_to_wif(privkey.get_bytes(), compressed) + return privkey, pubkey diff --git a/test/functional/wallet_blank.py b/test/functional/wallet_blank.py index eda3fda35b..4836eba3b2 100755 --- a/test/functional/wallet_blank.py +++ b/test/functional/wallet_blank.py @@ -10,11 +10,10 @@ from test_framework.address import ( ADDRESS_BCRT1_UNSPENDABLE, ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR, ) -from test_framework.key import ECKey from test_framework.util import ( assert_equal, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair class WalletBlankTest(BitcoinTestFramework): @@ -50,10 +49,8 @@ class WalletBlankTest(BitcoinTestFramework): assert_equal(info["descriptors"], False) assert_equal(info["blank"], True) - eckey = ECKey() - eckey.generate(compressed=comp) - - wallet.importpubkey(eckey.get_pubkey().get_bytes().hex()) + _, pubkey = generate_keypair(compressed=comp) + wallet.importpubkey(pubkey.hex()) assert_equal(wallet.getwalletinfo()["blank"], False) def test_importprivkey(self): @@ -67,10 +64,7 @@ class WalletBlankTest(BitcoinTestFramework): assert_equal(info["descriptors"], False) assert_equal(info["blank"], True) - eckey = ECKey() - eckey.generate(compressed=comp) - wif = bytes_to_wif(eckey.get_bytes(), eckey.is_compressed) - + wif, _ = generate_keypair(compressed=comp, wif=True) wallet.importprivkey(wif) assert_equal(wallet.getwalletinfo()["blank"], False) diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index a4e6f96cce..75b507c387 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -7,13 +7,13 @@ from test_framework.address import key_to_p2wpkh from test_framework.descriptors import descsum_create -from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) -from test_framework.wallet_util import bytes_to_wif, generate_wif_key +from test_framework.wallet_util import generate_keypair + EMPTY_PASSPHRASE_MSG = "Empty string given as passphrase, wallet will not be encrypted." LEGACY_WALLET_MSG = "Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future." @@ -50,14 +50,12 @@ class CreateWalletTest(BitcoinTestFramework): w1.importpubkey(w0.getaddressinfo(address1)['pubkey']) self.log.info('Test that private keys cannot be imported') - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) + privkey, pubkey = generate_keypair(wif=True) assert_raises_rpc_error(-4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey) if self.options.descriptors: result = w1.importdescriptors([{'desc': descsum_create('wpkh(' + privkey + ')'), 'timestamp': 'now'}]) else: - result = w1.importmulti([{'scriptPubKey': {'address': key_to_p2wpkh(eckey.get_pubkey().get_bytes())}, 'timestamp': 'now', 'keys': [privkey]}]) + result = w1.importmulti([{'scriptPubKey': {'address': key_to_p2wpkh(pubkey)}, 'timestamp': 'now', 'keys': [privkey]}]) assert not result[0]['success'] assert 'warnings' not in result[0] assert_equal(result[0]['error']['code'], -4) @@ -77,7 +75,7 @@ class CreateWalletTest(BitcoinTestFramework): assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getrawchangeaddress) # Import private key - w3.importprivkey(generate_wif_key()) + w3.importprivkey(generate_keypair(wif=True)[0]) # Imported private keys are currently ignored by the keypool assert_equal(w3.getwalletinfo()['keypoolsize'], 0) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) diff --git a/test/functional/wallet_fundrawtransaction.py b/test/functional/wallet_fundrawtransaction.py index c88e0b3f6e..46706d6ad2 100755 --- a/test/functional/wallet_fundrawtransaction.py +++ b/test/functional/wallet_fundrawtransaction.py @@ -10,7 +10,6 @@ from itertools import product from math import ceil from test_framework.descriptors import descsum_create -from test_framework.key import ECKey from test_framework.messages import ( COIN, ) @@ -25,7 +24,7 @@ from test_framework.util import ( count_bytes, find_vout_for_address, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair ERR_NOT_ENOUGH_PRESET_INPUTS = "The preselected coins total amount does not cover the transaction target. " \ "Please allow other inputs to be automatically selected or include more coins manually" @@ -999,11 +998,7 @@ class RawTransactionsTest(BitcoinTestFramework): def test_external_inputs(self): self.log.info("Test funding with external inputs") - - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) - + privkey, _ = generate_keypair(wif=True) self.nodes[2].createwallet("extfund") wallet = self.nodes[2].get_wallet_rpc("extfund") diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 77b407579f..5fe7c4b591 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -7,7 +7,6 @@ from decimal import Decimal from test_framework.address import key_to_p2wpkh from test_framework.blocktools import COINBASE_MATURITY -from test_framework.key import ECKey from test_framework.messages import ( CMerkleBlock, from_hex, @@ -17,7 +16,7 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair class ImportPrunedFundsTest(BitcoinTestFramework): @@ -40,10 +39,8 @@ class ImportPrunedFundsTest(BitcoinTestFramework): # pubkey address2 = self.nodes[0].getnewaddress() # privkey - eckey = ECKey() - eckey.generate() - address3_privkey = bytes_to_wif(eckey.get_bytes()) - address3 = key_to_p2wpkh(eckey.get_pubkey().get_bytes()) + address3_privkey, address3_pubkey = generate_keypair(wif=True) + address3 = key_to_p2wpkh(address3_pubkey) self.nodes[0].importprivkey(address3_privkey) # Check only one address diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index bfca344fd1..a19a3ac2cb 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -7,7 +7,6 @@ from test_framework.address import key_to_p2wpkh from test_framework.blocktools import COINBASE_MATURITY from test_framework.descriptors import descsum_create -from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework from test_framework.messages import MAX_BIP125_RBF_SEQUENCE from test_framework.util import ( @@ -15,7 +14,7 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair from decimal import Decimal @@ -202,10 +201,8 @@ class ListSinceBlockTest(BitcoinTestFramework): self.sync_all() # share utxo between nodes[1] and nodes[2] - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) - address = key_to_p2wpkh(eckey.get_pubkey().get_bytes()) + privkey, pubkey = generate_keypair(wif=True) + address = key_to_p2wpkh(pubkey) self.nodes[2].sendtoaddress(address, 10) self.generate(self.nodes[2], 6) self.nodes[2].importprivkey(privkey) diff --git a/test/functional/wallet_migration.py b/test/functional/wallet_migration.py index c6c2af10b1..320f5dd9df 100755 --- a/test/functional/wallet_migration.py +++ b/test/functional/wallet_migration.py @@ -6,6 +6,7 @@ import os import random +import shutil from test_framework.descriptors import descsum_create from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -470,6 +471,40 @@ class WalletMigrationTest(BitcoinTestFramework): assert_equal(bals, wallet.getbalances()) + def test_default_wallet(self): + self.log.info("Test migration of the wallet named as the empty string") + wallet = self.create_legacy_wallet("") + + wallet.migratewallet() + info = wallet.getwalletinfo() + assert_equal(info["descriptors"], True) + assert_equal(info["format"], "sqlite") + + def test_direct_file(self): + self.log.info("Test migration of a wallet that is not in a wallet directory") + wallet = self.create_legacy_wallet("plainfile") + wallet.unloadwallet() + + wallets_dir = os.path.join(self.nodes[0].datadir, "regtest", "wallets") + wallet_path = os.path.join(wallets_dir, "plainfile") + wallet_dat_path = os.path.join(wallet_path, "wallet.dat") + shutil.copyfile(wallet_dat_path, os.path.join(wallets_dir, "plainfile.bak")) + shutil.rmtree(wallet_path) + shutil.move(os.path.join(wallets_dir, "plainfile.bak"), wallet_path) + + self.nodes[0].loadwallet("plainfile") + info = wallet.getwalletinfo() + assert_equal(info["descriptors"], False) + assert_equal(info["format"], "bdb") + + wallet.migratewallet() + info = wallet.getwalletinfo() + assert_equal(info["descriptors"], True) + assert_equal(info["format"], "sqlite") + + assert os.path.isdir(wallet_path) + assert os.path.isfile(wallet_dat_path) + def run_test(self): self.generate(self.nodes[0], 101) @@ -482,6 +517,8 @@ class WalletMigrationTest(BitcoinTestFramework): self.test_encrypted() self.test_unloaded() self.test_unloaded_by_path() + self.test_default_wallet() + self.test_direct_file() if __name__ == '__main__': WalletMigrationTest().main() diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index ac3ec06eec..d7bb6ab1e7 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -9,7 +9,6 @@ from itertools import product from test_framework.authproxy import JSONRPCException from test_framework.descriptors import descsum_create -from test_framework.key import ECKey from test_framework.messages import ( ser_compact_size, WITNESS_SCALE_FACTOR, @@ -22,7 +21,8 @@ from test_framework.util import ( assert_raises_rpc_error, count_bytes, ) -from test_framework.wallet_util import bytes_to_wif +from test_framework.wallet_util import generate_keypair + class WalletSendTest(BitcoinTestFramework): def add_options(self, parser): @@ -500,9 +500,7 @@ class WalletSendTest(BitcoinTestFramework): assert res["complete"] self.log.info("External outputs") - eckey = ECKey() - eckey.generate() - privkey = bytes_to_wif(eckey.get_bytes()) + privkey, _ = generate_keypair(wif=True) self.nodes[1].createwallet("extsend") ext_wallet = self.nodes[1].get_wallet_rpc("extsend") diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py index af21e7b956..d953f48584 100755 --- a/test/fuzz/test_runner.py +++ b/test/fuzz/test_runner.py @@ -6,6 +6,7 @@ """ from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path import argparse import configparser import logging @@ -42,6 +43,11 @@ def main(): help='If true, run fuzzing binaries under the valgrind memory error detector', ) parser.add_argument( + "--empty_min_time", + type=int, + help="If set, run at least this long, if the existing fuzz inputs directory is empty.", + ) + parser.add_argument( '-x', '--exclude', help="A comma-separated list of targets to exclude", @@ -76,6 +82,7 @@ def main(): ) args = parser.parse_args() + args.corpus_dir = Path(args.corpus_dir) # Set up logging logging.basicConfig( @@ -180,6 +187,7 @@ def main(): src_dir=config['environment']['SRCDIR'], build_dir=config["environment"]["BUILDDIR"], use_valgrind=args.valgrind, + empty_min_time=args.empty_min_time, ) @@ -251,16 +259,22 @@ def merge_inputs(*, fuzz_pool, corpus, test_list, src_dir, build_dir, merge_dir) future.result() -def run_once(*, fuzz_pool, corpus, test_list, src_dir, build_dir, use_valgrind): +def run_once(*, fuzz_pool, corpus, test_list, src_dir, build_dir, use_valgrind, empty_min_time): jobs = [] for t in test_list: - corpus_path = os.path.join(corpus, t) + corpus_path = corpus / t os.makedirs(corpus_path, exist_ok=True) args = [ os.path.join(build_dir, 'src', 'test', 'fuzz', 'fuzz'), - '-runs=1', - corpus_path, ] + empty_dir = not any(corpus_path.iterdir()) + if empty_min_time and empty_dir: + args += [f"-max_total_time={empty_min_time}"] + else: + args += [ + "-runs=1", + corpus_path, + ] if use_valgrind: args = ['valgrind', '--quiet', '--error-exitcode=1'] + args diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index ae70fb49d4..8808a83e32 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -46,7 +46,6 @@ unsigned-integer-overflow:hash.cpp unsigned-integer-overflow:policy/fees.cpp unsigned-integer-overflow:prevector.h unsigned-integer-overflow:script/interpreter.cpp -unsigned-integer-overflow:txmempool.cpp unsigned-integer-overflow:xoroshiro128plusplus.h implicit-integer-sign-change:compat/stdin.cpp implicit-integer-sign-change:compressor.h |