wallet.cpp raw
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Limenka developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <wallet/wallet.h>
7
8 #include <limenka-build-config.h> // IWYU pragma: keep
9 #include <addresstype.h>
10 #include <blockfilter.h>
11 #include <chain.h>
12 #include <coins.h>
13 #include <common/args.h>
14 #include <common/messages.h>
15 #include <common/settings.h>
16 #include <common/signmessage.h>
17 #include <common/system.h>
18 #include <consensus/amount.h>
19 #include <consensus/consensus.h>
20 #include <consensus/validation.h>
21 #include <consensus/ct.h>
22 #include <external_signer.h>
23 #include <interfaces/chain.h>
24 #include <interfaces/handler.h>
25 #include <interfaces/wallet.h>
26 #include <kernel/chain.h>
27 #include <kernel/mempool_removal_reason.h>
28 #include <key.h>
29 #include <key_io.h>
30 #include <logging.h>
31 #include <node/types.h>
32 #include <outputtype.h>
33 #include <policy/feerate.h>
34 #include <primitives/block.h>
35 #include <primitives/transaction.h>
36 #include <psbt.h>
37 #include <pubkey.h>
38 #include <random.h>
39 #include <script/descriptor.h>
40 #include <script/interpreter.h>
41 #include <script/script.h>
42 #include <script/sign.h>
43 #include <script/signingprovider.h>
44 #include <script/solver.h>
45 #include <serialize.h>
46 #include <span.h>
47 #include <streams.h>
48 #include <support/allocators/secure.h>
49 #include <support/allocators/zeroafterfree.h>
50 #include <support/cleanse.h>
51 #include <sync.h>
52 #include <tinyformat.h>
53 #include <uint256.h>
54 #include <univalue.h>
55 #include <util/chaintype.h>
56 #include <util/check.h>
57 #include <util/fs.h>
58 #include <util/fs_helpers.h>
59 #include <util/moneystr.h>
60 #include <util/result.h>
61 #include <util/string.h>
62 #include <util/time.h>
63 #include <util/translation.h>
64 #include <wallet/coincontrol.h>
65 #include <wallet/context.h>
66 #include <wallet/crypter.h>
67 #include <wallet/db.h>
68 #include <wallet/external_signer_scriptpubkeyman.h>
69 #include <wallet/scriptpubkeyman.h>
70 #include <wallet/transaction.h>
71 #include <wallet/types.h>
72 #include <wallet/walletdb.h>
73 #include <wallet/walletutil.h>
74
75 #include <algorithm>
76 #include <cassert>
77 #include <condition_variable>
78 #include <exception>
79 #include <optional>
80 #include <stdexcept>
81 #include <thread>
82 #include <tuple>
83 #include <variant>
84
85 struct KeyOriginInfo;
86
87 using common::AmountErrMsg;
88 using common::AmountHighWarn;
89 using common::PSBTError;
90 using interfaces::FoundBlock;
91 using util::ReplaceAll;
92 using util::ToString;
93
94 namespace wallet {
95
96 /*
97 * Signal when transactions are added to wallet
98 */
99 boost::signals2::signal<void (const CTransactionRef &ptxn, const uint256 &blockHash)> CWallet::TransactionAddedToWallet;
100
101 bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
102 {
103 const auto update_function = [&wallet_name](common::SettingsValue& setting_value) {
104 if (!setting_value.isArray()) setting_value.setArray();
105 for (const auto& value : setting_value.getValues()) {
106 if (value.isStr() && value.get_str() == wallet_name) return interfaces::SettingsAction::SKIP_WRITE;
107 }
108 setting_value.push_back(wallet_name);
109 return interfaces::SettingsAction::WRITE;
110 };
111 return chain.updateRwSetting("wallet", update_function);
112 }
113
114 bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
115 {
116 const auto update_function = [&wallet_name](common::SettingsValue& setting_value) {
117 if (!setting_value.isArray()) return interfaces::SettingsAction::SKIP_WRITE;
118 common::SettingsValue new_value(common::SettingsValue::VARR);
119 for (const auto& value : setting_value.getValues()) {
120 if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
121 }
122 if (new_value.size() == setting_value.size()) return interfaces::SettingsAction::SKIP_WRITE;
123 setting_value = std::move(new_value);
124 return interfaces::SettingsAction::WRITE;
125 };
126 return chain.updateRwSetting("wallet", update_function);
127 }
128
129 static void UpdateWalletSetting(interfaces::Chain& chain,
130 const std::string& wallet_name,
131 std::optional<bool> load_on_startup,
132 std::vector<bilingual_str>& warnings)
133 {
134 if (!load_on_startup) return;
135 if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
136 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
137 } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
138 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
139 }
140 }
141
142 /**
143 * Refresh mempool status so the wallet is in an internally consistent state and
144 * immediately knows the transaction's status: Whether it can be considered
145 * trusted and is eligible to be abandoned ...
146 */
147 static void RefreshMempoolStatus(CWalletTx& tx, interfaces::Chain& chain)
148 {
149 if (chain.isInMempool(tx.GetHash())) {
150 tx.m_state = TxStateInMempool();
151 } else if (tx.state<TxStateInMempool>()) {
152 tx.m_state = TxStateInactive();
153 }
154 }
155
156 bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
157 {
158 LOCK(context.wallets_mutex);
159 assert(wallet);
160 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
161 if (i != context.wallets.end()) return false;
162 context.wallets.push_back(wallet);
163 wallet->ConnectScriptPubKeyManNotifiers();
164 wallet->NotifyCanGetAddressesChanged();
165 return true;
166 }
167
168 bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
169 {
170 assert(wallet);
171
172 interfaces::Chain& chain = wallet->chain();
173 std::string name = wallet->GetName();
174 WITH_LOCK(wallet->cs_wallet, wallet->WriteBestBlock());
175
176 // Unregister with the validation interface which also drops shared pointers.
177 wallet->DisconnectChainNotifications();
178 {
179 LOCK(context.wallets_mutex);
180 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
181 if (i == context.wallets.end()) return false;
182 context.wallets.erase(i);
183 }
184 // Notify unload so that upper layers release the shared pointer.
185 wallet->NotifyUnload();
186
187 // Write the wallet setting
188 UpdateWalletSetting(chain, name, load_on_start, warnings);
189
190 return true;
191 }
192
193 bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
194 {
195 std::vector<bilingual_str> warnings;
196 return RemoveWallet(context, wallet, load_on_start, warnings);
197 }
198
199 std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context)
200 {
201 LOCK(context.wallets_mutex);
202 return context.wallets;
203 }
204
205 std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count)
206 {
207 LOCK(context.wallets_mutex);
208 count = context.wallets.size();
209 return count == 1 ? context.wallets[0] : nullptr;
210 }
211
212 std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name)
213 {
214 LOCK(context.wallets_mutex);
215 for (const std::shared_ptr<CWallet>& wallet : context.wallets) {
216 if (wallet->GetName() == name) return wallet;
217 }
218 return nullptr;
219 }
220
221 std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet)
222 {
223 LOCK(context.wallets_mutex);
224 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
225 return interfaces::MakeCleanupHandler([&context, it] { LOCK(context.wallets_mutex); context.wallet_load_fns.erase(it); });
226 }
227
228 void NotifyWalletLoaded(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
229 {
230 LOCK(context.wallets_mutex);
231 for (auto& load_wallet : context.wallet_load_fns) {
232 load_wallet(interfaces::MakeWallet(context, wallet));
233 }
234 }
235
236 static GlobalMutex g_loading_wallet_mutex;
237 static GlobalMutex g_wallet_release_mutex;
238 static std::condition_variable g_wallet_release_cv;
239 static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
240 static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
241
242 // Custom deleter for shared_ptr<CWallet>.
243 static void FlushAndDeleteWallet(CWallet* wallet)
244 {
245 const std::string name = wallet->GetName();
246 wallet->WalletLogPrintf("Releasing wallet %s..\n", name);
247 wallet->Flush();
248 delete wallet;
249 // Wallet is now released, notify WaitForDeleteWallet, if any.
250 {
251 LOCK(g_wallet_release_mutex);
252 if (g_unloading_wallet_set.erase(name) == 0) {
253 // WaitForDeleteWallet was not called for this wallet, all done.
254 return;
255 }
256 }
257 g_wallet_release_cv.notify_all();
258 }
259
260 void WaitForDeleteWallet(std::shared_ptr<CWallet>&& wallet)
261 {
262 // Mark wallet for unloading.
263 const std::string name = wallet->GetName();
264 {
265 LOCK(g_wallet_release_mutex);
266 g_unloading_wallet_set.insert(name);
267 // Do not expect to be the only one removing this wallet.
268 // Multiple threads could simultaneously be waiting for deletion.
269 }
270
271 // Time to ditch our shared_ptr and wait for FlushAndDeleteWallet call.
272 wallet.reset();
273 {
274 WAIT_LOCK(g_wallet_release_mutex, lock);
275 while (g_unloading_wallet_set.count(name) == 1) {
276 g_wallet_release_cv.wait(lock);
277 }
278 }
279 }
280
281 namespace {
282 std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
283 {
284 try {
285 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
286 if (!database) {
287 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
288 return nullptr;
289 }
290
291 context.chain->initMessage(_("Loading wallet…"));
292 std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), options.create_flags, error, warnings);
293 if (!wallet) {
294 error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
295 status = DatabaseStatus::FAILED_LOAD;
296 return nullptr;
297 }
298
299 NotifyWalletLoaded(context, wallet);
300 AddWallet(context, wallet);
301 wallet->postInitProcess();
302
303 // Write the wallet setting
304 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
305
306 return wallet;
307 } catch (const std::runtime_error& e) {
308 error = Untranslated(e.what());
309 status = DatabaseStatus::FAILED_LOAD;
310 return nullptr;
311 }
312 }
313
314 class FastWalletRescanFilter
315 {
316 public:
317 FastWalletRescanFilter(const CWallet& wallet) : m_wallet(wallet)
318 {
319 // fast rescanning via block filters is only supported by descriptor wallets right now
320 assert(!m_wallet.IsLegacy());
321
322 // create initial filter with scripts from all ScriptPubKeyMans
323 for (auto spkm : m_wallet.GetAllScriptPubKeyMans()) {
324 auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
325 assert(desc_spkm != nullptr);
326 AddScriptPubKeys(desc_spkm);
327 // save each range descriptor's end for possible future filter updates
328 if (desc_spkm->IsHDEnabled()) {
329 m_last_range_ends.emplace(desc_spkm->GetID(), desc_spkm->GetEndRange());
330 }
331 }
332 }
333
334 void UpdateIfNeeded()
335 {
336 // repopulate filter with new scripts if top-up has happened since last iteration
337 for (const auto& [desc_spkm_id, last_range_end] : m_last_range_ends) {
338 auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
339 assert(desc_spkm != nullptr);
340 int32_t current_range_end{desc_spkm->GetEndRange()};
341 if (current_range_end > last_range_end) {
342 AddScriptPubKeys(desc_spkm, last_range_end);
343 m_last_range_ends.at(desc_spkm->GetID()) = current_range_end;
344 }
345 }
346 }
347
348 std::optional<bool> MatchesBlock(const uint256& block_hash) const
349 {
350 return m_wallet.chain().blockFilterMatchesAny(BlockFilterType::BASIC, block_hash, m_filter_set);
351 }
352
353 private:
354 const CWallet& m_wallet;
355 /** Map for keeping track of each range descriptor's last seen end range.
356 * This information is used to detect whether new addresses were derived
357 * (that is, if the current end range is larger than the saved end range)
358 * after processing a block and hence a filter set update is needed to
359 * take possible keypool top-ups into account.
360 */
361 std::map<uint256, int32_t> m_last_range_ends;
362 GCSFilter::ElementSet m_filter_set;
363
364 void AddScriptPubKeys(const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
365 {
366 for (const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
367 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
368 }
369 }
370 };
371 } // namespace
372
373 std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
374 {
375 auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
376 if (!result.second) {
377 error = Untranslated("Wallet already loading.");
378 status = DatabaseStatus::FAILED_LOAD;
379 return nullptr;
380 }
381 auto wallet = LoadWalletInternal(context, name, load_on_start, options, status, error, warnings);
382 WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
383 return wallet;
384 }
385
386 std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
387 {
388 uint64_t wallet_creation_flags = options.create_flags;
389 const SecureString& passphrase = options.create_passphrase;
390
391 ArgsManager& args = *Assert(context.args);
392
393 if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE;
394 else if (args.GetBoolArg("-swapbdbendian", false)) {
395 options.require_format = DatabaseFormat::BERKELEY_SWAP;
396 }
397
398 // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
399 bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
400
401 // Born encrypted wallets need to be created blank first.
402 if (!passphrase.empty()) {
403 wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
404 }
405
406 // Private keys must be disabled for an external signer wallet
407 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
408 error = Untranslated("Private keys must be disabled when using an external signer");
409 status = DatabaseStatus::FAILED_CREATE;
410 return nullptr;
411 }
412
413 // Descriptor support must be enabled for an external signer wallet
414 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) {
415 error = Untranslated("Descriptor support must be enabled when using an external signer");
416 status = DatabaseStatus::FAILED_CREATE;
417 return nullptr;
418 }
419
420 // Do not allow a passphrase when private keys are disabled
421 if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
422 error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
423 status = DatabaseStatus::FAILED_CREATE;
424 return nullptr;
425 }
426
427 // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
428 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
429 if (!database) {
430 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
431 status = DatabaseStatus::FAILED_VERIFY;
432 return nullptr;
433 }
434
435 // Make the wallet
436 context.chain->initMessage(_("Loading wallet…"));
437 std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings);
438 if (!wallet) {
439 error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
440 status = DatabaseStatus::FAILED_CREATE;
441 return nullptr;
442 }
443
444 // Encrypt the wallet
445 if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
446 if (!wallet->EncryptWallet(passphrase)) {
447 error = Untranslated("Error: Wallet created but failed to encrypt.");
448 status = DatabaseStatus::FAILED_ENCRYPT;
449 return nullptr;
450 }
451 if (!create_blank) {
452 // Unlock the wallet
453 if (!wallet->Unlock(passphrase)) {
454 error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
455 status = DatabaseStatus::FAILED_ENCRYPT;
456 return nullptr;
457 }
458
459 // Set a seed for the wallet
460 {
461 LOCK(wallet->cs_wallet);
462 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
463 wallet->SetupDescriptorScriptPubKeyMans();
464 } else {
465 for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
466 if (!spk_man->SetupGeneration()) {
467 error = Untranslated("Unable to generate initial keys");
468 status = DatabaseStatus::FAILED_CREATE;
469 return nullptr;
470 }
471 }
472 }
473 }
474
475 // Relock the wallet
476 wallet->Lock();
477 }
478 }
479
480 NotifyWalletLoaded(context, wallet);
481 AddWallet(context, wallet);
482 wallet->postInitProcess();
483
484 // Write the wallet settings
485 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
486
487 status = DatabaseStatus::SUCCESS;
488 return wallet;
489 }
490
491 // Re-creates wallet from the backup file by renaming and moving it into the wallet's directory.
492 // If 'load_after_restore=true', the wallet object will be fully initialized and appended to the context.
493 std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings, bool load_after_restore)
494 {
495 DatabaseOptions options;
496 ReadDatabaseArgs(*context.args, options);
497 options.require_existing = true;
498
499 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));
500 auto wallet_file = wallet_path / "wallet.dat";
501 std::shared_ptr<CWallet> wallet;
502 bool wallet_file_copied = false;
503 bool created_parent_dir = false;
504
505 try {
506 if (!fs::exists(backup_file)) {
507 error = Untranslated("Backup file does not exist");
508 status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE;
509 return nullptr;
510 }
511
512 // Wallet directories are allowed to exist, but must not contain a .dat file.
513 // Any existing wallet database is treated as a hard failure to prevent overwriting.
514 if (fs::exists(wallet_path)) {
515 // If this is a file, it is the db and we don't want to overwrite it.
516 if (!fs::is_directory(wallet_path)) {
517 error = Untranslated(strprintf("Failed to restore wallet. Database file exists '%s'.", fs::PathToString(wallet_path)));
518 status = DatabaseStatus::FAILED_ALREADY_EXISTS;
519 return nullptr;
520 }
521
522 // Check we are not going to overwrite an existing db file
523 if (fs::exists(wallet_file)) {
524 error = Untranslated(strprintf("Failed to restore wallet. Database file exists in '%s'.", fs::PathToString(wallet_file)));
525 status = DatabaseStatus::FAILED_ALREADY_EXISTS;
526 return nullptr;
527 }
528 } else {
529 // The directory doesn't exist, create it
530 if (!TryCreateDirectories(wallet_path)) {
531 error = Untranslated(strprintf("Failed to restore database path '%s'.", fs::PathToString(wallet_path)));
532 status = DatabaseStatus::FAILED_ALREADY_EXISTS;
533 return nullptr;
534 }
535 created_parent_dir = true;
536 }
537
538 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
539 wallet_file_copied = true;
540
541 if (load_after_restore) {
542 wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
543 }
544 } catch (const std::exception& e) {
545 assert(!wallet);
546 if (!error.empty()) error += Untranslated("\n");
547 error += Untranslated(strprintf("Unexpected exception: %s", e.what()));
548 }
549
550 // Remove created wallet path only when loading fails
551 if (load_after_restore && !wallet) {
552 if (wallet_file_copied) fs::remove(wallet_file);
553 // Clean up the parent directory if we created it during restoration.
554 // As we have created it, it must be empty after deleting the wallet file.
555 if (created_parent_dir) {
556 if (Assume(fs::is_empty(wallet_path))) {
557 fs::remove(wallet_path);
558 } else {
559 LogInfo("Failed wallet restore: Directory %s is not empty; leaving it alone\n", fs::PathToString(wallet_path));
560 }
561 }
562 }
563
564 return wallet;
565 }
566
567 /** @defgroup mapWallet
568 *
569 * @{
570 */
571
572 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
573 {
574 AssertLockHeld(cs_wallet);
575 const auto it = mapWallet.find(hash);
576 if (it == mapWallet.end())
577 return nullptr;
578 return &(it->second);
579 }
580
581 void CWallet::UpgradeKeyMetadata()
582 {
583 if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
584 return;
585 }
586
587 auto spk_man = GetLegacyScriptPubKeyMan();
588 if (!spk_man) {
589 return;
590 }
591
592 spk_man->UpgradeKeyMetadata();
593 SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
594 }
595
596 void CWallet::UpgradeDescriptorCache()
597 {
598 if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) || IsLocked() || IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
599 return;
600 }
601
602 for (ScriptPubKeyMan* spkm : GetAllScriptPubKeyMans()) {
603 DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
604 desc_spkm->UpgradeDescriptorCache();
605 }
606 SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED);
607 }
608
609 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
610 {
611 CCrypter crypter;
612 CKeyingMaterial _vMasterKey;
613
614 {
615 LOCK(cs_wallet);
616 for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
617 {
618 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
619 return false;
620 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
621 continue; // try another master key
622 if (Unlock(_vMasterKey)) {
623 // Migrate from legacy KDF to PBKDF2-HMAC-SHA512 with AEAD
624 if (pMasterKey.second.nDerivationMethod == 0) {
625 WalletLogPrintf("Migrating master key %u from legacy KDF to PBKDF2-HMAC-SHA512\n", pMasterKey.first);
626 CCrypter mig_crypter;
627 CMasterKey& mk = const_cast<CMasterKey&>(pMasterKey.second);
628 mk.nDerivationMethod = 2;
629 mk.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE_V2);
630 GetStrongRandBytes(mk.vchSalt);
631
632 // Calibrate PBKDF2 iterations to ~100ms
633 constexpr MillisecondsDouble target{100};
634 auto mig_start{SteadyClock::now()};
635 mig_crypter.SetKeyFromPassphrase(strWalletPassphrase, mk.vchSalt, 600000, mk.nDerivationMethod);
636 mk.nDeriveIterations = static_cast<unsigned int>(600000 * target / (SteadyClock::now() - mig_start));
637 mig_start = SteadyClock::now();
638 mig_crypter.SetKeyFromPassphrase(strWalletPassphrase, mk.vchSalt, mk.nDeriveIterations, mk.nDerivationMethod);
639 mk.nDeriveIterations = std::max(mk.nDeriveIterations, 600000u);
640
641 if (mig_crypter.SetKeyFromPassphrase(strWalletPassphrase, mk.vchSalt, mk.nDeriveIterations, mk.nDerivationMethod)
642 && mig_crypter.Encrypt(_vMasterKey, mk.vchCryptedKey)) {
643 WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, mk);
644 WalletLogPrintf("Master key %u migrated to PBKDF2-HMAC-SHA512\n", pMasterKey.first);
645 }
646 SetMinVersion(FEATURE_LATEST);
647 }
648 // Now that we've unlocked, upgrade the key metadata
649 UpgradeKeyMetadata();
650 // Now that we've unlocked, upgrade the descriptor cache
651 UpgradeDescriptorCache();
652 return true;
653 }
654 }
655 }
656 return false;
657 }
658
659 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
660 {
661 bool fWasLocked = IsLocked();
662
663 {
664 LOCK2(m_relock_mutex, cs_wallet);
665 Lock();
666
667 CCrypter crypter;
668 CKeyingMaterial _vMasterKey;
669 for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
670 {
671 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
672 return false;
673 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
674 return false;
675 if (Unlock(_vMasterKey))
676 {
677 constexpr MillisecondsDouble target{100};
678 auto start{SteadyClock::now()};
679 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
680 pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
681
682 start = SteadyClock::now();
683 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
684 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
685
686 if (pMasterKey.second.nDeriveIterations < 25000)
687 pMasterKey.second.nDeriveIterations = 25000;
688
689 WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
690
691 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
692 return false;
693 if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
694 return false;
695 WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second);
696 if (fWasLocked)
697 Lock();
698 return true;
699 }
700 }
701 }
702
703 return false;
704 }
705
706 void CWallet::SetLastBlockProcessedInMem(int block_height, uint256 block_hash)
707 {
708 AssertLockHeld(cs_wallet);
709
710 m_last_block_processed = block_hash;
711 m_last_block_processed_height = block_height;
712 }
713
714 void CWallet::SetLastBlockProcessed(int block_height, uint256 block_hash)
715 {
716 AssertLockHeld(cs_wallet);
717
718 SetLastBlockProcessedInMem(block_height, block_hash);
719 WriteBestBlock();
720 GetDatabase().IncrementUpdateCounter();
721 }
722
723 void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
724 {
725 LOCK(cs_wallet);
726 if (nWalletVersion >= nVersion)
727 return;
728 WalletLogPrintf("Setting minversion to %d\n", nVersion);
729 nWalletVersion = nVersion;
730
731 {
732 WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase());
733 if (nWalletVersion > 40000)
734 batch->WriteMinVersion(nWalletVersion);
735 if (!batch_in)
736 delete batch;
737 }
738 }
739
740 std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
741 {
742 std::set<uint256> result;
743 AssertLockHeld(cs_wallet);
744
745 const auto it = mapWallet.find(txid);
746 if (it == mapWallet.end())
747 return result;
748 const CWalletTx& wtx = it->second;
749
750 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
751
752 for (const CTxIn& txin : wtx.tx->vin)
753 {
754 if (mapTxSpends.count(txin.prevout) <= 1)
755 continue; // No conflict if zero or one spends
756 range = mapTxSpends.equal_range(txin.prevout);
757 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
758 result.insert(_it->second);
759 }
760 return result;
761 }
762
763 bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
764 {
765 AssertLockHeld(cs_wallet);
766 const Txid& txid = tx->GetHash();
767 for (unsigned int i = 0; i < tx->vout.size(); ++i) {
768 if (IsSpent(COutPoint(txid, i))) {
769 return true;
770 }
771 }
772 return false;
773 }
774
775 void CWallet::Flush()
776 {
777 GetDatabase().Flush();
778 }
779
780 void CWallet::Close()
781 {
782 GetDatabase().Close();
783 }
784
785 void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
786 {
787 // We want all the wallet transactions in range to have the same metadata as
788 // the oldest (smallest nOrderPos).
789 // So: find smallest nOrderPos:
790
791 int nMinOrderPos = std::numeric_limits<int>::max();
792 const CWalletTx* copyFrom = nullptr;
793 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
794 const CWalletTx* wtx = &mapWallet.at(it->second);
795 if (wtx->nOrderPos < nMinOrderPos) {
796 nMinOrderPos = wtx->nOrderPos;
797 copyFrom = wtx;
798 }
799 }
800
801 if (!copyFrom) {
802 return;
803 }
804
805 // Now copy data from copyFrom to rest:
806 for (TxSpends::iterator it = range.first; it != range.second; ++it)
807 {
808 const uint256& hash = it->second;
809 CWalletTx* copyTo = &mapWallet.at(hash);
810 if (copyFrom == copyTo) continue;
811 assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
812 if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
813 copyTo->mapValue = copyFrom->mapValue;
814 copyTo->vOrderForm = copyFrom->vOrderForm;
815 // fTimeReceivedIsTxTime not copied on purpose
816 // nTimeReceived not copied on purpose
817 copyTo->nTimeSmart = copyFrom->nTimeSmart;
818 copyTo->fFromMe = copyFrom->fFromMe;
819 // nOrderPos not copied on purpose
820 // cached members not copied on purpose
821 }
822 }
823
824 /**
825 * Outpoint is spent if any non-conflicted transaction
826 * spends it:
827 */
828 bool CWallet::IsSpent(const COutPoint& outpoint) const
829 {
830 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
831 range = mapTxSpends.equal_range(outpoint);
832
833 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
834 const uint256& wtxid = it->second;
835 const auto mit = mapWallet.find(wtxid);
836 if (mit != mapWallet.end()) {
837 const auto& wtx = mit->second;
838 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
839 return true; // Spent
840 }
841 }
842 return false;
843 }
844
845 void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch)
846 {
847 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
848
849 if (batch) {
850 UnlockCoin(outpoint, batch);
851 } else {
852 WalletBatch temp_batch(GetDatabase());
853 UnlockCoin(outpoint, &temp_batch);
854 }
855
856 std::pair<TxSpends::iterator, TxSpends::iterator> range;
857 range = mapTxSpends.equal_range(outpoint);
858 SyncMetaData(range);
859 }
860
861
862 void CWallet::AddToSpends(const CWalletTx& wtx, WalletBatch* batch)
863 {
864 if (wtx.IsCoinBase()) // Coinbases don't spend anything!
865 return;
866
867 for (const CTxIn& txin : wtx.tx->vin)
868 AddToSpends(txin.prevout, wtx.GetHash(), batch);
869 }
870
871 void CWallet::InitialiseAddressBookUsed()
872 {
873 for (const auto& entry : mapWallet) {
874 const CWalletTx& wtx = entry.second;
875 UpdateAddressBookUsed(wtx);
876 }
877 }
878
879 void CWallet::UpdateAddressBookUsed(const CWalletTx& wtx)
880 {
881 for (const auto& output : wtx.tx->vout) {
882 CTxDestination dest;
883 if (!ExtractDestination(output.scriptPubKey, dest)) continue;
884 m_address_book[dest].m_used = true;
885 }
886 }
887
888 bool CWallet::FindScriptPubKeyUsed(const std::set<CScript>& keys, const std::variant<std::monostate, std::function<void(const CWalletTx&)>, std::function<void(const CWalletTx&, uint32_t)>>& callback) const
889 {
890 AssertLockHeld(cs_wallet);
891 bool found_any = false;
892 for (const auto& key : keys) {
893 CTxDestination dest;
894 if (!ExtractDestination(key, dest)) continue;
895 const auto& address_book_it = m_address_book.find(dest);
896 if (address_book_it == m_address_book.end()) continue;
897 if (address_book_it->second.m_used) {
898 found_any = true;
899 break;
900 }
901 }
902 if (!found_any) return false;
903 if (std::holds_alternative<std::monostate>(callback)) return true;
904
905 found_any = false;
906 for (const auto& entry : mapWallet) {
907 const CWalletTx& wtx = entry.second;
908 for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
909 const auto& output = wtx.tx->vout[i];
910 if (keys.count(output.scriptPubKey)) {
911 found_any = true;
912 const auto callback_type = callback.index();
913 if (callback_type == 1) {
914 std::get<std::function<void(const CWalletTx&)>>(callback)(wtx);
915 break;
916 }
917 std::get<std::function<void(const CWalletTx&, uint32_t)>>(callback)(wtx, i);
918 }
919 }
920 }
921
922 return found_any;
923 }
924
925 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
926 {
927 if (IsCrypted())
928 return false;
929
930 CKeyingMaterial _vMasterKey;
931
932 _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
933 GetStrongRandBytes(_vMasterKey);
934
935 CMasterKey kMasterKey;
936
937 const unsigned int salt_size = (kMasterKey.nDerivationMethod >= 2) ? WALLET_CRYPTO_SALT_SIZE_V2 : WALLET_CRYPTO_SALT_SIZE;
938 kMasterKey.vchSalt.resize(salt_size);
939 GetStrongRandBytes(kMasterKey.vchSalt);
940
941 CCrypter crypter;
942 constexpr MillisecondsDouble target{100};
943 auto start{SteadyClock::now()};
944 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
945 kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
946
947 start = SteadyClock::now();
948 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
949 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
950
951 if (kMasterKey.nDeriveIterations < 25000)
952 kMasterKey.nDeriveIterations = 25000;
953
954 WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
955
956 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
957 return false;
958 if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
959 return false;
960
961 {
962 LOCK2(m_relock_mutex, cs_wallet);
963 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
964 WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
965 if (!encrypted_batch->TxnBegin()) {
966 delete encrypted_batch;
967 encrypted_batch = nullptr;
968 return false;
969 }
970 encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
971
972 for (const auto& spk_man_pair : m_spk_managers) {
973 auto spk_man = spk_man_pair.second.get();
974 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
975 encrypted_batch->TxnAbort();
976 delete encrypted_batch;
977 encrypted_batch = nullptr;
978 // We now probably have half of our keys encrypted in memory, and half not...
979 // die and let the user reload the unencrypted wallet.
980 assert(false);
981 }
982 }
983
984 // Re-encrypt the stealth CT keypair with the new master key.
985 if (m_stealth_keys_loaded) {
986 std::vector<uint8_t> view_enc, spend_enc;
987 CKey view_key, spend_key;
988 if (!view_key.Load(m_stealth_view_priv, m_stealth_view_pub, true) ||
989 !spend_key.Load(m_stealth_spend_priv, m_stealth_spend_pub, true) ||
990 !EncryptSecret(_vMasterKey, view_key.GetPrivKey(), m_stealth_view_pub.GetHash(), view_enc) ||
991 !EncryptSecret(_vMasterKey, spend_key.GetPrivKey(), m_stealth_spend_pub.GetHash(), spend_enc) ||
992 !encrypted_batch->WriteStealthKeys(m_stealth_view_pub, m_stealth_spend_pub,
993 CPrivKey(view_enc.begin(), view_enc.end()),
994 CPrivKey(spend_enc.begin(), spend_enc.end()))) {
995 encrypted_batch->TxnAbort();
996 delete encrypted_batch;
997 encrypted_batch = nullptr;
998 assert(false);
999 }
1000 m_stealth_view_priv.assign(view_enc.begin(), view_enc.end());
1001 m_stealth_spend_priv.assign(spend_enc.begin(), spend_enc.end());
1002 }
1003
1004 // Encryption was introduced in version 0.4.0
1005 SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
1006
1007 if (!encrypted_batch->TxnCommit()) {
1008 delete encrypted_batch;
1009 encrypted_batch = nullptr;
1010 // We now have keys encrypted in memory, but not on disk...
1011 // die to avoid confusion and let the user reload the unencrypted wallet.
1012 assert(false);
1013 }
1014
1015 delete encrypted_batch;
1016 encrypted_batch = nullptr;
1017
1018 Lock();
1019 Unlock(strWalletPassphrase);
1020
1021 // If we are using descriptors, make new descriptors with a new seed
1022 if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
1023 SetupDescriptorScriptPubKeyMans();
1024 } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
1025 // if we are using HD, replace the HD seed with a new one
1026 if (spk_man->IsHDEnabled()) {
1027 if (!spk_man->SetupGeneration(true)) {
1028 return false;
1029 }
1030 }
1031 }
1032 Lock();
1033
1034 // Need to completely rewrite the wallet file; if we don't, bdb might keep
1035 // bits of the unencrypted private key in slack space in the database file.
1036 GetDatabase().Rewrite();
1037
1038 // BDB seems to have a bad habit of writing old data into
1039 // slack space in .dat files; that is bad if the old data is
1040 // unencrypted private keys. So:
1041 GetDatabase().ReloadDbEnv();
1042
1043 }
1044 NotifyStatusChanged(this);
1045
1046 return true;
1047 }
1048
1049 DBErrors CWallet::ReorderTransactions()
1050 {
1051 LOCK(cs_wallet);
1052 WalletBatch batch(GetDatabase());
1053
1054 // Old wallets didn't have any defined order for transactions
1055 // Probably a bad idea to change the output of this
1056
1057 // First: get all CWalletTx into a sorted-by-time multimap.
1058 typedef std::multimap<int64_t, CWalletTx*> TxItems;
1059 TxItems txByTime;
1060
1061 for (auto& entry : mapWallet)
1062 {
1063 CWalletTx* wtx = &entry.second;
1064 txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
1065 }
1066
1067 nOrderPosNext = 0;
1068 std::vector<int64_t> nOrderPosOffsets;
1069 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
1070 {
1071 CWalletTx *const pwtx = (*it).second;
1072 int64_t& nOrderPos = pwtx->nOrderPos;
1073
1074 if (nOrderPos == -1)
1075 {
1076 nOrderPos = nOrderPosNext++;
1077 nOrderPosOffsets.push_back(nOrderPos);
1078
1079 if (!batch.WriteTx(*pwtx))
1080 return DBErrors::LOAD_FAIL;
1081 }
1082 else
1083 {
1084 int64_t nOrderPosOff = 0;
1085 for (const int64_t& nOffsetStart : nOrderPosOffsets)
1086 {
1087 if (nOrderPos >= nOffsetStart)
1088 ++nOrderPosOff;
1089 }
1090 nOrderPos += nOrderPosOff;
1091 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
1092
1093 if (!nOrderPosOff)
1094 continue;
1095
1096 // Since we're changing the order, write it back
1097 if (!batch.WriteTx(*pwtx))
1098 return DBErrors::LOAD_FAIL;
1099 }
1100 }
1101 batch.WriteOrderPosNext(nOrderPosNext);
1102
1103 return DBErrors::LOAD_OK;
1104 }
1105
1106 int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
1107 {
1108 AssertLockHeld(cs_wallet);
1109 int64_t nRet = nOrderPosNext++;
1110 if (batch) {
1111 batch->WriteOrderPosNext(nOrderPosNext);
1112 } else {
1113 WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
1114 }
1115 return nRet;
1116 }
1117
1118 void CWallet::MarkDirty()
1119 {
1120 {
1121 LOCK(cs_wallet);
1122 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
1123 item.second.MarkDirty();
1124 }
1125 }
1126
1127 bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
1128 {
1129 LOCK(cs_wallet);
1130
1131 auto mi = mapWallet.find(originalHash);
1132
1133 // There is a bug if MarkReplaced is not called on an existing wallet transaction.
1134 assert(mi != mapWallet.end());
1135
1136 CWalletTx& wtx = (*mi).second;
1137
1138 // Ensure for now that we're not overwriting data
1139 assert(wtx.mapValue.count("replaced_by_txid") == 0);
1140
1141 wtx.mapValue["replaced_by_txid"] = newHash.ToString();
1142
1143 // Refresh mempool status without waiting for transactionRemovedFromMempool or transactionAddedToMempool
1144 RefreshMempoolStatus(wtx, chain());
1145
1146 WalletBatch batch(GetDatabase());
1147
1148 bool success = true;
1149 if (!batch.WriteTx(wtx)) {
1150 WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
1151 success = false;
1152 }
1153
1154 NotifyTransactionChanged(originalHash, CT_UPDATED);
1155
1156 return success;
1157 }
1158
1159 void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
1160 {
1161 AssertLockHeld(cs_wallet);
1162 const CWalletTx* srctx = GetWalletTx(hash);
1163 if (!srctx) return;
1164
1165 CTxDestination dst;
1166 if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
1167 if (IsMine(dst)) {
1168 if (used != IsAddressPreviouslySpent(dst)) {
1169 if (used) {
1170 tx_destinations.insert(dst);
1171 }
1172 SetAddressPreviouslySpent(batch, dst, used);
1173 }
1174 }
1175 }
1176 }
1177
1178 bool CWallet::IsSpentKey(const CScript& scriptPubKey) const
1179 {
1180 AssertLockHeld(cs_wallet);
1181 CTxDestination dest;
1182 if (!ExtractDestination(scriptPubKey, dest)) {
1183 return false;
1184 }
1185 if (IsAddressPreviouslySpent(dest)) {
1186 return true;
1187 }
1188
1189 if (LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan()) {
1190 for (const auto& keyid : GetAffectedKeys(scriptPubKey, *spk_man)) {
1191 WitnessV0KeyHash wpkh_dest(keyid);
1192 if (IsAddressPreviouslySpent(wpkh_dest)) {
1193 return true;
1194 }
1195 ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
1196 if (IsAddressPreviouslySpent(sh_wpkh_dest)) {
1197 return true;
1198 }
1199 PKHash pkh_dest(keyid);
1200 if (IsAddressPreviouslySpent(pkh_dest)) {
1201 return true;
1202 }
1203 }
1204 }
1205 return false;
1206 }
1207
1208 CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose, bool rescanning_old_block)
1209 {
1210 LOCK(cs_wallet);
1211
1212 WalletBatch batch(GetDatabase(), fFlushOnClose);
1213
1214 uint256 hash = tx->GetHash();
1215
1216 if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
1217 // Mark used destinations
1218 std::set<CTxDestination> tx_destinations;
1219
1220 for (const CTxIn& txin : tx->vin) {
1221 const COutPoint& op = txin.prevout;
1222 SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
1223 }
1224
1225 MarkDestinationsDirty(tx_destinations);
1226 }
1227
1228 // Inserts only if not already there, returns tx inserted or tx found
1229 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1230 CWalletTx& wtx = (*ret.first).second;
1231 bool fInsertedNew = ret.second;
1232 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1233 if (fInsertedNew) {
1234 wtx.nTimeReceived = GetTime();
1235 wtx.nOrderPos = IncOrderPosNext(&batch);
1236 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1237 wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
1238 AddToSpends(wtx, &batch);
1239
1240 // Update birth time when tx time is older than it.
1241 MaybeUpdateBirthTime(wtx.GetTxTime());
1242 UpdateAddressBookUsed(wtx);
1243 }
1244
1245 if (!fInsertedNew)
1246 {
1247 if (state.index() != wtx.m_state.index()) {
1248 wtx.m_state = state;
1249 fUpdated = true;
1250 } else {
1251 assert(TxStateSerializedIndex(wtx.m_state) == TxStateSerializedIndex(state));
1252 assert(TxStateSerializedBlockHash(wtx.m_state) == TxStateSerializedBlockHash(state));
1253 }
1254 // If we have a witness-stripped version of this transaction, and we
1255 // see a new version with a witness, then we must be upgrading a pre-segwit
1256 // wallet. Store the new version of the transaction with the witness,
1257 // as the stripped-version must be invalid.
1258 // TODO: Store all versions of the transaction, instead of just one.
1259 if (tx->HasWitness() && !wtx.tx->HasWitness()) {
1260 wtx.SetTx(tx);
1261 fUpdated = true;
1262 }
1263 }
1264
1265 // Mark inactive coinbase transactions and their descendants as abandoned
1266 if (wtx.IsCoinBase() && wtx.isInactive()) {
1267 std::vector<CWalletTx*> txs{&wtx};
1268
1269 TxStateInactive inactive_state = TxStateInactive{/*abandoned=*/true};
1270
1271 while (!txs.empty()) {
1272 CWalletTx* desc_tx = txs.back();
1273 txs.pop_back();
1274 desc_tx->m_state = inactive_state;
1275 // Break caches since we have changed the state
1276 desc_tx->MarkDirty();
1277 batch.WriteTx(*desc_tx);
1278 MarkInputsDirty(desc_tx->tx);
1279 for (unsigned int i = 0; i < desc_tx->tx->vout.size(); ++i) {
1280 COutPoint outpoint(desc_tx->GetHash(), i);
1281 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1282 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1283 const auto wit = mapWallet.find(it->second);
1284 if (wit != mapWallet.end()) {
1285 txs.push_back(&wit->second);
1286 }
1287 }
1288 }
1289 }
1290 }
1291
1292 //// debug print
1293 WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
1294
1295 // Write to disk
1296 if (fInsertedNew || fUpdated)
1297 if (!batch.WriteTx(wtx))
1298 return nullptr;
1299
1300 // Break debit/credit balance caches:
1301 wtx.MarkDirty();
1302
1303 // Notify UI of new or updated transaction
1304 NotifyTransactionChanged(hash, fInsertedNew ? CT_NEW : CT_UPDATED);
1305
1306 // Notify listeners on new wallet transaction
1307 CWallet::TransactionAddedToWallet(wtx.tx, TxStateSerializedBlockHash(wtx.m_state));
1308
1309 #if HAVE_SYSTEM
1310 // notify an external script when a wallet transaction comes in or is updated
1311 if (!m_notify_tx_changed_scripts.empty()) {
1312 #ifdef WIN32
1313 // Substituting the wallet name isn't currently supported on windows
1314 // because windows shell escaping has not been implemented yet:
1315 // https://github.com/limenka/limenka/pull/13339#issuecomment-537384875
1316 const std::string walletname_escaped = "wallet_name_substitution_is_not_available_on_Windows";
1317 #else
1318 const std::string walletname_escaped = GetName();
1319 #endif
1320 const std::string txid_hex = hash.GetHex();
1321 std::string blockhash_hex, blockheight_str;
1322 if (auto* conf = wtx.state<TxStateConfirmed>()) {
1323 blockhash_hex = conf->confirmed_block_hash.GetHex();
1324 blockheight_str = ToString(conf->confirmed_block_height);
1325 } else {
1326 blockhash_hex = "unconfirmed";
1327 blockheight_str = "-1";
1328 }
1329
1330 for (std::string command : m_notify_tx_changed_scripts) {
1331 ReplaceAll(command, "%s", txid_hex);
1332 ReplaceAll(command, "%b", blockhash_hex);
1333 ReplaceAll(command, "%h", blockheight_str);
1334 ReplaceAll(command, "%w", walletname_escaped);
1335
1336 std::thread t(runCommand, command);
1337 t.detach(); // thread runs free
1338 }
1339 }
1340 #endif
1341
1342 return &wtx;
1343 }
1344
1345 bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx)
1346 {
1347 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(nullptr, TxStateInactive{}));
1348 CWalletTx& wtx = ins.first->second;
1349 if (!fill_wtx(wtx, ins.second)) {
1350 return false;
1351 }
1352 // If wallet doesn't have a chain (e.g when using limenka-wallet tool),
1353 // don't bother to update txn.
1354 if (HaveChain()) {
1355 wtx.updateState(chain());
1356 }
1357 if (/* insertion took place */ ins.second) {
1358 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1359 }
1360 AddToSpends(wtx);
1361 for (const CTxIn& txin : wtx.tx->vin) {
1362 auto it = mapWallet.find(txin.prevout.hash);
1363 if (it != mapWallet.end()) {
1364 CWalletTx& prevtx = it->second;
1365 if (auto* prev = prevtx.state<TxStateBlockConflicted>()) {
1366 MarkConflicted(prev->conflicting_block_hash, prev->conflicting_block_height, wtx.GetHash());
1367 }
1368 }
1369 }
1370
1371 // Update birth time when tx time is older than it.
1372 MaybeUpdateBirthTime(wtx.GetTxTime());
1373
1374 return true;
1375 }
1376
1377 bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const SyncTxState& state, bool fUpdate, bool rescanning_old_block)
1378 {
1379 const CTransaction& tx = *ptx;
1380 {
1381 AssertLockHeld(cs_wallet);
1382
1383 if (auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1384 for (const CTxIn& txin : tx.vin) {
1385 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1386 while (range.first != range.second) {
1387 if (range.first->second != tx.GetHash()) {
1388 WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), conf->confirmed_block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1389 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1390 }
1391 range.first++;
1392 }
1393 }
1394 }
1395
1396 bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1397 if (fExisted && !fUpdate) return false;
1398 const bool fStealthInvolvingMe = RecoverStealthReceipts(ptx);
1399 if (fExisted || IsMine(tx) || IsFromMe(tx) || fStealthInvolvingMe)
1400 {
1401 /* Check if any keys in the wallet keypool that were supposed to be unused
1402 * have appeared in a new transaction. If so, remove those keys from the keypool.
1403 * This can happen when restoring an old wallet backup that does not contain
1404 * the mostly recently created transactions from newer versions of the wallet.
1405 */
1406
1407 // loop though all outputs
1408 for (const CTxOut& txout: tx.vout) {
1409 for (const auto& spk_man : GetScriptPubKeyMans(txout.scriptPubKey)) {
1410 for (auto &dest : spk_man->MarkUnusedAddresses(txout.scriptPubKey)) {
1411 // If internal flag is not defined try to infer it from the ScriptPubKeyMan
1412 if (!dest.internal.has_value()) {
1413 dest.internal = IsInternalScriptPubKeyMan(spk_man);
1414 }
1415
1416 // skip if can't determine whether it's a receiving address or not
1417 if (!dest.internal.has_value()) continue;
1418
1419 // If this is a receiving address and it's not in the address book yet
1420 // (e.g. it wasn't generated on this node or we're restoring from backup)
1421 // add it to the address book for proper transaction accounting
1422 if (!*dest.internal && !FindAddressBookEntry(dest.dest, /* allow_change= */ false)) {
1423 SetAddressBook(dest.dest, "", AddressPurpose::RECEIVE);
1424 }
1425 }
1426 }
1427 }
1428
1429 // Block disconnection override an abandoned tx as unconfirmed
1430 // which means user may have to call abandontransaction again
1431 TxState tx_state = std::visit([](auto&& s) -> TxState { return s; }, state);
1432 CWalletTx* wtx = AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
1433 if (!wtx) {
1434 // Can only be nullptr if there was a db write error (missing db, read-only db or a db engine internal writing error).
1435 // As we only store arriving transaction in this process, and we don't want an inconsistent state, let's throw an error.
1436 throw std::runtime_error("DB error adding transaction to wallet, write failed");
1437 }
1438 return true;
1439 }
1440 }
1441 return false;
1442 }
1443
1444 bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
1445 {
1446 LOCK(cs_wallet);
1447 const CWalletTx* wtx = GetWalletTx(hashTx);
1448 return wtx && !wtx->isAbandoned() && GetTxDepthInMainChain(*wtx) == 0 && !wtx->InMempool();
1449 }
1450
1451 void CWallet::MarkInputsDirty(const CTransactionRef& tx)
1452 {
1453 for (const CTxIn& txin : tx->vin) {
1454 auto it = mapWallet.find(txin.prevout.hash);
1455 if (it != mapWallet.end()) {
1456 it->second.MarkDirty();
1457 }
1458 }
1459 }
1460
1461 bool CWallet::AbandonTransaction(const uint256& hashTx)
1462 {
1463 LOCK(cs_wallet);
1464 auto it = mapWallet.find(hashTx);
1465 assert(it != mapWallet.end());
1466 return AbandonTransaction(it->second);
1467 }
1468
1469 bool CWallet::AbandonTransaction(CWalletTx& tx)
1470 {
1471 // Can't mark abandoned if confirmed or in mempool
1472 if (GetTxDepthInMainChain(tx) != 0 || tx.InMempool()) {
1473 return false;
1474 }
1475
1476 auto try_updating_state = [](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1477 // If the orig tx was not in block/mempool, none of its spends can be.
1478 assert(!wtx.isConfirmed());
1479 assert(!wtx.InMempool());
1480 // If already conflicted or abandoned, no need to set abandoned
1481 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1482 wtx.m_state = TxStateInactive{/*abandoned=*/true};
1483 return TxUpdate::NOTIFY_CHANGED;
1484 }
1485 return TxUpdate::UNCHANGED;
1486 };
1487
1488 // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too.
1489 // States are not permanent, so these transactions can become unabandoned if they are re-added to the
1490 // mempool, or confirmed in a block, or conflicted.
1491 // Note: If the reorged coinbase is re-added to the main chain, the descendants that have not had their
1492 // states change will remain abandoned and will require manual broadcast if the user wants them.
1493
1494 RecursiveUpdateTxState(tx.GetHash(), try_updating_state);
1495
1496 return true;
1497 }
1498
1499 void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1500 {
1501 LOCK(cs_wallet);
1502
1503 // If number of conflict confirms cannot be determined, this means
1504 // that the block is still unknown or not yet part of the main chain,
1505 // for example when loading the wallet during a reindex. Do nothing in that
1506 // case.
1507 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1508 return;
1509 }
1510 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1511 if (conflictconfirms >= 0)
1512 return;
1513
1514 auto try_updating_state = [&](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1515 if (conflictconfirms < GetTxDepthInMainChain(wtx)) {
1516 // Block is 'more conflicted' than current confirm; update.
1517 // Mark transaction as conflicted with this block.
1518 wtx.m_state = TxStateBlockConflicted{hashBlock, conflicting_height};
1519 return TxUpdate::CHANGED;
1520 }
1521 return TxUpdate::UNCHANGED;
1522 };
1523
1524 // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too.
1525 RecursiveUpdateTxState(hashTx, try_updating_state);
1526
1527 }
1528
1529 void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) {
1530 // Do not flush the wallet here for performance reasons
1531 WalletBatch batch(GetDatabase(), false);
1532 RecursiveUpdateTxState(&batch, tx_hash, try_updating_state);
1533 }
1534
1535 void CWallet::RecursiveUpdateTxState(WalletBatch* batch, const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) {
1536 std::set<uint256> todo;
1537 std::set<uint256> done;
1538
1539 todo.insert(tx_hash);
1540
1541 while (!todo.empty()) {
1542 uint256 now = *todo.begin();
1543 todo.erase(now);
1544 done.insert(now);
1545 auto it = mapWallet.find(now);
1546 assert(it != mapWallet.end());
1547 CWalletTx& wtx = it->second;
1548
1549 TxUpdate update_state = try_updating_state(wtx);
1550 if (update_state != TxUpdate::UNCHANGED) {
1551 wtx.MarkDirty();
1552 if (batch) batch->WriteTx(wtx);
1553 // Iterate over all its outputs, and update those tx states as well (if applicable)
1554 for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1555 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(Txid::FromUint256(now), i));
1556 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1557 if (!done.count(iter->second)) {
1558 todo.insert(iter->second);
1559 }
1560 }
1561 }
1562
1563 if (update_state == TxUpdate::NOTIFY_CHANGED) {
1564 NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
1565 }
1566
1567 // If a transaction changes its tx state, that usually changes the balance
1568 // available of the outputs it spends. So force those to be recomputed
1569 MarkInputsDirty(wtx.tx);
1570 }
1571 }
1572 }
1573
1574 bool CWallet::SyncTransaction(const CTransactionRef& ptx, const SyncTxState& state, bool update_tx, bool rescanning_old_block)
1575 {
1576 if (!AddToWalletIfInvolvingMe(ptx, state, update_tx, rescanning_old_block))
1577 return false; // Not one of ours
1578
1579 // If a transaction changes 'conflicted' state, that changes the balance
1580 // available of the outputs it spends. So force those to be
1581 // recomputed, also:
1582 MarkInputsDirty(ptx);
1583 return true;
1584 }
1585
1586 void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
1587 LOCK(cs_wallet);
1588 SyncTransaction(tx, TxStateInMempool{});
1589
1590 auto it = mapWallet.find(tx->GetHash());
1591 if (it != mapWallet.end()) {
1592 RefreshMempoolStatus(it->second, chain());
1593 }
1594
1595 const Txid& txid = tx->GetHash();
1596
1597 for (const CTxIn& tx_in : tx->vin) {
1598 // For each wallet transaction spending this prevout..
1599 for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1600 const uint256& spent_id = range.first->second;
1601 // Skip the recently added tx
1602 if (spent_id == txid) continue;
1603 RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1604 return wtx.mempool_conflicts.insert(txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1605 });
1606 }
1607 }
1608 }
1609
1610 void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {
1611 LOCK(cs_wallet);
1612 auto it = mapWallet.find(tx->GetHash());
1613 if (it != mapWallet.end()) {
1614 RefreshMempoolStatus(it->second, chain());
1615 }
1616 // Handle transactions that were removed from the mempool because they
1617 // conflict with transactions in a newly connected block.
1618 if (reason == MemPoolRemovalReason::CONFLICT) {
1619 // Trigger external -walletnotify notifications for these transactions.
1620 // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
1621 //
1622 // 1. The transactionRemovedFromMempool callback does not currently
1623 // provide the conflicting block's hash and height, and for backwards
1624 // compatibility reasons it may not be not safe to store conflicted
1625 // wallet transactions with a null block hash. See
1626 // https://github.com/limenka/limenka/pull/18600#discussion_r420195993.
1627 // 2. For most of these transactions, the wallet's internal conflict
1628 // detection in the blockConnected handler will subsequently call
1629 // MarkConflicted and update them with CONFLICTED status anyway. This
1630 // applies to any wallet transaction that has inputs spent in the
1631 // block, or that has ancestors in the wallet with inputs spent by
1632 // the block.
1633 // 3. Longstanding behavior since the sync implementation in
1634 // https://github.com/limenka/limenka/pull/9371 and the prior sync
1635 // implementation before that was to mark these transactions
1636 // unconfirmed rather than conflicted.
1637 //
1638 // Nothing described above should be seen as an unchangeable requirement
1639 // when improving this code in the future. The wallet's heuristics for
1640 // distinguishing between conflicted and unconfirmed transactions are
1641 // imperfect, and could be improved in general, see
1642 // https://github.com/limenka/limenka-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1643 SyncTransaction(tx, TxStateInactive{});
1644 }
1645
1646 const Txid& txid = tx->GetHash();
1647
1648 for (const CTxIn& tx_in : tx->vin) {
1649 // Iterate over all wallet transactions spending txin.prev
1650 // and recursively mark them as no longer conflicting with
1651 // txid
1652 for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1653 const uint256& spent_id = range.first->second;
1654
1655 RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1656 return wtx.mempool_conflicts.erase(txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1657 });
1658 }
1659 }
1660 }
1661
1662 void CWallet::blockConnected(ChainstateRole role, const interfaces::BlockInfo& block)
1663 {
1664 assert(block.data);
1665 LOCK(cs_wallet);
1666
1667 switch (role) {
1668 case ChainstateRole::BACKGROUND:
1669 m_background_validation_height = block.height;
1670 return;
1671 case ChainstateRole::ASSUMEDVALID:
1672 if (m_background_validation_height == -1) {
1673 m_background_validation_height = 0;
1674 }
1675 break;
1676 case ChainstateRole::NORMAL:
1677 m_background_validation_height = -1;
1678 break;
1679 } // no default case, so the compiler can warn about missing cases
1680
1681 // Update the best block in memory first. This will set the best block's height, which is
1682 // needed by MarkConflicted.
1683 SetLastBlockProcessedInMem(block.height, block.hash);
1684
1685 // No need to scan block if it was created before the wallet birthday.
1686 // Uses chain max time and twice the grace period to adjust time for block time variability.
1687 if (block.chain_time_max < m_birth_time.load() - (TIMESTAMP_WINDOW * 2)) return;
1688
1689 // Scan block
1690 bool wallet_updated = false;
1691 for (size_t index = 0; index < block.data->vtx.size(); index++) {
1692 wallet_updated |= SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)});
1693 transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK);
1694 }
1695
1696 // Update on disk if this block resulted in us updating a tx, or periodically every 144 blocks (~1 day)
1697 if (wallet_updated || block.height % 144 == 0) {
1698 WriteBestBlock();
1699 GetDatabase().IncrementUpdateCounter();
1700 }
1701 }
1702
1703 void CWallet::blockDisconnected(const interfaces::BlockInfo& block)
1704 {
1705 assert(block.data);
1706 LOCK(cs_wallet);
1707
1708 // At block disconnection, this will change an abandoned transaction to
1709 // be unconfirmed, whether or not the transaction is added back to the mempool.
1710 // User may have to call abandontransaction again. It may be addressed in the
1711 // future with a stickier abandoned state or even removing abandontransaction call.
1712 int disconnect_height = block.height;
1713
1714 for (size_t index = 0; index < block.data->vtx.size(); index++) {
1715 const CTransactionRef& ptx = Assert(block.data)->vtx[index];
1716 // Coinbase transactions are not only inactive but also abandoned,
1717 // meaning they should never be relayed standalone via the p2p protocol.
1718 SyncTransaction(ptx, TxStateInactive{/*abandoned=*/index == 0});
1719
1720 for (const CTxIn& tx_in : ptx->vin) {
1721 // No other wallet transactions conflicted with this transaction
1722 if (mapTxSpends.count(tx_in.prevout) < 1) continue;
1723
1724 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.prevout);
1725
1726 // For all of the spends that conflict with this transaction
1727 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1728 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1729
1730 if (!wtx.isBlockConflicted()) continue;
1731
1732 auto try_updating_state = [&](CWalletTx& tx) {
1733 if (!tx.isBlockConflicted()) return TxUpdate::UNCHANGED;
1734 if (tx.state<TxStateBlockConflicted>()->conflicting_block_height >= disconnect_height) {
1735 tx.m_state = TxStateInactive{};
1736 return TxUpdate::CHANGED;
1737 }
1738 return TxUpdate::UNCHANGED;
1739 };
1740
1741 RecursiveUpdateTxState(wtx.tx->GetHash(), try_updating_state);
1742 }
1743 }
1744 }
1745
1746 // Update the best block
1747 SetLastBlockProcessed(block.height - 1, *Assert(block.prev_hash));
1748 }
1749
1750 void CWallet::updatedBlockTip()
1751 {
1752 m_best_block_time = GetTime();
1753 }
1754
1755 void CWallet::BlockUntilSyncedToCurrentChain() const {
1756 AssertLockNotHeld(cs_wallet);
1757 // Skip the queue-draining stuff if we know we're caught up with
1758 // chain().Tip(), otherwise put a callback in the validation interface queue and wait
1759 // for the queue to drain enough to execute it (indicating we are caught up
1760 // at least with the time we entered this function).
1761 uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1762 chain().waitForNotificationsIfTipChanged(last_block_hash);
1763 }
1764
1765 // Note that this function doesn't distinguish between a 0-valued input,
1766 // and a not-"is mine" (according to the filter) input.
1767 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1768 {
1769 {
1770 LOCK(cs_wallet);
1771 const auto mi = mapWallet.find(txin.prevout.hash);
1772 if (mi != mapWallet.end())
1773 {
1774 const CWalletTx& prev = (*mi).second;
1775 if (txin.prevout.n < prev.tx->vout.size())
1776 if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1777 return prev.tx->vout[txin.prevout.n].nValue;
1778 }
1779 }
1780 return 0;
1781 }
1782
1783 isminetype CWallet::IsMine(const CTxOut& txout) const
1784 {
1785 AssertLockHeld(cs_wallet);
1786 return IsMine(txout.scriptPubKey);
1787 }
1788
1789 isminetype CWallet::IsMine(const CTxDestination& dest) const
1790 {
1791 AssertLockHeld(cs_wallet);
1792 return IsMine(GetScriptForDestination(dest));
1793 }
1794
1795 isminetype CWallet::IsMine(const CScript& script) const
1796 {
1797 AssertLockHeld(cs_wallet);
1798
1799 // Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
1800 const auto& it = m_cached_spks.find(script);
1801 if (it != m_cached_spks.end()) {
1802 isminetype res = ISMINE_NO;
1803 for (const auto& spkm : it->second) {
1804 res = std::max(res, spkm->IsMine(script));
1805 }
1806 Assume(res == ISMINE_SPENDABLE);
1807 return res;
1808 }
1809
1810 // Legacy wallet
1811 if (LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan()) {
1812 return spkm->IsMine(script);
1813 }
1814
1815 return ISMINE_NO;
1816 }
1817
1818 bool CWallet::IsMine(const CTransaction& tx) const
1819 {
1820 AssertLockHeld(cs_wallet);
1821 for (const CTxOut& txout : tx.vout)
1822 if (IsMine(txout))
1823 return true;
1824 return false;
1825 }
1826
1827 isminetype CWallet::IsMine(const COutPoint& outpoint) const
1828 {
1829 AssertLockHeld(cs_wallet);
1830 auto wtx = GetWalletTx(outpoint.hash);
1831 if (!wtx) {
1832 return ISMINE_NO;
1833 }
1834 if (outpoint.n >= wtx->tx->vout.size()) {
1835 return ISMINE_NO;
1836 }
1837 return IsMine(wtx->tx->vout[outpoint.n]);
1838 }
1839
1840 bool CWallet::IsFromMe(const CTransaction& tx) const
1841 {
1842 LOCK(cs_wallet);
1843 for (const CTxIn& txin : tx.vin) {
1844 if (IsMine(txin.prevout)) {
1845 return true;
1846 }
1847 }
1848 return false;
1849 }
1850
1851 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1852 {
1853 CAmount nDebit = 0;
1854 for (const CTxIn& txin : tx.vin)
1855 {
1856 nDebit += GetDebit(txin, filter);
1857 if (!MoneyRange(nDebit))
1858 throw std::runtime_error(std::string(__func__) + ": value out of range");
1859 }
1860 return nDebit;
1861 }
1862
1863 bool CWallet::IsHDEnabled() const
1864 {
1865 // All Active ScriptPubKeyMans must be HD for this to be true
1866 bool result = false;
1867 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1868 if (!spk_man->IsHDEnabled()) return false;
1869 result = true;
1870 }
1871 return result;
1872 }
1873
1874 bool CWallet::CanGetAddresses(bool internal) const
1875 {
1876 LOCK(cs_wallet);
1877 if (m_spk_managers.empty()) return false;
1878 for (OutputType t : OUTPUT_TYPES) {
1879 auto spk_man = GetScriptPubKeyMan(t, internal);
1880 if (spk_man && spk_man->CanGetAddresses(internal)) {
1881 return true;
1882 }
1883 }
1884 return false;
1885 }
1886
1887 void CWallet::SetWalletFlag(uint64_t flags)
1888 {
1889 WalletBatch batch(GetDatabase());
1890 return SetWalletFlagWithDB(batch, flags);
1891 }
1892
1893 void CWallet::SetWalletFlagWithDB(WalletBatch& batch, uint64_t flags)
1894 {
1895 LOCK(cs_wallet);
1896 m_wallet_flags |= flags;
1897 if (!batch.WriteWalletFlags(m_wallet_flags))
1898 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1899 }
1900
1901 void CWallet::UnsetWalletFlag(uint64_t flag)
1902 {
1903 WalletBatch batch(GetDatabase());
1904 UnsetWalletFlagWithDB(batch, flag);
1905 }
1906
1907 void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
1908 {
1909 LOCK(cs_wallet);
1910 m_wallet_flags &= ~flag;
1911 if (!batch.WriteWalletFlags(m_wallet_flags))
1912 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1913 }
1914
1915 void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
1916 {
1917 UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
1918 }
1919
1920 bool CWallet::IsWalletFlagSet(uint64_t flag) const
1921 {
1922 return (m_wallet_flags & flag);
1923 }
1924
1925 bool CWallet::LoadWalletFlags(uint64_t flags)
1926 {
1927 LOCK(cs_wallet);
1928 if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1929 // contains unknown non-tolerable wallet flags
1930 return false;
1931 }
1932 m_wallet_flags = flags;
1933
1934 return true;
1935 }
1936
1937 void CWallet::InitWalletFlags(uint64_t flags)
1938 {
1939 LOCK(cs_wallet);
1940
1941 // We should never be writing unknown non-tolerable wallet flags
1942 assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1943 // This should only be used once, when creating a new wallet - so current flags are expected to be blank
1944 assert(m_wallet_flags == 0);
1945
1946 if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1947 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1948 }
1949
1950 if (!LoadWalletFlags(flags)) assert(false);
1951 }
1952
1953 bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1954 {
1955 auto spk_man = GetLegacyScriptPubKeyMan();
1956 if (!spk_man) {
1957 return false;
1958 }
1959 LOCK(spk_man->cs_KeyStore);
1960 return spk_man->ImportScripts(scripts, timestamp);
1961 }
1962
1963 bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1964 {
1965 auto spk_man = GetLegacyScriptPubKeyMan();
1966 if (!spk_man) {
1967 return false;
1968 }
1969 LOCK(spk_man->cs_KeyStore);
1970 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1971 }
1972
1973 bool CWallet::ImportPubKeys(const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const int64_t timestamp)
1974 {
1975 auto spk_man = GetLegacyScriptPubKeyMan();
1976 if (!spk_man) {
1977 return false;
1978 }
1979 LOCK(spk_man->cs_KeyStore);
1980 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, timestamp);
1981 }
1982
1983 bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
1984 {
1985 auto spk_man = GetLegacyScriptPubKeyMan();
1986 if (!spk_man) {
1987 return false;
1988 }
1989 LOCK(spk_man->cs_KeyStore);
1990 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1991 return false;
1992 }
1993 if (apply_label) {
1994 WalletBatch batch(GetDatabase());
1995 for (const CScript& script : script_pub_keys) {
1996 CTxDestination dest;
1997 ExtractDestination(script, dest);
1998 if (IsValidDestination(dest)) {
1999 SetAddressBookWithDB(batch, dest, label, AddressPurpose::RECEIVE);
2000 }
2001 }
2002 }
2003 return true;
2004 }
2005
2006 void CWallet::MaybeUpdateBirthTime(int64_t time)
2007 {
2008 int64_t birthtime = m_birth_time.load();
2009 if (time < birthtime) {
2010 m_birth_time = time;
2011 }
2012 }
2013
2014 /**
2015 * Scan active chain for relevant transactions after importing keys. This should
2016 * be called whenever new keys are added to the wallet, with the oldest key
2017 * creation time.
2018 *
2019 * @return Earliest timestamp that could be successfully scanned from. Timestamp
2020 * returned will be higher than startTime if relevant blocks could not be read.
2021 */
2022 int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
2023 {
2024 // Find starting block. May be null if nCreateTime is greater than the
2025 // highest blockchain timestamp, in which case there is nothing that needs
2026 // to be scanned.
2027 int start_height = 0;
2028 uint256 start_block;
2029 bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
2030 WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
2031
2032 if (start) {
2033 // TODO: this should take into account failure by ScanResult::USER_ABORT
2034 ScanResult result = ScanForWalletTransactions(start_block, start_height, /*max_height=*/{}, reserver, /*fUpdate=*/update, /*save_progress=*/false);
2035 if (result.status == ScanResult::FAILURE) {
2036 int64_t time_max;
2037 CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
2038 return time_max + TIMESTAMP_WINDOW + 1;
2039 }
2040 }
2041 return startTime;
2042 }
2043
2044 /**
2045 * Scan the block chain (starting in start_block) for transactions
2046 * from or to us. If fUpdate is true, found transactions that already
2047 * exist in the wallet will be updated. If max_height is not set, the
2048 * mempool will be scanned as well.
2049 *
2050 * @param[in] start_block Scan starting block. If block is not on the active
2051 * chain, the scan will return SUCCESS immediately.
2052 * @param[in] start_height Height of start_block
2053 * @param[in] max_height Optional max scanning height. If unset there is
2054 * no maximum and scanning can continue to the tip
2055 *
2056 * @return ScanResult returning scan information and indicating success or
2057 * failure. Return status will be set to SUCCESS if scan was
2058 * successful. FAILURE if a complete rescan was not possible (due to
2059 * pruning or corruption). USER_ABORT if the rescan was aborted before
2060 * it could complete.
2061 *
2062 * @pre Caller needs to make sure start_block (and the optional stop_block) are on
2063 * the main chain after to the addition of any new keys you want to detect
2064 * transactions for.
2065 */
2066 CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress)
2067 {
2068 constexpr auto INTERVAL_TIME{60s};
2069 auto current_time{reserver.now()};
2070 auto start_time{reserver.now()};
2071
2072 assert(reserver.isReserved());
2073
2074 uint256 block_hash = start_block;
2075 ScanResult result;
2076
2077 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
2078 if (!IsLegacy() && chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
2079
2080 WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(),
2081 fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks");
2082
2083 fAbortRescan = false;
2084 ShowProgress(strprintf("%s %s", GetDisplayName(), _("Rescanning…")), 0); // show rescan progress in GUI as dialog or on splashscreen, if rescan required on startup (e.g. due to corruption)
2085 uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
2086 uint256 end_hash = tip_hash;
2087 if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
2088 double progress_begin = chain().guessVerificationProgress(block_hash);
2089 double progress_end = chain().guessVerificationProgress(end_hash);
2090 double progress_current = progress_begin;
2091 int block_height = start_height;
2092 while (!fAbortRescan && !chain().shutdownRequested()) {
2093 if (progress_end - progress_begin > 0.0) {
2094 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
2095 } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
2096 m_scanning_progress = 0;
2097 }
2098 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
2099 ShowProgress(strprintf("%s %s", GetDisplayName(), _("Rescanning…")), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
2100 }
2101
2102 bool next_interval = reserver.now() >= current_time + INTERVAL_TIME;
2103 if (next_interval) {
2104 current_time = reserver.now();
2105 WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
2106 }
2107
2108 bool fetch_block{true};
2109 if (fast_rescan_filter) {
2110 fast_rescan_filter->UpdateIfNeeded();
2111 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
2112 if (matches_block.has_value()) {
2113 if (*matches_block) {
2114 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
2115 } else {
2116 result.last_scanned_block = block_hash;
2117 result.last_scanned_height = block_height;
2118 fetch_block = false;
2119 }
2120 } else {
2121 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
2122 }
2123 }
2124
2125 // Find next block separately from reading data above, because reading
2126 // is slow and there might be a reorg while it is read.
2127 bool block_still_active = false;
2128 bool next_block = false;
2129 uint256 next_block_hash;
2130 chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
2131
2132 if (fetch_block) {
2133 // Read block data
2134 CBlock block;
2135 chain().findBlock(block_hash, FoundBlock().data(block));
2136
2137 if (!block.IsNull()) {
2138 LOCK(cs_wallet);
2139 if (!block_still_active) {
2140 // Abort scan if current block is no longer active, to prevent
2141 // marking transactions as coming from the wrong block.
2142 result.last_failed_block = block_hash;
2143 result.status = ScanResult::FAILURE;
2144 break;
2145 }
2146 for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
2147 SyncTransaction(block.vtx[posInBlock], TxStateConfirmed{block_hash, block_height, static_cast<int>(posInBlock)}, fUpdate, /*rescanning_old_block=*/true);
2148 }
2149 // scan succeeded, record block as most recent successfully scanned
2150 result.last_scanned_block = block_hash;
2151 result.last_scanned_height = block_height;
2152
2153 if (save_progress && next_interval) {
2154 CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
2155
2156 if (!loc.IsNull()) {
2157 WalletLogPrintf("Saving scan progress %d.\n", block_height);
2158 WalletBatch batch(GetDatabase());
2159 batch.WriteBestBlock(loc);
2160 }
2161 }
2162 } else {
2163 // could not scan block, keep scanning but record this block as the most recent failure
2164 result.last_failed_block = block_hash;
2165 result.status = ScanResult::FAILURE;
2166 }
2167 }
2168 if (max_height && block_height >= *max_height) {
2169 break;
2170 }
2171 // If rescanning was triggered with cs_wallet permanently locked (AttachChain), additional blocks that were connected during the rescan
2172 // aren't processed here but will be processed with the pending blockConnected notifications after the lock is released.
2173 // If rescanning without a permanent cs_wallet lock, additional blocks that were added during the rescan will be re-processed if
2174 // the notification was processed and the last block height was updated.
2175 if (block_height >= WITH_LOCK(cs_wallet, return GetLastBlockHeight())) {
2176 break;
2177 }
2178
2179 {
2180 if (!next_block) {
2181 // break successfully when rescan has reached the tip, or
2182 // previous block is no longer on the chain due to a reorg
2183 break;
2184 }
2185
2186 // increment block and verification progress
2187 block_hash = next_block_hash;
2188 ++block_height;
2189 progress_current = chain().guessVerificationProgress(block_hash);
2190
2191 // handle updated tip hash
2192 const uint256 prev_tip_hash = tip_hash;
2193 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
2194 if (!max_height && prev_tip_hash != tip_hash) {
2195 // in case the tip has changed, update progress max
2196 progress_end = chain().guessVerificationProgress(tip_hash);
2197 }
2198 }
2199 }
2200 if (!max_height) {
2201 WalletLogPrintf("Scanning current mempool transactions.\n");
2202 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
2203 }
2204 ShowProgress(strprintf("%s %s", GetDisplayName(), _("Rescanning…")), 100); // hide progress dialog in GUI
2205 if (block_height && fAbortRescan) {
2206 WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
2207 result.status = ScanResult::USER_ABORT;
2208 } else if (block_height && chain().shutdownRequested()) {
2209 WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2210 result.status = ScanResult::USER_ABORT;
2211 } else {
2212 WalletLogPrintf("Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.now() - start_time));
2213 }
2214 return result;
2215 }
2216
2217 bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
2218 {
2219 AssertLockHeld(cs_wallet);
2220
2221 // Can't relay if wallet is not broadcasting
2222 if (!GetBroadcastTransactions()) return false;
2223 // Don't relay abandoned transactions
2224 if (wtx.isAbandoned()) return false;
2225 // Don't try to submit coinbase transactions. These would fail anyway but would
2226 // cause log spam.
2227 if (wtx.IsCoinBase()) return false;
2228 // Don't try to submit conflicted or confirmed transactions.
2229 if (GetTxDepthInMainChain(wtx) != 0) return false;
2230
2231 // Submit transaction to mempool for relay
2232 WalletLogPrintf("Submitting wtx %s to mempool for relay\n", wtx.GetHash().ToString());
2233 // We must set TxStateInMempool here. Even though it will also be set later by the
2234 // entered-mempool callback, if we did not there would be a race where a
2235 // user could call sendmoney in a loop and hit spurious out of funds errors
2236 // because we think that this newly generated transaction's change is
2237 // unavailable as we're not yet aware that it is in the mempool.
2238 //
2239 // If broadcast fails for any reason, trying to set wtx.m_state here would be incorrect.
2240 // If transaction was previously in the mempool, it should be updated when
2241 // TransactionRemovedFromMempool fires.
2242 bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, relay, err_string);
2243 if (ret) wtx.m_state = TxStateInMempool{};
2244 return ret;
2245 }
2246
2247 std::set<uint256> CWallet::GetTxConflicts(const CWalletTx& wtx) const
2248 {
2249 AssertLockHeld(cs_wallet);
2250
2251 const uint256 myHash{wtx.GetHash()};
2252 std::set<uint256> result{GetConflicts(myHash)};
2253 result.erase(myHash);
2254 return result;
2255 }
2256
2257 bool CWallet::ShouldResend() const
2258 {
2259 // Don't attempt to resubmit if the wallet is configured to not broadcast
2260 if (!fBroadcastTransactions) return false;
2261
2262 // During reindex, importing and IBD, old wallet transactions become
2263 // unconfirmed. Don't resend them as that would spam other nodes.
2264 // We only allow forcing mempool submission when not relaying to avoid this spam.
2265 if (!chain().isReadyToBroadcast()) return false;
2266
2267 // Do this infrequently and randomly to avoid giving away
2268 // that these are our transactions.
2269 if (NodeClock::now() < m_next_resend) return false;
2270
2271 return true;
2272 }
2273
2274 NodeClock::time_point CWallet::GetDefaultNextResend() { return FastRandomContext{}.rand_uniform_delay(NodeClock::now() + 12h, 24h); }
2275
2276 // Resubmit transactions from the wallet to the mempool, optionally asking the
2277 // mempool to relay them. On startup, we will do this for all unconfirmed
2278 // transactions but will not ask the mempool to relay them. We do this on startup
2279 // to ensure that our own mempool is aware of our transactions. There
2280 // is a privacy side effect here as not broadcasting on startup also means that we won't
2281 // inform the world of our wallet's state, particularly if the wallet (or node) is not
2282 // yet synced.
2283 //
2284 // Otherwise this function is called periodically in order to relay our unconfirmed txs.
2285 // We do this on a random timer to slightly obfuscate which transactions
2286 // come from our wallet.
2287 //
2288 // TODO: Ideally, we'd only resend transactions that we think should have been
2289 // mined in the most recent block. Any transaction that wasn't in the top
2290 // blockweight of transactions in the mempool shouldn't have been mined,
2291 // and so is probably just sitting in the mempool waiting to be confirmed.
2292 // Rebroadcasting does nothing to speed up confirmation and only damages
2293 // privacy.
2294 //
2295 // The `force` option results in all unconfirmed transactions being submitted to
2296 // the mempool. This does not necessarily result in those transactions being relayed,
2297 // that depends on the `relay` option. Periodic rebroadcast uses the pattern
2298 // relay=true force=false, while loading into the mempool
2299 // (on start, or after import) uses relay=false force=true.
2300 void CWallet::ResubmitWalletTransactions(bool relay, bool force)
2301 {
2302 // Don't attempt to resubmit if the wallet is configured to not broadcast,
2303 // even if forcing.
2304 if (!fBroadcastTransactions) return;
2305
2306 int submitted_tx_count = 0;
2307
2308 { // cs_wallet scope
2309 LOCK(cs_wallet);
2310
2311 // First filter for the transactions we want to rebroadcast.
2312 // We use a set with WalletTxOrderComparator so that rebroadcasting occurs in insertion order
2313 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2314 for (auto& [txid, wtx] : mapWallet) {
2315 // Only rebroadcast unconfirmed txs
2316 if (!wtx.isUnconfirmed()) continue;
2317
2318 // Attempt to rebroadcast all txes more than 5 minutes older than
2319 // the last block, or all txs if forcing.
2320 if (!force && wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
2321 to_submit.insert(&wtx);
2322 }
2323 // Now try submitting the transactions to the memory pool and (optionally) relay them.
2324 for (auto wtx : to_submit) {
2325 std::string unused_err_string;
2326 if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, relay)) ++submitted_tx_count;
2327 }
2328 } // cs_wallet
2329
2330 if (submitted_tx_count > 0) {
2331 WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2332 }
2333 }
2334
2335 /** @} */ // end of mapWallet
2336
2337 void MaybeResendWalletTxs(WalletContext& context)
2338 {
2339 for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
2340 if (!pwallet->ShouldResend()) continue;
2341 pwallet->ResubmitWalletTransactions(/*relay=*/true, /*force=*/false);
2342 pwallet->SetNextResend();
2343 }
2344 }
2345
2346
2347 /** @defgroup Actions
2348 *
2349 * @{
2350 */
2351
2352 bool CWallet::SignTransaction(CMutableTransaction& tx) const
2353 {
2354 AssertLockHeld(cs_wallet);
2355
2356 // Build coins map
2357 std::map<COutPoint, Coin> coins;
2358 for (auto& input : tx.vin) {
2359 const auto mi = mapWallet.find(input.prevout.hash);
2360 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2361 return false;
2362 }
2363 const CWalletTx& wtx = mi->second;
2364 int prev_height = wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height : 0;
2365 coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], prev_height, wtx.IsCoinBase());
2366 }
2367 std::map<int, bilingual_str> input_errors;
2368 return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
2369 }
2370
2371 bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum) const
2372 {
2373 // DEFAULT normalizes to ALL for BASE/WITNESS_V0 signing.
2374 int sighash_type = sighash == SIGHASH_DEFAULT ? SIGHASH_ALL : sighash;
2375
2376 // Try to sign with all ScriptPubKeyMans
2377 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2378 // spk_man->SignTransaction will return true if the transaction is complete,
2379 // so we can exit early and return true if that happens
2380 if (spk_man->SignTransaction(tx, coins, sighash_type, input_errors, inputs_amount_sum)) {
2381 return true;
2382 }
2383 }
2384
2385 // At this point, one input was not fully signed otherwise we would have exited already
2386 return false;
2387 }
2388
2389 std::optional<PSBTError> CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed, bool finalize) const
2390 {
2391 if (n_signed) {
2392 *n_signed = 0;
2393 }
2394 LOCK(cs_wallet);
2395 // Get all of the previous transactions
2396 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2397 const CTxIn& txin = psbtx.tx->vin[i];
2398 PSBTInput& input = psbtx.inputs.at(i);
2399
2400 if (PSBTInputSigned(input)) {
2401 continue;
2402 }
2403
2404 // If we have no utxo, grab it from the wallet.
2405 if (!input.non_witness_utxo) {
2406 const uint256& txhash = txin.prevout.hash;
2407 const auto it = mapWallet.find(txhash);
2408 if (it != mapWallet.end()) {
2409 const CWalletTx& wtx = it->second;
2410 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
2411 // The signing code will switch to the smaller witness_utxo if this is ok.
2412 input.non_witness_utxo = wtx.tx;
2413 }
2414 }
2415 }
2416
2417 const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
2418
2419 // Fill in information from ScriptPubKeyMans
2420 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2421 int n_signed_this_spkm = 0;
2422 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize)};
2423 if (error) {
2424 return error;
2425 }
2426
2427 if (n_signed) {
2428 (*n_signed) += n_signed_this_spkm;
2429 }
2430 }
2431
2432 RemoveUnnecessaryTransactions(psbtx, sighash_type);
2433
2434 // Complete if every input is now signed.
2435 complete = true;
2436 for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
2437 complete &= PSBTInputSignedAndVerified(psbtx, i, &txdata);
2438 }
2439
2440 return {};
2441 }
2442
2443 SigningResult CWallet::SignMessage(const MessageSignatureFormat format, const std::string& message, const CTxDestination& address, std::string& str_sig) const
2444 {
2445 SignatureData sigdata;
2446 CScript script_pub_key = GetScriptForDestination(address);
2447 for (const auto& spk_man_pair : m_spk_managers) {
2448 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2449 LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
2450 return spk_man_pair.second->SignMessage(format, message, address, str_sig);
2451 }
2452 }
2453 return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
2454 }
2455
2456 OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
2457 {
2458 // If -changetype is specified, always use that change type.
2459 if (change_type) {
2460 return *change_type;
2461 }
2462
2463 // if m_default_address_type is legacy, use legacy address as change.
2464 if (m_default_address_type == OutputType::LEGACY && GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true)) {
2465 return OutputType::LEGACY;
2466 }
2467
2468 bool any_tr{false};
2469 bool any_wpkh{false};
2470 bool any_sh{false};
2471 bool any_pkh{false};
2472 bool any_spk{false};
2473
2474 for (const auto& recipient : vecSend) {
2475 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2476 any_tr = true;
2477 } else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2478 any_wpkh = true;
2479 } else if (std::get_if<ScriptHash>(&recipient.dest)) {
2480 any_sh = true;
2481 } else if (std::get_if<PKHash>(&recipient.dest)) {
2482 any_pkh = true;
2483 } else if (std::get_if<WitnessV3SpkHash>(&recipient.dest)) {
2484 any_spk = true;
2485 }
2486 }
2487
2488 const bool has_p2spkh_spkman(GetScriptPubKeyMan(OutputType::P2SPKH, /*internal=*/true));
2489 if (has_p2spkh_spkman && any_spk) {
2490 return OutputType::P2SPKH;
2491 }
2492 const bool has_bech32m_spkman(GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/true));
2493 if (has_bech32m_spkman && any_tr && m_default_address_type == OutputType::BECH32M) {
2494 // Currently tr is the only type supported by the BECH32M spkman
2495 return OutputType::BECH32M;
2496 }
2497 const bool has_bech32_spkman(GetScriptPubKeyMan(OutputType::BECH32, /*internal=*/true));
2498 if (has_bech32_spkman && any_wpkh) {
2499 // Currently wpkh is the only type supported by the BECH32 spkman
2500 return OutputType::BECH32;
2501 }
2502 const bool has_p2sh_segwit_spkman(GetScriptPubKeyMan(OutputType::P2SH_SEGWIT, /*internal=*/true));
2503 if (has_p2sh_segwit_spkman && any_sh) {
2504 // Currently sh_wpkh is the only type supported by the P2SH_SEGWIT spkman
2505 // As of 2021 about 80% of all SH are wrapping WPKH, so use that
2506 return OutputType::P2SH_SEGWIT;
2507 }
2508 const bool has_legacy_spkman(GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true));
2509 if (has_legacy_spkman && any_pkh) {
2510 // Currently pkh is the only type supported by the LEGACY spkman
2511 return OutputType::LEGACY;
2512 }
2513 if (!GetScriptPubKeyMan(m_default_address_type, /*internal=*/true)) {
2514 // Default type not available, so look for anything else to fallback to
2515 // NOTE: Sane behaviour assumes OUTPUT_TYPES is sorted oldest to newest
2516 for (const auto& ot : OUTPUT_TYPES) {
2517 if (GetScriptPubKeyMan(ot, /*internal=*/true)) {
2518 return ot;
2519 }
2520 }
2521 }
2522 return m_default_address_type;
2523
2524 if (has_bech32m_spkman) {
2525 return OutputType::BECH32M;
2526 }
2527 if (has_p2spkh_spkman) {
2528 return OutputType::P2SPKH;
2529 }
2530 if (has_bech32_spkman) {
2531 return OutputType::BECH32;
2532 }
2533 // else use m_default_address_type for change
2534 return m_default_address_type;
2535 }
2536
2537 void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
2538 {
2539 LOCK(cs_wallet);
2540 WalletLogPrintf("CommitTransaction:\n%s\n", util::RemoveSuffixView(tx->ToString(), "\n"));
2541
2542 // Add tx to wallet, because if it has change it's also ours,
2543 // otherwise just for transaction history.
2544 CWalletTx* wtx = AddToWallet(tx, TxStateInactive{}, [&](CWalletTx& wtx, bool new_tx) {
2545 CHECK_NONFATAL(wtx.mapValue.empty());
2546 CHECK_NONFATAL(wtx.vOrderForm.empty());
2547 wtx.mapValue = std::move(mapValue);
2548 wtx.vOrderForm = std::move(orderForm);
2549 wtx.fTimeReceivedIsTxTime = true;
2550 wtx.fFromMe = true;
2551 return true;
2552 });
2553
2554 // wtx can only be null if the db write failed.
2555 if (!wtx) {
2556 throw std::runtime_error(std::string(__func__) + ": Wallet db error, transaction commit failed");
2557 }
2558
2559 // Notify that old coins are spent
2560 for (const CTxIn& txin : tx->vin) {
2561 CWalletTx &coin = mapWallet.at(txin.prevout.hash);
2562 coin.MarkDirty();
2563 NotifyTransactionChanged(coin.GetHash(), CT_UPDATED);
2564 }
2565
2566 if (!fBroadcastTransactions) {
2567 // Don't submit tx to the mempool
2568 return;
2569 }
2570
2571 std::string err_string;
2572 if (!SubmitTxMemoryPoolAndRelay(*wtx, err_string, true)) {
2573 WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2574 // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
2575 }
2576 }
2577
2578 DBErrors CWallet::LoadWallet(const do_init_used_flag do_init_used_flag_val)
2579 {
2580 LOCK(cs_wallet);
2581
2582 Assert(m_spk_managers.empty());
2583 Assert(m_wallet_flags == 0);
2584 DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
2585 if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2586 {
2587 if (GetDatabase().Rewrite("\x04pool"))
2588 {
2589 for (const auto& spk_man_pair : m_spk_managers) {
2590 spk_man_pair.second->RewriteDB();
2591 }
2592 }
2593 }
2594
2595 if (m_spk_managers.empty()) {
2596 assert(m_external_spk_managers.empty());
2597 assert(m_internal_spk_managers.empty());
2598 }
2599
2600 if (nLoadWalletRet != DBErrors::LOAD_OK) {
2601 return nLoadWalletRet;
2602 }
2603
2604 if (do_init_used_flag_val == do_init_used_flag::Init) InitialiseAddressBookUsed();
2605
2606 return DBErrors::LOAD_OK;
2607 }
2608
2609 util::Result<void> CWallet::RemoveTxs(std::vector<uint256>& txs_to_remove)
2610 {
2611 AssertLockHeld(cs_wallet);
2612 bilingual_str str_err; // future: make RunWithinTxn return a util::Result
2613 bool was_txn_committed = RunWithinTxn(GetDatabase(), /*process_desc=*/"remove transactions", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2614 util::Result<void> result{RemoveTxs(batch, txs_to_remove)};
2615 if (!result) str_err = util::ErrorString(result);
2616 return result.has_value();
2617 });
2618 if (!str_err.empty()) return util::Error{str_err};
2619 if (!was_txn_committed) return util::Error{_("Error starting/committing db txn for wallet transactions removal process")};
2620 return {}; // all good
2621 }
2622
2623 util::Result<void> CWallet::RemoveTxs(WalletBatch& batch, std::vector<uint256>& txs_to_remove)
2624 {
2625 AssertLockHeld(cs_wallet);
2626 if (!batch.HasActiveTxn()) return util::Error{strprintf(_("The transactions removal process can only be executed within a db txn"))};
2627
2628 // Check for transaction existence and remove entries from disk
2629 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2630 std::vector<TxIterator> erased_txs;
2631 bilingual_str str_err;
2632 for (const uint256& hash : txs_to_remove) {
2633 auto it_wtx = mapWallet.find(hash);
2634 if (it_wtx == mapWallet.end()) {
2635 return util::Error{strprintf(_("Transaction %s does not belong to this wallet"), hash.GetHex())};
2636 }
2637 if (!batch.EraseTx(hash)) {
2638 return util::Error{strprintf(_("Failure removing transaction: %s"), hash.GetHex())};
2639 }
2640 erased_txs.emplace_back(it_wtx);
2641 }
2642
2643 // Register callback to update the memory state only when the db txn is actually dumped to disk
2644 batch.RegisterTxnListener({.on_commit=[&, erased_txs]() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2645 // Update the in-memory state and notify upper layers about the removals
2646 for (const auto& it : erased_txs) {
2647 const uint256 hash{it->first};
2648 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2649 for (const auto& txin : it->second.tx->vin)
2650 mapTxSpends.erase(txin.prevout);
2651 mapWallet.erase(it);
2652 NotifyTransactionChanged(hash, CT_DELETED);
2653 }
2654
2655 MarkDirty();
2656 }, .on_abort={}});
2657
2658 return {};
2659 }
2660
2661 bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& new_purpose)
2662 {
2663 bool fUpdated = false;
2664 bool is_mine;
2665 std::optional<AddressPurpose> purpose;
2666 {
2667 LOCK(cs_wallet);
2668 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2669 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2670
2671 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2672 record.SetLabel(strName);
2673 is_mine = IsMine(address) != ISMINE_NO;
2674 if (new_purpose) { /* update purpose only if requested */
2675 record.purpose = new_purpose;
2676 }
2677 purpose = record.purpose;
2678 }
2679
2680 const std::string& encoded_dest = EncodeDestination(address);
2681 if (new_purpose && !batch.WritePurpose(encoded_dest, PurposeToString(*new_purpose))) {
2682 WalletLogPrintf("Error: fail to write address book 'purpose' entry\n");
2683 return false;
2684 }
2685 if (!batch.WriteName(encoded_dest, strName)) {
2686 WalletLogPrintf("Error: fail to write address book 'name' entry\n");
2687 return false;
2688 }
2689
2690 // In very old wallets, address purpose may not be recorded so we derive it from IsMine
2691 NotifyAddressBookChanged(address, strName, is_mine,
2692 purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND),
2693 (fUpdated ? CT_UPDATED : CT_NEW));
2694 return true;
2695 }
2696
2697 bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& purpose)
2698 {
2699 WalletBatch batch(GetDatabase());
2700 return SetAddressBookWithDB(batch, address, strName, purpose);
2701 }
2702
2703 bool CWallet::DelAddressBook(const CTxDestination& address)
2704 {
2705 return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){
2706 return DelAddressBookWithDB(batch, address);
2707 });
2708 }
2709
2710 bool CWallet::DelAddressBookWithDB(WalletBatch& batch, const CTxDestination& address)
2711 {
2712 const std::string& dest = EncodeDestination(address);
2713 {
2714 LOCK(cs_wallet);
2715 // If we want to delete receiving addresses, we should avoid calling EraseAddressData because it will delete the previously_spent value. Could instead just erase the label so it becomes a change address, and keep the data.
2716 // NOTE: This isn't a problem for sending addresses because they don't have any data that needs to be kept.
2717 // When adding new address data, it should be considered here whether to retain or delete it.
2718 if (IsMine(address)) {
2719 WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2720 return false;
2721 }
2722 // Delete data rows associated with this address
2723 if (!batch.EraseAddressData(address)) {
2724 WalletLogPrintf("Error: cannot erase address book entry data\n");
2725 return false;
2726 }
2727
2728 // Delete purpose entry
2729 if (!batch.ErasePurpose(dest)) {
2730 WalletLogPrintf("Error: cannot erase address book entry purpose\n");
2731 return false;
2732 }
2733
2734 // Delete name entry
2735 if (!batch.EraseName(dest)) {
2736 WalletLogPrintf("Error: cannot erase address book entry name\n");
2737 return false;
2738 }
2739
2740 // finally, remove it from the map
2741 m_address_book.erase(address);
2742 }
2743
2744 // All good, signal changes
2745 NotifyAddressBookChanged(address, "", /*is_mine=*/false, AddressPurpose::SEND, CT_DELETED);
2746 return true;
2747 }
2748
2749 size_t CWallet::KeypoolCountExternalKeys() const
2750 {
2751 AssertLockHeld(cs_wallet);
2752
2753 auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2754 if (legacy_spk_man) {
2755 return legacy_spk_man->KeypoolCountExternalKeys();
2756 }
2757
2758 unsigned int count = 0;
2759 for (auto spk_man : m_external_spk_managers) {
2760 count += spk_man.second->GetKeyPoolSize();
2761 }
2762
2763 return count;
2764 }
2765
2766 unsigned int CWallet::GetKeyPoolSize() const
2767 {
2768 AssertLockHeld(cs_wallet);
2769
2770 unsigned int count = 0;
2771 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2772 count += spk_man->GetKeyPoolSize();
2773 }
2774 return count;
2775 }
2776
2777 bool CWallet::TopUpKeyPool(unsigned int kpSize)
2778 {
2779 LOCK(cs_wallet);
2780 bool res = true;
2781 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2782 res &= spk_man->TopUp(kpSize);
2783 }
2784 return res;
2785 }
2786
2787 util::Result<void> CWallet::CheckAddressTypeUsable(OutputType type) const
2788 {
2789 if (type != OutputType::P2SPKH) return {};
2790 if (Params().GetChainType() != ChainType::FORK) return {};
2791 const int64_t mtp = chain().getTipMtp();
2792 if (mtp + Params().GetConsensus().nForkActivationBias >= Params().GetConsensus().nForkActivationMTP) return {};
2793 return util::Error{Untranslated("lm1 (p2spkh) addresses cannot be created before fork activation: their outputs would be spendable by anyone")};
2794 }
2795
2796 util::Result<CTxDestination> CWallet::GetNewDestination(const OutputType type, const std::string label)
2797 {
2798 LOCK(cs_wallet);
2799 if (const auto err = CheckAddressTypeUsable(type); !err) return util::Error{util::ErrorString(err)};
2800 auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false);
2801 if (!spk_man) {
2802 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2803 }
2804
2805 auto op_dest = spk_man->GetNewDestination(type);
2806 if (op_dest) {
2807 SetAddressBook(*op_dest, label, AddressPurpose::RECEIVE);
2808 }
2809
2810 return op_dest;
2811 }
2812
2813 util::Result<CTxDestination> CWallet::GetNewChangeDestination(const OutputType type)
2814 {
2815 LOCK(cs_wallet);
2816
2817 if (const auto err = CheckAddressTypeUsable(type); !err) return util::Error{util::ErrorString(err)};
2818 ReserveDestination reservedest(this, type);
2819 auto op_dest = reservedest.GetReservedDestination(true);
2820 if (op_dest) reservedest.KeepDestination();
2821
2822 return op_dest;
2823 }
2824
2825 std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
2826 {
2827 LOCK(cs_wallet);
2828 if (m_spk_managers.empty()) {
2829 return std::nullopt;
2830 }
2831
2832 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2833 for (const auto& spk_man_pair : m_spk_managers) {
2834 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2835 }
2836 return oldest_key;
2837 }
2838
2839 void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2840 for (auto& entry : mapWallet) {
2841 CWalletTx& wtx = entry.second;
2842 if (wtx.m_is_cache_empty) continue;
2843 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2844 CTxDestination dst;
2845 if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
2846 wtx.MarkDirty();
2847 break;
2848 }
2849 }
2850 }
2851 }
2852
2853 void CWallet::ForEachAddrBookEntry(const ListAddrBookFunc& func) const
2854 {
2855 AssertLockHeld(cs_wallet);
2856 for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2857 const auto& entry = item.second;
2858 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2859 }
2860 }
2861
2862 bool CWallet::IsDestinationActive(const CTxDestination& dest) const
2863 {
2864 const CScript& script{GetScriptForDestination(dest)};
2865 const std::set<ScriptPubKeyMan*>& spkms{GetActiveScriptPubKeyMans()};
2866 return std::any_of(spkms.cbegin(), spkms.cend(), [&script](const auto& spkm) { return spkm->IsKeyActive(script); });
2867 }
2868
2869 std::vector<CTxDestination> CWallet::ListAddrBookAddresses(const std::optional<AddrBookFilter>& _filter) const
2870 {
2871 AssertLockHeld(cs_wallet);
2872 std::vector<CTxDestination> result;
2873 AddrBookFilter filter = _filter ? *_filter : AddrBookFilter();
2874 ForEachAddrBookEntry([&result, &filter](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) {
2875 // Filter by change
2876 if (filter.ignore_change && is_change) return;
2877 // Filter by label
2878 if (filter.m_op_label && *filter.m_op_label != label) return;
2879 // All good
2880 result.emplace_back(dest);
2881 });
2882 return result;
2883 }
2884
2885 std::set<std::string> CWallet::ListAddrBookLabels(const std::optional<AddressPurpose> purpose) const
2886 {
2887 AssertLockHeld(cs_wallet);
2888 std::set<std::string> label_set;
2889 ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label,
2890 bool _is_change, const std::optional<AddressPurpose>& _purpose) {
2891 if (_is_change) return;
2892 if (!purpose || purpose == _purpose) {
2893 label_set.insert(_label);
2894 }
2895 });
2896 return label_set;
2897 }
2898
2899 util::Result<CTxDestination> ReserveDestination::GetReservedDestination(bool internal)
2900 {
2901 m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
2902 if (!m_spk_man) {
2903 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2904 }
2905
2906 if (nIndex == -1) {
2907 CKeyPool keypool;
2908 int64_t index;
2909 auto op_address = m_spk_man->GetReservedDestination(type, internal, index, keypool);
2910 if (!op_address) return op_address;
2911 nIndex = index;
2912 address = *op_address;
2913 fInternal = keypool.fInternal;
2914 }
2915 return address;
2916 }
2917
2918 void ReserveDestination::KeepDestination()
2919 {
2920 if (nIndex != -1) {
2921 m_spk_man->KeepDestination(nIndex, type);
2922 }
2923 nIndex = -1;
2924 address = CNoDestination();
2925 }
2926
2927 void ReserveDestination::ReturnDestination()
2928 {
2929 if (nIndex != -1) {
2930 m_spk_man->ReturnDestination(nIndex, fInternal, address);
2931 }
2932 nIndex = -1;
2933 address = CNoDestination();
2934 }
2935
2936 util::Result<void> CWallet::DisplayAddress(const CTxDestination& dest)
2937 {
2938 CScript scriptPubKey = GetScriptForDestination(dest);
2939 for (const auto& spk_man : GetScriptPubKeyMans(scriptPubKey)) {
2940 auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan *>(spk_man);
2941 if (signer_spk_man == nullptr) {
2942 continue;
2943 }
2944 ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
2945 return signer_spk_man->DisplayAddress(dest, signer);
2946 }
2947 return util::Error{_("There is no ScriptPubKeyManager for this address")};
2948 }
2949
2950 bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
2951 {
2952 AssertLockHeld(cs_wallet);
2953 setLockedCoins.insert(output);
2954 if (batch) {
2955 return batch->WriteLockedUTXO(output);
2956 }
2957 return true;
2958 }
2959
2960 bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
2961 {
2962 AssertLockHeld(cs_wallet);
2963 bool was_locked = setLockedCoins.erase(output);
2964 if (batch && was_locked) {
2965 return batch->EraseLockedUTXO(output);
2966 }
2967 return true;
2968 }
2969
2970 bool CWallet::UnlockAllCoins()
2971 {
2972 AssertLockHeld(cs_wallet);
2973 bool success = true;
2974 WalletBatch batch(GetDatabase());
2975 for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2976 success &= batch.EraseLockedUTXO(*it);
2977 }
2978 setLockedCoins.clear();
2979 return success;
2980 }
2981
2982 bool CWallet::IsLockedCoin(const COutPoint& output) const
2983 {
2984 AssertLockHeld(cs_wallet);
2985 return setLockedCoins.count(output) > 0;
2986 }
2987
2988 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2989 {
2990 AssertLockHeld(cs_wallet);
2991 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2992 it != setLockedCoins.end(); it++) {
2993 COutPoint outpt = (*it);
2994 vOutpts.push_back(outpt);
2995 }
2996 }
2997
2998 /** @} */ // end of Actions
2999
3000 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
3001 AssertLockHeld(cs_wallet);
3002 mapKeyBirth.clear();
3003
3004 // map in which we'll infer heights of other keys
3005 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
3006 TxStateConfirmed max_confirm{uint256{}, /*height=*/-1, /*index=*/-1};
3007 max_confirm.confirmed_block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
3008 CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.confirmed_block_height, FoundBlock().hash(max_confirm.confirmed_block_hash)));
3009
3010 {
3011 LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
3012 assert(spk_man != nullptr);
3013 LOCK(spk_man->cs_KeyStore);
3014
3015 // get birth times for keys with metadata
3016 for (const auto& entry : spk_man->mapKeyMetadata) {
3017 if (entry.second.nCreateTime) {
3018 mapKeyBirth[entry.first] = entry.second.nCreateTime;
3019 }
3020 }
3021
3022 // Prepare to infer birth heights for keys without metadata
3023 for (const CKeyID &keyid : spk_man->GetKeys()) {
3024 if (mapKeyBirth.count(keyid) == 0)
3025 mapKeyFirstBlock[keyid] = &max_confirm;
3026 }
3027
3028 // if there are no such keys, we're done
3029 if (mapKeyFirstBlock.empty())
3030 return;
3031
3032 // find first block that affects those keys, if there are any left
3033 for (const auto& entry : mapWallet) {
3034 // iterate over all wallet transactions...
3035 const CWalletTx &wtx = entry.second;
3036 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3037 // ... which are already in a block
3038 for (const CTxOut &txout : wtx.tx->vout) {
3039 // iterate over all their outputs
3040 for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
3041 // ... and all their affected keys
3042 auto rit = mapKeyFirstBlock.find(keyid);
3043 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
3044 rit->second = conf;
3045 }
3046 }
3047 }
3048 }
3049 }
3050 }
3051
3052 // Extract block timestamps for those keys
3053 for (const auto& entry : mapKeyFirstBlock) {
3054 int64_t block_time;
3055 CHECK_NONFATAL(chain().findBlock(entry.second->confirmed_block_hash, FoundBlock().time(block_time)));
3056 mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
3057 }
3058 }
3059
3060 /**
3061 * Compute smart timestamp for a transaction being added to the wallet.
3062 *
3063 * Logic:
3064 * - If sending a transaction, assign its timestamp to the current time.
3065 * - If receiving a transaction outside a block, assign its timestamp to the
3066 * current time.
3067 * - If receiving a transaction during a rescanning process, assign all its
3068 * (not already known) transactions' timestamps to the block time.
3069 * - If receiving a block with a future timestamp, assign all its (not already
3070 * known) transactions' timestamps to the current time.
3071 * - If receiving a block with a past timestamp, before the most recent known
3072 * transaction (that we care about), assign all its (not already known)
3073 * transactions' timestamps to the same timestamp as that most-recent-known
3074 * transaction.
3075 * - If receiving a block with a past timestamp, but after the most recent known
3076 * transaction, assign all its (not already known) transactions' timestamps to
3077 * the block time.
3078 *
3079 * For more information see CWalletTx::nTimeSmart,
3080 * https://limenkatalk.org/?topic=54527, or
3081 * https://github.com/limenka/limenka/pull/1393.
3082 */
3083 unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
3084 {
3085 std::optional<uint256> block_hash;
3086 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3087 block_hash = conf->confirmed_block_hash;
3088 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
3089 block_hash = conf->conflicting_block_hash;
3090 }
3091
3092 unsigned int nTimeSmart = wtx.nTimeReceived;
3093 if (block_hash) {
3094 int64_t blocktime;
3095 int64_t block_max_time;
3096 if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) {
3097 if (rescanning_old_block) {
3098 nTimeSmart = block_max_time;
3099 } else {
3100 int64_t latestNow = wtx.nTimeReceived;
3101 int64_t latestEntry = 0;
3102
3103 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
3104 int64_t latestTolerated = latestNow + 300;
3105 const TxItems& txOrdered = wtxOrdered;
3106 for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
3107 CWalletTx* const pwtx = it->second;
3108 if (pwtx == &wtx) {
3109 continue;
3110 }
3111 int64_t nSmartTime;
3112 nSmartTime = pwtx->nTimeSmart;
3113 if (!nSmartTime) {
3114 nSmartTime = pwtx->nTimeReceived;
3115 }
3116 if (nSmartTime <= latestTolerated) {
3117 latestEntry = nSmartTime;
3118 if (nSmartTime > latestNow) {
3119 latestNow = nSmartTime;
3120 }
3121 break;
3122 }
3123 }
3124
3125 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
3126 }
3127 } else {
3128 WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString());
3129 }
3130 }
3131 return nTimeSmart;
3132 }
3133
3134 bool CWallet::SetAddressPreviouslySpent(WalletBatch& batch, const CTxDestination& dest, bool used)
3135 {
3136 if (std::get_if<CNoDestination>(&dest))
3137 return false;
3138
3139 if (!used) {
3140 if (auto* data{common::FindKey(m_address_book, dest)}) data->previously_spent = false;
3141 return batch.WriteAddressPreviouslySpent(dest, false);
3142 }
3143
3144 LoadAddressPreviouslySpent(dest);
3145 return batch.WriteAddressPreviouslySpent(dest, true);
3146 }
3147
3148 void CWallet::LoadAddressPreviouslySpent(const CTxDestination& dest)
3149 {
3150 m_address_book[dest].previously_spent = true;
3151 }
3152
3153 void CWallet::LoadAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& request)
3154 {
3155 m_address_book[dest].receive_requests[id] = request;
3156 }
3157
3158 bool CWallet::IsAddressPreviouslySpent(const CTxDestination& dest) const
3159 {
3160 if (auto* data{common::FindKey(m_address_book, dest)}) return data->previously_spent;
3161 return false;
3162 }
3163
3164 std::vector<std::string> CWallet::GetAddressReceiveRequests() const
3165 {
3166 std::vector<std::string> values;
3167 for (const auto& [dest, entry] : m_address_book) {
3168 for (const auto& [id, request] : entry.receive_requests) {
3169 values.emplace_back(request);
3170 }
3171 }
3172 return values;
3173 }
3174
3175 bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
3176 {
3177 if (!batch.WriteAddressReceiveRequest(dest, id, value)) return false;
3178 m_address_book[dest].receive_requests[id] = value;
3179 return true;
3180 }
3181
3182 bool CWallet::EraseAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id)
3183 {
3184 if (!batch.EraseAddressReceiveRequest(dest, id)) return false;
3185 m_address_book[dest].receive_requests.erase(id);
3186 return true;
3187 }
3188
3189 static util::Result<fs::path> GetWalletPath(const std::string& name)
3190 {
3191 // Do some checking on wallet path. It should be either a:
3192 //
3193 // 1. Path where a directory can be created.
3194 // 2. Path to an existing directory.
3195 // 3. Path to a symlink to a directory.
3196 // 4. For backwards compatibility, the name of a data file in -walletdir.
3197 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
3198 fs::file_type path_type = fs::symlink_status(wallet_path).type();
3199 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
3200 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
3201 // Windows cross compile does not detect symlinks, so we need to explicitly check
3202 // whether a "regular file" is actually a symlink.
3203 (path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name) && !IsSymlink(wallet_path)))) {
3204 return util::Error{Untranslated(strprintf(
3205 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
3206 "database/log.?????????? files can be stored, a location where such a directory could be created, "
3207 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
3208 name, fs::quoted(fs::PathToString(GetWalletDir()))))};
3209 }
3210 return wallet_path;
3211 }
3212
3213 std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
3214 {
3215 const auto& wallet_path = GetWalletPath(name);
3216 if (!wallet_path) {
3217 error_string = util::ErrorString(wallet_path);
3218 status = DatabaseStatus::FAILED_BAD_PATH;
3219 return nullptr;
3220 }
3221 return MakeDatabase(*wallet_path, options, status, error_string);
3222 }
3223
3224 std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
3225 {
3226 interfaces::Chain* chain = context.chain;
3227 ArgsManager& args = *Assert(context.args);
3228 const std::string& walletFile = database->Filename();
3229
3230 const auto start{SteadyClock::now()};
3231 // TODO: Can't use std::make_shared because we need a custom deleter but
3232 // should be possible to use std::allocate_shared.
3233 std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3234 walletInstance->m_keypool_size = std::max(args.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{1});
3235 walletInstance->m_notify_tx_changed_scripts = args.GetArgs("-walletnotify");
3236
3237 // Load wallet
3238 bool rescan_required = false;
3239 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
3240 if (nLoadWalletRet != DBErrors::LOAD_OK) {
3241 if (nLoadWalletRet == DBErrors::CORRUPT) {
3242 error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
3243 return nullptr;
3244 }
3245 else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
3246 {
3247 warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
3248 " or address metadata may be missing or incorrect."),
3249 walletFile));
3250 }
3251 else if (nLoadWalletRet == DBErrors::TOO_NEW) {
3252 error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, CLIENT_NAME);
3253 return nullptr;
3254 }
3255 else if (nLoadWalletRet == DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED) {
3256 error = strprintf(_("Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
3257 return nullptr;
3258 }
3259 else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
3260 {
3261 error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
3262 return nullptr;
3263 } else if (nLoadWalletRet == DBErrors::NEED_RESCAN) {
3264 warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
3265 " Rescanning wallet."), walletFile));
3266 rescan_required = true;
3267 } else if (nLoadWalletRet == DBErrors::UNKNOWN_DESCRIPTOR) {
3268 error = strprintf(_("Unrecognized descriptor found. Loading wallet %s\n\n"
3269 "The wallet might have been created on a newer version.\n"
3270 "Please try running the latest software version.\n"), walletFile);
3271 return nullptr;
3272 } else if (nLoadWalletRet == DBErrors::UNEXPECTED_LEGACY_ENTRY) {
3273 error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
3274 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3275 return nullptr;
3276 } else {
3277 error = strprintf(_("Error loading %s"), walletFile);
3278 return nullptr;
3279 }
3280 }
3281
3282 // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3283 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3284 !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
3285 !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
3286 if (fFirstRun)
3287 {
3288 LOCK(walletInstance->cs_wallet);
3289
3290 // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
3291 walletInstance->SetMinVersion(FEATURE_LATEST);
3292
3293 walletInstance->InitWalletFlags(wallet_creation_flags);
3294
3295 // Only create LegacyScriptPubKeyMan when not descriptor wallet
3296 if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3297 walletInstance->SetupLegacyScriptPubKeyMan();
3298 }
3299
3300 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
3301 if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3302 walletInstance->SetupDescriptorScriptPubKeyMans();
3303 // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
3304 } else {
3305 // Legacy wallets need SetupGeneration here.
3306 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3307 if (!spk_man->SetupGeneration()) {
3308 error = _("Unable to generate initial keys");
3309 return nullptr;
3310 }
3311 }
3312 }
3313 }
3314
3315 if (chain) {
3316 std::optional<int> tip_height = chain->getHeight();
3317 if (tip_height) {
3318 walletInstance->SetLastBlockProcessed(*tip_height, chain->getBlockHash(*tip_height));
3319 }
3320 }
3321 } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
3322 // Make it impossible to disable private keys after creation
3323 error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
3324 return nullptr;
3325 } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3326 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3327 if (spk_man->HavePrivateKeys()) {
3328 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3329 break;
3330 }
3331 }
3332 }
3333
3334 if (!args.GetArg("-addresstype", "").empty()) {
3335 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-addresstype", ""));
3336 if (!parsed) {
3337 error = strprintf(_("Unknown address type '%s'"), args.GetArg("-addresstype", ""));
3338 return nullptr;
3339 }
3340 walletInstance->m_default_address_type = parsed.value();
3341 }
3342
3343 if (!args.GetArg("-changetype", "").empty()) {
3344 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-changetype", ""));
3345 if (!parsed) {
3346 error = strprintf(_("Unknown change type '%s'"), args.GetArg("-changetype", ""));
3347 return nullptr;
3348 }
3349 walletInstance->m_default_change_type = parsed.value();
3350 }
3351
3352 if (args.IsArgSet("-mintxfee")) {
3353 std::optional<CAmount> min_tx_fee = ParseMoney(args.GetArg("-mintxfee", ""));
3354 if (!min_tx_fee) {
3355 error = AmountErrMsg("mintxfee", args.GetArg("-mintxfee", ""));
3356 return nullptr;
3357 } else if (min_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3358 warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
3359 _("This is the minimum transaction fee you pay on every transaction."));
3360 }
3361
3362 walletInstance->m_min_fee = CFeeRate{min_tx_fee.value()};
3363 }
3364
3365 if (args.IsArgSet("-maxapsfee")) {
3366 const std::string max_aps_fee{args.GetArg("-maxapsfee", "")};
3367 if (max_aps_fee == "-1") {
3368 walletInstance->m_max_aps_fee = -1;
3369 } else if (std::optional<CAmount> max_fee = ParseMoney(max_aps_fee)) {
3370 if (max_fee.value() > HIGH_APS_FEE) {
3371 warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
3372 _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3373 }
3374 walletInstance->m_max_aps_fee = max_fee.value();
3375 } else {
3376 error = AmountErrMsg("maxapsfee", max_aps_fee);
3377 return nullptr;
3378 }
3379 }
3380
3381 if (args.IsArgSet("-fallbackfee")) {
3382 std::optional<CAmount> fallback_fee = ParseMoney(args.GetArg("-fallbackfee", ""));
3383 if (!fallback_fee) {
3384 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-fallbackfee", args.GetArg("-fallbackfee", ""));
3385 return nullptr;
3386 } else if (fallback_fee.value() > HIGH_TX_FEE_PER_KB) {
3387 warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
3388 _("This is the transaction fee you may pay when fee estimates are not available."));
3389 }
3390 walletInstance->m_fallback_fee = CFeeRate{fallback_fee.value()};
3391 }
3392
3393 // Disable fallback fee in case value was set to 0, enable if non-null value
3394 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
3395
3396 if (args.IsArgSet("-discardfee")) {
3397 std::optional<CAmount> discard_fee = ParseMoney(args.GetArg("-discardfee", ""));
3398 if (!discard_fee) {
3399 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-discardfee", args.GetArg("-discardfee", ""));
3400 return nullptr;
3401 } else if (discard_fee.value() > HIGH_TX_FEE_PER_KB) {
3402 warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
3403 _("This is the transaction fee you may discard if change is smaller than dust at this level"));
3404 }
3405 walletInstance->m_discard_rate = CFeeRate{discard_fee.value()};
3406 }
3407
3408 if (args.IsArgSet("-paytxfee")) {
3409 std::optional<CAmount> pay_tx_fee = ParseMoney(args.GetArg("-paytxfee", ""));
3410 if (!pay_tx_fee) {
3411 error = AmountErrMsg("paytxfee", args.GetArg("-paytxfee", ""));
3412 return nullptr;
3413 } else if (pay_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3414 warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
3415 _("This is the transaction fee you will pay if you send a transaction."));
3416 }
3417
3418 walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000};
3419
3420 if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
3421 error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3422 "-paytxfee", args.GetArg("-paytxfee", ""), chain->relayMinFee().ToString());
3423 return nullptr;
3424 }
3425 }
3426
3427 if (args.IsArgSet("-maxtxfee")) {
3428 std::optional<CAmount> max_fee = ParseMoney(args.GetArg("-maxtxfee", ""));
3429 if (!max_fee) {
3430 error = AmountErrMsg("maxtxfee", args.GetArg("-maxtxfee", ""));
3431 return nullptr;
3432 } else if (max_fee.value() > HIGH_MAX_TX_FEE) {
3433 warnings.push_back(strprintf(_("%s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee"));
3434 }
3435
3436 if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) {
3437 error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3438 "-maxtxfee", args.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
3439 return nullptr;
3440 }
3441
3442 walletInstance->m_default_max_tx_fee = max_fee.value();
3443 }
3444
3445 if (args.IsArgSet("-consolidatefeerate")) {
3446 if (std::optional<CAmount> consolidate_feerate = ParseMoney(args.GetArg("-consolidatefeerate", ""))) {
3447 walletInstance->m_consolidate_feerate = CFeeRate(*consolidate_feerate);
3448 } else {
3449 error = AmountErrMsg("consolidatefeerate", args.GetArg("-consolidatefeerate", ""));
3450 return nullptr;
3451 }
3452 }
3453
3454 if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
3455 warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
3456 _("The wallet will avoid paying less than the minimum relay fee."));
3457 }
3458
3459 walletInstance->m_confirm_target = args.GetIntArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
3460 walletInstance->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
3461 walletInstance->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
3462
3463 walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3464
3465 // Try to top up keypool. No-op if the wallet is locked.
3466 walletInstance->TopUpKeyPool();
3467
3468 // Cache the first key time
3469 std::optional<int64_t> time_first_key;
3470 for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3471 int64_t time = spk_man->GetTimeFirstKey();
3472 if (!time_first_key || time < *time_first_key) time_first_key = time;
3473 }
3474 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3475
3476 if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
3477 walletInstance->DisconnectChainNotifications();
3478 return nullptr;
3479 }
3480
3481 {
3482 LOCK(walletInstance->cs_wallet);
3483 walletInstance->SetBroadcastTransactions(args.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
3484 walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3485 walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3486 walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3487 }
3488
3489 return walletInstance;
3490 }
3491
3492 bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
3493 {
3494 LOCK(walletInstance->cs_wallet);
3495 // allow setting the chain if it hasn't been set already but prevent changing it
3496 assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
3497 walletInstance->m_chain = &chain;
3498
3499 // Unless allowed, ensure wallet files are not reused across chains:
3500 if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
3501 WalletBatch batch(walletInstance->GetDatabase());
3502 CBlockLocator locator;
3503 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
3504 // Wallet is assumed to be from another chain, if genesis block in the active
3505 // chain differs from the genesis block known to the wallet.
3506 if (chain.getBlockHash(0) != locator.vHave.back()) {
3507 error = Untranslated("Wallet files should not be reused across chains. Restart limenkad with -walletcrosschain to override.");
3508 return false;
3509 }
3510 }
3511 }
3512
3513 // Register wallet with validationinterface. It's done before rescan to avoid
3514 // missing block connections during the rescan.
3515 // Because of the wallet lock being held, block connection notifications are going to
3516 // be pending on the validation-side until lock release. Blocks that are connected while the
3517 // rescan is ongoing will not be processed in the rescan but with the block connected notifications,
3518 // so the wallet will only be completeley synced after the notifications delivery.
3519 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3520
3521 // If rescan_required = true, rescan_height remains equal to 0
3522 int rescan_height = 0;
3523 if (!rescan_required)
3524 {
3525 WalletBatch batch(walletInstance->GetDatabase());
3526 CBlockLocator locator;
3527 if (batch.ReadBestBlock(locator)) {
3528 if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
3529 rescan_height = *fork_height;
3530 }
3531 }
3532 }
3533
3534 const std::optional<int> tip_height = chain.getHeight();
3535 if (tip_height) {
3536 walletInstance->SetLastBlockProcessedInMem(*tip_height, chain.getBlockHash(*tip_height));
3537 } else {
3538 walletInstance->SetLastBlockProcessedInMem(-1, uint256());
3539 }
3540
3541 if (tip_height && *tip_height != rescan_height)
3542 {
3543 // No need to read and scan block if block was created before
3544 // our wallet birthday (as adjusted for block time variability)
3545 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3546 if (time_first_key) {
3547 FoundBlock found = FoundBlock().height(rescan_height);
3548 chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, found);
3549 if (!found.found) {
3550 // We were unable to find a block that had a time more recent than our earliest timestamp
3551 // or a height higher than the wallet was synced to, indicating that the wallet is newer than the
3552 // current chain tip. Skip rescanning in this case.
3553 rescan_height = *tip_height;
3554 }
3555 }
3556
3557 // Technically we could execute the code below in any case, but performing the
3558 // `while` loop below can make startup very slow, so only check blocks on disk
3559 // if necessary.
3560 if (chain.havePruned() || chain.hasAssumedValidChain()) {
3561 int block_height = *tip_height;
3562 while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3563 --block_height;
3564 }
3565
3566 if (rescan_height != block_height) {
3567 // We can't rescan beyond blocks we don't have data for, stop and throw an error.
3568 // This might happen if a user uses an old wallet within a pruned node
3569 // or if they ran -disablewallet for a longer time, then decided to re-enable
3570 // Exit early and print an error.
3571 // It also may happen if an assumed-valid chain is in use and therefore not
3572 // all block data is available.
3573 // If a block is pruned after this check, we will load the wallet,
3574 // but fail the rescan with a generic error.
3575
3576 error = chain.havePruned() ?
3577 _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of a pruned node)") :
3578 strprintf(_(
3579 "Error loading wallet. Wallet requires blocks to be downloaded, "
3580 "and software does not currently support loading wallets while "
3581 "blocks are being downloaded out of order when using assumeutxo "
3582 "snapshots. Wallet should be able to load successfully after "
3583 "node sync reaches height %s"), block_height);
3584 return false;
3585 }
3586 }
3587
3588 chain.initMessage(_("Rescanning…"));
3589 walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3590
3591 {
3592 WalletRescanReserver reserver(*walletInstance);
3593 if (!reserver.reserve()) {
3594 error = _("Failed to acquire rescan reserver during wallet initialization");
3595 return false;
3596 }
3597 ScanResult scan_res = walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true);
3598 if (ScanResult::SUCCESS != scan_res.status) {
3599 error = _("Failed to rescan the wallet during initialization");
3600 return false;
3601 }
3602 // Set and update the best block record
3603 // Set last block scanned as the last block processed as it may be different in case of a reorg.
3604 // Also save the best block locator because rescanning only updates it intermittently.
3605 walletInstance->SetLastBlockProcessed(*scan_res.last_scanned_height, scan_res.last_scanned_block);
3606 }
3607 }
3608
3609 return true;
3610 }
3611
3612 const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
3613 {
3614 const auto& address_book_it = m_address_book.find(dest);
3615 if (address_book_it == m_address_book.end()) return nullptr;
3616 if ((!allow_change) && address_book_it->second.IsChange()) {
3617 return nullptr;
3618 }
3619 return &address_book_it->second;
3620 }
3621
3622 bool CWallet::UpgradeWallet(int version, bilingual_str& error)
3623 {
3624 int prev_version = GetVersion();
3625 if (version == 0) {
3626 WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
3627 version = FEATURE_LATEST;
3628 } else {
3629 WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
3630 }
3631 if (version < prev_version) {
3632 error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3633 return false;
3634 }
3635
3636 LOCK(cs_wallet);
3637
3638 // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
3639 if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && version < FEATURE_PRE_SPLIT_KEYPOOL) {
3640 error = strprintf(_("Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified."), prev_version, version, FEATURE_PRE_SPLIT_KEYPOOL);
3641 return false;
3642 }
3643
3644 // Permanently upgrade to the version
3645 SetMinVersion(GetClosestWalletFeature(version));
3646
3647 for (auto spk_man : GetActiveScriptPubKeyMans()) {
3648 if (!spk_man->Upgrade(prev_version, version, error)) {
3649 return false;
3650 }
3651 }
3652 return true;
3653 }
3654
3655 void CWallet::postInitProcess()
3656 {
3657 // Add wallet transactions that aren't already in a block to mempool
3658 // Do this here as mempool requires genesis block to be loaded
3659 ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
3660
3661 // Update wallet transactions with current mempool transactions.
3662 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
3663 }
3664
3665 bool CWallet::BackupWallet(const std::string& strDest) const
3666 {
3667 WITH_LOCK(cs_wallet, WriteBestBlock());
3668 return GetDatabase().Backup(strDest);
3669 }
3670
3671 CKeyPool::CKeyPool()
3672 {
3673 nTime = GetTime();
3674 fInternal = false;
3675 m_pre_split = false;
3676 }
3677
3678 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
3679 {
3680 nTime = GetTime();
3681 vchPubKey = vchPubKeyIn;
3682 fInternal = internalIn;
3683 m_pre_split = false;
3684 }
3685
3686 int CWallet::GetTxDepthInMainChain(const CWalletTx& wtx) const
3687 {
3688 AssertLockHeld(cs_wallet);
3689 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3690 assert(conf->confirmed_block_height >= 0);
3691 return GetLastBlockHeight() - conf->confirmed_block_height + 1;
3692 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
3693 assert(conf->conflicting_block_height >= 0);
3694 return -1 * (GetLastBlockHeight() - conf->conflicting_block_height + 1);
3695 } else {
3696 return 0;
3697 }
3698 }
3699
3700 int CWallet::GetTxBlocksToMaturity(const CWalletTx& wtx) const
3701 {
3702 AssertLockHeld(cs_wallet);
3703
3704 if (!wtx.IsCoinBase()) {
3705 return 0;
3706 }
3707 int chain_depth = GetTxDepthInMainChain(wtx);
3708 assert(chain_depth >= 0); // coinbase tx should not be conflicted
3709 return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
3710 }
3711
3712 bool CWallet::IsTxImmatureCoinBase(const CWalletTx& wtx) const
3713 {
3714 AssertLockHeld(cs_wallet);
3715
3716 // note GetBlocksToMaturity is 0 for non-coinbase tx
3717 return GetTxBlocksToMaturity(wtx) > 0;
3718 }
3719
3720 bool CWallet::IsTxAssumed(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
3721 {
3722 AssertLockHeld(cs_wallet);
3723 if (GetBackgroundValidationHeight() == -1) return false;
3724 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3725 int height{conf->confirmed_block_height};
3726 return height > GetBackgroundValidationHeight();
3727 }
3728 return false;
3729 }
3730
3731
3732 bool CWallet::IsCrypted() const
3733 {
3734 return HasEncryptionKeys();
3735 }
3736
3737 bool CWallet::IsLocked() const
3738 {
3739 if (!IsCrypted()) {
3740 return false;
3741 }
3742 LOCK(cs_wallet);
3743 return vMasterKey.empty();
3744 }
3745
3746 bool CWallet::Lock()
3747 {
3748 if (!IsCrypted())
3749 return false;
3750
3751 {
3752 LOCK2(m_relock_mutex, cs_wallet);
3753 if (!vMasterKey.empty()) {
3754 memory_cleanse(vMasterKey.data(), vMasterKey.size() * sizeof(decltype(vMasterKey)::value_type));
3755 vMasterKey.clear();
3756 }
3757 }
3758
3759 NotifyStatusChanged(this);
3760 return true;
3761 }
3762
3763 bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn)
3764 {
3765 {
3766 LOCK(cs_wallet);
3767 for (const auto& spk_man_pair : m_spk_managers) {
3768 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3769 return false;
3770 }
3771 }
3772 vMasterKey = vMasterKeyIn;
3773 }
3774 NotifyStatusChanged(this);
3775 return true;
3776 }
3777
3778 std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
3779 {
3780 std::set<ScriptPubKeyMan*> spk_mans;
3781 for (bool internal : {false, true}) {
3782 for (OutputType t : OUTPUT_TYPES) {
3783 auto spk_man = GetScriptPubKeyMan(t, internal);
3784 if (spk_man) {
3785 spk_mans.insert(spk_man);
3786 }
3787 }
3788 }
3789 return spk_mans;
3790 }
3791
3792 bool CWallet::IsActiveScriptPubKeyMan(const ScriptPubKeyMan& spkm) const
3793 {
3794 for (const auto& [_, ext_spkm] : m_external_spk_managers) {
3795 if (ext_spkm == &spkm) return true;
3796 }
3797 for (const auto& [_, int_spkm] : m_internal_spk_managers) {
3798 if (int_spkm == &spkm) return true;
3799 }
3800 return false;
3801 }
3802
3803 std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
3804 {
3805 std::set<ScriptPubKeyMan*> spk_mans;
3806 for (const auto& spk_man_pair : m_spk_managers) {
3807 spk_mans.insert(spk_man_pair.second.get());
3808 }
3809 return spk_mans;
3810 }
3811
3812 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
3813 {
3814 const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
3815 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3816 if (it == spk_managers.end()) {
3817 return nullptr;
3818 }
3819 return it->second;
3820 }
3821
3822 std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script) const
3823 {
3824 std::set<ScriptPubKeyMan*> spk_mans;
3825
3826 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3827 const auto& it = m_cached_spks.find(script);
3828 if (it != m_cached_spks.end()) {
3829 spk_mans.insert(it->second.begin(), it->second.end());
3830 }
3831 SignatureData sigdata;
3832 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3833
3834 // Legacy wallet
3835 LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan();
3836 if (spkm && spkm->CanProvide(script, sigdata)) spk_mans.insert(spkm);
3837
3838 return spk_mans;
3839 }
3840
3841 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
3842 {
3843 if (m_spk_managers.count(id) > 0) {
3844 return m_spk_managers.at(id).get();
3845 }
3846 return nullptr;
3847 }
3848
3849 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3850 {
3851 SignatureData sigdata;
3852 return GetSolvingProvider(script, sigdata);
3853 }
3854
3855 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3856 {
3857 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3858 const auto& it = m_cached_spks.find(script);
3859 if (it != m_cached_spks.end()) {
3860 // All spkms for a given script must already be able to make a SigningProvider for the script, so just return the first one.
3861 Assume(it->second.at(0)->CanProvide(script, sigdata));
3862 return it->second.at(0)->GetSolvingProvider(script);
3863 }
3864
3865 // Legacy wallet
3866 LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan();
3867 if (spkm && spkm->CanProvide(script, sigdata)) return spkm->GetSolvingProvider(script);
3868
3869 return nullptr;
3870 }
3871
3872 std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const
3873 {
3874 std::vector<WalletDescriptor> descs;
3875 for (const auto spk_man: GetScriptPubKeyMans(script)) {
3876 if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3877 LOCK(desc_spk_man->cs_desc_man);
3878 descs.push_back(desc_spk_man->GetWalletDescriptor());
3879 }
3880 }
3881 return descs;
3882 }
3883
3884 LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
3885 {
3886 if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3887 return nullptr;
3888 }
3889 // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
3890 // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
3891 auto it = m_internal_spk_managers.find(OutputType::LEGACY);
3892 if (it == m_internal_spk_managers.end()) return nullptr;
3893 return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
3894 }
3895
3896 LegacyDataSPKM* CWallet::GetLegacyDataSPKM() const
3897 {
3898 if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3899 return nullptr;
3900 }
3901 auto it = m_internal_spk_managers.find(OutputType::LEGACY);
3902 if (it == m_internal_spk_managers.end()) return nullptr;
3903 return dynamic_cast<LegacyDataSPKM*>(it->second);
3904 }
3905
3906 LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
3907 {
3908 SetupLegacyScriptPubKeyMan();
3909 return GetLegacyScriptPubKeyMan();
3910 }
3911
3912 void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man)
3913 {
3914 // Add spkm_man to m_spk_managers before calling any method
3915 // that might access it.
3916 const auto& spkm = m_spk_managers[id] = std::move(spkm_man);
3917
3918 // Update birth time if needed
3919 MaybeUpdateBirthTime(spkm->GetTimeFirstKey());
3920 }
3921
3922 LegacyDataSPKM* CWallet::GetOrCreateLegacyDataSPKM()
3923 {
3924 SetupLegacyScriptPubKeyMan();
3925 return GetLegacyDataSPKM();
3926 }
3927
3928 void CWallet::SetupLegacyScriptPubKeyMan()
3929 {
3930 if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3931 return;
3932 }
3933
3934 std::unique_ptr<ScriptPubKeyMan> spk_manager = m_database->Format() == "bdb_ro" ?
3935 std::make_unique<LegacyDataSPKM>(*this) :
3936 std::make_unique<LegacyScriptPubKeyMan>(*this, m_keypool_size);
3937
3938 for (const auto& type : LEGACY_OUTPUT_TYPES) {
3939 m_internal_spk_managers[type] = spk_manager.get();
3940 m_external_spk_managers[type] = spk_manager.get();
3941 }
3942 uint256 id = spk_manager->GetID();
3943 AddScriptPubKeyMan(id, std::move(spk_manager));
3944 }
3945
3946 bool CWallet::WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const
3947 {
3948 LOCK(cs_wallet);
3949 return cb(vMasterKey);
3950 }
3951
3952 bool CWallet::HasEncryptionKeys() const
3953 {
3954 return !mapMasterKeys.empty();
3955 }
3956
3957 bool CWallet::HaveCryptedKeys() const
3958 {
3959 for (const auto& spkm : GetAllScriptPubKeyMans()) {
3960 if (spkm->HaveCryptedKeys()) return true;
3961 }
3962 return false;
3963 }
3964
3965 void CWallet::ConnectScriptPubKeyManNotifiers()
3966 {
3967 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3968 spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3969 spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3970 spk_man->NotifyFirstKeyTimeChanged.connect(std::bind(&CWallet::MaybeUpdateBirthTime, this, std::placeholders::_2));
3971 }
3972 }
3973
3974 DescriptorScriptPubKeyMan& CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
3975 {
3976 DescriptorScriptPubKeyMan* spk_manager;
3977 if (IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
3978 spk_manager = new ExternalSignerScriptPubKeyMan(*this, desc, m_keypool_size);
3979 } else {
3980 spk_manager = new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size);
3981 }
3982 AddScriptPubKeyMan(id, std::unique_ptr<ScriptPubKeyMan>(spk_manager));
3983 return *spk_manager;
3984 }
3985
3986 DescriptorScriptPubKeyMan& CWallet::SetupDescriptorScriptPubKeyMan(WalletBatch& batch, const CExtKey& master_key, const OutputType& output_type, bool internal)
3987 {
3988 AssertLockHeld(cs_wallet);
3989 auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, m_keypool_size));
3990 if (IsCrypted()) {
3991 if (IsLocked()) {
3992 throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3993 }
3994 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3995 throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3996 }
3997 }
3998 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3999 DescriptorScriptPubKeyMan* out = spk_manager.get();
4000 uint256 id = spk_manager->GetID();
4001 AddScriptPubKeyMan(id, std::move(spk_manager));
4002 AddActiveScriptPubKeyManWithDb(batch, id, output_type, internal);
4003 return *out;
4004 }
4005
4006 void CWallet::SetupDescriptorScriptPubKeyMans(WalletBatch& batch, const CExtKey& master_key)
4007 {
4008 AssertLockHeld(cs_wallet);
4009 for (bool internal : {false, true}) {
4010 for (OutputType t : OUTPUT_TYPES) {
4011 SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
4012 }
4013 }
4014 SetupStealthKeys(batch, master_key);
4015 }
4016
4017 bool CWallet::SetupStealthKeys(WalletBatch& batch, const CExtKey& master_key)
4018 {
4019 AssertLockHeld(cs_wallet);
4020
4021 CExtKey view_ext, spend_ext;
4022 if (!master_key.Derive(view_ext, wallet::STEALTH_VIEW_PATH)) return false;
4023 if (!master_key.Derive(spend_ext, wallet::STEALTH_SPEND_PATH)) return false;
4024 const CKey& view = view_ext.key;
4025 const CKey& spend = spend_ext.key;
4026
4027 // Dedicated record; the wallet is unencrypted at setup, so the private
4028 // keys are stored plaintext (EncryptWallet re-encrypts them later).
4029 if (!batch.WriteStealthKeys(view.GetPubKey(), spend.GetPubKey(),
4030 view.GetPrivKey(), spend.GetPrivKey())) {
4031 return false;
4032 }
4033 return SetStealthKeyRecord(view.GetPubKey(), spend.GetPubKey(),
4034 view.GetPrivKey(), spend.GetPrivKey());
4035 }
4036
4037 bool CWallet::SetStealthKeyRecord(const CPubKey& view_pub, const CPubKey& spend_pub,
4038 const CPrivKey& view_priv, const CPrivKey& spend_priv)
4039 {
4040 AssertLockHeld(cs_wallet);
4041 m_stealth_view_pub = view_pub;
4042 m_stealth_spend_pub = spend_pub;
4043 m_stealth_view_priv = view_priv;
4044 m_stealth_spend_priv = spend_priv;
4045 m_stealth_keys_loaded = true;
4046 return true;
4047 }
4048
4049 bool CWallet::GetStealthKeys(CKey& view_secret, CKey& spend_secret) const
4050 {
4051 LOCK(cs_wallet);
4052 if (!m_stealth_keys_loaded) return false;
4053
4054 if (IsCrypted()) {
4055 if (IsLocked()) return false;
4056 return WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
4057 return DecryptKey(encryption_key, m_stealth_view_priv, m_stealth_view_pub, view_secret) &&
4058 DecryptKey(encryption_key, m_stealth_spend_priv, m_stealth_spend_pub, spend_secret);
4059 });
4060 }
4061 return view_secret.Load(m_stealth_view_priv, m_stealth_view_pub, /*fSkipCheck=*/true) &&
4062 spend_secret.Load(m_stealth_spend_priv, m_stealth_spend_pub, /*fSkipCheck=*/true);
4063 }
4064
4065 WitnessV4StealthAddress CWallet::GetStealthDestination() const
4066 {
4067 CKey view, spend;
4068 if (!GetStealthKeys(view, spend)) return {};
4069 return WitnessV4StealthAddress{view.GetPubKey(), spend.GetPubKey()};
4070 }
4071
4072 bool CWallet::RecoverStealthReceipts(const CTransactionRef& ptx)
4073 {
4074 AssertLockHeld(cs_wallet);
4075 const CTransaction& tx = *ptx;
4076
4077 const int kidx = GetCTKernelOutputIndex(tx);
4078 if (kidx == NO_CT_KERNEL_OUTPUT) return false;
4079 const auto kernel = ParseCTKernelOutput(tx.vout[kidx]);
4080 if (!kernel || !kernel->has_stealth) return false;
4081
4082 CKey view, spend;
4083 if (!GetStealthKeys(view, spend)) return false;
4084
4085 std::vector<wallet::CTReceipt> receipts;
4086 for (size_t o = 0; o < tx.vout.size(); ++o) {
4087 if (static_cast<int>(o) == kidx) continue;
4088 int witver;
4089 std::vector<uint8_t> witprog;
4090 if (!tx.vout[o].scriptPubKey.IsWitnessProgram(witver, witprog)) continue;
4091 if (witver != 4 || witprog.size() != WITNESS_V4_BPCT_SIZE) continue;
4092 const auto rec = wallet::RecoverStealthOutput(view, spend, kernel->E,
4093 kernel->enc_amount,
4094 kernel->enc_blind, witprog);
4095 if (!rec) continue;
4096
4097 // Prove the range for the recovered amount and store a spendable
4098 // receipt (fresh proof seed from the CSPRNG).
4099 FastRandomContext rng_fast;
4100 auto seed_bytes = rng_fast.randbytes(BP_SCALAR_SIZE);
4101 wallet::CTReceipt receipt;
4102 receipt.SetAmount(rec->first);
4103 receipt.blinding = rec->second;
4104 receipt.vout_index = static_cast<uint32_t>(o);
4105 receipt.seed.assign(seed_bytes.begin(), seed_bytes.end());
4106 BPCommitment check;
4107 if (!ProveBulletproof(rec->first, receipt.blinding, receipt.seed,
4108 check, receipt.proof)) {
4109 continue;
4110 }
4111 if (check != witprog) continue;
4112 receipts.push_back(std::move(receipt));
4113 WalletLogPrintf("Recovered stealth CT output %s:%d (%s)\n",
4114 tx.GetHash().ToString(), o, AttosatsToString(rec->first));
4115 }
4116 if (receipts.empty()) return false;
4117
4118 // Merge with any receipts already stored for this txid (own change
4119 // outputs persist alongside recovered stealth outputs).
4120 WalletBatch batch(GetDatabase());
4121 std::vector<wallet::CTReceipt> all;
4122 batch.ReadCTReceipts(tx.GetHash(), all); // absent -> all stays empty
4123 for (auto& rec : receipts) {
4124 const bool dup = std::any_of(all.begin(), all.end(), [&](const wallet::CTReceipt& e) {
4125 return e.vout_index == rec.vout_index;
4126 });
4127 if (!dup) all.push_back(std::move(rec));
4128 }
4129 return batch.WriteCTReceipts(tx.GetHash(), all);
4130 }
4131
4132 void CWallet::SetupOwnDescriptorScriptPubKeyMans(WalletBatch& batch)
4133 {
4134 AssertLockHeld(cs_wallet);
4135 assert(!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
4136 // Make a seed
4137 CKey seed_key = GenerateRandomKey();
4138 CPubKey seed = seed_key.GetPubKey();
4139 assert(seed_key.VerifyPubKey(seed));
4140
4141 // Get the extended key
4142 CExtKey master_key;
4143 master_key.SetSeed(seed_key);
4144
4145 SetupDescriptorScriptPubKeyMans(batch, master_key);
4146 }
4147
4148 void CWallet::SetupDescriptorScriptPubKeyMans()
4149 {
4150 AssertLockHeld(cs_wallet);
4151
4152 if (!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
4153 if (!RunWithinTxn(GetDatabase(), /*process_desc=*/"setup descriptors", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet){
4154 SetupOwnDescriptorScriptPubKeyMans(batch);
4155 return true;
4156 })) throw std::runtime_error("Error: cannot process db transaction for descriptors setup");
4157 } else {
4158 ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
4159
4160 // TODO: add account parameter
4161 int account = 0;
4162 UniValue signer_res = signer.GetDescriptors(account);
4163
4164 if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
4165
4166 WalletBatch batch(GetDatabase());
4167 if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors import");
4168
4169 for (bool internal : {false, true}) {
4170 const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
4171 if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
4172 for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
4173 const std::string& desc_str = desc_val.getValStr();
4174 FlatSigningProvider keys;
4175 std::string desc_error;
4176 auto descs = Parse(desc_str, keys, desc_error, false);
4177 if (descs.empty()) {
4178 throw std::runtime_error(std::string(__func__) + ": Invalid descriptor \"" + desc_str + "\" (" + desc_error + ")");
4179 }
4180 auto& desc = descs.at(0);
4181 if (!desc->GetOutputType()) {
4182 continue;
4183 }
4184 OutputType t = *desc->GetOutputType();
4185 auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, m_keypool_size));
4186 spk_manager->SetupDescriptor(batch, std::move(desc));
4187 uint256 id = spk_manager->GetID();
4188 AddScriptPubKeyMan(id, std::move(spk_manager));
4189 AddActiveScriptPubKeyManWithDb(batch, id, t, internal);
4190 }
4191 }
4192
4193 // Ensure imported descriptors are committed to disk
4194 if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors import");
4195 }
4196 }
4197
4198 void CWallet::AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
4199 {
4200 WalletBatch batch(GetDatabase());
4201 return AddActiveScriptPubKeyManWithDb(batch, id, type, internal);
4202 }
4203
4204 void CWallet::AddActiveScriptPubKeyManWithDb(WalletBatch& batch, uint256 id, OutputType type, bool internal)
4205 {
4206 if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
4207 throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
4208 }
4209 LoadActiveScriptPubKeyMan(id, type, internal);
4210 }
4211
4212 void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
4213 {
4214 // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
4215 // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
4216 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
4217
4218 WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
4219 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
4220 auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
4221 auto spk_man = m_spk_managers.at(id).get();
4222 spk_mans[type] = spk_man;
4223
4224 const auto it = spk_mans_other.find(type);
4225 if (it != spk_mans_other.end() && it->second == spk_man) {
4226 spk_mans_other.erase(type);
4227 }
4228
4229 NotifyCanGetAddressesChanged();
4230 }
4231
4232 void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
4233 {
4234 auto spk_man = GetScriptPubKeyMan(type, internal);
4235 if (spk_man != nullptr && spk_man->GetID() == id) {
4236 WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
4237 WalletBatch batch(GetDatabase());
4238 if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
4239 throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
4240 }
4241
4242 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
4243 spk_mans.erase(type);
4244 }
4245
4246 NotifyCanGetAddressesChanged();
4247 }
4248
4249 bool CWallet::IsLegacy() const
4250 {
4251 return !IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS);
4252 }
4253
4254 DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const
4255 {
4256 for (auto& spk_man_pair : m_spk_managers) {
4257 // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
4258 DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
4259 if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
4260 return spk_manager;
4261 }
4262 }
4263
4264 return nullptr;
4265 }
4266
4267 std::optional<bool> CWallet::IsInternalScriptPubKeyMan(ScriptPubKeyMan* spk_man) const
4268 {
4269 // Legacy script pubkey man can't be either external or internal
4270 if (IsLegacy()) {
4271 return std::nullopt;
4272 }
4273
4274 // only active ScriptPubKeyMan can be internal
4275 if (!GetActiveScriptPubKeyMans().count(spk_man)) {
4276 return std::nullopt;
4277 }
4278
4279 const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
4280 if (!desc_spk_man) {
4281 throw std::runtime_error(std::string(__func__) + ": unexpected ScriptPubKeyMan type.");
4282 }
4283
4284 LOCK(desc_spk_man->cs_desc_man);
4285 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
4286 assert(type.has_value());
4287
4288 return GetScriptPubKeyMan(*type, /* internal= */ true) == desc_spk_man;
4289 }
4290
4291 ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
4292 {
4293 AssertLockHeld(cs_wallet);
4294
4295 if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4296 WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
4297 return nullptr;
4298 }
4299
4300 auto spk_man = GetDescriptorScriptPubKeyMan(desc);
4301 if (spk_man) {
4302 WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
4303 spk_man->UpdateWalletDescriptor(desc);
4304 } else {
4305 auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size));
4306 spk_man = new_spk_man.get();
4307
4308 // Save the descriptor to memory
4309 uint256 id = new_spk_man->GetID();
4310 AddScriptPubKeyMan(id, std::move(new_spk_man));
4311 }
4312
4313 // Add the private keys to the descriptor
4314 for (const auto& entry : signing_provider.keys) {
4315 const CKey& key = entry.second;
4316 spk_man->AddDescriptorKey(key, key.GetPubKey());
4317 }
4318
4319 // Top up key pool, the manager will generate new scriptPubKeys internally
4320 if (!spk_man->TopUp()) {
4321 WalletLogPrintf("Could not top up scriptPubKeys\n");
4322 return nullptr;
4323 }
4324
4325 // Apply the label if necessary
4326 // Note: we disable labels for ranged descriptors
4327 if (!desc.descriptor->IsRange()) {
4328 auto script_pub_keys = spk_man->GetScriptPubKeys();
4329 if (script_pub_keys.empty()) {
4330 WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
4331 return nullptr;
4332 }
4333
4334 if (!internal) {
4335 for (const auto& script : script_pub_keys) {
4336 CTxDestination dest;
4337 if (ExtractDestination(script, dest)) {
4338 SetAddressBook(dest, label, AddressPurpose::RECEIVE);
4339 }
4340 }
4341 }
4342 }
4343
4344 // Save the descriptor to DB
4345 spk_man->WriteDescriptor();
4346
4347 return spk_man;
4348 }
4349
4350 bool CWallet::MigrateToSQLite(bilingual_str& error)
4351 {
4352 AssertLockHeld(cs_wallet);
4353
4354 WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
4355
4356 if (m_database->Format() == "sqlite") {
4357 error = _("Error: This wallet already uses SQLite");
4358 return false;
4359 }
4360
4361 // Get all of the records for DB type migration
4362 std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
4363 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
4364 std::vector<std::pair<SerializeData, SerializeData>> records;
4365 if (!cursor) {
4366 error = _("Error: Unable to begin reading all records in the database");
4367 return false;
4368 }
4369 DatabaseCursor::Status status = DatabaseCursor::Status::FAIL;
4370 while (true) {
4371 DataStream ss_key{};
4372 DataStream ss_value{};
4373 status = cursor->Next(ss_key, ss_value);
4374 if (status != DatabaseCursor::Status::MORE) {
4375 break;
4376 }
4377 SerializeData key(ss_key.begin(), ss_key.end());
4378 SerializeData value(ss_value.begin(), ss_value.end());
4379 records.emplace_back(key, value);
4380 }
4381 cursor.reset();
4382 batch.reset();
4383 if (status != DatabaseCursor::Status::DONE) {
4384 error = _("Error: Unable to read all records in the database");
4385 return false;
4386 }
4387
4388 // Close this database and delete the file
4389 fs::path db_path = fs::PathFromString(m_database->Filename());
4390 m_database->Close();
4391 fs::remove(db_path);
4392
4393 // Generate the path for the location of the migrated wallet
4394 // Wallets that are plain files rather than wallet directories will be migrated to be wallet directories.
4395 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(m_name));
4396
4397 // Make new DB
4398 DatabaseOptions opts;
4399 opts.require_create = true;
4400 opts.require_format = DatabaseFormat::SQLITE;
4401 DatabaseStatus db_status;
4402 std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
4403 assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
4404 m_database.reset();
4405 m_database = std::move(new_db);
4406
4407 // Write existing records into the new DB
4408 batch = m_database->MakeBatch();
4409 bool began = batch->TxnBegin();
4410 assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
4411 for (const auto& [key, value] : records) {
4412 if (!batch->Write(Span{key}, Span{value})) {
4413 batch->TxnAbort();
4414 m_database->Close();
4415 fs::remove(m_database->Filename());
4416 assert(false); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
4417 }
4418 }
4419 bool committed = batch->TxnCommit();
4420 assert(committed); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
4421 return true;
4422 }
4423
4424 std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& error) const
4425 {
4426 AssertLockHeld(cs_wallet);
4427
4428 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
4429 if (!Assume(legacy_spkm)) {
4430 // This shouldn't happen
4431 error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
4432 return std::nullopt;
4433 }
4434
4435 std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
4436 if (res == std::nullopt) {
4437 error = _("Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4438 return std::nullopt;
4439 }
4440 return res;
4441 }
4442
4443 util::Result<void> CWallet::ApplyMigrationData(WalletBatch& local_wallet_batch, MigrationData& data)
4444 {
4445 AssertLockHeld(cs_wallet);
4446
4447 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
4448 if (!Assume(legacy_spkm)) {
4449 // This shouldn't happen
4450 return util::Error{Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"))};
4451 }
4452
4453 // Note: when the legacy wallet has no spendable scripts, it must be empty at the end of the process.
4454 bool has_spendable_material = !data.desc_spkms.empty() || data.master_key.key.IsValid();
4455
4456 // Get all invalid or non-watched scripts that will not be migrated
4457 std::set<CTxDestination> not_migrated_dests;
4458 for (const auto& script : legacy_spkm->GetNotMineScriptPubKeys()) {
4459 CTxDestination dest;
4460 if (ExtractDestination(script, dest)) not_migrated_dests.emplace(dest);
4461 }
4462
4463 // When the legacy wallet has no spendable scripts, the main wallet will be empty, leaving its script cache empty as well.
4464 // The watch-only and/or solvable wallet(s) will contain the scripts in their respective caches.
4465 if (!data.desc_spkms.empty()) Assume(!m_cached_spks.empty());
4466 if (!data.watch_descs.empty()) Assume(!data.watchonly_wallet->m_cached_spks.empty());
4467 if (!data.solvable_descs.empty()) Assume(!data.solvable_wallet->m_cached_spks.empty());
4468
4469 for (auto& desc_spkm : data.desc_spkms) {
4470 if (m_spk_managers.count(desc_spkm->GetID()) > 0) {
4471 return util::Error{_("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
4472 }
4473 uint256 id = desc_spkm->GetID();
4474 AddScriptPubKeyMan(id, std::move(desc_spkm));
4475 }
4476
4477 // Remove the LegacyScriptPubKeyMan from disk
4478 if (!legacy_spkm->DeleteRecordsWithDB(local_wallet_batch)) {
4479 return util::Error{_("Error: cannot remove legacy wallet records")};
4480 }
4481
4482 // Remove the LegacyScriptPubKeyMan from memory
4483 m_spk_managers.erase(legacy_spkm->GetID());
4484 m_external_spk_managers.clear();
4485 m_internal_spk_managers.clear();
4486
4487 // Setup new descriptors (only if we are migrating any key material)
4488 SetWalletFlagWithDB(local_wallet_batch, WALLET_FLAG_DESCRIPTORS);
4489 if (has_spendable_material && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
4490 // Use the existing master key if we have it
4491 if (data.master_key.key.IsValid()) {
4492 SetupDescriptorScriptPubKeyMans(local_wallet_batch, data.master_key);
4493 } else {
4494 // Setup with a new seed if we don't.
4495 SetupOwnDescriptorScriptPubKeyMans(local_wallet_batch);
4496 }
4497 }
4498
4499 // Get best block locator so that we can copy it to the watchonly and solvables
4500 CBlockLocator best_block_locator;
4501 if (!local_wallet_batch.ReadBestBlock(best_block_locator)) {
4502 return util::Error{_("Error: Unable to read wallet's best block locator record")};
4503 }
4504
4505 // Check if the transactions in the wallet are still ours. Either they belong here, or they belong in the watchonly wallet.
4506 // We need to go through these in the tx insertion order so that lookups to spends works.
4507 std::vector<uint256> txids_to_delete;
4508 std::unique_ptr<WalletBatch> watchonly_batch;
4509 if (data.watchonly_wallet) {
4510 watchonly_batch = std::make_unique<WalletBatch>(data.watchonly_wallet->GetDatabase());
4511 if (!watchonly_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.watchonly_wallet->GetName())};
4512 // Copy the next tx order pos to the watchonly wallet
4513 LOCK(data.watchonly_wallet->cs_wallet);
4514 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
4515 watchonly_batch->WriteOrderPosNext(data.watchonly_wallet->nOrderPosNext);
4516 // Write the best block locator to avoid rescanning on reload
4517 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4518 return util::Error{_("Error: Unable to write watchonly wallet best block locator record")};
4519 }
4520 }
4521 std::unique_ptr<WalletBatch> solvables_batch;
4522 if (data.solvable_wallet) {
4523 solvables_batch = std::make_unique<WalletBatch>(data.solvable_wallet->GetDatabase());
4524 if (!solvables_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.solvable_wallet->GetName())};
4525 // Write the best block locator to avoid rescanning on reload
4526 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
4527 return util::Error{_("Error: Unable to write solvable wallet best block locator record")};
4528 }
4529 }
4530 for (const auto& [_pos, wtx] : wtxOrdered) {
4531 // Check it is the watchonly wallet's
4532 // solvable_wallet doesn't need to be checked because transactions for those scripts weren't being watched for
4533 bool is_mine = IsMine(*wtx->tx) || IsFromMe(*wtx->tx);
4534 if (data.watchonly_wallet) {
4535 LOCK(data.watchonly_wallet->cs_wallet);
4536 if (data.watchonly_wallet->IsMine(*wtx->tx) || data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4537 // Add to watchonly wallet
4538 const uint256& hash = wtx->GetHash();
4539 const CWalletTx& to_copy_wtx = *wtx;
4540 if (!data.watchonly_wallet->LoadToWallet(hash, [&](CWalletTx& ins_wtx, bool new_tx) EXCLUSIVE_LOCKS_REQUIRED(data.watchonly_wallet->cs_wallet) {
4541 if (!new_tx) return false;
4542 ins_wtx.SetTx(to_copy_wtx.tx);
4543 ins_wtx.CopyFrom(to_copy_wtx);
4544 return true;
4545 })) {
4546 return util::Error{strprintf(_("Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
4547 }
4548 watchonly_batch->WriteTx(data.watchonly_wallet->mapWallet.at(hash));
4549 // Mark as to remove from the migrated wallet only if it does not also belong to it
4550 if (!is_mine) {
4551 txids_to_delete.push_back(hash);
4552 }
4553 continue;
4554 }
4555 }
4556 if (!is_mine) {
4557 // Both not ours and not in the watchonly wallet
4558 return util::Error{strprintf(_("Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
4559 }
4560 }
4561
4562 // Do the removes
4563 if (txids_to_delete.size() > 0) {
4564 if (auto res = RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
4565 return util::Error{_("Error: Could not delete watchonly transactions. ") + util::ErrorString(res)};
4566 }
4567 }
4568
4569 // Pair external wallets with their corresponding db handler
4570 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4571 if (data.watchonly_wallet) wallets_vec.emplace_back(data.watchonly_wallet, std::move(watchonly_batch));
4572 if (data.solvable_wallet) wallets_vec.emplace_back(data.solvable_wallet, std::move(solvables_batch));
4573
4574 // Write address book entry to disk
4575 auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
4576 auto address{EncodeDestination(dest)};
4577 if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
4578 if (entry.label) batch.WriteName(address, *entry.label);
4579 for (const auto& [id, request] : entry.receive_requests) {
4580 batch.WriteAddressReceiveRequest(dest, id, request);
4581 }
4582 if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
4583 };
4584
4585 // Check the address book data in the same way we did for transactions
4586 std::vector<CTxDestination> dests_to_delete;
4587 for (const auto& [dest, record] : m_address_book) {
4588 // Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
4589 // Entries for everything else ("send") will be cloned to all wallets.
4590 bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
4591 bool copied = false;
4592 for (auto& [wallet, batch] : wallets_vec) {
4593 LOCK(wallet->cs_wallet);
4594 if (require_transfer && !wallet->IsMine(dest)) continue;
4595
4596 // Copy the entire address book entry
4597 wallet->m_address_book[dest] = record;
4598 func_store_addr(*batch, dest, record);
4599
4600 copied = true;
4601 // Only delete 'receive' records that are no longer part of the original wallet
4602 if (require_transfer) {
4603 dests_to_delete.push_back(dest);
4604 break;
4605 }
4606 }
4607
4608 // Fail immediately if we ever found an entry that was ours and cannot be transferred
4609 // to any of the created wallets (watch-only, solvable).
4610 // Means that no inferred descriptor maps to the stored entry. Which mustn't happen.
4611 if (require_transfer && !copied) {
4612
4613 // Skip invalid/non-watched scripts that will not be migrated
4614 if (not_migrated_dests.count(dest) > 0) {
4615 dests_to_delete.push_back(dest);
4616 continue;
4617 }
4618
4619 return util::Error{_("Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4620 }
4621 }
4622
4623 // Persist external wallets address book entries
4624 for (auto& [wallet, batch] : wallets_vec) {
4625 if (!batch->TxnCommit()) {
4626 return util::Error{strprintf(_("Error: Unable to write data to disk for wallet %s"), wallet->GetName())};
4627 }
4628 }
4629
4630 // Remove the things to delete in this wallet
4631 if (dests_to_delete.size() > 0) {
4632 for (const auto& dest : dests_to_delete) {
4633 if (!DelAddressBookWithDB(local_wallet_batch, dest)) {
4634 return util::Error{_("Error: Unable to remove watchonly address book data")};
4635 }
4636 }
4637 }
4638
4639 // If there was no key material in the main wallet, there should be no records on it anymore.
4640 // This wallet will be discarded at the end of the process. Only wallets that contain the
4641 // migrated records will be presented to the user.
4642 if (!has_spendable_material) {
4643 if (!m_address_book.empty()) return util::Error{_("Error: Not all address book records were migrated")};
4644 if (!mapWallet.empty()) return util::Error{_("Error: Not all transaction records were migrated")};
4645 }
4646
4647 return {}; // all good
4648 }
4649
4650 bool CWallet::CanGrindR() const
4651 {
4652 return !IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER);
4653 }
4654
4655 // Returns wallet prefix for migration.
4656 // Used to name the backup file and newly created wallets.
4657 // E.g. a watch-only wallet is named "<prefix>_watchonly".
4658 static std::string MigrationPrefixName(CWallet& wallet)
4659 {
4660 const std::string& name{wallet.GetName()};
4661 return name.empty() ? "default_wallet" : name;
4662 }
4663
4664 bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error, MigrationResult& res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
4665 {
4666 AssertLockHeld(wallet.cs_wallet);
4667
4668 // Get all of the descriptors from the legacy wallet
4669 std::optional<MigrationData> data = wallet.GetDescriptorsForLegacy(error);
4670 if (data == std::nullopt) return false;
4671
4672 // Create the watchonly and solvable wallets if necessary
4673 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4674 DatabaseOptions options;
4675 options.require_existing = false;
4676 options.require_create = true;
4677 options.require_format = DatabaseFormat::SQLITE;
4678
4679 WalletContext empty_context;
4680 empty_context.args = context.args;
4681
4682 // Make the wallets
4683 options.create_flags = WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | WALLET_FLAG_DESCRIPTORS;
4684 if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
4685 options.create_flags |= WALLET_FLAG_AVOID_REUSE;
4686 }
4687 if (wallet.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
4688 options.create_flags |= WALLET_FLAG_KEY_ORIGIN_METADATA;
4689 }
4690 if (data->watch_descs.size() > 0) {
4691 wallet.WalletLogPrintf("Making a new watchonly wallet containing the watched scripts\n");
4692
4693 DatabaseStatus status;
4694 std::vector<bilingual_str> warnings;
4695 std::string wallet_name = MigrationPrefixName(wallet) + "_watchonly";
4696 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4697 if (!database) {
4698 error = strprintf(_("Wallet file creation failed: %s"), error);
4699 return false;
4700 }
4701
4702 data->watchonly_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4703 if (!data->watchonly_wallet) {
4704 error = _("Error: Failed to create new watchonly wallet");
4705 return false;
4706 }
4707 res.watchonly_wallet = data->watchonly_wallet;
4708 LOCK(data->watchonly_wallet->cs_wallet);
4709
4710 // Parse the descriptors and add them to the new wallet
4711 for (const auto& [desc_str, creation_time] : data->watch_descs) {
4712 // Parse the descriptor
4713 FlatSigningProvider keys;
4714 std::string parse_err;
4715 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4716 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4717 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4718
4719 // Add to the wallet
4720 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4721 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4722 }
4723
4724 // Add the wallet to settings
4725 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4726 }
4727 if (data->solvable_descs.size() > 0) {
4728 wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
4729
4730 DatabaseStatus status;
4731 std::vector<bilingual_str> warnings;
4732 std::string wallet_name = MigrationPrefixName(wallet) + "_solvables";
4733 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4734 if (!database) {
4735 error = strprintf(_("Wallet file creation failed: %s"), error);
4736 return false;
4737 }
4738
4739 data->solvable_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4740 if (!data->solvable_wallet) {
4741 error = _("Error: Failed to create new watchonly wallet");
4742 return false;
4743 }
4744 res.solvables_wallet = data->solvable_wallet;
4745 LOCK(data->solvable_wallet->cs_wallet);
4746
4747 // Parse the descriptors and add them to the new wallet
4748 for (const auto& [desc_str, creation_time] : data->solvable_descs) {
4749 // Parse the descriptor
4750 FlatSigningProvider keys;
4751 std::string parse_err;
4752 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4753 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4754 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4755
4756 // Add to the wallet
4757 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4758 data->solvable_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4759 }
4760
4761 // Add the wallet to settings
4762 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4763 }
4764 }
4765
4766 // Add the descriptors to wallet, remove LegacyScriptPubKeyMan, and cleanup txs and address book data
4767 return RunWithinTxn(wallet.GetDatabase(), /*process_desc=*/"apply migration process", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet){
4768 if (auto res_migration = wallet.ApplyMigrationData(batch, *data); !res_migration) {
4769 error = util::ErrorString(res_migration);
4770 return false;
4771 }
4772 wallet.WalletLogPrintf("Wallet migration complete.\n");
4773 return true;
4774 });
4775 }
4776
4777 util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context)
4778 {
4779 std::vector<bilingual_str> warnings;
4780 bilingual_str error;
4781
4782 // If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
4783 bool was_loaded = false;
4784 if (auto wallet = GetWallet(context, wallet_name)) {
4785 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4786 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4787 }
4788
4789 if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
4790 return util::Error{_("Unable to unload the wallet before migrating")};
4791 }
4792 WaitForDeleteWallet(std::move(wallet));
4793 was_loaded = true;
4794 } else {
4795 // Check if the wallet is BDB
4796 const auto& wallet_path = GetWalletPath(wallet_name);
4797 if (!wallet_path) {
4798 return util::Error{util::ErrorString(wallet_path)};
4799 }
4800 if (!fs::exists(*wallet_path)) {
4801 return util::Error{_("Error: Wallet does not exist")};
4802 }
4803 if (!IsBDBFile(BDBDataFile(*wallet_path))) {
4804 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4805 }
4806 }
4807
4808 // Load the wallet but only in the context of this function.
4809 // No signals should be connected nor should anything else be aware of this wallet
4810 WalletContext empty_context;
4811 empty_context.args = context.args;
4812 DatabaseOptions options;
4813 options.require_existing = true;
4814 options.require_format = DatabaseFormat::BERKELEY_RO;
4815 DatabaseStatus status;
4816 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4817 if (!database) {
4818 return util::Error{Untranslated("Wallet file verification failed.") + Untranslated(" ") + error};
4819 }
4820
4821 // Make the local wallet
4822 std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4823 if (!local_wallet) {
4824 return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
4825 }
4826
4827 return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, was_loaded);
4828 }
4829
4830 util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded)
4831 {
4832 MigrationResult res;
4833 bilingual_str error;
4834 std::vector<bilingual_str> warnings;
4835
4836 DatabaseOptions options;
4837 options.require_existing = true;
4838 DatabaseStatus status;
4839
4840 const std::string wallet_name = local_wallet->GetName();
4841
4842 // Helper to reload as normal for some of our exit scenarios
4843 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4844 assert(to_reload.use_count() == 1);
4845 std::string name = to_reload->GetName();
4846 to_reload.reset();
4847 to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4848 if (!to_reload) {
4849 LogError("Failed to load wallet '%s' after migration. Rolling back migration to preserve consistency. "
4850 "Error cause: %s\n", name, error.original);
4851 return false;
4852 }
4853 return true;
4854 };
4855
4856 // Before anything else, check if there is something to migrate.
4857 if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4858 if (was_loaded) {
4859 reload_wallet(local_wallet);
4860 }
4861 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4862 }
4863
4864 // Make a backup of the DB in the wallet's directory with a unique filename
4865 // using the wallet name and current timestamp. The backup filename is based
4866 // on the name of the parent directory containing the wallet data in most
4867 // cases, but in the case where the wallet name is a path to a data file,
4868 // the name of the data file is used, and in the case where the wallet name
4869 // is blank, "default_wallet" is used.
4870 fs::path this_wallet_dir = fs::absolute(fs::PathFromString(local_wallet->GetDatabase().Filename())).parent_path();
4871 const std::string backup_prefix = wallet_name.empty() ? MigrationPrefixName(*local_wallet) : [&] {
4872 // fs::weakly_canonical resolves relative specifiers and remove trailing slashes.
4873 const auto legacy_wallet_path = fs::weakly_canonical(GetWalletDir() / fs::PathFromString(wallet_name));
4874 return fs::PathToString(legacy_wallet_path.filename());
4875 }();
4876
4877 fs::path backup_filename = fs::PathFromString(strprintf("%s_%d.legacy.bak", backup_prefix, GetTime()));
4878 fs::path backup_path = this_wallet_dir / backup_filename;
4879 if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4880 if (was_loaded) {
4881 reload_wallet(local_wallet);
4882 }
4883 return util::Error{_("Error: Unable to make a backup of your wallet")};
4884 }
4885 res.backup_path = backup_path;
4886
4887 bool success = false;
4888
4889 // Unlock the wallet if needed
4890 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4891 if (was_loaded) {
4892 reload_wallet(local_wallet);
4893 }
4894 if (passphrase.find('\0') == std::string::npos) {
4895 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4896 } else {
4897 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4898 "The passphrase contains a null character (ie - a zero byte). "
4899 "If this passphrase was set with a version of this software prior to 25.0, "
4900 "please try again with only the characters up to — but not including — "
4901 "the first null character.")};
4902 }
4903 }
4904
4905 // Indicates whether the current wallet is empty after migration.
4906 // Notes:
4907 // When non-empty: the local wallet becomes the main spendable wallet.
4908 // When empty: The local wallet is excluded from the result, as the
4909 // user does not expect an empty spendable wallet after
4910 // migrating only watch-only scripts.
4911 bool empty_local_wallet = false;
4912
4913 {
4914 LOCK(local_wallet->cs_wallet);
4915 // First change to using SQLite
4916 if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
4917
4918 // In case we're migrating from file to directory, move the backup into it
4919 this_wallet_dir = fs::absolute(fs::PathFromString(local_wallet->GetDatabase().Filename())).parent_path();
4920 backup_path = this_wallet_dir / backup_filename;
4921 fs::rename(res.backup_path, backup_path);
4922 res.backup_path = backup_path;
4923
4924 // Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
4925 success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
4926 if (!success) {
4927 success = DoMigration(*local_wallet, context, error, res);
4928 // No scripts mean empty wallet after migration
4929 empty_local_wallet = local_wallet->GetAllScriptPubKeyMans().empty();
4930 } else {
4931 // Make sure that descriptors flag is actually set
4932 local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
4933 }
4934 }
4935
4936 // In case of loading failure, we need to remember the wallet files we have created to remove.
4937 // A `set` is used as it may be populated with the same wallet directory paths multiple times,
4938 // both before and after loading. This ensures the set is complete even if one of the wallets
4939 // fails to load.
4940 std::set<fs::path> wallet_files_to_remove;
4941 std::set<fs::path> wallet_empty_dirs_to_remove;
4942
4943 // Helper to track wallet files and directories for cleanup on failure.
4944 // Only directories of wallets created during migration (not the main wallet) are tracked.
4945 auto track_for_cleanup = [&](const CWallet& wallet) {
4946 const auto files = wallet.GetDatabase().Files();
4947 wallet_files_to_remove.insert(files.begin(), files.end());
4948 if (wallet.GetName() != wallet_name) {
4949 // If this isn’t the main wallet, mark its directory for removal.
4950 // This applies to the watch-only and solvable wallets.
4951 // Wallets stored directly as files in the top-level directory
4952 // (e.g. default unnamed wallets) don’t have a removable parent directory.
4953 wallet_empty_dirs_to_remove.insert(fs::PathFromString(wallet.GetDatabase().Filename()).parent_path());
4954 }
4955 };
4956
4957
4958 if (success) {
4959 Assume(!res.wallet); // We will set it here.
4960 // Check if the local wallet is empty after migration
4961 if (empty_local_wallet) {
4962 // This wallet has no records. We can safely remove it.
4963 std::vector<fs::path> paths_to_remove = local_wallet->GetDatabase().Files();
4964 local_wallet.reset();
4965 for (const auto& path_to_remove : paths_to_remove) fs::remove(path_to_remove);
4966 }
4967
4968 LogInfo("Loading new wallets after migration...\n");
4969 // Migration successful, unload all wallets locally, then reload them.
4970 // Note: We use a pointer to the shared_ptr to avoid increasing its reference count,
4971 // as 'reload_wallet' expects to be the sole owner (use_count == 1).
4972 for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
4973 if (success && *wallet_ptr) {
4974 std::shared_ptr<CWallet>& wallet = *wallet_ptr;
4975 // Track db path and load wallet
4976 track_for_cleanup(*wallet);
4977 if (!reload_wallet(wallet)) {
4978 success = false;
4979 break;
4980 }
4981
4982 // Set the first successfully loaded wallet as the main one.
4983 // The loop order is intentional and must always start with the local wallet.
4984 if (!res.wallet) {
4985 res.wallet_name = wallet->GetName();
4986 res.wallet = std::move(wallet);
4987 }
4988 }
4989 }
4990 }
4991 if (!success) {
4992 // Migration failed, cleanup
4993
4994 // Make list of wallets to cleanup
4995 std::vector<std::shared_ptr<CWallet>> created_wallets;
4996 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4997 if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
4998 if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
4999
5000 // Get the directories to remove after unloading
5001 for (std::shared_ptr<CWallet>& wallet : created_wallets) {
5002 track_for_cleanup(*wallet);
5003 }
5004
5005 // Unload the wallets
5006 for (std::shared_ptr<CWallet>& w : created_wallets) {
5007 if (w->HaveChain()) {
5008 // Unloading for wallets that were loaded for normal use
5009 if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
5010 error += _("\nUnable to cleanup failed migration");
5011 return util::Error{error};
5012 }
5013 WaitForDeleteWallet(std::move(w));
5014 } else {
5015 // Unloading for wallets in local context
5016 assert(w.use_count() == 1);
5017 w.reset();
5018 }
5019 }
5020
5021 // First, delete the db files we have created throughout this process and nothing else
5022 for (const fs::path& file : wallet_files_to_remove) {
5023 fs::remove(file);
5024 }
5025
5026 // Second, delete the created wallet directories and nothing else. They must be empty at this point.
5027 for (const fs::path& dir : wallet_empty_dirs_to_remove) {
5028 if (Assume(fs::is_empty(dir))) {
5029 fs::remove(dir);
5030 } else {
5031 LogInfo("Failed migration cleanup: Directory %s is not empty; leaving it alone\n", fs::PathToString(dir));
5032 }
5033 }
5034
5035 // Restore the backup
5036 // Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.
5037 // Reload it into memory if the wallet was previously loaded.
5038 bilingual_str restore_error;
5039 const auto& ptr_wallet = RestoreWallet(context, backup_path, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings, /*load_after_restore=*/was_loaded);
5040 if (!restore_error.empty()) {
5041 error += restore_error + _("\nUnable to restore backup of wallet.");
5042 return util::Error{error};
5043 }
5044
5045 // Verify that there is no dangling wallet: when the wallet wasn't loaded before, expect null.
5046 // This check is performed after restoration to avoid an early error before saving the backup.
5047 bool wallet_reloaded = ptr_wallet != nullptr;
5048 assert(was_loaded == wallet_reloaded);
5049
5050 return util::Error{error};
5051 }
5052 return res;
5053 }
5054
5055 void CWallet::CacheNewScriptPubKeys(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
5056 {
5057 for (const auto& script : spks) {
5058 m_cached_spks[script].push_back(spkm);
5059 }
5060 }
5061
5062 void CWallet::TopUpCallback(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
5063 {
5064 // Update scriptPubKey cache
5065 CacheNewScriptPubKeys(spks, spkm);
5066 }
5067
5068 std::set<CExtPubKey> CWallet::GetActiveHDPubKeys() const
5069 {
5070 AssertLockHeld(cs_wallet);
5071
5072 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
5073
5074 std::set<CExtPubKey> active_xpubs;
5075 for (const auto& spkm : GetActiveScriptPubKeyMans()) {
5076 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
5077 assert(desc_spkm);
5078 LOCK(desc_spkm->cs_desc_man);
5079 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
5080
5081 std::set<CPubKey> desc_pubkeys;
5082 std::set<CExtPubKey> desc_xpubs;
5083 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
5084 active_xpubs.merge(std::move(desc_xpubs));
5085 }
5086 return active_xpubs;
5087 }
5088
5089 std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const
5090 {
5091 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
5092
5093 for (const auto& spkm : GetAllScriptPubKeyMans()) {
5094 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
5095 assert(desc_spkm);
5096 LOCK(desc_spkm->cs_desc_man);
5097 if (std::optional<CKey> key = desc_spkm->GetKey(keyid)) {
5098 return key;
5099 }
5100 }
5101 return std::nullopt;
5102 }
5103
5104 void CWallet::WriteBestBlock() const
5105 {
5106 AssertLockHeld(cs_wallet);
5107
5108 if (!m_last_block_processed.IsNull()) {
5109 CBlockLocator loc;
5110 chain().findBlock(m_last_block_processed, FoundBlock().locator(loc));
5111
5112 if (!loc.IsNull()) {
5113 WalletBatch batch(GetDatabase());
5114 batch.WriteBestBlock(loc);
5115 }
5116 }
5117 }
5118
5119 void CWallet::DisconnectChainNotifications()
5120 {
5121 if (m_chain_notifications_handler) {
5122 m_chain_notifications_handler->disconnect();
5123 chain().waitForNotifications();
5124 m_chain_notifications_handler.reset();
5125 }
5126 }
5127
5128 } // namespace wallet
5129