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