Bitcoin Core 31.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
wallet.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-present The Bitcoin Core 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 <bitcoin-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>
21#include <external_signer.h>
22#include <interfaces/chain.h>
23#include <interfaces/handler.h>
24#include <interfaces/wallet.h>
26#include <kernel/types.h>
27#include <key.h>
28#include <key_io.h>
29#include <logging.h>
30#include <node/types.h>
31#include <outputtype.h>
32#include <policy/feerate.h>
33#include <policy/truc_policy.h>
34#include <primitives/block.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>
44#include <script/solver.h>
45#include <serialize.h>
46#include <span.h>
47#include <streams.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/check.h>
56#include <util/fs.h>
57#include <util/fs_helpers.h>
58#include <util/moneystr.h>
59#include <util/result.h>
60#include <util/string.h>
61#include <util/time.h>
62#include <util/translation.h>
63#include <wallet/coincontrol.h>
64#include <wallet/context.h>
65#include <wallet/crypter.h>
66#include <wallet/db.h>
69#include <wallet/transaction.h>
70#include <wallet/types.h>
71#include <wallet/walletdb.h>
72#include <wallet/walletutil.h>
73
74#include <algorithm>
75#include <cassert>
76#include <condition_variable>
77#include <exception>
78#include <optional>
79#include <stdexcept>
80#include <thread>
81#include <tuple>
82#include <variant>
83
84struct KeyOriginInfo;
85
92using util::ToString;
93
94namespace wallet {
95
96bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
97{
98 const auto update_function = [&wallet_name](common::SettingsValue& setting_value) {
99 if (!setting_value.isArray()) setting_value.setArray();
100 for (const auto& value : setting_value.getValues()) {
101 if (value.isStr() && value.get_str() == wallet_name) return interfaces::SettingsAction::SKIP_WRITE;
102 }
103 setting_value.push_back(wallet_name);
105 };
106 return chain.updateRwSetting("wallet", update_function);
107}
108
109bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
110{
111 const auto update_function = [&wallet_name](common::SettingsValue& setting_value) {
112 if (!setting_value.isArray()) return interfaces::SettingsAction::SKIP_WRITE;
114 for (const auto& value : setting_value.getValues()) {
115 if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
116 }
117 if (new_value.size() == setting_value.size()) return interfaces::SettingsAction::SKIP_WRITE;
118 setting_value = std::move(new_value);
120 };
121 return chain.updateRwSetting("wallet", update_function);
122}
123
125 const std::string& wallet_name,
126 std::optional<bool> load_on_startup,
127 std::vector<bilingual_str>& warnings)
128{
129 if (!load_on_startup) return;
130 if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
131 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
132 } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
133 warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
134 }
135}
136
143{
144 if (chain.isInMempool(tx.GetHash())) {
146 } else if (tx.state<TxStateInMempool>()) {
148 }
149}
150
151bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
152{
153 LOCK(context.wallets_mutex);
154 assert(wallet);
155 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
156 if (i != context.wallets.end()) return false;
157 context.wallets.push_back(wallet);
158 wallet->ConnectScriptPubKeyManNotifiers();
159 wallet->NotifyCanGetAddressesChanged();
160 return true;
161}
162
163bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
164{
165 assert(wallet);
166
167 interfaces::Chain& chain = wallet->chain();
168 std::string name = wallet->GetName();
169 WITH_LOCK(wallet->cs_wallet, wallet->WriteBestBlock());
170
171 // Unregister with the validation interface which also drops shared pointers.
172 wallet->DisconnectChainNotifications();
173 {
174 LOCK(context.wallets_mutex);
175 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
176 if (i == context.wallets.end()) return false;
177 context.wallets.erase(i);
178 }
179 // Notify unload so that upper layers release the shared pointer.
180 wallet->NotifyUnload();
181
182 // Write the wallet setting
183 UpdateWalletSetting(chain, name, load_on_start, warnings);
184
185 return true;
186}
187
188bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
189{
190 std::vector<bilingual_str> warnings;
191 return RemoveWallet(context, wallet, load_on_start, warnings);
192}
193
194std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context)
195{
196 LOCK(context.wallets_mutex);
197 return context.wallets;
198}
199
200std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count)
201{
202 LOCK(context.wallets_mutex);
203 count = context.wallets.size();
204 return count == 1 ? context.wallets[0] : nullptr;
205}
206
207std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name)
208{
209 LOCK(context.wallets_mutex);
210 for (const std::shared_ptr<CWallet>& wallet : context.wallets) {
211 if (wallet->GetName() == name) return wallet;
212 }
213 return nullptr;
214}
215
216std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet)
217{
218 LOCK(context.wallets_mutex);
219 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
220 return interfaces::MakeCleanupHandler([&context, it] { LOCK(context.wallets_mutex); context.wallet_load_fns.erase(it); });
221}
222
223void NotifyWalletLoaded(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
224{
225 LOCK(context.wallets_mutex);
226 for (auto& load_wallet : context.wallet_load_fns) {
227 load_wallet(interfaces::MakeWallet(context, wallet));
228 }
229}
230
233static std::condition_variable g_wallet_release_cv;
234static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
235static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
236
237// Custom deleter for shared_ptr<CWallet>.
239{
240 const std::string name = wallet->GetName();
241 wallet->WalletLogPrintf("Releasing wallet %s..\n", name);
242 delete wallet;
243 // Wallet is now released, notify WaitForDeleteWallet, if any.
244 {
246 if (g_unloading_wallet_set.erase(name) == 0) {
247 // WaitForDeleteWallet was not called for this wallet, all done.
248 return;
249 }
250 }
251 g_wallet_release_cv.notify_all();
252}
253
254void WaitForDeleteWallet(std::shared_ptr<CWallet>&& wallet)
255{
256 // Mark wallet for unloading.
257 const std::string name = wallet->GetName();
258 {
260 g_unloading_wallet_set.insert(name);
261 // Do not expect to be the only one removing this wallet.
262 // Multiple threads could simultaneously be waiting for deletion.
263 }
264
265 // Time to ditch our shared_ptr and wait for FlushAndDeleteWallet call.
266 wallet.reset();
267 {
269 while (g_unloading_wallet_set.contains(name)) {
270 g_wallet_release_cv.wait(lock);
271 }
272 }
273}
274
275namespace {
276std::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)
277{
278 try {
279 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
280 if (!database) {
281 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
282 return nullptr;
283 }
284
285 context.chain->initMessage(_("Loading wallet…"));
286 std::shared_ptr<CWallet> wallet = CWallet::LoadExisting(context, name, std::move(database), error, warnings);
287 if (!wallet) {
288 error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
290 return nullptr;
291 }
292
293 NotifyWalletLoaded(context, wallet);
294 AddWallet(context, wallet);
295 wallet->postInitProcess();
296
297 // Write the wallet setting
298 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
299
300 return wallet;
301 } catch (const std::runtime_error& e) {
302 error = Untranslated(e.what());
304 return nullptr;
305 }
306}
307
308class FastWalletRescanFilter
309{
310public:
311 FastWalletRescanFilter(const CWallet& wallet) : m_wallet(wallet)
312 {
313 // create initial filter with scripts from all ScriptPubKeyMans
314 for (auto spkm : m_wallet.GetAllScriptPubKeyMans()) {
315 auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
316 assert(desc_spkm != nullptr);
317 AddScriptPubKeys(desc_spkm);
318 // save each range descriptor's end for possible future filter updates
319 if (desc_spkm->IsHDEnabled()) {
320 m_last_range_ends.emplace(desc_spkm->GetID(), desc_spkm->GetEndRange());
321 }
322 }
323 }
324
325 void UpdateIfNeeded()
326 {
327 // repopulate filter with new scripts if top-up has happened since last iteration
328 for (const auto& [desc_spkm_id, last_range_end] : m_last_range_ends) {
329 auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
330 assert(desc_spkm != nullptr);
331 int32_t current_range_end{desc_spkm->GetEndRange()};
332 if (current_range_end > last_range_end) {
333 AddScriptPubKeys(desc_spkm, last_range_end);
334 m_last_range_ends.at(desc_spkm->GetID()) = current_range_end;
335 }
336 }
337 }
338
339 std::optional<bool> MatchesBlock(const uint256& block_hash) const
340 {
341 return m_wallet.chain().blockFilterMatchesAny(BlockFilterType::BASIC, block_hash, m_filter_set);
342 }
343
344private:
345 const CWallet& m_wallet;
352 std::map<uint256, int32_t> m_last_range_ends;
353 GCSFilter::ElementSet m_filter_set;
354
355 void AddScriptPubKeys(const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
356 {
357 for (const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
358 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
359 }
360 }
361};
362} // namespace
363
364std::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)
365{
366 auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
367 if (!result.second) {
368 error = Untranslated("Wallet already loading.");
370 return nullptr;
371 }
372 auto wallet = LoadWalletInternal(context, name, load_on_start, options, status, error, warnings);
373 WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
374 return wallet;
375}
376
377std::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)
378{
379 // Wallet must have a non-empty name
380 if (name.empty()) {
381 error = Untranslated("Wallet name cannot be empty");
383 return nullptr;
384 }
385
386 uint64_t wallet_creation_flags = options.create_flags;
387 const SecureString& passphrase = options.create_passphrase;
388
389 // Only descriptor wallets can be created
390 Assert(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS);
392
393 // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
394 bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
395
396 // Born encrypted wallets need to be created blank first.
397 if (!passphrase.empty()) {
398 wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
399 }
400
401 // Private keys must be disabled for an external signer wallet
402 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
403 error = Untranslated("Private keys must be disabled when using an external signer");
405 return nullptr;
406 }
407
408 // Do not allow a passphrase when private keys are disabled
409 if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
410 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.");
412 return nullptr;
413 }
414
415 // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
416 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
417 if (!database) {
418 error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
420 return nullptr;
421 }
422
423 // Make the wallet
424 context.chain->initMessage(_("Creating wallet…"));
425 std::shared_ptr<CWallet> wallet = CWallet::CreateNew(context, name, std::move(database), wallet_creation_flags, error, warnings);
426 if (!wallet) {
427 error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
429 return nullptr;
430 }
431
432 // Encrypt the wallet
433 if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
434 if (!wallet->EncryptWallet(passphrase)) {
435 error = Untranslated("Error: Wallet created but failed to encrypt.");
437 return nullptr;
438 }
439 if (!create_blank) {
440 // Unlock the wallet
441 if (!wallet->Unlock(passphrase)) {
442 error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
444 return nullptr;
445 }
446
447 // Set a seed for the wallet
448 {
449 LOCK(wallet->cs_wallet);
450 wallet->SetupDescriptorScriptPubKeyMans();
451 }
452
453 // Relock the wallet
454 wallet->Lock();
455 }
456 }
457
458 WITH_LOCK(wallet->cs_wallet, wallet->LogStats());
459 NotifyWalletLoaded(context, wallet);
460 AddWallet(context, wallet);
461 wallet->postInitProcess();
462
463 // Write the wallet settings
464 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
465
467 return wallet;
468}
469
470// Re-creates wallet from the backup file by renaming and moving it into the wallet's directory.
471// If 'load_after_restore=true', the wallet object will be fully initialized and appended to the context.
472std::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, bool allow_unnamed)
473{
474 // Error if the wallet name is empty and allow_unnamed == false
475 // allow_unnamed == true is only used by migration to migrate an unnamed wallet
476 if (!allow_unnamed && wallet_name.empty()) {
477 error = Untranslated("Wallet name cannot be empty");
479 return nullptr;
480 }
481
482 DatabaseOptions options;
483 ReadDatabaseArgs(*context.args, options);
484 options.require_existing = true;
485
486 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));
487 auto wallet_file = wallet_path / "wallet.dat";
488 std::shared_ptr<CWallet> wallet;
489 bool wallet_file_copied = false;
490 bool created_parent_dir = false;
491
492 try {
493 if (!fs::exists(backup_file)) {
494 error = Untranslated("Backup file does not exist");
496 return nullptr;
497 }
498
499 // Wallet directories are allowed to exist, but must not contain a .dat file.
500 // Any existing wallet database is treated as a hard failure to prevent overwriting.
501 if (fs::exists(wallet_path)) {
502 // If this is a file, it is the db and we don't want to overwrite it.
503 if (!fs::is_directory(wallet_path)) {
504 error = Untranslated(strprintf("Failed to restore wallet. Database file exists '%s'.", fs::PathToString(wallet_path)));
506 return nullptr;
507 }
508
509 // Check we are not going to overwrite an existing db file
510 if (fs::exists(wallet_file)) {
511 error = Untranslated(strprintf("Failed to restore wallet. Database file exists in '%s'.", fs::PathToString(wallet_file)));
513 return nullptr;
514 }
515 } else {
516 // The directory doesn't exist, create it
517 if (!TryCreateDirectories(wallet_path)) {
518 error = Untranslated(strprintf("Failed to restore database path '%s'.", fs::PathToString(wallet_path)));
520 return nullptr;
521 }
522 created_parent_dir = true;
523 }
524
525 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
526 wallet_file_copied = true;
527
528 if (load_after_restore) {
529 wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
530 }
531 } catch (const std::exception& e) {
532 assert(!wallet);
533 if (!error.empty()) error += Untranslated("\n");
534 error += Untranslated(strprintf("Unexpected exception: %s", e.what()));
535 }
536
537 // Remove created wallet path only when loading fails
538 if (load_after_restore && !wallet) {
539 if (wallet_file_copied) fs::remove(wallet_file);
540 // Clean up the parent directory if we created it during restoration.
541 // As we have created it, it must be empty after deleting the wallet file.
542 if (created_parent_dir) {
543 Assume(fs::is_empty(wallet_path));
544 fs::remove(wallet_path);
545 }
546 }
547
548 return wallet;
549}
550
555
556const CWalletTx* CWallet::GetWalletTx(const Txid& hash) const
557{
559 const auto it = mapWallet.find(hash);
560 if (it == mapWallet.end())
561 return nullptr;
562 return &(it->second);
563}
564
577
578/* Given a wallet passphrase string and an unencrypted master key, determine the proper key
579 * derivation parameters (should take at least 100ms) and encrypt the master key. */
580static bool EncryptMasterKey(const SecureString& wallet_passphrase, const CKeyingMaterial& plain_master_key, CMasterKey& master_key)
581{
582 constexpr MillisecondsDouble target{100};
583 auto start{SteadyClock::now()};
584 CCrypter crypter;
585
586 crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod);
587 master_key.nDeriveIterations = static_cast<unsigned int>(master_key.nDeriveIterations * target / (SteadyClock::now() - start));
588
589 start = SteadyClock::now();
590 crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod);
591 master_key.nDeriveIterations = (master_key.nDeriveIterations + static_cast<unsigned int>(master_key.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
592
595 }
596
597 if (!crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod)) {
598 return false;
599 }
600 if (!crypter.Encrypt(plain_master_key, master_key.vchCryptedKey)) {
601 return false;
602 }
603
604 return true;
605}
606
607static bool DecryptMasterKey(const SecureString& wallet_passphrase, const CMasterKey& master_key, CKeyingMaterial& plain_master_key)
608{
609 CCrypter crypter;
610 if (!crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod)) {
611 return false;
612 }
613 if (!crypter.Decrypt(master_key.vchCryptedKey, plain_master_key)) {
614 return false;
615 }
616
617 return true;
618}
619
620bool CWallet::Unlock(const SecureString& strWalletPassphrase)
621{
622 CKeyingMaterial plain_master_key;
623
624 {
626 for (const auto& [_, master_key] : mapMasterKeys)
627 {
628 if (!DecryptMasterKey(strWalletPassphrase, master_key, plain_master_key)) {
629 continue; // try another master key
630 }
631 if (Unlock(plain_master_key)) {
632 // Now that we've unlocked, upgrade the descriptor cache
634 return true;
635 }
636 }
637 }
638 return false;
639}
640
641bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
642{
643 bool fWasLocked = IsLocked();
644
645 {
647 Lock();
648
649 CKeyingMaterial plain_master_key;
650 for (auto& [master_key_id, master_key] : mapMasterKeys)
651 {
652 if (!DecryptMasterKey(strOldWalletPassphrase, master_key, plain_master_key)) {
653 return false;
654 }
655 if (Unlock(plain_master_key))
656 {
657 if (!EncryptMasterKey(strNewWalletPassphrase, plain_master_key, master_key)) {
658 return false;
659 }
660 WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", master_key.nDeriveIterations);
661
662 WalletBatch(GetDatabase()).WriteMasterKey(master_key_id, master_key);
663 if (fWasLocked)
664 Lock();
665 return true;
666 }
667 }
668 }
669
670 return false;
671}
672
673void CWallet::SetLastBlockProcessedInMem(int block_height, uint256 block_hash)
674{
676
677 m_last_block_processed = block_hash;
678 m_last_block_processed_height = block_height;
679}
680
681void CWallet::SetLastBlockProcessed(int block_height, uint256 block_hash)
682{
684
685 SetLastBlockProcessedInMem(block_height, block_hash);
687}
688
689std::set<Txid> CWallet::GetConflicts(const Txid& txid) const
690{
691 std::set<Txid> result;
693
694 const auto it = mapWallet.find(txid);
695 if (it == mapWallet.end())
696 return result;
697 const CWalletTx& wtx = it->second;
698
699 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
700
701 for (const CTxIn& txin : wtx.tx->vin)
702 {
703 if (mapTxSpends.count(txin.prevout) <= 1)
704 continue; // No conflict if zero or one spends
705 range = mapTxSpends.equal_range(txin.prevout);
706 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
707 result.insert(_it->second);
708 }
709 return result;
710}
711
713{
715 const Txid& txid = tx->GetHash();
716 for (unsigned int i = 0; i < tx->vout.size(); ++i) {
717 if (IsSpent(COutPoint(txid, i))) {
718 return true;
719 }
720 }
721 return false;
722}
723
725{
726 GetDatabase().Close();
727}
728
729void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
730{
731 // We want all the wallet transactions in range to have the same metadata as
732 // the oldest (smallest nOrderPos).
733 // So: find smallest nOrderPos:
734
735 int nMinOrderPos = std::numeric_limits<int>::max();
736 const CWalletTx* copyFrom = nullptr;
737 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
738 const CWalletTx* wtx = &mapWallet.at(it->second);
739 if (wtx->nOrderPos < nMinOrderPos) {
740 nMinOrderPos = wtx->nOrderPos;
741 copyFrom = wtx;
742 }
743 }
744
745 if (!copyFrom) {
746 return;
747 }
748
749 // Now copy data from copyFrom to rest:
750 for (TxSpends::iterator it = range.first; it != range.second; ++it)
751 {
752 const Txid& hash = it->second;
753 CWalletTx* copyTo = &mapWallet.at(hash);
754 if (copyFrom == copyTo) continue;
755 assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
756 if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
757 copyTo->mapValue = copyFrom->mapValue;
758 copyTo->vOrderForm = copyFrom->vOrderForm;
759 // nTimeReceived not copied on purpose
760 copyTo->nTimeSmart = copyFrom->nTimeSmart;
761 // nOrderPos not copied on purpose
762 // cached members not copied on purpose
763 }
764}
765
770bool CWallet::IsSpent(const COutPoint& outpoint) const
771{
772 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
773 range = mapTxSpends.equal_range(outpoint);
774
775 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
776 const Txid& txid = it->second;
777 const auto mit = mapWallet.find(txid);
778 if (mit != mapWallet.end()) {
779 const auto& wtx = mit->second;
780 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
781 return true; // Spent
782 }
783 }
784 return false;
785}
786
787void CWallet::AddToSpends(const COutPoint& outpoint, const Txid& txid)
788{
789 mapTxSpends.insert(std::make_pair(outpoint, txid));
790
791 UnlockCoin(outpoint);
792
793 std::pair<TxSpends::iterator, TxSpends::iterator> range;
794 range = mapTxSpends.equal_range(outpoint);
795 SyncMetaData(range);
796}
797
798
800{
801 if (wtx.IsCoinBase()) // Coinbases don't spend anything!
802 return;
803
804 for (const CTxIn& txin : wtx.tx->vin)
805 AddToSpends(txin.prevout, wtx.GetHash());
806}
807
808bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
809{
810 // Only descriptor wallets can be encrypted
812
813 if (HasEncryptionKeys())
814 return false;
815
816 CKeyingMaterial plain_master_key;
817
818 plain_master_key.resize(WALLET_CRYPTO_KEY_SIZE);
819 GetStrongRandBytes(plain_master_key);
820
821 CMasterKey master_key;
822
823 master_key.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
824 GetStrongRandBytes(master_key.vchSalt);
825
826 if (!EncryptMasterKey(strWalletPassphrase, plain_master_key, master_key)) {
827 return false;
828 }
829 WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", master_key.nDeriveIterations);
830
831 {
833 mapMasterKeys[++nMasterKeyMaxID] = master_key;
834 WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
835 if (!encrypted_batch->TxnBegin()) {
836 delete encrypted_batch;
837 encrypted_batch = nullptr;
838 return false;
839 }
840 encrypted_batch->WriteMasterKey(nMasterKeyMaxID, master_key);
841
842 for (const auto& spk_man_pair : m_spk_managers) {
843 auto spk_man = spk_man_pair.second.get();
844 if (!spk_man->Encrypt(plain_master_key, encrypted_batch)) {
845 encrypted_batch->TxnAbort();
846 delete encrypted_batch;
847 encrypted_batch = nullptr;
848 // We now probably have half of our keys encrypted in memory, and half not...
849 // die and let the user reload the unencrypted wallet.
850 assert(false);
851 }
852 }
853
854 if (!encrypted_batch->TxnCommit()) {
855 delete encrypted_batch;
856 encrypted_batch = nullptr;
857 // We now have keys encrypted in memory, but not on disk...
858 // die to avoid confusion and let the user reload the unencrypted wallet.
859 assert(false);
860 }
861
862 delete encrypted_batch;
863 encrypted_batch = nullptr;
864
865 Lock();
866 Unlock(strWalletPassphrase);
867
868 // Make new descriptors with a new seed
871 }
872 Lock();
873
874 // Need to completely rewrite the wallet file; if we don't, the database might keep
875 // bits of the unencrypted private key in slack space in the database file.
876 GetDatabase().Rewrite();
877 }
879
880 return true;
881}
882
884{
886 WalletBatch batch(GetDatabase());
887
888 // Old wallets didn't have any defined order for transactions
889 // Probably a bad idea to change the output of this
890
891 // First: get all CWalletTx into a sorted-by-time multimap.
892 typedef std::multimap<int64_t, CWalletTx*> TxItems;
893 TxItems txByTime;
894
895 for (auto& entry : mapWallet)
896 {
897 CWalletTx* wtx = &entry.second;
898 txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
899 }
900
901 nOrderPosNext = 0;
902 std::vector<int64_t> nOrderPosOffsets;
903 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
904 {
905 CWalletTx *const pwtx = (*it).second;
906 int64_t& nOrderPos = pwtx->nOrderPos;
907
908 if (nOrderPos == -1)
909 {
910 nOrderPos = nOrderPosNext++;
911 nOrderPosOffsets.push_back(nOrderPos);
912
913 if (!batch.WriteTx(*pwtx))
914 return DBErrors::LOAD_FAIL;
915 }
916 else
917 {
918 int64_t nOrderPosOff = 0;
919 for (const int64_t& nOffsetStart : nOrderPosOffsets)
920 {
921 if (nOrderPos >= nOffsetStart)
922 ++nOrderPosOff;
923 }
924 nOrderPos += nOrderPosOff;
925 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
926
927 if (!nOrderPosOff)
928 continue;
929
930 // Since we're changing the order, write it back
931 if (!batch.WriteTx(*pwtx))
932 return DBErrors::LOAD_FAIL;
933 }
934 }
935 batch.WriteOrderPosNext(nOrderPosNext);
936
937 return DBErrors::LOAD_OK;
938}
939
941{
943 int64_t nRet = nOrderPosNext++;
944 if (batch) {
945 batch->WriteOrderPosNext(nOrderPosNext);
946 } else {
947 WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
948 }
949 return nRet;
950}
951
953{
954 {
956 for (auto& [_, wtx] : mapWallet)
957 wtx.MarkDirty();
958 }
959}
960
961bool CWallet::MarkReplaced(const Txid& originalHash, const Txid& newHash)
962{
964
965 auto mi = mapWallet.find(originalHash);
966
967 // There is a bug if MarkReplaced is not called on an existing wallet transaction.
968 assert(mi != mapWallet.end());
969
970 CWalletTx& wtx = (*mi).second;
971
972 // Ensure for now that we're not overwriting data
973 assert(!wtx.mapValue.contains("replaced_by_txid"));
974
975 wtx.mapValue["replaced_by_txid"] = newHash.ToString();
976
977 // Refresh mempool status without waiting for transactionRemovedFromMempool or transactionAddedToMempool
979
980 WalletBatch batch(GetDatabase());
981
982 bool success = true;
983 if (!batch.WriteTx(wtx)) {
984 WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
985 success = false;
986 }
987
989
990 return success;
991}
992
993void CWallet::SetSpentKeyState(WalletBatch& batch, const Txid& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
994{
996 const CWalletTx* srctx = GetWalletTx(hash);
997 if (!srctx) return;
998
999 CTxDestination dst;
1000 if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
1001 if (IsMine(dst)) {
1002 if (used != IsAddressPreviouslySpent(dst)) {
1003 if (used) {
1004 tx_destinations.insert(dst);
1005 }
1006 SetAddressPreviouslySpent(batch, dst, used);
1007 }
1008 }
1009 }
1010}
1011
1012bool CWallet::IsSpentKey(const CScript& scriptPubKey) const
1013{
1015 CTxDestination dest;
1016 if (!ExtractDestination(scriptPubKey, dest)) {
1017 return false;
1018 }
1019 if (IsAddressPreviouslySpent(dest)) {
1020 return true;
1021 }
1022 return false;
1023}
1024
1025CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx, bool rescanning_old_block)
1026{
1027 LOCK(cs_wallet);
1028
1029 WalletBatch batch(GetDatabase());
1030
1031 Txid hash = tx->GetHash();
1032
1034 // Mark used destinations
1035 std::set<CTxDestination> tx_destinations;
1036
1037 for (const CTxIn& txin : tx->vin) {
1038 const COutPoint& op = txin.prevout;
1039 SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
1040 }
1041
1042 MarkDestinationsDirty(tx_destinations);
1043 }
1044
1045 // Inserts only if not already there, returns tx inserted or tx found
1046 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1047 CWalletTx& wtx = (*ret.first).second;
1048 bool fInsertedNew = ret.second;
1049 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1050 if (fInsertedNew) {
1051 wtx.nTimeReceived = GetTime();
1052 wtx.nOrderPos = IncOrderPosNext(&batch);
1053 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1054 wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
1055 AddToSpends(wtx);
1056
1057 // Update birth time when tx time is older than it.
1059 }
1060
1061 if (!fInsertedNew)
1062 {
1063 if (state.index() != wtx.m_state.index()) {
1064 wtx.m_state = state;
1065 fUpdated = true;
1066 } else {
1069 }
1070 // If we have a witness-stripped version of this transaction, and we
1071 // see a new version with a witness, then we must be upgrading a pre-segwit
1072 // wallet. Store the new version of the transaction with the witness,
1073 // as the stripped-version must be invalid.
1074 // TODO: Store all versions of the transaction, instead of just one.
1075 if (tx->HasWitness() && !wtx.tx->HasWitness()) {
1076 wtx.SetTx(tx);
1077 fUpdated = true;
1078 }
1079 }
1080
1081 // Mark inactive coinbase transactions and their descendants as abandoned
1082 if (wtx.IsCoinBase() && wtx.isInactive()) {
1083 std::vector<CWalletTx*> txs{&wtx};
1084
1085 TxStateInactive inactive_state = TxStateInactive{/*abandoned=*/true};
1086
1087 while (!txs.empty()) {
1088 CWalletTx* desc_tx = txs.back();
1089 txs.pop_back();
1090 desc_tx->m_state = inactive_state;
1091 // Break caches since we have changed the state
1092 desc_tx->MarkDirty();
1093 batch.WriteTx(*desc_tx);
1094 MarkInputsDirty(desc_tx->tx);
1095 for (unsigned int i = 0; i < desc_tx->tx->vout.size(); ++i) {
1096 COutPoint outpoint(desc_tx->GetHash(), i);
1097 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1098 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1099 const auto wit = mapWallet.find(it->second);
1100 if (wit != mapWallet.end()) {
1101 txs.push_back(&wit->second);
1102 }
1103 }
1104 }
1105 }
1106 }
1107
1109 WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
1110
1111 // Write to disk
1112 if (fInsertedNew || fUpdated)
1113 if (!batch.WriteTx(wtx))
1114 return nullptr;
1115
1116 // Break debit/credit balance caches:
1117 wtx.MarkDirty();
1118
1119 // Cache the outputs that belong to the wallet
1120 RefreshTXOsFromTx(wtx);
1121
1122 // Notify UI of new or updated transaction
1123 NotifyTransactionChanged(hash, fInsertedNew ? CT_NEW : CT_UPDATED);
1124
1125#if HAVE_SYSTEM
1126 // notify an external script when a wallet transaction comes in or is updated
1127 std::string strCmd = m_notify_tx_changed_script;
1128
1129 if (!strCmd.empty())
1130 {
1131 ReplaceAll(strCmd, "%s", hash.GetHex());
1132 if (auto* conf = wtx.state<TxStateConfirmed>())
1133 {
1134 ReplaceAll(strCmd, "%b", conf->confirmed_block_hash.GetHex());
1135 ReplaceAll(strCmd, "%h", ToString(conf->confirmed_block_height));
1136 } else {
1137 ReplaceAll(strCmd, "%b", "unconfirmed");
1138 ReplaceAll(strCmd, "%h", "-1");
1139 }
1140#ifndef WIN32
1141 // Substituting the wallet name isn't currently supported on windows
1142 // because windows shell escaping has not been implemented yet:
1143 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
1144 // A few ways it could be implemented in the future are described in:
1145 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
1146 ReplaceAll(strCmd, "%w", ShellEscape(GetName()));
1147#endif
1148 std::thread t(runCommand, strCmd);
1149 t.detach(); // thread runs free
1150 }
1151#endif
1152
1153 return &wtx;
1154}
1155
1156bool CWallet::LoadToWallet(const Txid& hash, const UpdateWalletTxFn& fill_wtx)
1157{
1158 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(nullptr, TxStateInactive{}));
1159 CWalletTx& wtx = ins.first->second;
1160 if (!fill_wtx(wtx, ins.second)) {
1161 return false;
1162 }
1163 // If wallet doesn't have a chain (e.g when using bitcoin-wallet tool),
1164 // don't bother to update txn.
1165 if (HaveChain()) {
1166 wtx.updateState(chain());
1167 }
1168 if (/* insertion took place */ ins.second) {
1169 wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1170 }
1171 AddToSpends(wtx);
1172 for (const CTxIn& txin : wtx.tx->vin) {
1173 auto it = mapWallet.find(txin.prevout.hash);
1174 if (it != mapWallet.end()) {
1175 CWalletTx& prevtx = it->second;
1176 if (auto* prev = prevtx.state<TxStateBlockConflicted>()) {
1177 MarkConflicted(prev->conflicting_block_hash, prev->conflicting_block_height, wtx.GetHash());
1178 }
1179 }
1180 }
1181
1182 // Update birth time when tx time is older than it.
1184
1185 // Make sure the tx outputs are known by the wallet
1186 RefreshTXOsFromTx(wtx);
1187 return true;
1188}
1189
1190bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const SyncTxState& state, bool fUpdate, bool rescanning_old_block)
1191{
1192 const CTransaction& tx = *ptx;
1193 {
1195
1196 if (auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1197 for (const CTxIn& txin : tx.vin) {
1198 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1199 while (range.first != range.second) {
1200 if (range.first->second != tx.GetHash()) {
1201 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);
1202 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1203 }
1204 range.first++;
1205 }
1206 }
1207 }
1208
1209 bool fExisted = mapWallet.contains(tx.GetHash());
1210 if (fExisted && !fUpdate) return false;
1211 if (fExisted || IsMine(tx) || IsFromMe(tx))
1212 {
1213 /* Check if any keys in the wallet keypool that were supposed to be unused
1214 * have appeared in a new transaction. If so, remove those keys from the keypool.
1215 * This can happen when restoring an old wallet backup that does not contain
1216 * the mostly recently created transactions from newer versions of the wallet.
1217 */
1218
1219 // loop though all outputs
1220 for (const CTxOut& txout: tx.vout) {
1221 for (const auto& spk_man : GetScriptPubKeyMans(txout.scriptPubKey)) {
1222 for (auto &dest : spk_man->MarkUnusedAddresses(txout.scriptPubKey)) {
1223 // If internal flag is not defined try to infer it from the ScriptPubKeyMan
1224 if (!dest.internal.has_value()) {
1225 dest.internal = IsInternalScriptPubKeyMan(spk_man);
1226 }
1227
1228 // skip if can't determine whether it's a receiving address or not
1229 if (!dest.internal.has_value()) continue;
1230
1231 // If this is a receiving address and it's not in the address book yet
1232 // (e.g. it wasn't generated on this node or we're restoring from backup)
1233 // add it to the address book for proper transaction accounting
1234 if (!*dest.internal && !FindAddressBookEntry(dest.dest, /* allow_change= */ false)) {
1236 }
1237 }
1238 }
1239 }
1240
1241 // Block disconnection override an abandoned tx as unconfirmed
1242 // which means user may have to call abandontransaction again
1243 TxState tx_state = std::visit([](auto&& s) -> TxState { return s; }, state);
1244 CWalletTx* wtx = AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, rescanning_old_block);
1245 if (!wtx) {
1246 // Can only be nullptr if there was a db write error (missing db, read-only db or a db engine internal writing error).
1247 // As we only store arriving transaction in this process, and we don't want an inconsistent state, let's throw an error.
1248 throw std::runtime_error("DB error adding transaction to wallet, write failed");
1249 }
1250 return true;
1251 }
1252 }
1253 return false;
1254}
1255
1257{
1258 LOCK(cs_wallet);
1259 const CWalletTx* wtx = GetWalletTx(hashTx);
1260 return wtx && !wtx->isAbandoned() && GetTxDepthInMainChain(*wtx) == 0 && !wtx->InMempool();
1261}
1262
1263void CWallet::UpdateTrucSiblingConflicts(const CWalletTx& parent_wtx, const Txid& child_txid, bool add_conflict) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
1264{
1265 // Find all other txs in our wallet that spend utxos from this parent
1266 // so that we can mark them as mempool-conflicted by this new tx.
1267 for (long unsigned int i = 0; i < parent_wtx.tx->vout.size(); i++) {
1268 for (auto range = mapTxSpends.equal_range(COutPoint(parent_wtx.tx->GetHash(), i)); range.first != range.second; range.first++) {
1269 const Txid& sibling_txid = range.first->second;
1270 // Skip the child_tx itself
1271 if (sibling_txid == child_txid) continue;
1272 RecursiveUpdateTxState(/*batch=*/nullptr, sibling_txid, [&child_txid, add_conflict](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1273 return add_conflict ? (wtx.mempool_conflicts.insert(child_txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED)
1274 : (wtx.mempool_conflicts.erase(child_txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED);
1275 });
1276 }
1277 }
1278}
1279
1281{
1282 for (const CTxIn& txin : tx->vin) {
1283 auto it = mapWallet.find(txin.prevout.hash);
1284 if (it != mapWallet.end()) {
1285 it->second.MarkDirty();
1286 }
1287 }
1288}
1289
1291{
1292 LOCK(cs_wallet);
1293 auto it = mapWallet.find(hashTx);
1294 assert(it != mapWallet.end());
1295 return AbandonTransaction(it->second);
1296}
1297
1299{
1300 // Can't mark abandoned if confirmed or in mempool
1301 if (GetTxDepthInMainChain(tx) != 0 || tx.InMempool()) {
1302 return false;
1303 }
1304
1305 auto try_updating_state = [](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1306 // If the orig tx was not in block/mempool, none of its spends can be.
1307 assert(!wtx.isConfirmed());
1308 assert(!wtx.InMempool());
1309 // If already conflicted or abandoned, no need to set abandoned
1310 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1311 wtx.m_state = TxStateInactive{/*abandoned=*/true};
1313 }
1314 return TxUpdate::UNCHANGED;
1315 };
1316
1317 // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too.
1318 // States are not permanent, so these transactions can become unabandoned if they are re-added to the
1319 // mempool, or confirmed in a block, or conflicted.
1320 // Note: If the reorged coinbase is re-added to the main chain, the descendants that have not had their
1321 // states change will remain abandoned and will require manual broadcast if the user wants them.
1322
1323 RecursiveUpdateTxState(tx.GetHash(), try_updating_state);
1324
1325 return true;
1326}
1327
1328void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const Txid& hashTx)
1329{
1330 LOCK(cs_wallet);
1331
1332 // If number of conflict confirms cannot be determined, this means
1333 // that the block is still unknown or not yet part of the main chain,
1334 // for example when loading the wallet during a reindex. Do nothing in that
1335 // case.
1336 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1337 return;
1338 }
1339 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1340 if (conflictconfirms >= 0)
1341 return;
1342
1343 auto try_updating_state = [&](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1344 if (conflictconfirms < GetTxDepthInMainChain(wtx)) {
1345 // Block is 'more conflicted' than current confirm; update.
1346 // Mark transaction as conflicted with this block.
1347 wtx.m_state = TxStateBlockConflicted{hashBlock, conflicting_height};
1348 return TxUpdate::CHANGED;
1349 }
1350 return TxUpdate::UNCHANGED;
1351 };
1352
1353 // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too.
1354 RecursiveUpdateTxState(hashTx, try_updating_state);
1355
1356}
1357
1358void CWallet::RecursiveUpdateTxState(const Txid& tx_hash, const TryUpdatingStateFn& try_updating_state) {
1359 WalletBatch batch(GetDatabase());
1360 RecursiveUpdateTxState(&batch, tx_hash, try_updating_state);
1361}
1362
1363void CWallet::RecursiveUpdateTxState(WalletBatch* batch, const Txid& tx_hash, const TryUpdatingStateFn& try_updating_state) {
1364 std::set<Txid> todo;
1365 std::set<Txid> done;
1366
1367 todo.insert(tx_hash);
1368
1369 while (!todo.empty()) {
1370 Txid now = *todo.begin();
1371 todo.erase(now);
1372 done.insert(now);
1373 auto it = mapWallet.find(now);
1374 assert(it != mapWallet.end());
1375 CWalletTx& wtx = it->second;
1376
1377 TxUpdate update_state = try_updating_state(wtx);
1378 if (update_state != TxUpdate::UNCHANGED) {
1379 wtx.MarkDirty();
1380 if (batch) batch->WriteTx(wtx);
1381 // Iterate over all its outputs, and update those tx states as well (if applicable)
1382 for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1383 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
1384 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1385 if (!done.contains(iter->second)) {
1386 todo.insert(iter->second);
1387 }
1388 }
1389 }
1390
1391 if (update_state == TxUpdate::NOTIFY_CHANGED) {
1393 }
1394
1395 // If a transaction changes its tx state, that usually changes the balance
1396 // available of the outputs it spends. So force those to be recomputed
1397 MarkInputsDirty(wtx.tx);
1398 }
1399 }
1400}
1401
1402bool CWallet::SyncTransaction(const CTransactionRef& ptx, const SyncTxState& state, bool update_tx, bool rescanning_old_block)
1403{
1404 if (!AddToWalletIfInvolvingMe(ptx, state, update_tx, rescanning_old_block))
1405 return false; // Not one of ours
1406
1407 // If a transaction changes 'conflicted' state, that changes the balance
1408 // available of the outputs it spends. So force those to be
1409 // recomputed, also:
1410 MarkInputsDirty(ptx);
1411 return true;
1412}
1413
1415 LOCK(cs_wallet);
1417
1418 auto it = mapWallet.find(tx->GetHash());
1419 if (it != mapWallet.end()) {
1420 RefreshMempoolStatus(it->second, chain());
1421 }
1422
1423 const Txid& txid = tx->GetHash();
1424
1425 for (const CTxIn& tx_in : tx->vin) {
1426 // For each wallet transaction spending this prevout..
1427 for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1428 const Txid& spent_id = range.first->second;
1429 // Skip the recently added tx
1430 if (spent_id == txid) continue;
1431 RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1432 return wtx.mempool_conflicts.insert(txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1433 });
1434 }
1435
1436 }
1437
1438 if (tx->version == TRUC_VERSION) {
1439 // Unconfirmed TRUC transactions are only allowed a 1-parent-1-child topology.
1440 // For any unconfirmed v3 parents (there should be a maximum of 1 except in reorgs),
1441 // record this child so the wallet doesn't try to spend any other outputs
1442 for (const CTxIn& tx_in : tx->vin) {
1443 auto parent_it = mapWallet.find(tx_in.prevout.hash);
1444 if (parent_it != mapWallet.end()) {
1445 CWalletTx& parent_wtx = parent_it->second;
1446 if (parent_wtx.isUnconfirmed()) {
1447 parent_wtx.truc_child_in_mempool = tx->GetHash();
1448 // Even though these siblings do not spend the same utxos, they can't
1449 // be present in the mempool at the same time because of TRUC policy rules
1450 UpdateTrucSiblingConflicts(parent_wtx, txid, /*add_conflict=*/true);
1451 }
1452 }
1453 }
1454 }
1455}
1456
1458 LOCK(cs_wallet);
1459 auto it = mapWallet.find(tx->GetHash());
1460 if (it != mapWallet.end()) {
1461 RefreshMempoolStatus(it->second, chain());
1462 }
1463 // Handle transactions that were removed from the mempool because they
1464 // conflict with transactions in a newly connected block.
1465 if (reason == MemPoolRemovalReason::CONFLICT) {
1466 // Trigger external -walletnotify notifications for these transactions.
1467 // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
1468 //
1469 // 1. The transactionRemovedFromMempool callback does not currently
1470 // provide the conflicting block's hash and height, and for backwards
1471 // compatibility reasons it may not be not safe to store conflicted
1472 // wallet transactions with a null block hash. See
1473 // https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1474 // 2. For most of these transactions, the wallet's internal conflict
1475 // detection in the blockConnected handler will subsequently call
1476 // MarkConflicted and update them with CONFLICTED status anyway. This
1477 // applies to any wallet transaction that has inputs spent in the
1478 // block, or that has ancestors in the wallet with inputs spent by
1479 // the block.
1480 // 3. Longstanding behavior since the sync implementation in
1481 // https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1482 // implementation before that was to mark these transactions
1483 // unconfirmed rather than conflicted.
1484 //
1485 // Nothing described above should be seen as an unchangeable requirement
1486 // when improving this code in the future. The wallet's heuristics for
1487 // distinguishing between conflicted and unconfirmed transactions are
1488 // imperfect, and could be improved in general, see
1489 // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1491 }
1492
1493 const Txid& txid = tx->GetHash();
1494
1495 for (const CTxIn& tx_in : tx->vin) {
1496 // Iterate over all wallet transactions spending txin.prev
1497 // and recursively mark them as no longer conflicting with
1498 // txid
1499 for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
1500 const Txid& spent_id = range.first->second;
1501
1502 RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1503 return wtx.mempool_conflicts.erase(txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1504 });
1505 }
1506 }
1507
1508 if (tx->version == TRUC_VERSION) {
1509 // If this tx has a parent, unset its truc_child_in_mempool to make it possible
1510 // to spend from the parent again. If this tx was replaced by another
1511 // child of the same parent, transactionAddedToMempool
1512 // will update truc_child_in_mempool
1513 for (const CTxIn& tx_in : tx->vin) {
1514 auto parent_it = mapWallet.find(tx_in.prevout.hash);
1515 if (parent_it != mapWallet.end()) {
1516 CWalletTx& parent_wtx = parent_it->second;
1517 if (parent_wtx.truc_child_in_mempool == tx->GetHash()) {
1518 parent_wtx.truc_child_in_mempool = std::nullopt;
1519 UpdateTrucSiblingConflicts(parent_wtx, txid, /*add_conflict=*/false);
1520 }
1521 }
1522 }
1523 }
1524}
1525
1527{
1528 if (role.historical) {
1529 return;
1530 }
1531 assert(block.data);
1532 LOCK(cs_wallet);
1533
1534 // Update the best block in memory first. This will set the best block's height, which is
1535 // needed by MarkConflicted.
1537
1538 // No need to scan block if it was created before the wallet birthday.
1539 // Uses chain max time and twice the grace period to adjust time for block time variability.
1540 if (block.chain_time_max < m_birth_time.load() - (TIMESTAMP_WINDOW * 2)) return;
1541
1542 // Scan block
1543 bool wallet_updated = false;
1544 for (size_t index = 0; index < block.data->vtx.size(); index++) {
1545 wallet_updated |= SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)});
1547 }
1548
1549 // Update on disk if this block resulted in us updating a tx, or periodically every 144 blocks (~1 day)
1550 if (wallet_updated || block.height % 144 == 0) {
1552 }
1553}
1554
1556{
1557 assert(block.data);
1558 LOCK(cs_wallet);
1559
1560 // At block disconnection, this will change an abandoned transaction to
1561 // be unconfirmed, whether or not the transaction is added back to the mempool.
1562 // User may have to call abandontransaction again. It may be addressed in the
1563 // future with a stickier abandoned state or even removing abandontransaction call.
1564 int disconnect_height = block.height;
1565
1566 for (size_t index = 0; index < block.data->vtx.size(); index++) {
1567 const CTransactionRef& ptx = block.data->vtx[index];
1568 // Coinbase transactions are not only inactive but also abandoned,
1569 // meaning they should never be relayed standalone via the p2p protocol.
1570 SyncTransaction(ptx, TxStateInactive{/*abandoned=*/index == 0});
1571
1572 for (const CTxIn& tx_in : ptx->vin) {
1573 // No other wallet transactions conflicted with this transaction
1574 if (!mapTxSpends.contains(tx_in.prevout)) continue;
1575
1576 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.prevout);
1577
1578 // For all of the spends that conflict with this transaction
1579 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1580 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1581
1582 if (!wtx.isBlockConflicted()) continue;
1583
1584 auto try_updating_state = [&](CWalletTx& tx) {
1585 if (!tx.isBlockConflicted()) return TxUpdate::UNCHANGED;
1586 if (tx.state<TxStateBlockConflicted>()->conflicting_block_height >= disconnect_height) {
1587 tx.m_state = TxStateInactive{};
1588 return TxUpdate::CHANGED;
1589 }
1590 return TxUpdate::UNCHANGED;
1591 };
1592
1593 RecursiveUpdateTxState(wtx.tx->GetHash(), try_updating_state);
1594 }
1595 }
1596 }
1597
1598 // Update the best block
1599 SetLastBlockProcessed(block.height - 1, *Assert(block.prev_hash));
1600}
1601
1606
1607void CWallet::BlockUntilSyncedToCurrentChain() const {
1609 // Skip the queue-draining stuff if we know we're caught up with
1610 // chain().Tip(), otherwise put a callback in the validation interface queue and wait
1611 // for the queue to drain enough to execute it (indicating we are caught up
1612 // at least with the time we entered this function).
1613 uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1614 chain().waitForNotificationsIfTipChanged(last_block_hash);
1615}
1616
1617// Note that this function doesn't distinguish between a 0-valued input,
1618// and a not-"is mine" input.
1620{
1621 LOCK(cs_wallet);
1622 auto txo = GetTXO(txin.prevout);
1623 if (txo) {
1624 return txo->GetTxOut().nValue;
1625 }
1626 return 0;
1627}
1628
1629bool CWallet::IsMine(const CTxOut& txout) const
1630{
1632 return IsMine(txout.scriptPubKey);
1633}
1634
1635bool CWallet::IsMine(const CTxDestination& dest) const
1636{
1638 return IsMine(GetScriptForDestination(dest));
1639}
1640
1642{
1644
1645 // Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
1646 const auto& it = m_cached_spks.find(script);
1647 if (it != m_cached_spks.end()) {
1648 bool res = false;
1649 for (const auto& spkm : it->second) {
1650 res = res || spkm->IsMine(script);
1651 }
1652 Assume(res);
1653 return res;
1654 }
1655
1656 return false;
1657}
1658
1659bool CWallet::IsMine(const CTransaction& tx) const
1660{
1662 for (const CTxOut& txout : tx.vout)
1663 if (IsMine(txout))
1664 return true;
1665 return false;
1666}
1667
1668bool CWallet::IsMine(const COutPoint& outpoint) const
1669{
1671 auto wtx = GetWalletTx(outpoint.hash);
1672 if (!wtx) {
1673 return false;
1674 }
1675 if (outpoint.n >= wtx->tx->vout.size()) {
1676 return false;
1677 }
1678 return IsMine(wtx->tx->vout[outpoint.n]);
1679}
1680
1681bool CWallet::IsFromMe(const CTransaction& tx) const
1682{
1683 LOCK(cs_wallet);
1684 for (const CTxIn& txin : tx.vin) {
1685 if (GetTXO(txin.prevout)) return true;
1686 }
1687 return false;
1688}
1689
1691{
1692 CAmount nDebit = 0;
1693 for (const CTxIn& txin : tx.vin)
1694 {
1695 nDebit += GetDebit(txin);
1696 if (!MoneyRange(nDebit))
1697 throw std::runtime_error(std::string(__func__) + ": value out of range");
1698 }
1699 return nDebit;
1700}
1701
1703{
1704 // All Active ScriptPubKeyMans must be HD for this to be true
1705 bool result = false;
1706 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1707 if (!spk_man->IsHDEnabled()) return false;
1708 result = true;
1709 }
1710 return result;
1711}
1712
1713bool CWallet::CanGetAddresses(bool internal) const
1714{
1715 LOCK(cs_wallet);
1716 if (m_spk_managers.empty()) return false;
1717 for (OutputType t : OUTPUT_TYPES) {
1718 auto spk_man = GetScriptPubKeyMan(t, internal);
1719 if (spk_man && spk_man->CanGetAddresses(internal)) {
1720 return true;
1721 }
1722 }
1723 return false;
1724}
1725
1727{
1728 WalletBatch batch(GetDatabase());
1729 return SetWalletFlagWithDB(batch, flags);
1730}
1731
1733{
1734 LOCK(cs_wallet);
1736 if (!batch.WriteWalletFlags(m_wallet_flags))
1737 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1738}
1739
1740void CWallet::UnsetWalletFlag(uint64_t flag)
1741{
1742 WalletBatch batch(GetDatabase());
1743 UnsetWalletFlagWithDB(batch, flag);
1744}
1745
1747{
1748 LOCK(cs_wallet);
1749 m_wallet_flags &= ~flag;
1750 if (!batch.WriteWalletFlags(m_wallet_flags))
1751 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1752}
1753
1758
1759bool CWallet::IsWalletFlagSet(uint64_t flag) const
1760{
1761 return (m_wallet_flags & flag);
1762}
1763
1765{
1766 LOCK(cs_wallet);
1767 if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1768 // contains unknown non-tolerable wallet flags
1769 return false;
1770 }
1772
1773 return true;
1774}
1775
1777{
1778 LOCK(cs_wallet);
1779
1780 // We should never be writing unknown non-tolerable wallet flags
1781 assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1782 // This should only be used once, when creating a new wallet - so current flags are expected to be blank
1783 assert(m_wallet_flags == 0);
1784
1785 if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1786 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1787 }
1788
1789 if (!LoadWalletFlags(flags)) assert(false);
1790}
1791
1793{
1794 return m_wallet_flags;
1795}
1796
1798{
1799 int64_t birthtime = m_birth_time.load();
1800 if (time < birthtime) {
1801 m_birth_time = time;
1802 }
1803}
1804
1813int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1814{
1815 // Find starting block. May be null if nCreateTime is greater than the
1816 // highest blockchain timestamp, in which case there is nothing that needs
1817 // to be scanned.
1818 int start_height = 0;
1819 uint256 start_block;
1820 bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1821 WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
1822
1823 if (start) {
1824 // TODO: this should take into account failure by ScanResult::USER_ABORT
1825 ScanResult result = ScanForWalletTransactions(start_block, start_height, /*max_height=*/{}, reserver, /*fUpdate=*/update, /*save_progress=*/false);
1826 if (result.status == ScanResult::FAILURE) {
1827 int64_t time_max;
1828 CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
1829 return time_max + TIMESTAMP_WINDOW + 1;
1830 }
1831 }
1832 return startTime;
1833}
1834
1857CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress)
1858{
1859 constexpr auto INTERVAL_TIME{60s};
1860 auto current_time{reserver.now()};
1861 auto start_time{reserver.now()};
1862
1863 assert(reserver.isReserved());
1864
1865 uint256 block_hash = start_block;
1866 ScanResult result;
1867
1868 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1869 if (chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
1870
1871 WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(),
1872 fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks");
1873
1874 fAbortRescan = false;
1875 ShowProgress(strprintf("[%s] %s", DisplayName(), _("Rescanning…")), 0); // show rescan progress in GUI as dialog or on splashscreen, if rescan required on startup (e.g. due to corruption)
1876 uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1877 uint256 end_hash = tip_hash;
1878 if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
1879 double progress_begin = chain().guessVerificationProgress(block_hash);
1880 double progress_end = chain().guessVerificationProgress(end_hash);
1881 double progress_current = progress_begin;
1882 int block_height = start_height;
1883 while (!fAbortRescan && !chain().shutdownRequested()) {
1884 if (progress_end - progress_begin > 0.0) {
1885 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1886 } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
1888 }
1889 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1890 ShowProgress(strprintf("[%s] %s", DisplayName(), _("Rescanning…")), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1891 }
1892
1893 bool next_interval = reserver.now() >= current_time + INTERVAL_TIME;
1894 if (next_interval) {
1895 current_time = reserver.now();
1896 WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1897 }
1898
1899 bool fetch_block{true};
1900 if (fast_rescan_filter) {
1901 fast_rescan_filter->UpdateIfNeeded();
1902 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1903 if (matches_block.has_value()) {
1904 if (*matches_block) {
1905 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1906 } else {
1907 result.last_scanned_block = block_hash;
1908 result.last_scanned_height = block_height;
1909 fetch_block = false;
1910 }
1911 } else {
1912 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1913 }
1914 }
1915
1916 // Find next block separately from reading data above, because reading
1917 // is slow and there might be a reorg while it is read.
1918 bool block_still_active = false;
1919 bool next_block = false;
1920 uint256 next_block_hash;
1921 chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1922
1923 if (fetch_block) {
1924 // Read block data and locator if needed (the locator is usually null unless we need to save progress)
1925 CBlock block;
1926 CBlockLocator loc;
1927 // Find block
1928 FoundBlock found_block{FoundBlock().data(block)};
1929 if (save_progress && next_interval) found_block.locator(loc);
1930 chain().findBlock(block_hash, found_block);
1931
1932 if (!block.IsNull()) {
1933 LOCK(cs_wallet);
1934 if (!block_still_active) {
1935 // Abort scan if current block is no longer active, to prevent
1936 // marking transactions as coming from the wrong block.
1937 result.last_failed_block = block_hash;
1938 result.status = ScanResult::FAILURE;
1939 break;
1940 }
1941 for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1942 SyncTransaction(block.vtx[posInBlock], TxStateConfirmed{block_hash, block_height, static_cast<int>(posInBlock)}, fUpdate, /*rescanning_old_block=*/true);
1943 }
1944 // scan succeeded, record block as most recent successfully scanned
1945 result.last_scanned_block = block_hash;
1946 result.last_scanned_height = block_height;
1947
1948 if (!loc.IsNull()) {
1949 WalletLogPrintf("Saving scan progress %d.\n", block_height);
1950 WalletBatch batch(GetDatabase());
1951 batch.WriteBestBlock(loc);
1952 }
1953 } else {
1954 // could not scan block, keep scanning but record this block as the most recent failure
1955 result.last_failed_block = block_hash;
1956 result.status = ScanResult::FAILURE;
1957 }
1958 }
1959 if (max_height && block_height >= *max_height) {
1960 break;
1961 }
1962 // If rescanning was triggered with cs_wallet permanently locked (AttachChain), additional blocks that were connected during the rescan
1963 // aren't processed here but will be processed with the pending blockConnected notifications after the lock is released.
1964 // If rescanning without a permanent cs_wallet lock, additional blocks that were added during the rescan will be re-processed if
1965 // the notification was processed and the last block height was updated.
1966 if (block_height >= WITH_LOCK(cs_wallet, return GetLastBlockHeight())) {
1967 break;
1968 }
1969
1970 {
1971 if (!next_block) {
1972 // break successfully when rescan has reached the tip, or
1973 // previous block is no longer on the chain due to a reorg
1974 break;
1975 }
1976
1977 // increment block and verification progress
1978 block_hash = next_block_hash;
1979 ++block_height;
1980 progress_current = chain().guessVerificationProgress(block_hash);
1981
1982 // handle updated tip hash
1983 const uint256 prev_tip_hash = tip_hash;
1984 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1985 if (!max_height && prev_tip_hash != tip_hash) {
1986 // in case the tip has changed, update progress max
1987 progress_end = chain().guessVerificationProgress(tip_hash);
1988 }
1989 }
1990 }
1991 if (!max_height) {
1992 WalletLogPrintf("Scanning current mempool transactions.\n");
1993 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
1994 }
1995 ShowProgress(strprintf("[%s] %s", DisplayName(), _("Rescanning…")), 100); // hide progress dialog in GUI
1996 if (block_height && fAbortRescan) {
1997 WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1999 } else if (block_height && chain().shutdownRequested()) {
2000 WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2002 } else {
2003 WalletLogPrintf("Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.now() - start_time));
2004 }
2005 return result;
2006}
2007
2009 std::string& err_string,
2010 node::TxBroadcast broadcast_method) const
2011{
2013
2014 // Can't relay if wallet is not broadcasting
2015 if (!GetBroadcastTransactions()) return false;
2016 // Don't relay abandoned transactions
2017 if (wtx.isAbandoned()) return false;
2018 // Don't try to submit coinbase transactions. These would fail anyway but would
2019 // cause log spam.
2020 if (wtx.IsCoinBase()) return false;
2021 // Don't try to submit conflicted or confirmed transactions.
2022 if (GetTxDepthInMainChain(wtx) != 0) return false;
2023
2024 const char* what{""};
2025 switch (broadcast_method) {
2027 what = "to mempool and for broadcast to peers";
2028 break;
2030 what = "to mempool without broadcast";
2031 break;
2033 what = "for private broadcast without adding to the mempool";
2034 break;
2035 }
2036 WalletLogPrintf("Submitting wtx %s %s\n", wtx.GetHash().ToString(), what);
2037 // We must set TxStateInMempool here. Even though it will also be set later by the
2038 // entered-mempool callback, if we did not there would be a race where a
2039 // user could call sendmoney in a loop and hit spurious out of funds errors
2040 // because we think that this newly generated transaction's change is
2041 // unavailable as we're not yet aware that it is in the mempool.
2042 //
2043 // If broadcast fails for any reason, trying to set wtx.m_state here would be incorrect.
2044 // If transaction was previously in the mempool, it should be updated when
2045 // TransactionRemovedFromMempool fires.
2046 bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, broadcast_method, err_string);
2047 if (ret) wtx.m_state = TxStateInMempool{};
2048 return ret;
2049}
2050
2051std::set<Txid> CWallet::GetTxConflicts(const CWalletTx& wtx) const
2052{
2054
2055 const Txid myHash{wtx.GetHash()};
2056 std::set<Txid> result{GetConflicts(myHash)};
2057 result.erase(myHash);
2058 return result;
2059}
2060
2062{
2063 // Don't attempt to resubmit if the wallet is configured to not broadcast
2064 if (!fBroadcastTransactions) return false;
2065
2066 // During reindex, importing and IBD, old wallet transactions become
2067 // unconfirmed. Don't resend them as that would spam other nodes.
2068 // We only allow forcing mempool submission when not relaying to avoid this spam.
2069 if (!chain().isReadyToBroadcast()) return false;
2070
2071 // Do this infrequently and randomly to avoid giving away
2072 // that these are our transactions.
2073 if (NodeClock::now() < m_next_resend) return false;
2074
2075 return true;
2076}
2077
2079
2080// Resubmit transactions from the wallet to the mempool, optionally asking the
2081// mempool to relay them. On startup, we will do this for all unconfirmed
2082// transactions but will not ask the mempool to relay them. We do this on startup
2083// to ensure that our own mempool is aware of our transactions. There
2084// is a privacy side effect here as not broadcasting on startup also means that we won't
2085// inform the world of our wallet's state, particularly if the wallet (or node) is not
2086// yet synced.
2087//
2088// Otherwise this function is called periodically in order to relay our unconfirmed txs.
2089// We do this on a random timer to slightly obfuscate which transactions
2090// come from our wallet.
2091//
2092// TODO: Ideally, we'd only resend transactions that we think should have been
2093// mined in the most recent block. Any transaction that wasn't in the top
2094// blockweight of transactions in the mempool shouldn't have been mined,
2095// and so is probably just sitting in the mempool waiting to be confirmed.
2096// Rebroadcasting does nothing to speed up confirmation and only damages
2097// privacy.
2098//
2099// The `force` option results in all unconfirmed transactions being submitted to
2100// the mempool. This does not necessarily result in those transactions being relayed,
2101// that depends on the `broadcast_method` option. Periodic rebroadcast uses the pattern
2102// broadcast_method=TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL force=false, while loading into
2103// the mempool (on start, or after import) uses
2104// broadcast_method=TxBroadcast::MEMPOOL_NO_BROADCAST force=true.
2106{
2107 // Don't attempt to resubmit if the wallet is configured to not broadcast,
2108 // even if forcing.
2109 if (!fBroadcastTransactions) return;
2110
2111 int submitted_tx_count = 0;
2112
2113 { // cs_wallet scope
2114 LOCK(cs_wallet);
2115
2116 // First filter for the transactions we want to rebroadcast.
2117 // We use a set with WalletTxOrderComparator so that rebroadcasting occurs in insertion order
2118 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2119 for (auto& [txid, wtx] : mapWallet) {
2120 // Only rebroadcast unconfirmed txs
2121 if (!wtx.isUnconfirmed()) continue;
2122
2123 // Attempt to rebroadcast all txes more than 5 minutes older than
2124 // the last block, or all txs if forcing.
2125 if (!force && wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
2126 to_submit.insert(&wtx);
2127 }
2128 // Now try submitting the transactions to the memory pool and (optionally) relay them.
2129 for (auto wtx : to_submit) {
2130 std::string unused_err_string;
2131 if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, broadcast_method)) ++submitted_tx_count;
2132 }
2133 } // cs_wallet
2134
2135 if (submitted_tx_count > 0) {
2136 WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2137 }
2138}
2139 // end of mapWallet
2141
2143{
2144 for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
2145 if (!pwallet->ShouldResend()) continue;
2146 pwallet->ResubmitWalletTransactions(node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL, /*force=*/false);
2147 pwallet->SetNextResend();
2148 }
2149}
2150
2151
2153{
2155
2156 // Build coins map
2157 std::map<COutPoint, Coin> coins;
2158 for (auto& input : tx.vin) {
2159 const auto mi = mapWallet.find(input.prevout.hash);
2160 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2161 return false;
2162 }
2163 const CWalletTx& wtx = mi->second;
2164 int prev_height = wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height : 0;
2165 coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], prev_height, wtx.IsCoinBase());
2166 }
2167 std::map<int, bilingual_str> input_errors;
2168 return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
2169}
2170
2171bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
2172{
2173 // Try to sign with all ScriptPubKeyMans
2174 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2175 // spk_man->SignTransaction will return true if the transaction is complete,
2176 // so we can exit early and return true if that happens
2177 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2178 return true;
2179 }
2180 }
2181
2182 // At this point, one input was not fully signed otherwise we would have exited already
2183 return false;
2184}
2185
2186std::optional<PSBTError> CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, std::optional<int> sighash_type, bool sign, bool bip32derivs, size_t * n_signed, bool finalize) const
2187{
2188 if (n_signed) {
2189 *n_signed = 0;
2190 }
2191 LOCK(cs_wallet);
2192 // Get all of the previous transactions
2193 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2194 const CTxIn& txin = psbtx.tx->vin[i];
2195 PSBTInput& input = psbtx.inputs.at(i);
2196
2197 if (PSBTInputSigned(input)) {
2198 continue;
2199 }
2200
2201 // If we have no utxo, grab it from the wallet.
2202 if (!input.non_witness_utxo) {
2203 const Txid& txhash = txin.prevout.hash;
2204 const auto it = mapWallet.find(txhash);
2205 if (it != mapWallet.end()) {
2206 const CWalletTx& wtx = it->second;
2207 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
2208 // The signing code will switch to the smaller witness_utxo if this is ok.
2209 input.non_witness_utxo = wtx.tx;
2210 }
2211 }
2212 }
2213
2214 const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
2215
2216 // Fill in information from ScriptPubKeyMans
2217 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2218 int n_signed_this_spkm = 0;
2219 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize)};
2220 if (error) {
2221 return error;
2222 }
2223
2224 if (n_signed) {
2225 (*n_signed) += n_signed_this_spkm;
2226 }
2227 }
2228
2230
2231 // Complete if every input is now signed
2232 complete = true;
2233 for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
2234 complete &= PSBTInputSignedAndVerified(psbtx, i, &txdata);
2235 }
2236
2237 return {};
2238}
2239
2240SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2241{
2242 SignatureData sigdata;
2243 CScript script_pub_key = GetScriptForDestination(pkhash);
2244 for (const auto& spk_man_pair : m_spk_managers) {
2245 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2246 LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
2247 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2248 }
2249 }
2251}
2252
2253OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
2254{
2255 // If -changetype is specified, always use that change type.
2256 if (change_type) {
2257 return *change_type;
2258 }
2259
2260 // if m_default_address_type is legacy, use legacy address as change.
2262 return OutputType::LEGACY;
2263 }
2264
2265 bool any_tr{false};
2266 bool any_wpkh{false};
2267 bool any_sh{false};
2268 bool any_pkh{false};
2269
2270 for (const auto& recipient : vecSend) {
2271 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2272 any_tr = true;
2273 } else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2274 any_wpkh = true;
2275 } else if (std::get_if<ScriptHash>(&recipient.dest)) {
2276 any_sh = true;
2277 } else if (std::get_if<PKHash>(&recipient.dest)) {
2278 any_pkh = true;
2279 }
2280 }
2281
2282 const bool has_bech32m_spkman(GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/true));
2283 if (has_bech32m_spkman && any_tr) {
2284 // Currently tr is the only type supported by the BECH32M spkman
2285 return OutputType::BECH32M;
2286 }
2287 const bool has_bech32_spkman(GetScriptPubKeyMan(OutputType::BECH32, /*internal=*/true));
2288 if (has_bech32_spkman && any_wpkh) {
2289 // Currently wpkh is the only type supported by the BECH32 spkman
2290 return OutputType::BECH32;
2291 }
2292 const bool has_p2sh_segwit_spkman(GetScriptPubKeyMan(OutputType::P2SH_SEGWIT, /*internal=*/true));
2293 if (has_p2sh_segwit_spkman && any_sh) {
2294 // Currently sh_wpkh is the only type supported by the P2SH_SEGWIT spkman
2295 // As of 2021 about 80% of all SH are wrapping WPKH, so use that
2297 }
2298 const bool has_legacy_spkman(GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true));
2299 if (has_legacy_spkman && any_pkh) {
2300 // Currently pkh is the only type supported by the LEGACY spkman
2301 return OutputType::LEGACY;
2302 }
2303
2304 if (has_bech32m_spkman) {
2305 return OutputType::BECH32M;
2306 }
2307 if (has_bech32_spkman) {
2308 return OutputType::BECH32;
2309 }
2310 // else use m_default_address_type for change
2312}
2313
2314void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
2315{
2316 LOCK(cs_wallet);
2317 WalletLogPrintf("CommitTransaction:\n%s\n", util::RemoveSuffixView(tx->ToString(), "\n"));
2318
2319 // Add tx to wallet, because if it has change it's also ours,
2320 // otherwise just for transaction history.
2321 CWalletTx* wtx = AddToWallet(tx, TxStateInactive{}, [&](CWalletTx& wtx, bool new_tx) {
2322 CHECK_NONFATAL(wtx.mapValue.empty());
2323 CHECK_NONFATAL(wtx.vOrderForm.empty());
2324 wtx.mapValue = std::move(mapValue);
2325 wtx.vOrderForm = std::move(orderForm);
2326 return true;
2327 });
2328
2329 // wtx can only be null if the db write failed.
2330 if (!wtx) {
2331 throw std::runtime_error(std::string(__func__) + ": Wallet db error, transaction commit failed");
2332 }
2333
2334 // Notify that old coins are spent
2335 for (const CTxIn& txin : tx->vin) {
2336 CWalletTx &coin = mapWallet.at(txin.prevout.hash);
2337 coin.MarkDirty();
2339 }
2340
2342 // Don't submit tx to the mempool
2343 return;
2344 }
2345
2346 std::string err_string;
2348 WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2349 // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
2350 }
2351}
2352
2353DBErrors CWallet::PopulateWalletFromDB(bilingual_str& error, std::vector<bilingual_str>& warnings)
2354{
2355 LOCK(cs_wallet);
2356
2357 Assert(m_spk_managers.empty());
2358 Assert(m_wallet_flags == 0);
2359 DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
2360 if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2361 {
2362 if (GetDatabase().Rewrite())
2363 {
2364 for (const auto& spk_man_pair : m_spk_managers) {
2365 spk_man_pair.second->RewriteDB();
2366 }
2367 }
2368 }
2369
2370 if (m_spk_managers.empty()) {
2373 }
2374
2375 const auto wallet_file = m_database->Filename();
2376 switch (nLoadWalletRet) {
2377 case DBErrors::LOAD_OK:
2378 break;
2380 warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
2381 " or address metadata may be missing or incorrect."),
2382 wallet_file));
2383 break;
2385 warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
2386 " Rescanning wallet."), wallet_file));
2387 break;
2388 case DBErrors::CORRUPT:
2389 error = strprintf(_("Error loading %s: Wallet corrupted"), wallet_file);
2390 break;
2391 case DBErrors::TOO_NEW:
2392 error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), wallet_file, CLIENT_NAME);
2393 break;
2395 error = strprintf(_("Error loading %s: External signer wallet being loaded without external signer support compiled"), wallet_file);
2396 break;
2398 error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
2399 break;
2401 error = strprintf(_("Unrecognized descriptor found. Loading wallet %s\n\n"
2402 "The wallet might have been created on a newer version.\n"
2403 "Please try running the latest software version.\n"), wallet_file);
2404 break;
2406 error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
2407 "The wallet might have been tampered with or created with malicious intent.\n"), wallet_file);
2408 break;
2410 error = strprintf(_("Error loading %s: Wallet is a legacy wallet. Please migrate to a descriptor wallet using the migration tool (migratewallet RPC)."), wallet_file);
2411 break;
2413 error = strprintf(_("Error loading %s"), wallet_file);
2414 break;
2415 } // no default case, so the compiler can warn about missing cases
2416 return nLoadWalletRet;
2417}
2418
2419util::Result<void> CWallet::RemoveTxs(std::vector<Txid>& txs_to_remove)
2420{
2422 bilingual_str str_err; // future: make RunWithinTxn return a util::Result
2423 bool was_txn_committed = RunWithinTxn(GetDatabase(), /*process_desc=*/"remove transactions", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2424 util::Result<void> result{RemoveTxs(batch, txs_to_remove)};
2425 if (!result) str_err = util::ErrorString(result);
2426 return result.has_value();
2427 });
2428 if (!str_err.empty()) return util::Error{str_err};
2429 if (!was_txn_committed) return util::Error{_("Error starting/committing db txn for wallet transactions removal process")};
2430 return {}; // all good
2431}
2432
2433util::Result<void> CWallet::RemoveTxs(WalletBatch& batch, std::vector<Txid>& txs_to_remove)
2434{
2436 if (!batch.HasActiveTxn()) return util::Error{strprintf(_("The transactions removal process can only be executed within a db txn"))};
2437
2438 // Check for transaction existence and remove entries from disk
2439 std::vector<decltype(mapWallet)::const_iterator> erased_txs;
2440 bilingual_str str_err;
2441 for (const Txid& hash : txs_to_remove) {
2442 auto it_wtx = mapWallet.find(hash);
2443 if (it_wtx == mapWallet.end()) {
2444 return util::Error{strprintf(_("Transaction %s does not belong to this wallet"), hash.GetHex())};
2445 }
2446 if (!batch.EraseTx(hash)) {
2447 return util::Error{strprintf(_("Failure removing transaction: %s"), hash.GetHex())};
2448 }
2449 erased_txs.emplace_back(it_wtx);
2450 }
2451
2452 // Register callback to update the memory state only when the db txn is actually dumped to disk
2453 batch.RegisterTxnListener({.on_commit=[&, erased_txs]() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2454 // Update the in-memory state and notify upper layers about the removals
2455 for (const auto& it : erased_txs) {
2456 const Txid hash{it->first};
2457 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2458 for (const auto& txin : it->second.tx->vin) {
2459 auto range = mapTxSpends.equal_range(txin.prevout);
2460 for (auto iter = range.first; iter != range.second; ++iter) {
2461 if (iter->second == hash) {
2462 mapTxSpends.erase(iter);
2463 break;
2464 }
2465 }
2466 }
2467 for (unsigned int i = 0; i < it->second.tx->vout.size(); ++i) {
2468 m_txos.erase(COutPoint(hash, i));
2469 }
2470 mapWallet.erase(it);
2472 }
2473
2474 MarkDirty();
2475 }, .on_abort={}});
2476
2477 return {};
2478}
2479
2480bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& new_purpose)
2481{
2482 bool fUpdated = false;
2483 bool is_mine;
2484 std::optional<AddressPurpose> purpose;
2485 {
2486 LOCK(cs_wallet);
2487 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2488 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2489
2490 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2491 record.SetLabel(strName);
2492 is_mine = IsMine(address);
2493 if (new_purpose) { /* update purpose only if requested */
2494 record.purpose = new_purpose;
2495 }
2496 purpose = record.purpose;
2497 }
2498
2499 const std::string& encoded_dest = EncodeDestination(address);
2500 if (new_purpose && !batch.WritePurpose(encoded_dest, PurposeToString(*new_purpose))) {
2501 WalletLogPrintf("Error: fail to write address book 'purpose' entry\n");
2502 return false;
2503 }
2504 if (!batch.WriteName(encoded_dest, strName)) {
2505 WalletLogPrintf("Error: fail to write address book 'name' entry\n");
2506 return false;
2507 }
2508
2509 // In very old wallets, address purpose may not be recorded so we derive it from IsMine
2510 NotifyAddressBookChanged(address, strName, is_mine,
2511 purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND),
2512 (fUpdated ? CT_UPDATED : CT_NEW));
2513 return true;
2514}
2515
2516bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& purpose)
2517{
2518 WalletBatch batch(GetDatabase());
2519 return SetAddressBookWithDB(batch, address, strName, purpose);
2520}
2521
2523{
2524 return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){
2525 return DelAddressBookWithDB(batch, address);
2526 });
2527}
2528
2530{
2531 const std::string& dest = EncodeDestination(address);
2532 {
2533 LOCK(cs_wallet);
2534 // 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.
2535 // NOTE: This isn't a problem for sending addresses because they don't have any data that needs to be kept.
2536 // When adding new address data, it should be considered here whether to retain or delete it.
2537 if (IsMine(address)) {
2538 WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2539 return false;
2540 }
2541 // Delete data rows associated with this address
2542 if (!batch.EraseAddressData(address)) {
2543 WalletLogPrintf("Error: cannot erase address book entry data\n");
2544 return false;
2545 }
2546
2547 // Delete purpose entry
2548 if (!batch.ErasePurpose(dest)) {
2549 WalletLogPrintf("Error: cannot erase address book entry purpose\n");
2550 return false;
2551 }
2552
2553 // Delete name entry
2554 if (!batch.EraseName(dest)) {
2555 WalletLogPrintf("Error: cannot erase address book entry name\n");
2556 return false;
2557 }
2558
2559 // finally, remove it from the map
2560 m_address_book.erase(address);
2561 }
2562
2563 // All good, signal changes
2564 NotifyAddressBookChanged(address, "", /*is_mine=*/false, AddressPurpose::SEND, CT_DELETED);
2565 return true;
2566}
2567
2569{
2571
2572 unsigned int count = 0;
2573 for (auto spk_man : m_external_spk_managers) {
2574 count += spk_man.second->GetKeyPoolSize();
2575 }
2576
2577 return count;
2578}
2579
2580unsigned int CWallet::GetKeyPoolSize() const
2581{
2583
2584 unsigned int count = 0;
2585 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2586 count += spk_man->GetKeyPoolSize();
2587 }
2588 return count;
2589}
2590
2591bool CWallet::TopUpKeyPool(unsigned int kpSize)
2592{
2593 LOCK(cs_wallet);
2594 bool res = true;
2595 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2596 res &= spk_man->TopUp(kpSize);
2597 }
2598 return res;
2599}
2600
2602{
2603 LOCK(cs_wallet);
2604 auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false);
2605 if (!spk_man) {
2606 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2607 }
2608
2609 auto op_dest = spk_man->GetNewDestination(type);
2610 if (op_dest) {
2611 SetAddressBook(*op_dest, label, AddressPurpose::RECEIVE);
2612 }
2613
2614 return op_dest;
2615}
2616
2618{
2619 LOCK(cs_wallet);
2620
2621 ReserveDestination reservedest(this, type);
2622 auto op_dest = reservedest.GetReservedDestination(true);
2623 if (op_dest) reservedest.KeepDestination();
2624
2625 return op_dest;
2626}
2627
2628void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2629 for (auto& entry : mapWallet) {
2630 CWalletTx& wtx = entry.second;
2631 if (wtx.m_is_cache_empty) continue;
2632 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2633 CTxDestination dst;
2634 if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.contains(dst)) {
2635 wtx.MarkDirty();
2636 break;
2637 }
2638 }
2639 }
2640}
2641
2643{
2645 for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2646 const auto& entry = item.second;
2647 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2648 }
2649}
2650
2651std::vector<CTxDestination> CWallet::ListAddrBookAddresses(const std::optional<AddrBookFilter>& _filter) const
2652{
2654 std::vector<CTxDestination> result;
2655 AddrBookFilter filter = _filter ? *_filter : AddrBookFilter();
2656 ForEachAddrBookEntry([&result, &filter](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) {
2657 // Filter by change
2658 if (filter.ignore_change && is_change) return;
2659 // Filter by label
2660 if (filter.m_op_label && *filter.m_op_label != label) return;
2661 // All good
2662 result.emplace_back(dest);
2663 });
2664 return result;
2665}
2666
2667std::set<std::string> CWallet::ListAddrBookLabels(const std::optional<AddressPurpose> purpose) const
2668{
2670 std::set<std::string> label_set;
2671 ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label,
2672 bool _is_change, const std::optional<AddressPurpose>& _purpose) {
2673 if (_is_change) return;
2674 if (!purpose || purpose == _purpose) {
2675 label_set.insert(_label);
2676 }
2677 });
2678 return label_set;
2679}
2680
2682{
2683 m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
2684 if (!m_spk_man) {
2685 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2686 }
2687
2688 if (nIndex == -1) {
2689 int64_t index;
2690 auto op_address = m_spk_man->GetReservedDestination(type, internal, index);
2691 if (!op_address) return op_address;
2692 nIndex = index;
2693 address = *op_address;
2694 }
2695 return address;
2696}
2697
2699{
2700 if (nIndex != -1) {
2701 m_spk_man->KeepDestination(nIndex, type);
2702 }
2703 nIndex = -1;
2705}
2706
2708{
2709 if (nIndex != -1) {
2710 m_spk_man->ReturnDestination(nIndex, fInternal, address);
2711 }
2712 nIndex = -1;
2714}
2715
2717{
2718 CScript scriptPubKey = GetScriptForDestination(dest);
2719 for (const auto& spk_man : GetScriptPubKeyMans(scriptPubKey)) {
2720 auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan *>(spk_man);
2721 if (signer_spk_man == nullptr) {
2722 continue;
2723 }
2725 if (!signer) throw std::runtime_error(util::ErrorString(signer).original);
2726 return signer_spk_man->DisplayAddress(dest, *signer);
2727 }
2728 return util::Error{_("There is no ScriptPubKeyManager for this address")};
2729}
2730
2731void CWallet::LoadLockedCoin(const COutPoint& coin, bool persistent)
2732{
2734 m_locked_coins.emplace(coin, persistent);
2735}
2736
2737bool CWallet::LockCoin(const COutPoint& output, bool persist)
2738{
2740 LoadLockedCoin(output, persist);
2741 if (persist) {
2742 WalletBatch batch(GetDatabase());
2743 return batch.WriteLockedUTXO(output);
2744 }
2745 return true;
2746}
2747
2749{
2751 auto locked_coin_it = m_locked_coins.find(output);
2752 if (locked_coin_it != m_locked_coins.end()) {
2753 bool persisted = locked_coin_it->second;
2754 m_locked_coins.erase(locked_coin_it);
2755 if (persisted) {
2756 WalletBatch batch(GetDatabase());
2757 return batch.EraseLockedUTXO(output);
2758 }
2759 }
2760 return true;
2761}
2762
2764{
2766 bool success = true;
2767 WalletBatch batch(GetDatabase());
2768 for (const auto& [coin, persistent] : m_locked_coins) {
2769 if (persistent) success = success && batch.EraseLockedUTXO(coin);
2770 }
2771 m_locked_coins.clear();
2772 return success;
2773}
2774
2775bool CWallet::IsLockedCoin(const COutPoint& output) const
2776{
2778 return m_locked_coins.contains(output);
2779}
2780
2781void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2782{
2784 for (const auto& [coin, _] : m_locked_coins) {
2785 vOutpts.push_back(coin);
2786 }
2787}
2788
2812unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
2813{
2814 std::optional<uint256> block_hash;
2815 if (auto* conf = wtx.state<TxStateConfirmed>()) {
2816 block_hash = conf->confirmed_block_hash;
2817 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
2818 block_hash = conf->conflicting_block_hash;
2819 }
2820
2821 unsigned int nTimeSmart = wtx.nTimeReceived;
2822 if (block_hash) {
2823 int64_t blocktime;
2824 int64_t block_max_time;
2825 if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) {
2826 if (rescanning_old_block) {
2827 nTimeSmart = block_max_time;
2828 } else {
2829 int64_t latestNow = wtx.nTimeReceived;
2830 int64_t latestEntry = 0;
2831
2832 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2833 int64_t latestTolerated = latestNow + 300;
2834 const TxItems& txOrdered = wtxOrdered;
2835 for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2836 CWalletTx* const pwtx = it->second;
2837 if (pwtx == &wtx) {
2838 continue;
2839 }
2840 int64_t nSmartTime;
2841 nSmartTime = pwtx->nTimeSmart;
2842 if (!nSmartTime) {
2843 nSmartTime = pwtx->nTimeReceived;
2844 }
2845 if (nSmartTime <= latestTolerated) {
2846 latestEntry = nSmartTime;
2847 if (nSmartTime > latestNow) {
2848 latestNow = nSmartTime;
2849 }
2850 break;
2851 }
2852 }
2853
2854 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2855 }
2856 } else {
2857 WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString());
2858 }
2859 }
2860 return nTimeSmart;
2861}
2862
2864{
2865 if (std::get_if<CNoDestination>(&dest))
2866 return false;
2867
2868 if (!used) {
2869 if (auto* data{common::FindKey(m_address_book, dest)}) data->previously_spent = false;
2870 return batch.WriteAddressPreviouslySpent(dest, false);
2871 }
2872
2874 return batch.WriteAddressPreviouslySpent(dest, true);
2875}
2876
2878{
2879 m_address_book[dest].previously_spent = true;
2880}
2881
2882void CWallet::LoadAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& request)
2883{
2884 m_address_book[dest].receive_requests[id] = request;
2885}
2886
2888{
2889 if (auto* data{common::FindKey(m_address_book, dest)}) return data->previously_spent;
2890 return false;
2891}
2892
2893std::vector<std::string> CWallet::GetAddressReceiveRequests() const
2894{
2895 std::vector<std::string> values;
2896 for (const auto& [dest, entry] : m_address_book) {
2897 for (const auto& [id, request] : entry.receive_requests) {
2898 values.emplace_back(request);
2899 }
2900 }
2901 return values;
2902}
2903
2904bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
2905{
2906 if (!batch.WriteAddressReceiveRequest(dest, id, value)) return false;
2907 m_address_book[dest].receive_requests[id] = value;
2908 return true;
2909}
2910
2911bool CWallet::EraseAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id)
2912{
2913 if (!batch.EraseAddressReceiveRequest(dest, id)) return false;
2914 m_address_book[dest].receive_requests.erase(id);
2915 return true;
2916}
2917
2919{
2920 // Do some checking on wallet path. It should be either a:
2921 //
2922 // 1. Path where a directory can be created.
2923 // 2. Path to an existing directory.
2924 // 3. Path to a symlink to a directory.
2925 // 4. For backwards compatibility, the name of a data file in -walletdir.
2926 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
2927 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2928 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2929 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2930 (path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
2932 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2933 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2934 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2935 name, fs::quoted(fs::PathToString(GetWalletDir()))))};
2936 }
2937 return wallet_path;
2938}
2939
2940std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2941{
2942 const auto& wallet_path = GetWalletPath(name);
2943 if (!wallet_path) {
2944 error_string = util::ErrorString(wallet_path);
2946 return nullptr;
2947 }
2948 return MakeDatabase(*wallet_path, options, status, error_string);
2949}
2950
2951bool CWallet::LoadWalletArgs(std::shared_ptr<CWallet> wallet, const WalletContext& context, bilingual_str& error, std::vector<bilingual_str>& warnings)
2952{
2953 interfaces::Chain* chain = context.chain;
2954 const ArgsManager& args = *Assert(context.args);
2955
2956 if (!args.GetArg("-addresstype", "").empty()) {
2957 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-addresstype", ""));
2958 if (!parsed) {
2959 error = strprintf(_("Unknown address type '%s'"), args.GetArg("-addresstype", ""));
2960 return false;
2961 }
2962 wallet->m_default_address_type = parsed.value();
2963 }
2964
2965 if (!args.GetArg("-changetype", "").empty()) {
2966 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-changetype", ""));
2967 if (!parsed) {
2968 error = strprintf(_("Unknown change type '%s'"), args.GetArg("-changetype", ""));
2969 return false;
2970 }
2971 wallet->m_default_change_type = parsed.value();
2972 }
2973
2974 if (const auto arg{args.GetArg("-mintxfee")}) {
2975 std::optional<CAmount> min_tx_fee = ParseMoney(*arg);
2976 if (!min_tx_fee) {
2977 error = AmountErrMsg("mintxfee", *arg);
2978 return false;
2979 } else if (min_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
2980 warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
2981 _("This is the minimum transaction fee you pay on every transaction."));
2982 }
2983
2984 wallet->m_min_fee = CFeeRate{min_tx_fee.value()};
2985 }
2986
2987 if (const auto arg{args.GetArg("-maxapsfee")}) {
2988 const std::string& max_aps_fee{*arg};
2989 if (max_aps_fee == "-1") {
2990 wallet->m_max_aps_fee = -1;
2991 } else if (std::optional<CAmount> max_fee = ParseMoney(max_aps_fee)) {
2992 if (max_fee.value() > HIGH_APS_FEE) {
2993 warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
2994 _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2995 }
2996 wallet->m_max_aps_fee = max_fee.value();
2997 } else {
2998 error = AmountErrMsg("maxapsfee", max_aps_fee);
2999 return false;
3000 }
3001 }
3002
3003 if (const auto arg{args.GetArg("-fallbackfee")}) {
3004 std::optional<CAmount> fallback_fee = ParseMoney(*arg);
3005 if (!fallback_fee) {
3006 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-fallbackfee", *arg);
3007 return false;
3008 } else if (fallback_fee.value() > HIGH_TX_FEE_PER_KB) {
3009 warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
3010 _("This is the transaction fee you may pay when fee estimates are not available."));
3011 }
3012 wallet->m_fallback_fee = CFeeRate{fallback_fee.value()};
3013 }
3014
3015 // Disable fallback fee in case value was set to 0, enable if non-null value
3016 wallet->m_allow_fallback_fee = wallet->m_fallback_fee.GetFeePerK() != 0;
3017
3018 if (const auto arg{args.GetArg("-discardfee")}) {
3019 std::optional<CAmount> discard_fee = ParseMoney(*arg);
3020 if (!discard_fee) {
3021 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-discardfee", *arg);
3022 return false;
3023 } else if (discard_fee.value() > HIGH_TX_FEE_PER_KB) {
3024 warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
3025 _("This is the transaction fee you may discard if change is smaller than dust at this level"));
3026 }
3027 wallet->m_discard_rate = CFeeRate{discard_fee.value()};
3028 }
3029
3030 if (const auto arg{args.GetArg("-maxtxfee")}) {
3031 std::optional<CAmount> max_fee = ParseMoney(*arg);
3032 if (!max_fee) {
3033 error = AmountErrMsg("maxtxfee", *arg);
3034 return false;
3035 } else if (max_fee.value() > HIGH_MAX_TX_FEE) {
3036 warnings.push_back(strprintf(_("%s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee"));
3037 }
3038
3039 if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) {
3040 error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3041 "-maxtxfee", *arg, chain->relayMinFee().ToString());
3042 return false;
3043 }
3044
3045 wallet->m_default_max_tx_fee = max_fee.value();
3046 }
3047
3048 if (const auto arg{args.GetArg("-consolidatefeerate")}) {
3049 if (std::optional<CAmount> consolidate_feerate = ParseMoney(*arg)) {
3050 wallet->m_consolidate_feerate = CFeeRate(*consolidate_feerate);
3051 } else {
3052 error = AmountErrMsg("consolidatefeerate", *arg);
3053 return false;
3054 }
3055 }
3056
3057 if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
3058 warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
3059 _("The wallet will avoid paying less than the minimum relay fee."));
3060 }
3061
3062 wallet->m_confirm_target = args.GetIntArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
3063 wallet->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
3064 wallet->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
3065
3066 wallet->m_keypool_size = std::max(args.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{1});
3067 wallet->m_notify_tx_changed_script = args.GetArg("-walletnotify", "");
3068 wallet->SetBroadcastTransactions(args.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
3069
3070 return true;
3071}
3072
3073std::shared_ptr<CWallet> CWallet::CreateNew(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
3074{
3075 interfaces::Chain* chain = context.chain;
3076 const std::string& walletFile = database->Filename();
3077
3078 const auto start{SteadyClock::now()};
3079 // TODO: Can't use std::make_shared because we need a custom deleter but
3080 // should be possible to use std::allocate_shared.
3081 std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3082
3083 if (!LoadWalletArgs(walletInstance, context, error, warnings)) {
3084 return nullptr;
3085 }
3086
3087 // Initialize version key.
3088 if(!WalletBatch(walletInstance->GetDatabase()).WriteVersion(CLIENT_VERSION)) {
3089 error = strprintf(_("Error creating %s: Could not write version metadata."), walletFile);
3090 return nullptr;
3091 }
3092 {
3093 LOCK(walletInstance->cs_wallet);
3094
3095 // Init with passed flags.
3096 // Always set the cache upgrade flag as this feature is supported from the beginning.
3097 walletInstance->InitWalletFlags(wallet_creation_flags | WALLET_FLAG_LAST_HARDENED_XPUB_CACHED);
3098
3099 // Only descriptor wallets can be created
3100 assert(walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
3101
3102 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
3103 walletInstance->SetupDescriptorScriptPubKeyMans();
3104 }
3105
3106 if (chain) {
3107 std::optional<int> tip_height = chain->getHeight();
3108 if (tip_height) {
3109 walletInstance->SetLastBlockProcessed(*tip_height, chain->getBlockHash(*tip_height));
3110 }
3111 }
3112 }
3113
3114 walletInstance->WalletLogPrintf("Wallet completed creation in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3115
3116 // Try to top up keypool. No-op if the wallet is locked.
3117 walletInstance->TopUpKeyPool();
3118
3119 if (chain && !AttachChain(walletInstance, *chain, /*rescan_required=*/false, error, warnings)) {
3120 walletInstance->DisconnectChainNotifications();
3121 return nullptr;
3122 }
3123
3124 return walletInstance;
3125}
3126
3127std::shared_ptr<CWallet> CWallet::LoadExisting(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, bilingual_str& error, std::vector<bilingual_str>& warnings)
3128{
3129 interfaces::Chain* chain = context.chain;
3130 const std::string& walletFile = database->Filename();
3131
3132 const auto start{SteadyClock::now()};
3133 std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3134
3135 if (!LoadWalletArgs(walletInstance, context, error, warnings)) {
3136 return nullptr;
3137 }
3138
3139 // Load wallet
3140 auto nLoadWalletRet = walletInstance->PopulateWalletFromDB(error, warnings);
3141 bool rescan_required = nLoadWalletRet == DBErrors::NEED_RESCAN;
3142 if (nLoadWalletRet != DBErrors::LOAD_OK && nLoadWalletRet != DBErrors::NONCRITICAL_ERROR && !rescan_required) {
3143 return nullptr;
3144 }
3145
3146 if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3147 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3148 if (spk_man->HavePrivateKeys()) {
3149 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3150 break;
3151 }
3152 }
3153 }
3154
3155 walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3156
3157 // Try to top up keypool. No-op if the wallet is locked.
3158 walletInstance->TopUpKeyPool();
3159
3160 if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
3161 walletInstance->DisconnectChainNotifications();
3162 return nullptr;
3163 }
3164
3165 WITH_LOCK(walletInstance->cs_wallet, walletInstance->LogStats());
3166
3167 return walletInstance;
3168}
3169
3170
3171bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
3172{
3173 LOCK(walletInstance->cs_wallet);
3174 // allow setting the chain if it hasn't been set already but prevent changing it
3175 assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
3176 walletInstance->m_chain = &chain;
3177
3178 // Unless allowed, ensure wallet files are not reused across chains:
3179 if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
3180 WalletBatch batch(walletInstance->GetDatabase());
3181 CBlockLocator locator;
3182 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
3183 // Wallet is assumed to be from another chain, if genesis block in the active
3184 // chain differs from the genesis block known to the wallet.
3185 if (chain.getBlockHash(0) != locator.vHave.back()) {
3186 error = Untranslated("Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3187 return false;
3188 }
3189 }
3190 }
3191
3192 // Register wallet with validationinterface. It's done before rescan to avoid
3193 // missing block connections during the rescan.
3194 // Because of the wallet lock being held, block connection notifications are going to
3195 // be pending on the validation-side until lock release. Blocks that are connected while the
3196 // rescan is ongoing will not be processed in the rescan but with the block connected notifications,
3197 // so the wallet will only be completeley synced after the notifications delivery.
3198 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3199
3200 // If rescan_required = true, rescan_height remains equal to 0
3201 int rescan_height = 0;
3202 if (!rescan_required)
3203 {
3204 WalletBatch batch(walletInstance->GetDatabase());
3205 CBlockLocator locator;
3206 if (batch.ReadBestBlock(locator)) {
3207 if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
3208 rescan_height = *fork_height;
3209 }
3210 }
3211 }
3212
3213 const std::optional<int> tip_height = chain.getHeight();
3214 if (tip_height) {
3215 walletInstance->SetLastBlockProcessedInMem(*tip_height, chain.getBlockHash(*tip_height));
3216 } else {
3217 walletInstance->SetLastBlockProcessedInMem(-1, uint256());
3218 }
3219
3220 if (tip_height && *tip_height != rescan_height)
3221 {
3222 // No need to read and scan block if block was created before
3223 // our wallet birthday (as adjusted for block time variability)
3224 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3225 if (time_first_key) {
3226 FoundBlock found = FoundBlock().height(rescan_height);
3227 chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, found);
3228 if (!found.found) {
3229 // We were unable to find a block that had a time more recent than our earliest timestamp
3230 // or a height higher than the wallet was synced to, indicating that the wallet is newer than the
3231 // current chain tip. Skip rescanning in this case.
3232 rescan_height = *tip_height;
3233 }
3234 }
3235
3236 // Technically we could execute the code below in any case, but performing the
3237 // `while` loop below can make startup very slow, so only check blocks on disk
3238 // if necessary.
3239 if (chain.havePruned() || chain.hasAssumedValidChain()) {
3240 int block_height = *tip_height;
3241 while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3242 --block_height;
3243 }
3244
3245 if (rescan_height != block_height) {
3246 // We can't rescan beyond blocks we don't have data for, stop and throw an error.
3247 // This might happen if a user uses an old wallet within a pruned node
3248 // or if they ran -disablewallet for a longer time, then decided to re-enable
3249 // Exit early and print an error.
3250 // It also may happen if an assumed-valid chain is in use and therefore not
3251 // all block data is available.
3252 // If a block is pruned after this check, we will load the wallet,
3253 // but fail the rescan with a generic error.
3254
3255 error = chain.havePruned() ?
3256 _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of a pruned node)") :
3257 strprintf(_(
3258 "Error loading wallet. Wallet requires blocks to be downloaded, "
3259 "and software does not currently support loading wallets while "
3260 "blocks are being downloaded out of order when using assumeutxo "
3261 "snapshots. Wallet should be able to load successfully after "
3262 "node sync reaches height %s"), block_height);
3263 return false;
3264 }
3265 }
3266
3267 chain.initMessage(_("Rescanning…"));
3268 walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3269
3270 {
3271 WalletRescanReserver reserver(*walletInstance);
3272 if (!reserver.reserve()) {
3273 error = _("Failed to acquire rescan reserver during wallet initialization");
3274 return false;
3275 }
3276 ScanResult scan_res = walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true);
3277 if (ScanResult::SUCCESS != scan_res.status) {
3278 error = _("Failed to rescan the wallet during initialization");
3279 return false;
3280 }
3281 // Set and update the best block record
3282 // Set last block scanned as the last block processed as it may be different in case of a reorg.
3283 // Also save the best block locator because rescanning only updates it intermittently.
3284 walletInstance->SetLastBlockProcessed(*scan_res.last_scanned_height, scan_res.last_scanned_block);
3285 }
3286 }
3287
3288 return true;
3289}
3290
3291const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
3292{
3293 const auto& address_book_it = m_address_book.find(dest);
3294 if (address_book_it == m_address_book.end()) return nullptr;
3295 if ((!allow_change) && address_book_it->second.IsChange()) {
3296 return nullptr;
3297 }
3298 return &address_book_it->second;
3299}
3300
3302{
3303 // Add wallet transactions that aren't already in a block to mempool
3304 // Do this here as mempool requires genesis block to be loaded
3306
3307 // Update wallet transactions with current mempool transactions.
3308 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
3309}
3310
3311bool CWallet::BackupWallet(const std::string& strDest) const
3312{
3314 return GetDatabase().Backup(strDest);
3315}
3316
3318{
3320 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3321 assert(conf->confirmed_block_height >= 0);
3322 return GetLastBlockHeight() - conf->confirmed_block_height + 1;
3323 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
3324 assert(conf->conflicting_block_height >= 0);
3325 return -1 * (GetLastBlockHeight() - conf->conflicting_block_height + 1);
3326 } else {
3327 return 0;
3328 }
3329}
3330
3332{
3334
3335 if (!wtx.IsCoinBase()) {
3336 return 0;
3337 }
3338 int chain_depth = GetTxDepthInMainChain(wtx);
3339 assert(chain_depth >= 0); // coinbase tx should not be conflicted
3340 return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
3341}
3342
3344{
3346
3347 // note GetBlocksToMaturity is 0 for non-coinbase tx
3348 return GetTxBlocksToMaturity(wtx) > 0;
3349}
3350
3352{
3353 if (!HasEncryptionKeys()) {
3354 return false;
3355 }
3356 LOCK(cs_wallet);
3357 return vMasterKey.empty();
3358}
3359
3361{
3362 if (!HasEncryptionKeys())
3363 return false;
3364
3365 {
3367 if (!vMasterKey.empty()) {
3368 memory_cleanse(vMasterKey.data(), vMasterKey.size() * sizeof(decltype(vMasterKey)::value_type));
3369 vMasterKey.clear();
3370 }
3371 }
3372
3373 NotifyStatusChanged(this);
3374 return true;
3375}
3376
3377bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn)
3378{
3379 {
3380 LOCK(cs_wallet);
3381 for (const auto& spk_man_pair : m_spk_managers) {
3382 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3383 return false;
3384 }
3385 }
3386 vMasterKey = vMasterKeyIn;
3387 }
3388 NotifyStatusChanged(this);
3389 return true;
3390}
3391
3392std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
3393{
3394 std::set<ScriptPubKeyMan*> spk_mans;
3395 for (bool internal : {false, true}) {
3396 for (OutputType t : OUTPUT_TYPES) {
3397 auto spk_man = GetScriptPubKeyMan(t, internal);
3398 if (spk_man) {
3399 spk_mans.insert(spk_man);
3400 }
3401 }
3402 }
3403 return spk_mans;
3404}
3405
3407{
3408 for (const auto& [_, ext_spkm] : m_external_spk_managers) {
3409 if (ext_spkm == &spkm) return true;
3410 }
3411 for (const auto& [_, int_spkm] : m_internal_spk_managers) {
3412 if (int_spkm == &spkm) return true;
3413 }
3414 return false;
3415}
3416
3417std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
3418{
3419 std::set<ScriptPubKeyMan*> spk_mans;
3420 for (const auto& spk_man_pair : m_spk_managers) {
3421 spk_mans.insert(spk_man_pair.second.get());
3422 }
3423 return spk_mans;
3424}
3425
3427{
3428 const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
3429 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3430 if (it == spk_managers.end()) {
3431 return nullptr;
3432 }
3433 return it->second;
3434}
3435
3436std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script) const
3437{
3438 std::set<ScriptPubKeyMan*> spk_mans;
3439
3440 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3441 const auto& it = m_cached_spks.find(script);
3442 if (it != m_cached_spks.end()) {
3443 spk_mans.insert(it->second.begin(), it->second.end());
3444 }
3445 SignatureData sigdata;
3446 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3447
3448 return spk_mans;
3449}
3450
3452{
3453 if (m_spk_managers.contains(id)) {
3454 return m_spk_managers.at(id).get();
3455 }
3456 return nullptr;
3457}
3458
3459std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3460{
3461 SignatureData sigdata;
3462 return GetSolvingProvider(script, sigdata);
3463}
3464
3465std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3466{
3467 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3468 const auto& it = m_cached_spks.find(script);
3469 if (it != m_cached_spks.end()) {
3470 // All spkms for a given script must already be able to make a SigningProvider for the script, so just return the first one.
3471 Assume(it->second.at(0)->CanProvide(script, sigdata));
3472 return it->second.at(0)->GetSolvingProvider(script);
3473 }
3474
3475 return nullptr;
3476}
3477
3478std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const
3479{
3480 std::vector<WalletDescriptor> descs;
3481 for (const auto spk_man: GetScriptPubKeyMans(script)) {
3482 if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3483 LOCK(desc_spk_man->cs_desc_man);
3484 descs.push_back(desc_spk_man->GetWalletDescriptor());
3485 }
3486 }
3487 return descs;
3488}
3489
3491{
3493 return nullptr;
3494 }
3496 if (it == m_internal_spk_managers.end()) return nullptr;
3497 return dynamic_cast<LegacyDataSPKM*>(it->second);
3498}
3499
3500void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man)
3501{
3502 // Add spkm_man to m_spk_managers before calling any method
3503 // that might access it.
3504 const auto& spkm = m_spk_managers[id] = std::move(spkm_man);
3505
3506 // Update birth time if needed
3507 MaybeUpdateBirthTime(spkm->GetTimeFirstKey());
3508}
3509
3515
3517{
3519 return;
3520 }
3521
3522 Assert(m_database->Format() == "bdb_ro" || m_database->Format() == "mock");
3523 std::unique_ptr<ScriptPubKeyMan> spk_manager = std::make_unique<LegacyDataSPKM>(*this);
3524
3525 for (const auto& type : LEGACY_OUTPUT_TYPES) {
3526 m_internal_spk_managers[type] = spk_manager.get();
3527 m_external_spk_managers[type] = spk_manager.get();
3528 }
3529 uint256 id = spk_manager->GetID();
3530 AddScriptPubKeyMan(id, std::move(spk_manager));
3531}
3532
3533bool CWallet::WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const
3534{
3535 LOCK(cs_wallet);
3536 return cb(vMasterKey);
3537}
3538
3540{
3541 return !mapMasterKeys.empty();
3542}
3543
3545{
3546 for (const auto& spkm : GetAllScriptPubKeyMans()) {
3547 if (spkm->HaveCryptedKeys()) return true;
3548 }
3549 return false;
3550}
3551
3553{
3554 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3555 spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3556 spk_man->NotifyFirstKeyTimeChanged.connect([this](const ScriptPubKeyMan*, int64_t time) {
3558 });
3559 }
3560}
3561
3563{
3564 DescriptorScriptPubKeyMan* spk_manager;
3566 spk_manager = new ExternalSignerScriptPubKeyMan(*this, desc, m_keypool_size);
3567 } else {
3568 spk_manager = new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size);
3569 }
3570 AddScriptPubKeyMan(id, std::unique_ptr<ScriptPubKeyMan>(spk_manager));
3571 return *spk_manager;
3572}
3573
3574DescriptorScriptPubKeyMan& CWallet::SetupDescriptorScriptPubKeyMan(WalletBatch& batch, const CExtKey& master_key, const OutputType& output_type, bool internal)
3575{
3577 auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, m_keypool_size));
3578 if (HasEncryptionKeys()) {
3579 if (IsLocked()) {
3580 throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3581 }
3582 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3583 throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3584 }
3585 }
3586 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3587 DescriptorScriptPubKeyMan* out = spk_manager.get();
3588 uint256 id = spk_manager->GetID();
3589 AddScriptPubKeyMan(id, std::move(spk_manager));
3590 AddActiveScriptPubKeyManWithDb(batch, id, output_type, internal);
3591 return *out;
3592}
3593
3595{
3597 for (bool internal : {false, true}) {
3598 for (OutputType t : OUTPUT_TYPES) {
3599 SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
3600 }
3601 }
3602}
3603
3605{
3608 // Make a seed
3609 CKey seed_key = GenerateRandomKey();
3610 CPubKey seed = seed_key.GetPubKey();
3611 assert(seed_key.VerifyPubKey(seed));
3612
3613 // Get the extended key
3614 CExtKey master_key;
3615 master_key.SetSeed(seed_key);
3616
3617 SetupDescriptorScriptPubKeyMans(batch, master_key);
3618}
3619
3621{
3623
3625 if (!RunWithinTxn(GetDatabase(), /*process_desc=*/"setup descriptors", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet){
3627 return true;
3628 })) throw std::runtime_error("Error: cannot process db transaction for descriptors setup");
3629 } else {
3631 if (!signer) throw std::runtime_error(util::ErrorString(signer).original);
3632
3633 // TODO: add account parameter
3634 int account = 0;
3635 UniValue signer_res = signer->GetDescriptors(account);
3636
3637 if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3638
3639 WalletBatch batch(GetDatabase());
3640 if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors import");
3641
3642 for (bool internal : {false, true}) {
3643 const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
3644 if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3645 for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
3646 const std::string& desc_str = desc_val.getValStr();
3648 std::string desc_error;
3649 auto descs = Parse(desc_str, keys, desc_error, false);
3650 if (descs.empty()) {
3651 throw std::runtime_error(std::string(__func__) + ": Invalid descriptor \"" + desc_str + "\" (" + desc_error + ")");
3652 }
3653 auto& desc = descs.at(0);
3654 if (!desc->GetOutputType()) {
3655 continue;
3656 }
3657 OutputType t = *desc->GetOutputType();
3658 auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, m_keypool_size));
3659 spk_manager->SetupDescriptor(batch, std::move(desc));
3660 uint256 id = spk_manager->GetID();
3661 AddScriptPubKeyMan(id, std::move(spk_manager));
3662 AddActiveScriptPubKeyManWithDb(batch, id, t, internal);
3663 }
3664 }
3665
3666 // Ensure imported descriptors are committed to disk
3667 if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors import");
3668 }
3669}
3670
3672{
3673 WalletBatch batch(GetDatabase());
3674 return AddActiveScriptPubKeyManWithDb(batch, id, type, internal);
3675}
3676
3678{
3679 if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
3680 throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
3681 }
3682 LoadActiveScriptPubKeyMan(id, type, internal);
3683}
3684
3686{
3687 // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
3688 // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
3690
3691 WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3692 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3693 auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
3694 auto spk_man = m_spk_managers.at(id).get();
3695 spk_mans[type] = spk_man;
3696
3697 const auto it = spk_mans_other.find(type);
3698 if (it != spk_mans_other.end() && it->second == spk_man) {
3699 spk_mans_other.erase(type);
3700 }
3701
3703}
3704
3706{
3707 auto spk_man = GetScriptPubKeyMan(type, internal);
3708 if (spk_man != nullptr && spk_man->GetID() == id) {
3709 WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3710 WalletBatch batch(GetDatabase());
3711 if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3712 throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3713 }
3714
3715 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3716 spk_mans.erase(type);
3717 }
3718
3720}
3721
3723{
3724 auto spk_man_pair = m_spk_managers.find(desc.id);
3725
3726 if (spk_man_pair != m_spk_managers.end()) {
3727 // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
3728 DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair->second.get());
3729 if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3730 return spk_manager;
3731 }
3732 }
3733
3734 return nullptr;
3735}
3736
3737std::optional<bool> CWallet::IsInternalScriptPubKeyMan(ScriptPubKeyMan* spk_man) const
3738{
3739 // only active ScriptPubKeyMan can be internal
3740 if (!GetActiveScriptPubKeyMans().contains(spk_man)) {
3741 return std::nullopt;
3742 }
3743
3744 const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
3745 if (!desc_spk_man) {
3746 throw std::runtime_error(std::string(__func__) + ": unexpected ScriptPubKeyMan type.");
3747 }
3748
3749 LOCK(desc_spk_man->cs_desc_man);
3750 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3751 assert(type.has_value());
3752
3753 return GetScriptPubKeyMan(*type, /* internal= */ true) == desc_spk_man;
3754}
3755
3757{
3759
3761
3762 auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3763 if (spk_man) {
3764 WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
3765 if (auto spkm_res = spk_man->UpdateWalletDescriptor(desc); !spkm_res) {
3766 return util::Error{util::ErrorString(spkm_res)};
3767 }
3768 } else {
3769 auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size));
3770 spk_man = new_spk_man.get();
3771
3772 // Save the descriptor to memory
3773 uint256 id = new_spk_man->GetID();
3774 AddScriptPubKeyMan(id, std::move(new_spk_man));
3775 }
3776
3777 // Add the private keys to the descriptor
3778 for (const auto& entry : signing_provider.keys) {
3779 const CKey& key = entry.second;
3780 spk_man->AddDescriptorKey(key, key.GetPubKey());
3781 }
3782
3783 // Top up key pool, the manager will generate new scriptPubKeys internally
3784 if (!spk_man->TopUp()) {
3785 return util::Error{_("Could not top up scriptPubKeys")};
3786 }
3787
3788 // Apply the label if necessary
3789 // Note: we disable labels for ranged descriptors
3790 if (!desc.descriptor->IsRange()) {
3791 auto script_pub_keys = spk_man->GetScriptPubKeys();
3792 if (script_pub_keys.empty()) {
3793 return util::Error{_("Could not generate scriptPubKeys (cache is empty)")};
3794 }
3795
3796 if (!internal) {
3797 for (const auto& script : script_pub_keys) {
3798 CTxDestination dest;
3799 if (ExtractDestination(script, dest)) {
3801 }
3802 }
3803 }
3804 }
3805
3806 // Save the descriptor to DB
3807 spk_man->WriteDescriptor();
3808
3809 // Break balance caches so that outputs that are now IsMine in already known txs will be included in the balance
3810 MarkDirty();
3811
3812 return std::reference_wrapper(*spk_man);
3813}
3814
3816{
3818
3819 WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3820
3821 if (m_database->Format() == "sqlite") {
3822 error = _("Error: This wallet already uses SQLite");
3823 return false;
3824 }
3825
3826 // Get all of the records for DB type migration
3827 std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
3828 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3829 std::vector<std::pair<SerializeData, SerializeData>> records;
3830 if (!cursor) {
3831 error = _("Error: Unable to begin reading all records in the database");
3832 return false;
3833 }
3835 while (true) {
3836 DataStream ss_key{};
3837 DataStream ss_value{};
3838 status = cursor->Next(ss_key, ss_value);
3839 if (status != DatabaseCursor::Status::MORE) {
3840 break;
3841 }
3842 SerializeData key(ss_key.begin(), ss_key.end());
3843 SerializeData value(ss_value.begin(), ss_value.end());
3844 records.emplace_back(key, value);
3845 }
3846 cursor.reset();
3847 batch.reset();
3848 if (status != DatabaseCursor::Status::DONE) {
3849 error = _("Error: Unable to read all records in the database");
3850 return false;
3851 }
3852
3853 // Close this database and delete the file
3854 fs::path db_path = fs::PathFromString(m_database->Filename());
3855 m_database->Close();
3856 fs::remove(db_path);
3857
3858 // Generate the path for the location of the migrated wallet
3859 // Wallets that are plain files rather than wallet directories will be migrated to be wallet directories.
3860 const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(m_name));
3861
3862 // Make new DB
3863 DatabaseOptions opts;
3864 opts.require_create = true;
3866 DatabaseStatus db_status;
3867 std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
3868 assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
3869 m_database.reset();
3870 m_database = std::move(new_db);
3871
3872 // Write existing records into the new DB
3873 batch = m_database->MakeBatch();
3874 bool began = batch->TxnBegin();
3875 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.
3876 for (const auto& [key, value] : records) {
3877 if (!batch->Write(std::span{key}, std::span{value})) {
3878 batch->TxnAbort();
3879 m_database->Close();
3880 fs::remove(m_database->Filename());
3881 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.
3882 }
3883 }
3884 bool committed = batch->TxnCommit();
3885 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.
3886 return true;
3887}
3888
3889std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& error) const
3890{
3892
3893 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
3894 if (!Assume(legacy_spkm)) {
3895 // This shouldn't happen
3896 error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
3897 return std::nullopt;
3898 }
3899
3900 std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
3901 if (res == std::nullopt) {
3902 error = _("Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
3903 return std::nullopt;
3904 }
3905 return res;
3906}
3907
3909{
3911
3912 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
3913 if (!Assume(legacy_spkm)) {
3914 // This shouldn't happen
3915 return util::Error{Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"))};
3916 }
3917
3918 // Note: when the legacy wallet has no spendable scripts, it must be empty at the end of the process.
3919 bool has_spendable_material = !data.desc_spkms.empty() || data.master_key.key.IsValid();
3920
3921 // Get all invalid or non-watched scripts that will not be migrated
3922 std::set<CTxDestination> not_migrated_dests;
3923 for (const auto& script : legacy_spkm->GetNotMineScriptPubKeys()) {
3924 CTxDestination dest;
3925 if (ExtractDestination(script, dest)) not_migrated_dests.emplace(dest);
3926 }
3927
3928 // When the legacy wallet has no spendable scripts, the main wallet will be empty, leaving its script cache empty as well.
3929 // The watch-only and/or solvable wallet(s) will contain the scripts in their respective caches.
3930 if (!data.desc_spkms.empty()) Assume(!m_cached_spks.empty());
3931 if (!data.watch_descs.empty()) Assume(!data.watchonly_wallet->m_cached_spks.empty());
3932 if (!data.solvable_descs.empty()) Assume(!data.solvable_wallet->m_cached_spks.empty());
3933
3934 for (auto& desc_spkm : data.desc_spkms) {
3935 if (m_spk_managers.contains(desc_spkm->GetID())) {
3936 return util::Error{_("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
3937 }
3938 uint256 id = desc_spkm->GetID();
3939 AddScriptPubKeyMan(id, std::move(desc_spkm));
3940 }
3941
3942 // Remove the LegacyScriptPubKeyMan from disk
3943 if (!legacy_spkm->DeleteRecordsWithDB(local_wallet_batch)) {
3944 return util::Error{_("Error: cannot remove legacy wallet records")};
3945 }
3946
3947 // Remove the LegacyScriptPubKeyMan from memory
3948 m_spk_managers.erase(legacy_spkm->GetID());
3951
3952 // Setup new descriptors (only if we are migrating any key material)
3954 if (has_spendable_material && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3955 // Use the existing master key if we have it
3956 if (data.master_key.key.IsValid()) {
3957 SetupDescriptorScriptPubKeyMans(local_wallet_batch, data.master_key);
3958 } else {
3959 // Setup with a new seed if we don't.
3960 SetupOwnDescriptorScriptPubKeyMans(local_wallet_batch);
3961 }
3962 }
3963
3964 // Get best block locator so that we can copy it to the watchonly and solvables
3965 CBlockLocator best_block_locator;
3966 if (!local_wallet_batch.ReadBestBlock(best_block_locator)) {
3967 return util::Error{_("Error: Unable to read wallet's best block locator record")};
3968 }
3969
3970 // Update m_txos to match the descriptors remaining in this wallet
3971 m_txos.clear();
3973
3974 // Check if the transactions in the wallet are still ours. Either they belong here, or they belong in the watchonly wallet.
3975 // We need to go through these in the tx insertion order so that lookups to spends works.
3976 std::vector<Txid> txids_to_delete;
3977 std::unique_ptr<WalletBatch> watchonly_batch;
3978 if (data.watchonly_wallet) {
3979 watchonly_batch = std::make_unique<WalletBatch>(data.watchonly_wallet->GetDatabase());
3980 if (!watchonly_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.watchonly_wallet->GetName())};
3981 // Copy the next tx order pos to the watchonly wallet
3982 LOCK(data.watchonly_wallet->cs_wallet);
3983 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
3984 watchonly_batch->WriteOrderPosNext(data.watchonly_wallet->nOrderPosNext);
3985 // Write the best block locator to avoid rescanning on reload
3986 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
3987 return util::Error{_("Error: Unable to write watchonly wallet best block locator record")};
3988 }
3989 }
3990 std::unique_ptr<WalletBatch> solvables_batch;
3991 if (data.solvable_wallet) {
3992 solvables_batch = std::make_unique<WalletBatch>(data.solvable_wallet->GetDatabase());
3993 if (!solvables_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.solvable_wallet->GetName())};
3994 // Write the best block locator to avoid rescanning on reload
3995 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
3996 return util::Error{_("Error: Unable to write solvable wallet best block locator record")};
3997 }
3998 }
3999 for (const auto& [_pos, wtx] : wtxOrdered) {
4000 // Check it is the watchonly wallet's
4001 // solvable_wallet doesn't need to be checked because transactions for those scripts weren't being watched for
4002 bool is_mine = IsMine(*wtx->tx) || IsFromMe(*wtx->tx);
4003 if (data.watchonly_wallet) {
4004 LOCK(data.watchonly_wallet->cs_wallet);
4005 if (data.watchonly_wallet->IsMine(*wtx->tx) || data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4006 // Add to watchonly wallet
4007 const Txid& hash = wtx->GetHash();
4008 const CWalletTx& to_copy_wtx = *wtx;
4009 if (!data.watchonly_wallet->LoadToWallet(hash, [&](CWalletTx& ins_wtx, bool new_tx) EXCLUSIVE_LOCKS_REQUIRED(data.watchonly_wallet->cs_wallet) {
4010 if (!new_tx) return false;
4011 ins_wtx.SetTx(to_copy_wtx.tx);
4012 ins_wtx.CopyFrom(to_copy_wtx);
4013 return true;
4014 })) {
4015 return util::Error{strprintf(_("Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
4016 }
4017 watchonly_batch->WriteTx(data.watchonly_wallet->mapWallet.at(hash));
4018 // Mark as to remove from the migrated wallet only if it does not also belong to it
4019 if (!is_mine) {
4020 txids_to_delete.push_back(hash);
4021 }
4022 continue;
4023 }
4024 }
4025 if (!is_mine) {
4026 // Both not ours and not in the watchonly wallet
4027 return util::Error{strprintf(_("Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
4028 }
4029 }
4030
4031 // Do the removes
4032 if (txids_to_delete.size() > 0) {
4033 if (auto res = RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
4034 return util::Error{_("Error: Could not delete watchonly transactions. ") + util::ErrorString(res)};
4035 }
4036 }
4037
4038 // Pair external wallets with their corresponding db handler
4039 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4040 if (data.watchonly_wallet) wallets_vec.emplace_back(data.watchonly_wallet, std::move(watchonly_batch));
4041 if (data.solvable_wallet) wallets_vec.emplace_back(data.solvable_wallet, std::move(solvables_batch));
4042
4043 // Write address book entry to disk
4044 auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
4045 auto address{EncodeDestination(dest)};
4046 if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
4047 if (entry.label) batch.WriteName(address, *entry.label);
4048 for (const auto& [id, request] : entry.receive_requests) {
4049 batch.WriteAddressReceiveRequest(dest, id, request);
4050 }
4051 if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
4052 };
4053
4054 // Check the address book data in the same way we did for transactions
4055 std::vector<CTxDestination> dests_to_delete;
4056 for (const auto& [dest, record] : m_address_book) {
4057 // Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
4058 // Entries for everything else ("send") will be cloned to all wallets.
4059 bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
4060 bool copied = false;
4061 for (auto& [wallet, batch] : wallets_vec) {
4062 LOCK(wallet->cs_wallet);
4063 if (require_transfer && !wallet->IsMine(dest)) continue;
4064
4065 // Copy the entire address book entry
4066 wallet->m_address_book[dest] = record;
4067 func_store_addr(*batch, dest, record);
4068
4069 copied = true;
4070 // Only delete 'receive' records that are no longer part of the original wallet
4071 if (require_transfer) {
4072 dests_to_delete.push_back(dest);
4073 break;
4074 }
4075 }
4076
4077 // Fail immediately if we ever found an entry that was ours and cannot be transferred
4078 // to any of the created wallets (watch-only, solvable).
4079 // Means that no inferred descriptor maps to the stored entry. Which mustn't happen.
4080 if (require_transfer && !copied) {
4081
4082 // Skip invalid/non-watched scripts that will not be migrated
4083 if (not_migrated_dests.contains(dest)) {
4084 dests_to_delete.push_back(dest);
4085 continue;
4086 }
4087
4088 return util::Error{_("Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4089 }
4090 }
4091
4092 // Persist external wallets address book entries
4093 for (auto& [wallet, batch] : wallets_vec) {
4094 if (!batch->TxnCommit()) {
4095 return util::Error{strprintf(_("Error: Unable to write data to disk for wallet %s"), wallet->GetName())};
4096 }
4097 }
4098
4099 // Remove the things to delete in this wallet
4100 if (dests_to_delete.size() > 0) {
4101 for (const auto& dest : dests_to_delete) {
4102 if (!DelAddressBookWithDB(local_wallet_batch, dest)) {
4103 return util::Error{_("Error: Unable to remove watchonly address book data")};
4104 }
4105 }
4106 }
4107
4108 // If there was no key material in the main wallet, there should be no records on it anymore.
4109 // This wallet will be discarded at the end of the process. Only wallets that contain the
4110 // migrated records will be presented to the user.
4111 if (!has_spendable_material) {
4112 if (!m_address_book.empty()) return util::Error{_("Error: Not all address book records were migrated")};
4113 if (!mapWallet.empty()) return util::Error{_("Error: Not all transaction records were migrated")};
4114 }
4115
4116 return {}; // all good
4117}
4118
4123
4124// Returns wallet prefix for migration.
4125// Used to name the backup file and newly created wallets.
4126// E.g. a watch-only wallet is named "<prefix>_watchonly".
4128{
4129 const std::string& name{wallet.GetName()};
4130 return name.empty() ? "default_wallet" : name;
4131}
4132
4134{
4135 AssertLockHeld(wallet.cs_wallet);
4136
4137 // Get all of the descriptors from the legacy wallet
4138 std::optional<MigrationData> data = wallet.GetDescriptorsForLegacy(error);
4139 if (data == std::nullopt) return false;
4140
4141 // Create the watchonly and solvable wallets if necessary
4142 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4143 DatabaseOptions options;
4144 options.require_existing = false;
4145 options.require_create = true;
4147
4148 WalletContext empty_context;
4149 empty_context.args = context.args;
4150
4151 // Make the wallets
4153 if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
4155 }
4156 if (wallet.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
4158 }
4159 if (data->watch_descs.size() > 0) {
4160 wallet.WalletLogPrintf("Making a new watchonly wallet containing the watched scripts\n");
4161
4162 DatabaseStatus status;
4163 std::vector<bilingual_str> warnings;
4164 std::string wallet_name = MigrationPrefixName(wallet) + "_watchonly";
4165 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4166 if (!database) {
4167 error = strprintf(_("Wallet file creation failed: %s"), error);
4168 return false;
4169 }
4170
4171 data->watchonly_wallet = CWallet::CreateNew(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4172 if (!data->watchonly_wallet) {
4173 error = _("Error: Failed to create new watchonly wallet");
4174 return false;
4175 }
4176 res.watchonly_wallet = data->watchonly_wallet;
4177 LOCK(data->watchonly_wallet->cs_wallet);
4178
4179 // Parse the descriptors and add them to the new wallet
4180 for (const auto& [desc_str, creation_time] : data->watch_descs) {
4181 // Parse the descriptor
4183 std::string parse_err;
4184 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /*require_checksum=*/ true);
4185 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4186 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4187
4188 // Add to the wallet
4189 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4190 if (auto spkm_res = data->watchonly_wallet->AddWalletDescriptor(w_desc, keys, "", false); !spkm_res) {
4191 throw std::runtime_error(util::ErrorString(spkm_res).original);
4192 }
4193 }
4194
4195 // Add the wallet to settings
4196 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4197 }
4198 if (data->solvable_descs.size() > 0) {
4199 wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
4200
4201 DatabaseStatus status;
4202 std::vector<bilingual_str> warnings;
4203 std::string wallet_name = MigrationPrefixName(wallet) + "_solvables";
4204 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4205 if (!database) {
4206 error = strprintf(_("Wallet file creation failed: %s"), error);
4207 return false;
4208 }
4209
4210 data->solvable_wallet = CWallet::CreateNew(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4211 if (!data->solvable_wallet) {
4212 error = _("Error: Failed to create new watchonly wallet");
4213 return false;
4214 }
4215 res.solvables_wallet = data->solvable_wallet;
4216 LOCK(data->solvable_wallet->cs_wallet);
4217
4218 // Parse the descriptors and add them to the new wallet
4219 for (const auto& [desc_str, creation_time] : data->solvable_descs) {
4220 // Parse the descriptor
4222 std::string parse_err;
4223 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /*require_checksum=*/ true);
4224 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4225 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4226
4227 // Add to the wallet
4228 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4229 if (auto spkm_res = data->solvable_wallet->AddWalletDescriptor(w_desc, keys, "", false); !spkm_res) {
4230 throw std::runtime_error(util::ErrorString(spkm_res).original);
4231 }
4232 }
4233
4234 // Add the wallet to settings
4235 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4236 }
4237 }
4238
4239 // Add the descriptors to wallet, remove LegacyScriptPubKeyMan, and cleanup txs and address book data
4240 return RunWithinTxn(wallet.GetDatabase(), /*process_desc=*/"apply migration process", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet){
4241 if (auto res_migration = wallet.ApplyMigrationData(batch, *data); !res_migration) {
4242 error = util::ErrorString(res_migration);
4243 return false;
4244 }
4245 wallet.WalletLogPrintf("Wallet migration complete.\n");
4246 return true;
4247 });
4248}
4249
4250util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context)
4251{
4252 std::vector<bilingual_str> warnings;
4253 bilingual_str error;
4254
4255 // The only kind of wallets that could be loaded are descriptor ones, which don't need to be migrated.
4256 if (auto wallet = GetWallet(context, wallet_name)) {
4257 assert(wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
4258 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4259 } else {
4260 // Check if the wallet is BDB
4261 const auto& wallet_path = GetWalletPath(wallet_name);
4262 if (!wallet_path) {
4263 return util::Error{util::ErrorString(wallet_path)};
4264 }
4265 if (!fs::exists(*wallet_path)) {
4266 return util::Error{_("Error: Wallet does not exist")};
4267 }
4268 if (!IsBDBFile(BDBDataFile(*wallet_path))) {
4269 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4270 }
4271 }
4272
4273 // Load the wallet but only in the context of this function.
4274 // No signals should be connected nor should anything else be aware of this wallet
4275 WalletContext empty_context;
4276 empty_context.args = context.args;
4277 DatabaseOptions options;
4278 options.require_existing = true;
4280 DatabaseStatus status;
4281 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4282 if (!database) {
4283 return util::Error{Untranslated("Wallet file verification failed.") + Untranslated(" ") + error};
4284 }
4285
4286 // Make the local wallet
4287 std::shared_ptr<CWallet> local_wallet = CWallet::LoadExisting(empty_context, wallet_name, std::move(database), error, warnings);
4288 if (!local_wallet) {
4289 return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
4290 }
4291
4292 return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context);
4293}
4294
4295util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context)
4296{
4297 MigrationResult res;
4298 bilingual_str error;
4299 std::vector<bilingual_str> warnings;
4300
4301 DatabaseOptions options;
4302 options.require_existing = true;
4303 DatabaseStatus status;
4304
4305 const std::string wallet_name = local_wallet->GetName();
4306
4307 // Before anything else, check if there is something to migrate.
4308 if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4309 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4310 }
4311
4312 // Make a backup of the DB in the wallet's directory with a unique filename
4313 // using the wallet name and current timestamp. The backup filename is based
4314 // on the name of the parent directory containing the wallet data in most
4315 // cases, but in the case where the wallet name is a path to a data file,
4316 // the name of the data file is used, and in the case where the wallet name
4317 // is blank, "default_wallet" is used.
4318 const std::string backup_prefix = wallet_name.empty() ? MigrationPrefixName(*local_wallet) : [&] {
4319 // fs::weakly_canonical resolves relative specifiers and remove trailing slashes.
4320 const auto legacy_wallet_path = fs::weakly_canonical(GetWalletDir() / fs::PathFromString(wallet_name));
4321 return fs::PathToString(legacy_wallet_path.filename());
4322 }();
4323
4324 fs::path backup_filename = fs::PathFromString(strprintf("%s_%d.legacy.bak", backup_prefix, GetTime()));
4325 fs::path backup_path = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
4326 if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4327 return util::Error{_("Error: Unable to make a backup of your wallet")};
4328 }
4329 res.backup_path = backup_path;
4330
4331 bool success = false;
4332
4333 // Unlock the wallet if needed
4334 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4335 if (passphrase.find('\0') == std::string::npos) {
4336 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4337 } else {
4338 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4339 "The passphrase contains a null character (ie - a zero byte). "
4340 "If this passphrase was set with a version of this software prior to 25.0, "
4341 "please try again with only the characters up to — but not including — "
4342 "the first null character.")};
4343 }
4344 }
4345
4346 // Indicates whether the current wallet is empty after migration.
4347 // Notes:
4348 // When non-empty: the local wallet becomes the main spendable wallet.
4349 // When empty: The local wallet is excluded from the result, as the
4350 // user does not expect an empty spendable wallet after
4351 // migrating only watch-only scripts.
4352 bool empty_local_wallet = false;
4353
4354 {
4355 LOCK(local_wallet->cs_wallet);
4356 // First change to using SQLite
4357 if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
4358
4359 // Do the migration of keys and scripts for non-empty wallets, and cleanup if it fails
4360 if (HasLegacyRecords(*local_wallet)) {
4361 success = DoMigration(*local_wallet, context, error, res);
4362 // No scripts mean empty wallet after migration
4363 empty_local_wallet = local_wallet->GetAllScriptPubKeyMans().empty();
4364 } else {
4365 // Make sure that descriptors flag is actually set
4366 local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
4367 success = true;
4368 }
4369 }
4370
4371 // In case of loading failure, we need to remember the wallet files we have created to remove.
4372 // A `set` is used as it may be populated with the same wallet directory paths multiple times,
4373 // both before and after loading. This ensures the set is complete even if one of the wallets
4374 // fails to load.
4375 std::set<fs::path> wallet_files_to_remove;
4376 std::set<fs::path> wallet_empty_dirs_to_remove;
4377
4378 // Helper to track wallet files and directories for cleanup on failure.
4379 // Only directories of wallets created during migration (not the main wallet) are tracked.
4380 auto track_for_cleanup = [&](const CWallet& wallet) {
4381 const auto files = wallet.GetDatabase().Files();
4382 wallet_files_to_remove.insert(files.begin(), files.end());
4383 if (wallet.GetName() != wallet_name) {
4384 // If this isn’t the main wallet, mark its directory for removal.
4385 // This applies to the watch-only and solvable wallets.
4386 // Wallets stored directly as files in the top-level directory
4387 // (e.g. default unnamed wallets) don’t have a removable parent directory.
4388 wallet_empty_dirs_to_remove.insert(fs::PathFromString(wallet.GetDatabase().Filename()).parent_path());
4389 }
4390 };
4391
4392
4393 if (success) {
4394 Assume(!res.wallet); // We will set it here.
4395 // Check if the local wallet is empty after migration
4396 if (empty_local_wallet) {
4397 // This wallet has no records. We can safely remove it.
4398 std::vector<fs::path> paths_to_remove = local_wallet->GetDatabase().Files();
4399 local_wallet.reset();
4400 for (const auto& path_to_remove : paths_to_remove) fs::remove(path_to_remove);
4401 }
4402
4403 LogInfo("Loading new wallets after migration...\n");
4404 // Migration successful, load all the migrated wallets.
4405 for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
4406 if (success && *wallet_ptr) {
4407 std::shared_ptr<CWallet>& wallet = *wallet_ptr;
4408 // Track db path and load wallet
4409 track_for_cleanup(*wallet);
4410 assert(wallet.use_count() == 1);
4411 std::string wallet_name = wallet->GetName();
4412 wallet.reset();
4413 wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4414 if (!wallet) {
4415 LogError("Failed to load wallet '%s' after migration. Rolling back migration to preserve consistency. "
4416 "Error cause: %s\n", wallet_name, error.original);
4417 success = false;
4418 break;
4419 }
4420
4421 // Set the first successfully loaded wallet as the main one.
4422 // The loop order is intentional and must always start with the local wallet.
4423 if (!res.wallet) {
4424 res.wallet_name = wallet->GetName();
4425 res.wallet = std::move(wallet);
4426 }
4427 }
4428 }
4429 }
4430 if (!success) {
4431 // Make list of wallets to cleanup
4432 std::vector<std::shared_ptr<CWallet>> created_wallets;
4433 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4434 if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
4435 if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
4436
4437 // Get the directories to remove after unloading
4438 for (std::shared_ptr<CWallet>& wallet : created_wallets) {
4439 track_for_cleanup(*wallet);
4440 }
4441
4442 // Unload the wallets
4443 for (std::shared_ptr<CWallet>& w : created_wallets) {
4444 if (w->HaveChain()) {
4445 // Unloading for wallets that were loaded for normal use
4446 if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
4447 error += _("\nUnable to cleanup failed migration");
4448 return util::Error{error};
4449 }
4450 WaitForDeleteWallet(std::move(w));
4451 } else {
4452 // Unloading for wallets in local context
4453 assert(w.use_count() == 1);
4454 w.reset();
4455 }
4456 }
4457
4458 // First, delete the db files we have created throughout this process and nothing else
4459 for (const fs::path& file : wallet_files_to_remove) {
4460 fs::remove(file);
4461 }
4462
4463 // Second, delete the created wallet directories and nothing else. They must be empty at this point.
4464 for (const fs::path& dir : wallet_empty_dirs_to_remove) {
4465 Assume(fs::is_empty(dir));
4466 fs::remove(dir);
4467 }
4468
4469 // Restore the backup
4470 // Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.
4471 bilingual_str restore_error;
4472 const auto& ptr_wallet = RestoreWallet(context, backup_path, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings, /*load_after_restore=*/false, /*allow_unnamed=*/true);
4473 if (!restore_error.empty()) {
4474 error += restore_error + _("\nUnable to restore backup of wallet.");
4475 return util::Error{error};
4476 }
4477 // Verify that the legacy wallet is not loaded after restoring from the backup.
4478 assert(!ptr_wallet);
4479
4480 return util::Error{error};
4481 }
4482 return res;
4483}
4484
4485void CWallet::CacheNewScriptPubKeys(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4486{
4487 for (const auto& script : spks) {
4488 m_cached_spks[script].push_back(spkm);
4489 }
4490}
4491
4492void CWallet::TopUpCallback(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4493{
4494 // Update scriptPubKey cache
4495 CacheNewScriptPubKeys(spks, spkm);
4496}
4497
4498std::set<CExtPubKey> CWallet::GetActiveHDPubKeys() const
4499{
4501
4503
4504 std::set<CExtPubKey> active_xpubs;
4505 for (const auto& spkm : GetActiveScriptPubKeyMans()) {
4506 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4507 assert(desc_spkm);
4508 LOCK(desc_spkm->cs_desc_man);
4509 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
4510
4511 std::set<CPubKey> desc_pubkeys;
4512 std::set<CExtPubKey> desc_xpubs;
4513 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4514 active_xpubs.merge(std::move(desc_xpubs));
4515 }
4516 return active_xpubs;
4517}
4518
4519std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const
4520{
4522
4523 for (const auto& spkm : GetAllScriptPubKeyMans()) {
4524 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4525 assert(desc_spkm);
4526 LOCK(desc_spkm->cs_desc_man);
4527 if (std::optional<CKey> key = desc_spkm->GetKey(keyid)) {
4528 return key;
4529 }
4530 }
4531 return std::nullopt;
4532}
4533
4535{
4537
4538 if (!m_last_block_processed.IsNull()) {
4539 CBlockLocator loc;
4540 chain().findBlock(m_last_block_processed, FoundBlock().locator(loc));
4541
4542 if (!loc.IsNull()) {
4543 WalletBatch batch(GetDatabase());
4544 batch.WriteBestBlock(loc);
4545 }
4546 }
4547}
4548
4550{
4552 for (uint32_t i = 0; i < wtx.tx->vout.size(); ++i) {
4553 const CTxOut& txout = wtx.tx->vout.at(i);
4554 if (!IsMine(txout)) continue;
4555 COutPoint outpoint(wtx.GetHash(), i);
4556 if (m_txos.contains(outpoint)) {
4557 } else {
4558 m_txos.emplace(outpoint, WalletTXO{wtx, txout});
4559 }
4560 }
4561}
4562
4564{
4566 for (const auto& [_, wtx] : mapWallet) {
4567 RefreshTXOsFromTx(wtx);
4568 }
4569}
4570
4571std::optional<WalletTXO> CWallet::GetTXO(const COutPoint& outpoint) const
4572{
4574 const auto& it = m_txos.find(outpoint);
4575 if (it == m_txos.end()) {
4576 return std::nullopt;
4577 }
4578 return it->second;
4579}
4580
4589
4590} // namespace wallet
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:151
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:163
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
bool MoneyRange(const CAmount &nValue)
Definition amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative).
Definition amount.h:12
ArgsManager gArgs
Definition args.cpp:40
int ret
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition string.h:246
int flags
ArgsManager & args
Definition bitcoind.cpp:277
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
Definition chain.h:37
#define CHECK_NONFATAL(condition)
Identity function.
Definition check.h:109
#define Assert(val)
Identity function.
Definition check.h:113
#define STR_INTERNAL_BUG(msg)
Definition check.h:96
#define Assume(val)
Assume is the identity function.
Definition check.h:125
bool IsNull() const
Definition block.h:54
Definition block.h:74
std::vector< CTransactionRef > vtx
Definition block.h:77
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
Definition feerate.h:32
An encapsulated private key.
Definition key.h:36
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:183
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition key.cpp:237
A reference to a CKey: the Hash160 of its serialized public key.
Definition pubkey.h:24
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:29
uint32_t n
Definition transaction.h:32
An encapsulated public key.
Definition pubkey.h:34
Serialized script, used inside transaction inputs and outputs.
Definition script.h:405
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const Txid & GetHash() const LIFETIMEBOUND
const std::vector< CTxIn > vin
An input of a transaction.
Definition transaction.h:62
COutPoint prevout
Definition transaction.h:64
An output of a transaction.
CScript scriptPubKey
void MarkDestinationsDirty(const std::set< CTxDestination > &destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks all outputs in each one of the destinations dirty, so their cache is reset and does not return ...
Definition wallet.cpp:2628
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
Definition wallet.cpp:2516
bool TopUpKeyPool(unsigned int kpSize=0)
Definition wallet.cpp:2591
bool HaveChain() const
Interface to assert chain access.
Definition wallet.h:494
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
Definition wallet.h:857
DBErrors PopulateWalletFromDB(bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:2353
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2580
std::optional< WalletTXO > GetTXO(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:4571
bool IsActiveScriptPubKeyMan(const ScriptPubKeyMan &spkm) const
Definition wallet.cpp:3406
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, bool rescan_required, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
Definition wallet.cpp:3171
static std::shared_ptr< CWallet > LoadExisting(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:3127
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Definition wallet.cpp:3671
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Definition wallet.cpp:3685
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2775
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
Definition wallet.cpp:2152
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
Definition wallet.h:477
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
Definition wallet.cpp:3459
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3343
void RefreshAllTXOs() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Cache outputs that belong to the wallet for all transactions in the wallet.
Definition wallet.cpp:4563
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
Definition wallet.cpp:3677
void TopUpCallback(const std::set< CScript > &spks, ScriptPubKeyMan *spkm) override
Definition wallet.cpp:4492
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
Definition wallet.cpp:3392
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3291
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
Definition wallet.cpp:3301
int GetTxDepthInMainChain(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition wallet.cpp:3317
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, std::optional< int > sighash_type=std::nullopt, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
Definition wallet.cpp:2186
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2904
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition wallet.h:986
LegacyDataSPKM * GetLegacyDataSPKM() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition wallet.cpp:3490
void DisconnectChainNotifications()
Disconnect chain notifications and wait for all notifications to be processed.
Definition wallet.cpp:4581
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
Definition wallet.cpp:2651
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
Definition wallet.cpp:3722
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
Definition wallet.cpp:3562
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
Definition wallet.cpp:3889
bool HaveCryptedKeys() const
Definition wallet.cpp:3544
LegacyDataSPKM * GetOrCreateLegacyDataSPKM()
Definition wallet.cpp:3510
interfaces::Chain & chain() const
Interface for accessing chain state.
Definition wallet.h:520
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition wallet.h:470
bool Unlock(const CKeyingMaterial &vMasterKeyIn)
Definition wallet.cpp:3377
bool MigrateToSQLite(bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Move all records from the BDB database to a new SQLite database for storage.
Definition wallet.cpp:3815
bool BackupWallet(const std::string &strDest) const
Definition wallet.cpp:3311
bool SetAddressPreviouslySpent(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2863
util::Result< void > RemoveTxs(std::vector< Txid > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
Definition wallet.cpp:2419
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2893
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
Definition wallet.cpp:3478
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2568
void CacheNewScriptPubKeys(const std::set< CScript > &spks, ScriptPubKeyMan *spkm)
Add scriptPubKeys for this ScriptPubKeyMan into the scriptPubKey cache.
Definition wallet.cpp:4485
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3331
void WalletLogPrintf(util::ConstevalFormatString< sizeof...(Params)> wallet_fmt, const Params &... params) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition wallet.h:938
bool HasEncryptionKeys() const override
Definition wallet.cpp:3539
bool CanGrindR() const
Whether the (external) signer performs R-value signature grinding.
Definition wallet.cpp:4119
util::Result< CTxDestination > GetNewChangeDestination(OutputType type)
Definition wallet.cpp:2617
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Definition wallet.cpp:3737
void LoadLockedCoin(const COutPoint &coin, bool persistent) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2731
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Definition wallet.cpp:2240
boost::signals2::signal< void(const Txid &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition wallet.h:842
util::Result< void > ApplyMigrationData(WalletBatch &local_wallet_batch, MigrationData &data) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3908
bool Lock()
Definition wallet.cpp:3360
WalletDatabase & GetDatabase() const override
Definition wallet.h:462
std::optional< CKey > GetKey(const CKeyID &keyid) const
Definition wallet.cpp:4519
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2911
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
Definition wallet.cpp:2480
void WriteBestBlock() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Write the current best block to database.
Definition wallet.cpp:4534
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition wallet.h:845
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
Definition wallet.cpp:2529
std::string DisplayName() const
Return wallet name for display, like LogName() but translates "default wallet" string.
Definition wallet.h:930
void LoadAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &request) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Appends payment request to destination.
Definition wallet.cpp:2882
void AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
Definition wallet.cpp:3500
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Definition wallet.cpp:3705
bool LockCoin(const COutPoint &output, bool persist) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2737
std::set< CExtPubKey > GetActiveHDPubKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve the xpubs in use by the active descriptors.
Definition wallet.cpp:4498
bool IsLocked() const override
Definition wallet.cpp:3351
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
Definition wallet.cpp:2253
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Definition wallet.h:848
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
Definition wallet.cpp:3417
void RefreshTXOsFromTx(const CWalletTx &wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Cache outputs that belong to the wallet from a single transaction.
Definition wallet.cpp:4549
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
Definition wallet.cpp:2812
std::set< std::string > ListAddrBookLabels(std::optional< AddressPurpose > purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
Definition wallet.cpp:2667
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2781
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string > > orderForm)
Submit the transaction to the node's mempool and then relay to peers.
Definition wallet.cpp:2314
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2763
util::Result< CTxDestination > GetNewDestination(OutputType type, const std::string &label)
Definition wallet.cpp:2601
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition wallet.cpp:3426
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2887
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Definition wallet.cpp:3533
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.h:992
RecursiveMutex cs_wallet
Main wallet lock.
Definition wallet.h:460
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2642
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
Definition wallet.cpp:3552
static std::shared_ptr< CWallet > CreateNew(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:3073
bool DelAddressBook(const CTxDestination &address)
Definition wallet.cpp:2522
void SetupLegacyScriptPubKeyMan()
Make a Legacy(Data)SPKM and set it for all types, internal, and external.
Definition wallet.cpp:3516
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, AddressPurpose purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition wallet.h:836
void SetupOwnDescriptorScriptPubKeyMans(WalletBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new seed and default DescriptorScriptPubKeyMans for this wallet.
Definition wallet.cpp:3604
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
Definition wallet.h:854
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3620
DescriptorScriptPubKeyMan & SetupDescriptorScriptPubKeyMan(WalletBatch &batch, const CExtKey &master_key, const OutputType &output_type, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMan and add it to the wallet.
Definition wallet.cpp:3574
bool UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2748
void LoadAddressPreviouslySpent(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks destination as previously spent.
Definition wallet.cpp:2877
util::Result< std::reference_wrapper< DescriptorScriptPubKeyMan > > AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
Definition wallet.cpp:3756
static bool LoadWalletArgs(std::shared_ptr< CWallet > wallet, const WalletContext &context, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:2951
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
Definition wallet.cpp:3436
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition wallet.cpp:2716
A UTXO entry.
Definition coins.h:35
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:133
const_iterator begin() const
Definition streams.h:163
const_iterator end() const
Definition streams.h:165
Fast randomness source.
Definition random.h:386
std::unordered_set< Element, ByteVectorHash > ElementSet
Definition blockfilter.h:33
Different type to mark Mutex at global scope.
Definition sync.h:134
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
Definition random.h:329
void push_back(UniValue val)
Definition univalue.cpp:103
bool isArray() const
Definition univalue.h:87
const UniValue & find_value(std::string_view key) const
Definition univalue.cpp:232
size_t size() const
Definition univalue.h:71
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
bool isObject() const
Definition univalue.h:88
std::string ToString() const
Definition uint256.cpp:21
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
virtual bool updateRwSetting(const std::string &name, const SettingsUpdate &update_function)=0
virtual void waitForNotifications()=0
Wait for all pending notifications up to this point to be processed.
virtual bool isInMempool(const Txid &txid)=0
Check if transaction is in mempool.
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
virtual double guessVerificationProgress(const uint256 &block_hash)=0
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, node::TxBroadcast broadcast_method, std::string &err_string)=0
FoundBlock & locator(CBlockLocator &locator)
Return locator if block is in the active chain.
Definition chain.h:63
FoundBlock & height(int &height)
Definition chain.h:56
FoundBlock & data(CBlock &data)
Definition chain.h:68
256-bit opaque blob.
Definition uint256.h:195
bool has_value() const noexcept
Definition result.h:64
Encryption/decryption context with key information.
Definition crypter.h:72
bool Decrypt(std::span< const unsigned char > ciphertext, CKeyingMaterial &plaintext) const
Definition crypter.cpp:94
bool SetKeyFromPassphrase(const SecureString &key_data, std::span< const unsigned char > salt, unsigned int rounds, unsigned int derivation_method)
Definition crypter.cpp:41
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
Definition crypter.cpp:76
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
Definition crypter.h:35
std::vector< unsigned char > vchSalt
Definition crypter.h:38
unsigned int nDerivationMethod
0 = EVP_sha512()
Definition crypter.h:40
std::vector< unsigned char > vchCryptedKey
Definition crypter.h:37
unsigned int nDeriveIterations
Definition crypter.h:41
static constexpr unsigned int DEFAULT_DERIVE_ITERATIONS
Default/minimum number of key derivation rounds.
Definition crypter.h:48
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition wallet.h:310
std::atomic< bool > fAbortRescan
Definition wallet.h:316
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Definition wallet.h:620
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
Definition wallet.h:741
OutputType m_default_address_type
Definition wallet.h:732
static std::shared_ptr< CWallet > LoadExisting(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:3127
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
Definition wallet.h:399
std::function< void(const CTxDestination &dest, const std::string &label, bool is_change, const std::optional< AddressPurpose > purpose)> ListAddrBookFunc
Walk-through the address book entries.
Definition wallet.h:774
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3291
unsigned int nMasterKeyMaxID
Definition wallet.h:474
std::atomic< double > m_scanning_progress
Definition wallet.h:320
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
Definition wallet.h:417
interfaces::Chain & chain() const
Interface for accessing chain state.
Definition wallet.h:520
std::unique_ptr< interfaces::Handler > m_chain_notifications_handler
Registered interfaces::Chain::Notifications handler.
Definition wallet.h:517
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
Definition wallet.h:418
std::string m_name
Wallet name: relative directory name or "" for default wallet.
Definition wallet.h:396
RecursiveMutex m_relock_mutex
Definition wallet.h:597
std::string m_notify_tx_changed_script
Notify external script when a wallet transaction comes in or is updated (handled by -walletnotify).
Definition wallet.h:747
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
Definition wallet.h:327
TxItems wtxOrdered
Definition wallet.h:501
MasterKeyMap mapMasterKeys
Definition wallet.h:473
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
Definition wallet.h:324
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
Definition wallet.h:382
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Definition wallet.h:848
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process,...
Definition wallet.h:744
RecursiveMutex cs_wallet
Main wallet lock.
Definition wallet.h:460
friend class WalletRescanReserver
Definition wallet.h:321
std::atomic< int64_t > m_best_block_time
Definition wallet.h:329
std::unordered_map< CScript, std::vector< ScriptPubKeyMan * >, SaltedSipHasher > m_cached_spks
Cache of descriptor ScriptPubKeys used for IsMine. Maps ScriptPubKey to set of spkms.
Definition wallet.h:435
std::multimap< int64_t, CWalletTx * > TxItems
Definition wallet.h:500
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
Definition wallet.h:422
std::function< TxUpdate(CWalletTx &wtx)> TryUpdatingStateFn
Definition wallet.h:368
std::atomic< int64_t > m_birth_time
Definition wallet.h:333
A transaction with a bunch of additional info that only the owner cares about.
bool isBlockConflicted() const
const Txid & GetHash() const LIFETIMEBOUND
const T * state() const
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
std::vector< std::pair< std::string, std::string > > vOrderForm
std::set< Txid > mempool_conflicts
mapValue_t mapValue
Key/value map with information about the transaction.
void updateState(interfaces::Chain &chain)
int64_t nOrderPos
position in ordered transaction list
bool isUnconfirmed() const
unsigned int nTimeReceived
time received by this node
CTransactionRef tx
void SetTx(CTransactionRef arg)
bool IsCoinBase() const
bool InMempool() const
bool isAbandoned() const
std::optional< Txid > truc_child_in_mempool
bool isInactive() const
int64_t GetTxTime() const
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
void MarkDirty()
make sure balances are recalculated
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
std::optional< CKey > GetKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet,...
bool HasWalletDescriptor(const WalletDescriptor &desc) const
static util::Result< ExternalSigner > GetExternalSigner()
bool DeleteRecordsWithDB(WalletBatch &batch)
Delete all the records of this LegacyScriptPubKeyMan from disk.
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
uint256 GetID() const override
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid,...
A wrapper to reserve an address from a wallet.
Definition wallet.h:198
const CWallet *const pwallet
The wallet to reserve from.
Definition wallet.h:201
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
Definition wallet.cpp:2698
CTxDestination address
The destination.
Definition wallet.h:208
bool fInternal
Whether this is from the internal (change output) keypool.
Definition wallet.h:210
void ReturnDestination()
Return reserved address.
Definition wallet.cpp:2707
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called.
Definition wallet.h:203
int64_t nIndex
The index of the address's key in the keypool.
Definition wallet.h:206
OutputType const type
Definition wallet.h:204
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
Definition wallet.cpp:2681
Access to the wallet database.
Definition walletdb.h:193
bool TxnAbort()
Abort current transaction.
bool EraseName(const std::string &strAddress)
Definition walletdb.cpp:81
DBErrors LoadWallet(CWallet *pwallet)
bool WriteBestBlock(const CBlockLocator &locator)
Definition walletdb.cpp:177
void RegisterTxnListener(const DbTxnListener &l)
Registers db txn callback functions.
bool ReadBestBlock(CBlockLocator &locator)
Definition walletdb.cpp:183
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition walletdb.cpp:151
bool WriteWalletFlags(uint64_t flags)
bool TxnBegin()
Begin a new transaction.
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition walletdb.cpp:76
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition walletdb.cpp:88
bool EraseAddressData(const CTxDestination &dest)
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition walletdb.cpp:200
bool WriteTx(const CWalletTx &wtx)
Definition walletdb.cpp:98
bool ErasePurpose(const std::string &strAddress)
Definition walletdb.cpp:93
bool EraseLockedUTXO(const COutPoint &output)
Definition walletdb.cpp:287
bool WriteLockedUTXO(const COutPoint &output)
Definition walletdb.cpp:282
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition walletdb.cpp:205
bool WriteVersion(int client_version)
Write the given client_version.
Definition walletdb.h:269
bool EraseTx(Txid hash)
Definition walletdb.cpp:103
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
Definition walletdb.cpp:211
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
Descriptor with some wallet metadata.
Definition walletutil.h:64
std::shared_ptr< Descriptor > descriptor
Definition walletutil.h:66
Clock::time_point now() const
Definition wallet.h:1116
bool reserve(bool with_passphrase=false)
Definition wallet.h:1098
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition cleanse.cpp:14
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition client.cpp:395
static const int CLIENT_VERSION
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition string.cpp:11
std::string ShellEscape(const std::string &arg)
Definition system.cpp:41
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
Definition consensus.h:19
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1012
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
Definition wallet.cpp:940
void RecursiveUpdateTxState(const Txid &tx_hash, const TryUpdatingStateFn &try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction (and its in-wallet descendants) as a particular tx state.
Definition wallet.cpp:1358
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
Definition wallet.cpp:1280
bool HasWalletSpend(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet.
Definition wallet.cpp:712
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition wallet.cpp:641
bool AbandonTransaction(const Txid &hashTx)
Definition wallet.cpp:1290
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:729
void SetWalletFlagWithDB(WalletBatch &batch, uint64_t flags)
Store wallet flags.
Definition wallet.cpp:1732
static bool EncryptMasterKey(const SecureString &wallet_passphrase, const CKeyingMaterial &plain_master_key, CMasterKey &master_key)
Definition wallet.cpp:580
uint64_t GetWalletFlags() const
Retrieve all of the wallet's flags.
Definition wallet.cpp:1792
void updatedBlockTip() override
Definition wallet.cpp:1602
bool TransactionCanBeAbandoned(const Txid &hashTx) const
Return whether transaction can be abandoned.
Definition wallet.cpp:1256
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(void SetWalletFlag(uint64_t flags)
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
Definition wallet.cpp:1726
void MaybeUpdateBirthTime(int64_t time)
Updates wallet birth time if 'time' is below it.
Definition wallet.cpp:1797
void blockDisconnected(const interfaces::BlockInfo &block) override
Definition wallet.cpp:1555
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate, bool save_progress)
Scan the block chain (starting in start_block) for transactions from or to us.
Definition wallet.cpp:1857
std::set< Txid > GetConflicts(const Txid &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs).
Definition wallet.cpp:689
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition wallet.cpp:1759
static bool DecryptMasterKey(const SecureString &wallet_passphrase, const CMasterKey &master_key, CKeyingMaterial &plain_master_key)
Definition wallet.cpp:607
void AddToSpends(const COutPoint &outpoint, const Txid &txid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:787
void SetLastBlockProcessedInMem(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:673
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
Definition wallet.cpp:1746
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
Definition wallet.cpp:770
void ResubmitWalletTransactions(node::TxBroadcast broadcast_method, bool force)
Definition wallet.cpp:2105
std::set< Txid > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2051
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
Definition wallet.cpp:1754
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
Definition wallet.cpp:1025
bool MarkReplaced(const Txid &originalHash, const Txid &newHash)
Mark a transaction as replaced by another transaction.
Definition wallet.cpp:961
bool CanGetAddresses(bool internal=false) const
Definition wallet.cpp:1713
void MarkDirty()
Definition wallet.cpp:952
void UpdateTrucSiblingConflicts(const CWalletTx &parent_wtx, const Txid &child_txid, bool add_conflict) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Update mempool conflicts for TRUC sibling transactions.
Definition wallet.cpp:1263
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
Definition wallet.cpp:1764
bool IsHDEnabled() const
Definition wallet.cpp:1702
bool SubmitTxMemoryPoolAndRelay(CWalletTx &wtx, std::string &err_string, node::TxBroadcast broadcast_method) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for optional mempool insertion and relay to peers.
Definition wallet.cpp:2008
void blockConnected(const kernel::ChainstateRole &role, const interfaces::BlockInfo &block) override
Definition wallet.cpp:1526
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
Definition wallet.cpp:1457
static NodeClock::time_point GetDefaultNextResend()
Definition wallet.cpp:2078
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
Definition wallet.cpp:2061
const CWalletTx * GetWalletTx(const Txid &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:556
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
Definition wallet.cpp:1776
bool SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1402
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
Definition wallet.cpp:1740
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition wallet.cpp:808
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Set last block processed height, and write to database.
Definition wallet.cpp:681
bool LoadToWallet(const Txid &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1156
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition wallet.cpp:1813
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
Definition wallet.cpp:1681
DBErrors ReorderTransactions()
Definition wallet.cpp:883
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, const SyncTxState &state, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
Definition wallet.cpp:1190
bool IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1635
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
Definition wallet.cpp:565
void SetSpentKeyState(WalletBatch &batch, const Txid &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:993
CAmount GetDebit(const CTxIn &txin) const
Returns amount of debit, i.e.
Definition wallet.cpp:1619
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const Txid &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
Definition wallet.cpp:1328
void transactionAddedToMempool(const CTransactionRef &tx) override
Definition wallet.cpp:1414
void Close()
Close wallet database.
Definition wallet.cpp:724
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
Definition messages.cpp:166
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
Definition interpreter.h:36
CKey GenerateRandomKey(bool compressed) noexcept
Definition key.cpp:475
std::string EncodeDestination(const CTxDestination &dest)
Definition key_io.cpp:294
#define LogInfo(...)
Definition log.h:95
#define LogError(...)
Definition log.h:97
#define LogDebug(category,...)
Definition log.h:115
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
Definition moneystr.cpp:45
static int sign(const secp256k1_context *ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64)
Definition musig.c:106
PSBTError
Definition types.h:17
UniValue SettingsValue
Definition settings.h:28
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
Definition settings.h:107
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
Definition messages.cpp:166
bilingual_str AmountHighWarn(const std::string &optname)
Definition messages.cpp:161
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition fs.cpp:34
std::unique_ptr< Handler > MakeCleanupHandler(std::function< void()> cleanup)
Return handler wrapping a cleanup function.
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
TxBroadcast
How to broadcast a local transaction.
Definition types.h:165
@ MEMPOOL_AND_BROADCAST_TO_ALL
Add the transaction to the mempool and broadcast to all peers for which tx relay is enabled.
Definition types.h:167
@ MEMPOOL_NO_BROADCAST
Add the transaction to the mempool, but don't broadcast to anybody.
Definition types.h:169
@ NO_MEMPOOL_PRIVATE_BROADCAST
Omit the mempool and directly send the transaction via a few dedicated connections to peers on privac...
Definition types.h:172
bilingual_str ErrorString(const Result< T > &result)
Definition result.h:93
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
Definition string.h:174
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition string.h:246
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition string.cpp:11
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
Definition transaction.h:82
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
Definition wallet.h:122
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition db.cpp:153
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)
Definition wallet.cpp:364
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
Definition wallet.cpp:2142
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition wallet.cpp:194
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
std::map< std::string, std::string > mapValue_t
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition crypter.h:63
DBErrors
Overview of wallet database classes:
Definition walletdb.h:44
@ UNEXPECTED_LEGACY_ENTRY
Definition walletdb.h:53
@ EXTERNAL_SIGNER_SUPPORT_REQUIRED
Definition walletdb.h:48
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
Definition wallet.cpp:96
static GlobalMutex g_wallet_release_mutex
Definition wallet.cpp:232
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
Definition wallet.cpp:109
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition crypter.h:14
static void RefreshMempoolStatus(CWalletTx &tx, interfaces::Chain &chain)
Refresh mempool status so the wallet is in an internally consistent state and immediately knows the t...
Definition wallet.cpp:142
static const bool DEFAULT_WALLETCROSSCHAIN
Definition wallet.h:135
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
Definition wallet.cpp:216
bool HasLegacyRecords(CWallet &wallet)
Returns true if there are any DBKeys::LEGACY_TYPES record in the wallet db.
Definition walletdb.cpp:506
fs::path GetWalletDir()
Get the path of the wallet directory.
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Definition wallet.cpp:4250
static const bool DEFAULT_WALLET_RBF
-walletrbf default
Definition wallet.h:132
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
Definition wallet.h:139
static std::condition_variable g_wallet_release_cv
Definition wallet.cpp:233
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
Definition wallet.cpp:2940
bool IsBDBFile(const fs::path &path)
Definition db.cpp:94
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:223
fs::path BDBDataFile(const fs::path &wallet_path)
Definition db.cpp:75
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
Definition wallet.h:141
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
Definition wallet.h:130
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, bool allow_unnamed)
Definition wallet.cpp:472
std::string PurposeToString(AddressPurpose p)
Definition wallet.h:280
static const bool DEFAULT_WALLETBROADCAST
Definition wallet.h:133
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
Definition context.h:24
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:151
bool DoMigration(CWallet &wallet, WalletContext &context, bilingual_str &error, MigrationResult &res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition wallet.cpp:4133
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition wallet.h:150
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
Definition transaction.h:79
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:124
static std::string MigrationPrefixName(CWallet &wallet)
Definition wallet.cpp:4127
static GlobalMutex g_loading_wallet_mutex
Definition wallet.cpp:231
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition crypter.h:15
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)
Definition wallet.cpp:377
static void FlushAndDeleteWallet(CWallet *wallet)
Definition wallet.cpp:238
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition walletutil.h:56
@ WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
Definition walletutil.h:27
@ WALLET_FLAG_KEY_ORIGIN_METADATA
Definition walletutil.h:24
@ WALLET_FLAG_AVOID_REUSE
Definition walletutil.h:21
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition walletutil.h:53
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition walletutil.h:30
@ WALLET_FLAG_BLANK_WALLET
Definition walletutil.h:50
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Definition wallet.cpp:254
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition wallet.cpp:207
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
Definition wallet.h:126
static util::Result< fs::path > GetWalletPath(const std::string &name)
Definition wallet.cpp:2918
DatabaseStatus
Definition db.h:186
@ FAILED_INVALID_BACKUP_FILE
Definition db.h:198
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:163
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
Definition wallet.cpp:200
std::optional< OutputType > ParseOutputType(std::string_view type)
const std::string & FormatOutputType(OutputType type)
OutputType
Definition outputtype.h:18
static constexpr auto OUTPUT_TYPES
Definition outputtype.h:26
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction &psbt, unsigned int input_index, const PrecomputedTransactionData *txdata)
Checks whether a PSBTInput is already signed by doing script verification using final fields.
Definition psbt.cpp:325
void RemoveUnnecessaryTransactions(PartiallySignedTransaction &psbtx)
Reduces the size of the PSBT by dropping unnecessary non_witness_utxos (i.e.
Definition psbt.cpp:514
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
Definition psbt.cpp:320
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
Definition psbt.cpp:385
void GetStrongRandBytes(std::span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition random.cpp:607
const char * name
Definition rest.cpp:48
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition secure.h:53
SigningResult
Definition signmessage.h:43
@ PRIVATE_KEY_NOT_AVAILABLE
Definition signmessage.h:45
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition block.h:117
std::vector< uint256 > vHave
Definition block.h:127
bool IsNull() const
Definition block.h:145
Definition key.h:231
void SetSeed(std::span< const std::byte > seed)
Definition key.cpp:491
A mutable version of CTransaction.
std::vector< CTxIn > vin
std::map< CKeyID, CKey > keys
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition time.cpp:30
std::chrono::time_point< NodeClock > time_point
Definition time.h:19
A structure for PSBTs which contain per-input information.
Definition psbt.h:262
CTransactionRef non_witness_utxo
Definition psbt.h:263
A version of CTransaction with the PSBT format.
Definition psbt.h:1139
std::vector< PSBTInput > inputs
Definition psbt.h:1144
std::optional< CMutableTransaction > tx
Definition psbt.h:1140
interfaces::Chain * chain
Definition context.h:37
ArgsManager * args
Definition context.h:39
Bilingual messages:
Definition translation.h:24
bool empty() const
Definition translation.h:35
std::string original
Definition translation.h:25
Block data sent with blockConnected, blockDisconnected notifications.
Definition chain.h:19
const uint256 * prev_hash
Definition chain.h:21
const CBlock * data
Definition chain.h:25
const uint256 & hash
Definition chain.h:20
unsigned int chain_time_max
Definition chain.h:29
Information about chainstate that notifications are sent from.
Definition types.h:18
Definition musig.c:31
Address book data.
Definition wallet.h:239
std::optional< AddressPurpose > purpose
Address purpose which was originally recorded for payment protocol support but now serves as a cached...
Definition wallet.h:254
void SetLabel(std::string name)
Definition wallet.h:277
std::optional< std::string > m_op_label
Definition wallet.h:755
std::optional< int > last_scanned_height
Definition wallet.h:641
enum wallet::CWallet::ScanResult::@273233031336335332015254221053060000163044056224 status
SecureString create_passphrase
Definition db.h:177
std::optional< DatabaseFormat > require_format
Definition db.h:175
uint64_t create_flags
Definition db.h:176
struct containing information needed for migrating legacy wallets to descriptor wallets
std::shared_ptr< CWallet > watchonly_wallet
Definition wallet.h:1138
std::string wallet_name
Definition wallet.h:1136
std::shared_ptr< CWallet > solvables_wallet
Definition wallet.h:1139
std::shared_ptr< CWallet > wallet
Definition wallet.h:1137
State of rejected transaction that conflicts with a confirmed block.
Definition transaction.h:47
State of transaction confirmed in a block.
Definition transaction.h:32
State of transaction added to mempool.
Definition transaction.h:42
interfaces::Chain * chain
Definition context.h:37
ArgsManager * args
Definition context.h:39
#define WAIT_LOCK(cs, name)
Definition sync.h:264
#define AssertLockNotHeld(cs)
Definition sync.h:141
#define LOCK2(cs1, cs2)
Definition sync.h:259
#define LOCK(cs)
Definition sync.h:258
#define WITH_LOCK(cs, code)
Definition sync.h:289
#define AssertLockHeld(cs)
Definition sync.h:136
bilingual_str AmountHighWarn(const std::string &optname)
Definition messages.cpp:161
static int count
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define GUARDED_BY(x)
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
transaction_identifier< false > Txid
Txid commits to all transaction fields except the witness.
consteval auto _(util::TranslatedLiteral str)
Definition translation.h:79
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition translation.h:82
static constexpr decltype(CTransaction::version) TRUC_VERSION
Definition truc_policy.h:20
@ CT_UPDATED
@ CT_DELETED
@ CT_NEW
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition time.cpp:81
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
Definition time.h:94
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:73
assert(!tx.IsCoinBase())
DatabaseStatus
Definition db.h:186
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.