util.cpp raw
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 <test/util/setup_common.h>
11 #include <validationinterface.h>
12 #include <wallet/context.h>
13 #include <wallet/wallet.h>
14 #include <wallet/walletdb.h>
15
16 #include <sqlite3.h>
17
18 #include <memory>
19
20 namespace wallet {
21 std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
22 {
23 auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
24 {
25 LOCK2(wallet->cs_wallet, ::cs_main);
26 wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
27 }
28 {
29 LOCK(wallet->cs_wallet);
30 wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
31 wallet->SetupDescriptorScriptPubKeyMans();
32
33 FlatSigningProvider provider;
34 std::string error;
35 auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
36 assert(descs.size() == 1);
37 auto& desc = descs.at(0);
38 WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
39 Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
40 }
41 WalletRescanReserver reserver(*wallet);
42 reserver.reserve();
43 CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*save_progress=*/false);
44 assert(result.status == CWallet::ScanResult::SUCCESS);
45 assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
46 assert(*result.last_scanned_height == cchain.Height());
47 assert(result.last_failed_block.IsNull());
48 return wallet;
49 }
50
51 std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
52 {
53 bilingual_str _error;
54 std::vector<bilingual_str> _warnings;
55 auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, /*born_encrypted=*/false, _error, _warnings);
56 NotifyWalletLoaded(context, wallet);
57 if (context.chain) {
58 wallet->postInitProcess();
59 }
60 return wallet;
61 }
62
63 std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
64 {
65 DatabaseOptions options;
66 options.require_create = true;
67 options.create_flags = WALLET_FLAG_DESCRIPTORS;
68 DatabaseStatus status;
69 bilingual_str error;
70 std::vector<bilingual_str> warnings;
71 auto database = MakeWalletDatabase("", options, status, error);
72 return TestCreateWallet(std::move(database), context, options.create_flags);
73 }
74
75
76 std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
77 {
78 bilingual_str error;
79 std::vector<bilingual_str> warnings;
80 auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
81 NotifyWalletLoaded(context, wallet);
82 if (context.chain) {
83 wallet->postInitProcess();
84 }
85 return wallet;
86 }
87
88 std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
89 {
90 DatabaseOptions options;
91 options.require_existing = true;
92 DatabaseStatus status;
93 bilingual_str error;
94 std::vector<bilingual_str> warnings;
95 auto database = MakeWalletDatabase("", options, status, error);
96 return TestLoadWallet(std::move(database), context);
97 }
98
99 void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
100 {
101 // Calls SyncWithValidationInterfaceQueue
102 wallet->chain().waitForNotificationsIfTipChanged({});
103 wallet->m_chain_notifications_handler.reset();
104 WaitForDeleteWallet(std::move(wallet));
105 }
106
107 std::string getnewaddress(CWallet& w)
108 {
109 constexpr auto output_type = OutputType::BECH32;
110 return EncodeDestination(getNewDestination(w, output_type));
111 }
112
113 CTxDestination getNewDestination(CWallet& w, OutputType output_type)
114 {
115 return *Assert(w.GetNewDestination(output_type, ""));
116 }
117
118 MockableSQLiteDatabase::MockableSQLiteDatabase()
119 : InMemoryWalletDatabase()
120 {}
121
122 std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
123 {
124 return std::make_unique<MockableSQLiteDatabase>();
125 }
126
127 wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
128 {
129 keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
130
131 FlatSigningProvider keys;
132 std::string error;
133 auto parsed_descs = Parse(desc_str, keys, error, false);
134 Assert(success == (!parsed_descs.empty()));
135 if (!success) return nullptr;
136 auto& desc = parsed_descs.at(0);
137
138 const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
139
140 WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
141
142 LOCK(keystore.cs_wallet);
143 auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
144 return &spkm.value().get();
145 };
146 } // namespace wallet
147