Branch data Line data Source code
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>
11 : : #include <test/util/setup_common.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 : :
21 : : namespace wallet {
22 : 4 : std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
23 : : {
24 [ + - ]: 4 : auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
25 : 4 : {
26 [ + - + - ]: 4 : LOCK2(wallet->cs_wallet, ::cs_main);
27 [ - + + - ]: 8 : wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
28 [ + - ]: 4 : }
29 : 4 : {
30 [ + - ]: 4 : LOCK(wallet->cs_wallet);
31 [ + - ]: 4 : wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
32 [ + - ]: 4 : wallet->SetupDescriptorScriptPubKeyMans();
33 : :
34 : 4 : FlatSigningProvider provider;
35 [ + - ]: 4 : std::string error;
36 [ + - + - : 12 : auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
- + + - ]
37 [ - + - + ]: 4 : assert(descs.size() == 1);
38 [ + - ]: 4 : auto& desc = descs.at(0);
39 [ + - + - ]: 4 : WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
40 [ + - + - ]: 8 : Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
41 [ + - ]: 4 : }
42 : 4 : WalletRescanReserver reserver(*wallet);
43 : 4 : reserver.reserve();
44 [ - + + - ]: 8 : CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
45 [ - + ]: 4 : assert(result.status == CWallet::ScanResult::SUCCESS);
46 [ - + - + ]: 8 : assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
47 [ - + - + ]: 4 : assert(*result.last_scanned_height == cchain.Height());
48 [ - + ]: 4 : assert(result.last_failed_block.IsNull());
49 : 4 : return wallet;
50 : 4 : }
51 : :
52 : 3 : std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
53 : : {
54 [ + - ]: 3 : bilingual_str _error;
55 : 3 : std::vector<bilingual_str> _warnings;
56 [ + - + - ]: 6 : auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, _error, _warnings);
57 [ + - ]: 3 : NotifyWalletLoaded(context, wallet);
58 [ + + ]: 3 : if (context.chain) {
59 [ + - ]: 2 : wallet->postInitProcess();
60 : : }
61 : 6 : return wallet;
62 : 6 : }
63 : :
64 : 3 : std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
65 : : {
66 [ + - ]: 3 : DatabaseOptions options;
67 : 3 : options.require_create = true;
68 : 3 : options.create_flags = WALLET_FLAG_DESCRIPTORS;
69 : 3 : DatabaseStatus status;
70 [ + - ]: 3 : bilingual_str error;
71 : 3 : std::vector<bilingual_str> warnings;
72 [ + - + - ]: 3 : auto database = MakeWalletDatabase("", options, status, error);
73 [ + - ]: 3 : return TestCreateWallet(std::move(database), context, options.create_flags);
74 : 6 : }
75 : :
76 : :
77 : 2 : std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
78 : : {
79 [ + - ]: 2 : bilingual_str error;
80 : 2 : std::vector<bilingual_str> warnings;
81 [ + - + - ]: 4 : auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
82 [ + - ]: 2 : NotifyWalletLoaded(context, wallet);
83 [ + - ]: 2 : if (context.chain) {
84 [ + - ]: 2 : wallet->postInitProcess();
85 : : }
86 : 4 : return wallet;
87 : 4 : }
88 : :
89 : 2 : std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
90 : : {
91 [ + - ]: 2 : DatabaseOptions options;
92 : 2 : options.require_existing = true;
93 : 2 : DatabaseStatus status;
94 [ + - ]: 2 : bilingual_str error;
95 : 2 : std::vector<bilingual_str> warnings;
96 [ + - + - ]: 2 : auto database = MakeWalletDatabase("", options, status, error);
97 [ + - ]: 2 : return TestLoadWallet(std::move(database), context);
98 : 4 : }
99 : :
100 : 4 : void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
101 : : {
102 : : // Calls SyncWithValidationInterfaceQueue
103 : 4 : wallet->chain().waitForNotificationsIfTipChanged({});
104 [ + - ]: 4 : wallet->m_chain_notifications_handler.reset();
105 : 4 : WaitForDeleteWallet(std::move(wallet));
106 : 4 : }
107 : :
108 : 0 : std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database)
109 : : {
110 : 0 : std::unique_ptr<DatabaseBatch> batch_orig = database.MakeBatch();
111 [ # # ]: 0 : std::unique_ptr<DatabaseCursor> cursor_orig = batch_orig->GetNewCursor();
112 : :
113 [ # # ]: 0 : std::unique_ptr<WalletDatabase> new_db = CreateMockableWalletDatabase();
114 [ # # ]: 0 : std::unique_ptr<DatabaseBatch> new_db_batch = new_db->MakeBatch();
115 [ # # ]: 0 : MockableSQLiteBatch* batch_new = dynamic_cast<MockableSQLiteBatch*>(new_db_batch.get());
116 [ # # ]: 0 : Assert(batch_new);
117 : :
118 : 0 : while (true) {
119 : 0 : DataStream key, value;
120 [ # # ]: 0 : DatabaseCursor::Status status = cursor_orig->Next(key, value);
121 [ # # ]: 0 : Assert(status != DatabaseCursor::Status::FAIL);
122 [ # # ]: 0 : if (status != DatabaseCursor::Status::MORE) break;
123 [ # # ]: 0 : batch_new->WriteKey(std::move(key), std::move(value));
124 : 0 : }
125 : :
126 : 0 : return new_db;
127 : 0 : }
128 : :
129 : 0 : std::string getnewaddress(CWallet& w)
130 : : {
131 : 0 : constexpr auto output_type = OutputType::BECH32;
132 [ # # ]: 0 : return EncodeDestination(getNewDestination(w, output_type));
133 : : }
134 : :
135 : 0 : CTxDestination getNewDestination(CWallet& w, OutputType output_type)
136 : : {
137 [ # # # # ]: 0 : return *Assert(w.GetNewDestination(output_type, ""));
138 : : }
139 : :
140 : 75 : MockableSQLiteDatabase::MockableSQLiteDatabase()
141 [ + - + - : 225 : : SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), SQLITE_OPEN_MEMORY)
+ - + - +
- ]
142 : 75 : {}
143 : :
144 : 75 : std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
145 : : {
146 : 75 : return std::make_unique<MockableSQLiteDatabase>();
147 : : }
148 : :
149 : 20 : wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
150 : : {
151 : 20 : keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
152 : :
153 : 20 : FlatSigningProvider keys;
154 [ - + ]: 20 : std::string error;
155 [ - + + - ]: 20 : auto parsed_descs = Parse(desc_str, keys, error, false);
156 [ - + ]: 20 : Assert(success == (!parsed_descs.empty()));
157 [ + + ]: 20 : if (!success) return nullptr;
158 [ + - ]: 14 : auto& desc = parsed_descs.at(0);
159 : :
160 : 14 : const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
161 : :
162 [ + - + - ]: 14 : WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
163 : :
164 [ + - ]: 14 : LOCK(keystore.cs_wallet);
165 [ + - + - ]: 28 : auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
166 : 14 : return &spkm.value().get();
167 [ + - ]: 34 : };
168 : : } // namespace wallet
|