Bitcoin Core 31.99.0
P2P Digital Currency
util.cpp
Go to the documentation of this file.
1// Copyright (c) 2021-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <wallet/test/util.h>
6
7#include <chain.h>
8#include <key.h>
9#include <key_io.h>
10#include <streams.h>
12#include <validationinterface.h>
13#include <wallet/context.h>
14#include <wallet/wallet.h>
15#include <wallet/walletdb.h>
16
17#include <sqlite3.h>
18
19#include <memory>
20
21namespace wallet {
22std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
23{
24 auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
25 {
26 LOCK2(wallet->cs_wallet, ::cs_main);
27 wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
28 }
29 {
30 LOCK(wallet->cs_wallet);
31 wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
32 wallet->SetupDescriptorScriptPubKeyMans();
33
34 FlatSigningProvider provider;
35 std::string error;
36 auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
37 assert(descs.size() == 1);
38 auto& desc = descs.at(0);
39 WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
40 Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
41 }
43 reserver.reserve();
44 CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
46 assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
47 assert(*result.last_scanned_height == cchain.Height());
49 return wallet;
50}
51
52std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
53{
54 bilingual_str _error;
55 std::vector<bilingual_str> _warnings;
56 auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, _error, _warnings);
57 NotifyWalletLoaded(context, wallet);
58 if (context.chain) {
59 wallet->postInitProcess();
60 }
61 return wallet;
62}
63
64std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
65{
66 DatabaseOptions options;
67 options.require_create = true;
69 DatabaseStatus status;
70 bilingual_str error;
71 std::vector<bilingual_str> warnings;
72 auto database = MakeWalletDatabase("", options, status, error);
73 return TestCreateWallet(std::move(database), context, options.create_flags);
74}
75
76
77std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
78{
79 bilingual_str error;
80 std::vector<bilingual_str> warnings;
81 auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
82 NotifyWalletLoaded(context, wallet);
83 if (context.chain) {
84 wallet->postInitProcess();
85 }
86 return wallet;
87}
88
89std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
90{
91 DatabaseOptions options;
92 options.require_existing = true;
93 DatabaseStatus status;
94 bilingual_str error;
95 std::vector<bilingual_str> warnings;
96 auto database = MakeWalletDatabase("", options, status, error);
97 return TestLoadWallet(std::move(database), context);
98}
99
100void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
101{
102 // Calls SyncWithValidationInterfaceQueue
103 wallet->chain().waitForNotificationsIfTipChanged({});
104 wallet->m_chain_notifications_handler.reset();
105 WaitForDeleteWallet(std::move(wallet));
106}
107
108std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database)
109{
110 std::unique_ptr<DatabaseBatch> batch_orig = database.MakeBatch();
111 std::unique_ptr<DatabaseCursor> cursor_orig = batch_orig->GetNewCursor();
112
113 std::unique_ptr<WalletDatabase> new_db = CreateMockableWalletDatabase();
114 std::unique_ptr<DatabaseBatch> new_db_batch = new_db->MakeBatch();
115 MockableSQLiteBatch* batch_new = dynamic_cast<MockableSQLiteBatch*>(new_db_batch.get());
116 Assert(batch_new);
117
118 while (true) {
119 DataStream key, value;
120 DatabaseCursor::Status status = cursor_orig->Next(key, value);
122 if (status != DatabaseCursor::Status::MORE) break;
123 batch_new->WriteKey(std::move(key), std::move(value));
124 }
125
126 return new_db;
127}
128
129std::string getnewaddress(CWallet& w)
130{
131 constexpr auto output_type = OutputType::BECH32;
132 return EncodeDestination(getNewDestination(w, output_type));
133}
134
136{
137 return *Assert(w.GetNewDestination(output_type, ""));
138}
139
141 : SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), SQLITE_OPEN_MEMORY)
142{}
143
144std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
145{
146 return std::make_unique<MockableSQLiteDatabase>();
147}
148
149wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
150{
152
154 std::string error;
155 auto parsed_descs = Parse(desc_str, keys, error, false);
156 Assert(success == (!parsed_descs.empty()));
157 if (!success) return nullptr;
158 auto& desc = parsed_descs.at(0);
159
160 const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
161
162 WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
163
164 LOCK(keystore.cs_wallet);
165 auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
166 return &spkm.value().get();
167};
168} // namespace wallet
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
#define Assert(val)
Identity function.
Definition: check.h:116
uint256 GetBlockHash() const
Definition: chain.h:198
An in-memory indexed chain of blocks.
Definition: chain.h:380
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:396
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
Definition: chain.h:390
int Height() const
Return the maximal height in the chain.
Definition: chain.h:425
An encapsulated private key.
Definition: key.h:36
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:165
constexpr bool IsNull() const
Definition: uint256.h:49
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:118
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:309
static std::shared_ptr< CWallet > LoadExisting(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:3152
util::Result< CTxDestination > GetNewDestination(OutputType type, const std::string &label)
Definition: wallet.cpp:2626
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:459
static std::shared_ptr< CWallet > CreateNew(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:3098
util::Result< std::reference_wrapper< DescriptorScriptPubKeyMan > > AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
Definition: wallet.cpp:3783
bool WriteKey(DataStream &&key, DataStream &&value, bool overwrite=true) override
Definition: sqlite.cpp:490
An instance of this class represents one SQLite3 database.
Definition: sqlite.h:104
An instance of this class represents one database.
Definition: db.h:130
virtual std::unique_ptr< DatabaseBatch > MakeBatch()=0
Make a DatabaseBatch connected to this database.
Descriptor with some wallet metadata.
Definition: walletutil.h:64
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1088
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1098
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:396
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(void SetWalletFlag(uint64_t flags)
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
Definition: wallet.cpp:1763
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:232
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:295
wallet::DescriptorScriptPubKeyMan * CreateDescriptor(CWallet &keystore, const std::string &desc_str, const bool success)
Definition: util.cpp:149
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase()
Definition: util.cpp:144
std::unique_ptr< CWallet > CreateSyncedWallet(interfaces::Chain &chain, CChain &cchain, const CKey &key)
Definition: util.cpp:22
void TestUnloadWallet(std::shared_ptr< CWallet > &&wallet)
Definition: util.cpp:100
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
Definition: wallet.cpp:2965
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:223
std::unique_ptr< WalletDatabase > DuplicateMockDatabase(WalletDatabase &database)
Definition: util.cpp:108
std::shared_ptr< CWallet > TestLoadWallet(std::unique_ptr< WalletDatabase > database, WalletContext &context)
Definition: util.cpp:77
std::shared_ptr< CWallet > TestCreateWallet(std::unique_ptr< WalletDatabase > database, WalletContext &context, uint64_t create_flags)
Definition: util.cpp:52
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:53
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:254
RPCMethod getnewaddress()
Definition: addresses.cpp:21
CTxDestination getNewDestination(CWallet &w, OutputType output_type)
Returns a new destination, of an specific type, from the wallet.
Definition: util.cpp:135
DatabaseStatus
Definition: db.h:186
OutputType
Definition: outputtype.h:18
Bilingual messages:
Definition: translation.h:24
std::optional< int > last_scanned_height
Definition: wallet.h:647
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
Definition: wallet.h:646
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
Definition: wallet.h:653
enum wallet::CWallet::ScanResult::@18 status
bool require_existing
Definition: db.h:173
uint64_t create_flags
Definition: db.h:176
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
interfaces::Chain * chain
Definition: context.h:37
#define LOCK2(cs1, cs2)
Definition: sync.h:269
#define LOCK(cs)
Definition: sync.h:268
assert(!tx.IsCoinBase())