mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-12 13:42:10 +02:00
451fdd26a4test: wallet: Constructing a DSPKM that can't TopUp() throws. (David Gumberg)32946e0291wallet: Setup new autogenerated descriptors on construction (Ava Chow)e20aaff70fwallet: Construct ExternalSignerSPKM with the new descriptor (Ava Chow)aa4f7823aawallet: include keys when constructing DescriptorSPKM during import (Ava Chow)6538f69135fuzz: Skip adding descriptor to wallet if it cannot be expanded (Ava Chow)8be5ee554btest: wallet: Check that loading wallet with both unencrypted and encrypted keys fails. (David Gumberg)80b0c25992wallet: Load everything into DescSPKM on construction (Ava Chow)f713fd1725refactor: wallet: Don't reuse WALLET_BLANK flag for born-encrypted wallets. (David Gumberg)cd912c4e10wallet: Consolidate generation setup callers into one function (Ava Chow)0301c758eawallet migration, fuzz: Migrate hd seed once (Ava Chow) Pull request description: Instead of constructing ScriptPubKeyMans with no data, and then loading data as we find it, we should gather everything first and then load it all on construction. If there actually is no data and we want to setup generation, then that should also occur in a constructor rather than afterwards. This change is only applied to DescriptorScriptPubKeyMan and ExternalSignerScriptPubKeyMan, and should be done for any ScriptPubKeyMans added in the future. I don't think it's really worth it to do this for LegacyScriptPubKeyMan since it would make loading performance worse (or cause layer violations) and it's (supposed to be) going away soon. ACKs for top commit: polespinasa: ACK451fdd26a4davidgumberg: re crACK451fdd26a4w0xlt: ACK451fdd26a4Tree-SHA512: 58a889bf7c77d5da78041907a76a1958207f95a19bec8dc4d86d4e4108d256a729e0949c0973f7d447178f78a7fd4268cda71d358cae4dec5a76dc453b5283af
147 lines
5.0 KiB
C++
147 lines
5.0 KiB
C++
// Copyright (c) 2021-present 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 <wallet/test/util.h>
|
|
|
|
#include <chain.h>
|
|
#include <key.h>
|
|
#include <key_io.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <validationinterface.h>
|
|
#include <wallet/context.h>
|
|
#include <wallet/wallet.h>
|
|
#include <wallet/walletdb.h>
|
|
|
|
#include <sqlite3.h>
|
|
|
|
#include <memory>
|
|
|
|
namespace wallet {
|
|
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
|
|
{
|
|
auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
|
|
{
|
|
LOCK2(wallet->cs_wallet, ::cs_main);
|
|
wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
|
|
}
|
|
{
|
|
LOCK(wallet->cs_wallet);
|
|
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
wallet->SetupDescriptorScriptPubKeyMans();
|
|
|
|
FlatSigningProvider provider;
|
|
std::string error;
|
|
auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
|
|
assert(descs.size() == 1);
|
|
auto& desc = descs.at(0);
|
|
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
|
|
Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
|
|
}
|
|
WalletRescanReserver reserver(*wallet);
|
|
reserver.reserve();
|
|
CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*save_progress=*/false);
|
|
assert(result.status == CWallet::ScanResult::SUCCESS);
|
|
assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
|
|
assert(*result.last_scanned_height == cchain.Height());
|
|
assert(result.last_failed_block.IsNull());
|
|
return wallet;
|
|
}
|
|
|
|
std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
|
|
{
|
|
bilingual_str _error;
|
|
std::vector<bilingual_str> _warnings;
|
|
auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, /*born_encrypted=*/false, _error, _warnings);
|
|
NotifyWalletLoaded(context, wallet);
|
|
if (context.chain) {
|
|
wallet->postInitProcess();
|
|
}
|
|
return wallet;
|
|
}
|
|
|
|
std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
|
|
{
|
|
DatabaseOptions options;
|
|
options.require_create = true;
|
|
options.create_flags = WALLET_FLAG_DESCRIPTORS;
|
|
DatabaseStatus status;
|
|
bilingual_str error;
|
|
std::vector<bilingual_str> warnings;
|
|
auto database = MakeWalletDatabase("", options, status, error);
|
|
return TestCreateWallet(std::move(database), context, options.create_flags);
|
|
}
|
|
|
|
|
|
std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
|
|
{
|
|
bilingual_str error;
|
|
std::vector<bilingual_str> warnings;
|
|
auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
|
|
NotifyWalletLoaded(context, wallet);
|
|
if (context.chain) {
|
|
wallet->postInitProcess();
|
|
}
|
|
return wallet;
|
|
}
|
|
|
|
std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
|
|
{
|
|
DatabaseOptions options;
|
|
options.require_existing = true;
|
|
DatabaseStatus status;
|
|
bilingual_str error;
|
|
std::vector<bilingual_str> warnings;
|
|
auto database = MakeWalletDatabase("", options, status, error);
|
|
return TestLoadWallet(std::move(database), context);
|
|
}
|
|
|
|
void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
|
|
{
|
|
// Calls SyncWithValidationInterfaceQueue
|
|
wallet->chain().waitForNotificationsIfTipChanged({});
|
|
wallet->m_chain_notifications_handler.reset();
|
|
WaitForDeleteWallet(std::move(wallet));
|
|
}
|
|
|
|
std::string getnewaddress(CWallet& w)
|
|
{
|
|
constexpr auto output_type = OutputType::BECH32;
|
|
return EncodeDestination(getNewDestination(w, output_type));
|
|
}
|
|
|
|
CTxDestination getNewDestination(CWallet& w, OutputType output_type)
|
|
{
|
|
return *Assert(w.GetNewDestination(output_type, ""));
|
|
}
|
|
|
|
MockableSQLiteDatabase::MockableSQLiteDatabase()
|
|
: SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), SQLITE_OPEN_MEMORY)
|
|
{}
|
|
|
|
std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
|
|
{
|
|
return std::make_unique<MockableSQLiteDatabase>();
|
|
}
|
|
|
|
wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
|
|
{
|
|
keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
|
|
|
|
FlatSigningProvider keys;
|
|
std::string error;
|
|
auto parsed_descs = Parse(desc_str, keys, error, false);
|
|
Assert(success == (!parsed_descs.empty()));
|
|
if (!success) return nullptr;
|
|
auto& desc = parsed_descs.at(0);
|
|
|
|
const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
|
|
|
|
WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
|
|
|
|
LOCK(keystore.cs_wallet);
|
|
auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
|
|
return &spkm.value().get();
|
|
};
|
|
} // namespace wallet
|