diff options
Diffstat (limited to 'src/wallet/test/fuzz')
-rw-r--r-- | src/wallet/test/fuzz/coinselection.cpp | 4 | ||||
-rw-r--r-- | src/wallet/test/fuzz/scriptpubkeyman.cpp | 16 | ||||
-rw-r--r-- | src/wallet/test/fuzz/wallet_bdb_parser.cpp | 135 |
3 files changed, 153 insertions, 2 deletions
diff --git a/src/wallet/test/fuzz/coinselection.cpp b/src/wallet/test/fuzz/coinselection.cpp index 331590df7f..644a8dd7ad 100644 --- a/src/wallet/test/fuzz/coinselection.cpp +++ b/src/wallet/test/fuzz/coinselection.cpp @@ -270,7 +270,7 @@ FUZZ_TARGET(coinselection) if (result_srd) { assert(result_srd->GetSelectedValue() >= target); assert(result_srd->GetChange(CHANGE_LOWER, coin_params.m_change_fee) > 0); // Demonstrate that SRD creates change of at least CHANGE_LOWER - result_srd->ComputeAndSetWaste(coin_params.min_viable_change, coin_params.m_cost_of_change, coin_params.m_change_fee); + result_srd->RecalculateWaste(coin_params.min_viable_change, coin_params.m_cost_of_change, coin_params.m_change_fee); (void)result_srd->GetShuffledInputVector(); (void)result_srd->GetInputSet(); } @@ -279,7 +279,7 @@ FUZZ_TARGET(coinselection) auto result_knapsack = KnapsackSolver(group_all, target, change_target, fast_random_context, MAX_STANDARD_TX_WEIGHT); if (result_knapsack) { assert(result_knapsack->GetSelectedValue() >= target); - result_knapsack->ComputeAndSetWaste(coin_params.min_viable_change, coin_params.m_cost_of_change, coin_params.m_change_fee); + result_knapsack->RecalculateWaste(coin_params.min_viable_change, coin_params.m_cost_of_change, coin_params.m_change_fee); (void)result_knapsack->GetShuffledInputVector(); (void)result_knapsack->GetInputSet(); } diff --git a/src/wallet/test/fuzz/scriptpubkeyman.cpp b/src/wallet/test/fuzz/scriptpubkeyman.cpp index 228e9629ed..835470aeae 100644 --- a/src/wallet/test/fuzz/scriptpubkeyman.cpp +++ b/src/wallet/test/fuzz/scriptpubkeyman.cpp @@ -137,6 +137,15 @@ FUZZ_TARGET(scriptpubkeyman, .init = initialize_spkm) PKHash{ConsumeUInt160(fuzzed_data_provider)}}; std::string str_sig; (void)spk_manager->SignMessage(msg, pk_hash, str_sig); + (void)spk_manager->GetMetadata(dest); + } + } + }, + [&] { + auto spks{spk_manager->GetScriptPubKeys()}; + for (const CScript& spk : spks) { + if (fuzzed_data_provider.ConsumeBool()) { + spk_manager->MarkUnusedAddresses(spk); } } }, @@ -148,6 +157,10 @@ FUZZ_TARGET(scriptpubkeyman, .init = initialize_spkm) } spk_manager->AddDescriptorKey(key, key.GetPubKey()); spk_manager->TopUp(); + LOCK(spk_manager->cs_desc_man); + auto particular_key{spk_manager->GetKey(key.GetPubKey().GetID())}; + assert(*particular_key == key); + assert(spk_manager->HasPrivKey(key.GetPubKey().GetID())); }, [&] { std::string descriptor; @@ -194,6 +207,9 @@ FUZZ_TARGET(scriptpubkeyman, .init = initialize_spkm) } ); } + + (void)spk_manager->GetEndRange(); + (void)spk_manager->GetKeyPoolSize(); } } // namespace diff --git a/src/wallet/test/fuzz/wallet_bdb_parser.cpp b/src/wallet/test/fuzz/wallet_bdb_parser.cpp new file mode 100644 index 0000000000..5216e09769 --- /dev/null +++ b/src/wallet/test/fuzz/wallet_bdb_parser.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <config/bitcoin-config.h> // IWYU pragma: keep +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> +#include <util/fs.h> +#include <util/time.h> +#include <util/translation.h> +#include <wallet/bdb.h> +#include <wallet/db.h> +#include <wallet/dump.h> +#include <wallet/migrate.h> + +#include <fstream> +#include <iostream> + +using wallet::DatabaseOptions; +using wallet::DatabaseStatus; + +namespace { +TestingSetup* g_setup; +} // namespace + +void initialize_wallet_bdb_parser() +{ + static auto testing_setup = MakeNoLogFileContext<TestingSetup>(); + g_setup = testing_setup.get(); +} + +FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser) +{ + const auto wallet_path = g_setup->m_args.GetDataDirNet() / "fuzzed_wallet.dat"; + + { + AutoFile outfile{fsbridge::fopen(wallet_path, "wb")}; + outfile << Span{buffer}; + } + + const DatabaseOptions options{}; + DatabaseStatus status; + bilingual_str error; + + fs::path bdb_ro_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb_ro.dump"}; + if (fs::exists(bdb_ro_dumpfile)) { // Writing into an existing dump file will throw an exception + remove(bdb_ro_dumpfile); + } + g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_ro_dumpfile)); + +#ifdef USE_BDB + bool bdb_ro_err = false; + bool bdb_ro_strict_err = false; +#endif + auto db{MakeBerkeleyRODatabase(wallet_path, options, status, error)}; + if (db) { + assert(DumpWallet(g_setup->m_args, *db, error)); + } else { +#ifdef USE_BDB + bdb_ro_err = true; +#endif + if (error.original.starts_with("AutoFile::ignore: end of file") || + error.original.starts_with("AutoFile::read: end of file") || + error.original == "Not a BDB file" || + error.original == "Unexpected page type, should be 9 (BTree Metadata)" || + error.original == "Unexpected database flags, should only be 0x20 (subdatabases)" || + error.original == "Unexpected outer database root page type" || + error.original == "Unexpected number of entries in outer database root page" || + error.original == "Subdatabase page number has unexpected length" || + error.original == "Unknown record type in records page" || + error.original == "Unknown record type in internal page" || + error.original == "Unexpected page size" || + error.original == "Unexpected page type" || + error.original == "Page number mismatch" || + error.original == "Bad btree level" || + error.original == "Bad page size" || + error.original == "Meta page number mismatch" || + error.original == "Data record position not in page" || + error.original == "Internal record position not in page" || + error.original == "LSNs are not reset, this database is not completely flushed. Please reopen then close the database with a version that has BDB support" || + error.original == "Records page has odd number of records" || + error.original == "Bad overflow record page type") { + // Do nothing + } else if (error.original == "Subdatabase last page is greater than database last page" || + error.original == "Page number is greater than database last page" || + error.original == "Last page number could not fit in file" || + error.original == "Subdatabase has an unexpected name" || + error.original == "Unsupported BDB data file version number" || + error.original == "BDB builtin encryption is not supported") { +#ifdef USE_BDB + bdb_ro_strict_err = true; +#endif + } else { + throw std::runtime_error(error.original); + } + } + +#ifdef USE_BDB + // Try opening with BDB + fs::path bdb_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb.dump"}; + if (fs::exists(bdb_dumpfile)) { // Writing into an existing dump file will throw an exception + remove(bdb_dumpfile); + } + g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_dumpfile)); + + try { + auto db{MakeBerkeleyDatabase(wallet_path, options, status, error)}; + if (bdb_ro_err && !db) { + return; + } + assert(db); + if (bdb_ro_strict_err) { + // BerkeleyRO will be stricter than BDB. Ignore when those specific errors are hit. + return; + } + assert(!bdb_ro_err); + assert(DumpWallet(g_setup->m_args, *db, error)); + } catch (const std::runtime_error& e) { + if (bdb_ro_err) return; + throw e; + } + + // Make sure the dumpfiles match + if (fs::exists(bdb_ro_dumpfile) && fs::exists(bdb_dumpfile)) { + std::ifstream bdb_ro_dump(bdb_ro_dumpfile, std::ios_base::binary | std::ios_base::in); + std::ifstream bdb_dump(bdb_dumpfile, std::ios_base::binary | std::ios_base::in); + assert(std::equal( + std::istreambuf_iterator<char>(bdb_ro_dump.rdbuf()), + std::istreambuf_iterator<char>(), + std::istreambuf_iterator<char>(bdb_dump.rdbuf()))); + } +#endif +} |