Bitcoin Core 29.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-present The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <wallet/wallet.h>
7
8#include <bitcoin-build-config.h> // IWYU pragma: keep
9#include <addresstype.h>
10#include <blockfilter.h>
11#include <chain.h>
12#include <coins.h>
13#include <common/args.h>
14#include <common/messages.h>
15#include <common/settings.h>
16#include <common/signmessage.h>
17#include <common/system.h>
18#include <consensus/amount.h>
19#include <consensus/consensus.h>
21#include <external_signer.h>
22#include <interfaces/chain.h>
23#include <interfaces/handler.h>
24#include <interfaces/wallet.h>
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 (size_t index = 0; index < block.data->vtx.size(); index++) {
1552 const CTransactionRef& ptx = block.data->vtx[index];
1553 // Coinbase transactions are not only inactive but also abandoned,
1554 // meaning they should never be relayed standalone via the p2p protocol.
1555 SyncTransaction(ptx, TxStateInactive{/*abandoned=*/index == 0});
1556
1557 for (const CTxIn& tx_in : ptx->vin) {
1558 // No other wallet transactions conflicted with this transaction
1559 if (mapTxSpends.count(tx_in.prevout) < 1) continue;
1560
1561 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.prevout);
1562
1563 // For all of the spends that conflict with this transaction
1564 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1565 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1566
1567 if (!wtx.isBlockConflicted()) continue;
1568
1569 auto try_updating_state = [&](CWalletTx& tx) {
1570 if (!tx.isBlockConflicted()) return TxUpdate::UNCHANGED;
1571 if (tx.state<TxStateBlockConflicted>()->conflicting_block_height >= disconnect_height) {
1572 tx.m_state = TxStateInactive{};
1573 return TxUpdate::CHANGED;
1574 }
1575 return TxUpdate::UNCHANGED;
1576 };
1577
1578 RecursiveUpdateTxState(wtx.tx->GetHash(), try_updating_state);
1579 }
1580 }
1581 }
1582}
1583
1585{
1587}
1588
1589void CWallet::BlockUntilSyncedToCurrentChain() const {
1591 // Skip the queue-draining stuff if we know we're caught up with
1592 // chain().Tip(), otherwise put a callback in the validation interface queue and wait
1593 // for the queue to drain enough to execute it (indicating we are caught up
1594 // at least with the time we entered this function).
1595 uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1596 chain().waitForNotificationsIfTipChanged(last_block_hash);
1597}
1598
1599// Note that this function doesn't distinguish between a 0-valued input,
1600// and a not-"is mine" (according to the filter) input.
1601CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1602{
1603 {
1604 LOCK(cs_wallet);
1605 const auto mi = mapWallet.find(txin.prevout.hash);
1606 if (mi != mapWallet.end())
1607 {
1608 const CWalletTx& prev = (*mi).second;
1609 if (txin.prevout.n < prev.tx->vout.size())
1610 if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1611 return prev.tx->vout[txin.prevout.n].nValue;
1612 }
1613 }
1614 return 0;
1615}
1616
1618{
1620 return IsMine(txout.scriptPubKey);
1621}
1622
1624{
1626 return IsMine(GetScriptForDestination(dest));
1627}
1628
1630{
1632
1633 // Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
1634 const auto& it = m_cached_spks.find(script);
1635 if (it != m_cached_spks.end()) {
1636 isminetype res = ISMINE_NO;
1637 for (const auto& spkm : it->second) {
1638 res = std::max(res, spkm->IsMine(script));
1639 }
1640 Assume(res == ISMINE_SPENDABLE);
1641 return res;
1642 }
1643
1644 // Legacy wallet
1646 return spkm->IsMine(script);
1647 }
1648
1649 return ISMINE_NO;
1650}
1651
1652bool CWallet::IsMine(const CTransaction& tx) const
1653{
1655 for (const CTxOut& txout : tx.vout)
1656 if (IsMine(txout))
1657 return true;
1658 return false;
1659}
1660
1662{
1664 auto wtx = GetWalletTx(outpoint.hash);
1665 if (!wtx) {
1666 return ISMINE_NO;
1667 }
1668 if (outpoint.n >= wtx->tx->vout.size()) {
1669 return ISMINE_NO;
1670 }
1671 return IsMine(wtx->tx->vout[outpoint.n]);
1672}
1673
1674bool CWallet::IsFromMe(const CTransaction& tx) const
1675{
1676 return (GetDebit(tx, ISMINE_ALL) > 0);
1677}
1678
1680{
1681 CAmount nDebit = 0;
1682 for (const CTxIn& txin : tx.vin)
1683 {
1684 nDebit += GetDebit(txin, filter);
1685 if (!MoneyRange(nDebit))
1686 throw std::runtime_error(std::string(__func__) + ": value out of range");
1687 }
1688 return nDebit;
1689}
1690
1692{
1693 // All Active ScriptPubKeyMans must be HD for this to be true
1694 bool result = false;
1695 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1696 if (!spk_man->IsHDEnabled()) return false;
1697 result = true;
1698 }
1699 return result;
1700}
1701
1702bool CWallet::CanGetAddresses(bool internal) const
1703{
1704 LOCK(cs_wallet);
1705 if (m_spk_managers.empty()) return false;
1706 for (OutputType t : OUTPUT_TYPES) {
1707 auto spk_man = GetScriptPubKeyMan(t, internal);
1708 if (spk_man && spk_man->CanGetAddresses(internal)) {
1709 return true;
1710 }
1711 }
1712 return false;
1713}
1714
1716{
1717 WalletBatch batch(GetDatabase());
1718 return SetWalletFlagWithDB(batch, flags);
1719}
1720
1722{
1723 LOCK(cs_wallet);
1725 if (!batch.WriteWalletFlags(m_wallet_flags))
1726 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1727}
1728
1729void CWallet::UnsetWalletFlag(uint64_t flag)
1730{
1731 WalletBatch batch(GetDatabase());
1732 UnsetWalletFlagWithDB(batch, flag);
1733}
1734
1736{
1737 LOCK(cs_wallet);
1738 m_wallet_flags &= ~flag;
1739 if (!batch.WriteWalletFlags(m_wallet_flags))
1740 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1741}
1742
1744{
1746}
1747
1748bool CWallet::IsWalletFlagSet(uint64_t flag) const
1749{
1750 return (m_wallet_flags & flag);
1751}
1752
1754{
1755 LOCK(cs_wallet);
1756 if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1757 // contains unknown non-tolerable wallet flags
1758 return false;
1759 }
1761
1762 return true;
1763}
1764
1766{
1767 LOCK(cs_wallet);
1768
1769 // We should never be writing unknown non-tolerable wallet flags
1770 assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1771 // This should only be used once, when creating a new wallet - so current flags are expected to be blank
1772 assert(m_wallet_flags == 0);
1773
1774 if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1775 throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1776 }
1777
1778 if (!LoadWalletFlags(flags)) assert(false);
1779}
1780
1781bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1782{
1783 auto spk_man = GetLegacyScriptPubKeyMan();
1784 if (!spk_man) {
1785 return false;
1786 }
1787 LOCK(spk_man->cs_KeyStore);
1788 return spk_man->ImportScripts(scripts, timestamp);
1789}
1790
1791bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1792{
1793 auto spk_man = GetLegacyScriptPubKeyMan();
1794 if (!spk_man) {
1795 return false;
1796 }
1797 LOCK(spk_man->cs_KeyStore);
1798 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1799}
1800
1801bool 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)
1802{
1803 auto spk_man = GetLegacyScriptPubKeyMan();
1804 if (!spk_man) {
1805 return false;
1806 }
1807 LOCK(spk_man->cs_KeyStore);
1808 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, timestamp);
1809}
1810
1811bool 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)
1812{
1813 auto spk_man = GetLegacyScriptPubKeyMan();
1814 if (!spk_man) {
1815 return false;
1816 }
1817 LOCK(spk_man->cs_KeyStore);
1818 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1819 return false;
1820 }
1821 if (apply_label) {
1822 WalletBatch batch(GetDatabase());
1823 for (const CScript& script : script_pub_keys) {
1824 CTxDestination dest;
1826 if (IsValidDestination(dest)) {
1827 SetAddressBookWithDB(batch, dest, label, AddressPurpose::RECEIVE);
1828 }
1829 }
1830 }
1831 return true;
1832}
1833
1835{
1836 int64_t birthtime = m_birth_time.load();
1837 if (time < birthtime) {
1838 m_birth_time = time;
1839 }
1840}
1841
1850int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1851{
1852 // Find starting block. May be null if nCreateTime is greater than the
1853 // highest blockchain timestamp, in which case there is nothing that needs
1854 // to be scanned.
1855 int start_height = 0;
1856 uint256 start_block;
1857 bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1858 WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
1859
1860 if (start) {
1861 // TODO: this should take into account failure by ScanResult::USER_ABORT
1862 ScanResult result = ScanForWalletTransactions(start_block, start_height, /*max_height=*/{}, reserver, /*fUpdate=*/update, /*save_progress=*/false);
1863 if (result.status == ScanResult::FAILURE) {
1864 int64_t time_max;
1865 CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
1866 return time_max + TIMESTAMP_WINDOW + 1;
1867 }
1868 }
1869 return startTime;
1870}
1871
1894CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress)
1895{
1896 constexpr auto INTERVAL_TIME{60s};
1897 auto current_time{reserver.now()};
1898 auto start_time{reserver.now()};
1899
1900 assert(reserver.isReserved());
1901
1902 uint256 block_hash = start_block;
1903 ScanResult result;
1904
1905 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1906 if (!IsLegacy() && chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
1907
1908 WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(),
1909 fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks");
1910
1911 fAbortRescan = false;
1912 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)
1913 uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1914 uint256 end_hash = tip_hash;
1915 if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
1916 double progress_begin = chain().guessVerificationProgress(block_hash);
1917 double progress_end = chain().guessVerificationProgress(end_hash);
1918 double progress_current = progress_begin;
1919 int block_height = start_height;
1920 while (!fAbortRescan && !chain().shutdownRequested()) {
1921 if (progress_end - progress_begin > 0.0) {
1922 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1923 } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
1925 }
1926 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1927 ShowProgress(strprintf("%s %s", GetDisplayName(), _("Rescanning…")), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1928 }
1929
1930 bool next_interval = reserver.now() >= current_time + INTERVAL_TIME;
1931 if (next_interval) {
1932 current_time = reserver.now();
1933 WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1934 }
1935
1936 bool fetch_block{true};
1937 if (fast_rescan_filter) {
1938 fast_rescan_filter->UpdateIfNeeded();
1939 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1940 if (matches_block.has_value()) {
1941 if (*matches_block) {
1942 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1943 } else {
1944 result.last_scanned_block = block_hash;
1945 result.last_scanned_height = block_height;
1946 fetch_block = false;
1947 }
1948 } else {
1949 LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1950 }
1951 }
1952
1953 // Find next block separately from reading data above, because reading
1954 // is slow and there might be a reorg while it is read.
1955 bool block_still_active = false;
1956 bool next_block = false;
1957 uint256 next_block_hash;
1958 chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1959
1960 if (fetch_block) {
1961 // Read block data
1962 CBlock block;
1963 chain().findBlock(block_hash, FoundBlock().data(block));
1964
1965 if (!block.IsNull()) {
1966 LOCK(cs_wallet);
1967 if (!block_still_active) {
1968 // Abort scan if current block is no longer active, to prevent
1969 // marking transactions as coming from the wrong block.
1970 result.last_failed_block = block_hash;
1971 result.status = ScanResult::FAILURE;
1972 break;
1973 }
1974 for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1975 SyncTransaction(block.vtx[posInBlock], TxStateConfirmed{block_hash, block_height, static_cast<int>(posInBlock)}, fUpdate, /*rescanning_old_block=*/true);
1976 }
1977 // scan succeeded, record block as most recent successfully scanned
1978 result.last_scanned_block = block_hash;
1979 result.last_scanned_height = block_height;
1980
1981 if (save_progress && next_interval) {
1982 CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
1983
1984 if (!loc.IsNull()) {
1985 WalletLogPrintf("Saving scan progress %d.\n", block_height);
1986 WalletBatch batch(GetDatabase());
1987 batch.WriteBestBlock(loc);
1988 }
1989 }
1990 } else {
1991 // could not scan block, keep scanning but record this block as the most recent failure
1992 result.last_failed_block = block_hash;
1993 result.status = ScanResult::FAILURE;
1994 }
1995 }
1996 if (max_height && block_height >= *max_height) {
1997 break;
1998 }
1999 // If rescanning was triggered with cs_wallet permanently locked (AttachChain), additional blocks that were connected during the rescan
2000 // aren't processed here but will be processed with the pending blockConnected notifications after the lock is released.
2001 // If rescanning without a permanent cs_wallet lock, additional blocks that were added during the rescan will be re-processed if
2002 // the notification was processed and the last block height was updated.
2003 if (block_height >= WITH_LOCK(cs_wallet, return GetLastBlockHeight())) {
2004 break;
2005 }
2006
2007 {
2008 if (!next_block) {
2009 // break successfully when rescan has reached the tip, or
2010 // previous block is no longer on the chain due to a reorg
2011 break;
2012 }
2013
2014 // increment block and verification progress
2015 block_hash = next_block_hash;
2016 ++block_height;
2017 progress_current = chain().guessVerificationProgress(block_hash);
2018
2019 // handle updated tip hash
2020 const uint256 prev_tip_hash = tip_hash;
2021 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
2022 if (!max_height && prev_tip_hash != tip_hash) {
2023 // in case the tip has changed, update progress max
2024 progress_end = chain().guessVerificationProgress(tip_hash);
2025 }
2026 }
2027 }
2028 if (!max_height) {
2029 WalletLogPrintf("Scanning current mempool transactions.\n");
2030 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
2031 }
2032 ShowProgress(strprintf("%s %s", GetDisplayName(), _("Rescanning…")), 100); // hide progress dialog in GUI
2033 if (block_height && fAbortRescan) {
2034 WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
2036 } else if (block_height && chain().shutdownRequested()) {
2037 WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2039 } else {
2040 WalletLogPrintf("Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.now() - start_time));
2041 }
2042 return result;
2043}
2044
2045bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
2046{
2048
2049 // Can't relay if wallet is not broadcasting
2050 if (!GetBroadcastTransactions()) return false;
2051 // Don't relay abandoned transactions
2052 if (wtx.isAbandoned()) return false;
2053 // Don't try to submit coinbase transactions. These would fail anyway but would
2054 // cause log spam.
2055 if (wtx.IsCoinBase()) return false;
2056 // Don't try to submit conflicted or confirmed transactions.
2057 if (GetTxDepthInMainChain(wtx) != 0) return false;
2058
2059 // Submit transaction to mempool for relay
2060 WalletLogPrintf("Submitting wtx %s to mempool for relay\n", wtx.GetHash().ToString());
2061 // We must set TxStateInMempool here. Even though it will also be set later by the
2062 // entered-mempool callback, if we did not there would be a race where a
2063 // user could call sendmoney in a loop and hit spurious out of funds errors
2064 // because we think that this newly generated transaction's change is
2065 // unavailable as we're not yet aware that it is in the mempool.
2066 //
2067 // If broadcast fails for any reason, trying to set wtx.m_state here would be incorrect.
2068 // If transaction was previously in the mempool, it should be updated when
2069 // TransactionRemovedFromMempool fires.
2070 bool ret = chain().broadcastTransaction(wtx.tx, m_default_max_tx_fee, relay, err_string);
2071 if (ret) wtx.m_state = TxStateInMempool{};
2072 return ret;
2073}
2074
2075std::set<uint256> CWallet::GetTxConflicts(const CWalletTx& wtx) const
2076{
2078
2079 const uint256 myHash{wtx.GetHash()};
2080 std::set<uint256> result{GetConflicts(myHash)};
2081 result.erase(myHash);
2082 return result;
2083}
2084
2086{
2087 // Don't attempt to resubmit if the wallet is configured to not broadcast
2088 if (!fBroadcastTransactions) return false;
2089
2090 // During reindex, importing and IBD, old wallet transactions become
2091 // unconfirmed. Don't resend them as that would spam other nodes.
2092 // We only allow forcing mempool submission when not relaying to avoid this spam.
2093 if (!chain().isReadyToBroadcast()) return false;
2094
2095 // Do this infrequently and randomly to avoid giving away
2096 // that these are our transactions.
2097 if (NodeClock::now() < m_next_resend) return false;
2098
2099 return true;
2100}
2101
2103
2104// Resubmit transactions from the wallet to the mempool, optionally asking the
2105// mempool to relay them. On startup, we will do this for all unconfirmed
2106// transactions but will not ask the mempool to relay them. We do this on startup
2107// to ensure that our own mempool is aware of our transactions. There
2108// is a privacy side effect here as not broadcasting on startup also means that we won't
2109// inform the world of our wallet's state, particularly if the wallet (or node) is not
2110// yet synced.
2111//
2112// Otherwise this function is called periodically in order to relay our unconfirmed txs.
2113// We do this on a random timer to slightly obfuscate which transactions
2114// come from our wallet.
2115//
2116// TODO: Ideally, we'd only resend transactions that we think should have been
2117// mined in the most recent block. Any transaction that wasn't in the top
2118// blockweight of transactions in the mempool shouldn't have been mined,
2119// and so is probably just sitting in the mempool waiting to be confirmed.
2120// Rebroadcasting does nothing to speed up confirmation and only damages
2121// privacy.
2122//
2123// The `force` option results in all unconfirmed transactions being submitted to
2124// the mempool. This does not necessarily result in those transactions being relayed,
2125// that depends on the `relay` option. Periodic rebroadcast uses the pattern
2126// relay=true force=false, while loading into the mempool
2127// (on start, or after import) uses relay=false force=true.
2128void CWallet::ResubmitWalletTransactions(bool relay, bool force)
2129{
2130 // Don't attempt to resubmit if the wallet is configured to not broadcast,
2131 // even if forcing.
2132 if (!fBroadcastTransactions) return;
2133
2134 int submitted_tx_count = 0;
2135
2136 { // cs_wallet scope
2137 LOCK(cs_wallet);
2138
2139 // First filter for the transactions we want to rebroadcast.
2140 // We use a set with WalletTxOrderComparator so that rebroadcasting occurs in insertion order
2141 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2142 for (auto& [txid, wtx] : mapWallet) {
2143 // Only rebroadcast unconfirmed txs
2144 if (!wtx.isUnconfirmed()) continue;
2145
2146 // Attempt to rebroadcast all txes more than 5 minutes older than
2147 // the last block, or all txs if forcing.
2148 if (!force && wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
2149 to_submit.insert(&wtx);
2150 }
2151 // Now try submitting the transactions to the memory pool and (optionally) relay them.
2152 for (auto wtx : to_submit) {
2153 std::string unused_err_string;
2154 if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, relay)) ++submitted_tx_count;
2155 }
2156 } // cs_wallet
2157
2158 if (submitted_tx_count > 0) {
2159 WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2160 }
2161}
2162 // end of mapWallet
2164
2166{
2167 for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
2168 if (!pwallet->ShouldResend()) continue;
2169 pwallet->ResubmitWalletTransactions(/*relay=*/true, /*force=*/false);
2170 pwallet->SetNextResend();
2171 }
2172}
2173
2174
2181{
2183
2184 // Build coins map
2185 std::map<COutPoint, Coin> coins;
2186 for (auto& input : tx.vin) {
2187 const auto mi = mapWallet.find(input.prevout.hash);
2188 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2189 return false;
2190 }
2191 const CWalletTx& wtx = mi->second;
2192 int prev_height = wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height : 0;
2193 coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], prev_height, wtx.IsCoinBase());
2194 }
2195 std::map<int, bilingual_str> input_errors;
2196 return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
2197}
2198
2199bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
2200{
2201 // Try to sign with all ScriptPubKeyMans
2202 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2203 // spk_man->SignTransaction will return true if the transaction is complete,
2204 // so we can exit early and return true if that happens
2205 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2206 return true;
2207 }
2208 }
2209
2210 // At this point, one input was not fully signed otherwise we would have exited already
2211 return false;
2212}
2213
2214std::optional<PSBTError> CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed, bool finalize) const
2215{
2216 if (n_signed) {
2217 *n_signed = 0;
2218 }
2219 LOCK(cs_wallet);
2220 // Get all of the previous transactions
2221 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2222 const CTxIn& txin = psbtx.tx->vin[i];
2223 PSBTInput& input = psbtx.inputs.at(i);
2224
2225 if (PSBTInputSigned(input)) {
2226 continue;
2227 }
2228
2229 // If we have no utxo, grab it from the wallet.
2230 if (!input.non_witness_utxo) {
2231 const uint256& txhash = txin.prevout.hash;
2232 const auto it = mapWallet.find(txhash);
2233 if (it != mapWallet.end()) {
2234 const CWalletTx& wtx = it->second;
2235 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
2236 // The signing code will switch to the smaller witness_utxo if this is ok.
2237 input.non_witness_utxo = wtx.tx;
2238 }
2239 }
2240 }
2241
2242 const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
2243
2244 // Fill in information from ScriptPubKeyMans
2245 for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
2246 int n_signed_this_spkm = 0;
2247 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize)};
2248 if (error) {
2249 return error;
2250 }
2251
2252 if (n_signed) {
2253 (*n_signed) += n_signed_this_spkm;
2254 }
2255 }
2256
2257 RemoveUnnecessaryTransactions(psbtx, sighash_type);
2258
2259 // Complete if every input is now signed
2260 complete = true;
2261 for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
2262 complete &= PSBTInputSignedAndVerified(psbtx, i, &txdata);
2263 }
2264
2265 return {};
2266}
2267
2268SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2269{
2270 SignatureData sigdata;
2271 CScript script_pub_key = GetScriptForDestination(pkhash);
2272 for (const auto& spk_man_pair : m_spk_managers) {
2273 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2274 LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
2275 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2276 }
2277 }
2279}
2280
2281OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
2282{
2283 // If -changetype is specified, always use that change type.
2284 if (change_type) {
2285 return *change_type;
2286 }
2287
2288 // if m_default_address_type is legacy, use legacy address as change.
2290 return OutputType::LEGACY;
2291 }
2292
2293 bool any_tr{false};
2294 bool any_wpkh{false};
2295 bool any_sh{false};
2296 bool any_pkh{false};
2297
2298 for (const auto& recipient : vecSend) {
2299 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2300 any_tr = true;
2301 } else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2302 any_wpkh = true;
2303 } else if (std::get_if<ScriptHash>(&recipient.dest)) {
2304 any_sh = true;
2305 } else if (std::get_if<PKHash>(&recipient.dest)) {
2306 any_pkh = true;
2307 }
2308 }
2309
2310 const bool has_bech32m_spkman(GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/true));
2311 if (has_bech32m_spkman && any_tr) {
2312 // Currently tr is the only type supported by the BECH32M spkman
2313 return OutputType::BECH32M;
2314 }
2315 const bool has_bech32_spkman(GetScriptPubKeyMan(OutputType::BECH32, /*internal=*/true));
2316 if (has_bech32_spkman && any_wpkh) {
2317 // Currently wpkh is the only type supported by the BECH32 spkman
2318 return OutputType::BECH32;
2319 }
2320 const bool has_p2sh_segwit_spkman(GetScriptPubKeyMan(OutputType::P2SH_SEGWIT, /*internal=*/true));
2321 if (has_p2sh_segwit_spkman && any_sh) {
2322 // Currently sh_wpkh is the only type supported by the P2SH_SEGWIT spkman
2323 // As of 2021 about 80% of all SH are wrapping WPKH, so use that
2325 }
2326 const bool has_legacy_spkman(GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true));
2327 if (has_legacy_spkman && any_pkh) {
2328 // Currently pkh is the only type supported by the LEGACY spkman
2329 return OutputType::LEGACY;
2330 }
2331
2332 if (has_bech32m_spkman) {
2333 return OutputType::BECH32M;
2334 }
2335 if (has_bech32_spkman) {
2336 return OutputType::BECH32;
2337 }
2338 // else use m_default_address_type for change
2340}
2341
2342void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
2343{
2344 LOCK(cs_wallet);
2345 WalletLogPrintf("CommitTransaction:\n%s\n", util::RemoveSuffixView(tx->ToString(), "\n"));
2346
2347 // Add tx to wallet, because if it has change it's also ours,
2348 // otherwise just for transaction history.
2349 CWalletTx* wtx = AddToWallet(tx, TxStateInactive{}, [&](CWalletTx& wtx, bool new_tx) {
2350 CHECK_NONFATAL(wtx.mapValue.empty());
2351 CHECK_NONFATAL(wtx.vOrderForm.empty());
2352 wtx.mapValue = std::move(mapValue);
2353 wtx.vOrderForm = std::move(orderForm);
2354 wtx.fTimeReceivedIsTxTime = true;
2355 wtx.fFromMe = true;
2356 return true;
2357 });
2358
2359 // wtx can only be null if the db write failed.
2360 if (!wtx) {
2361 throw std::runtime_error(std::string(__func__) + ": Wallet db error, transaction commit failed");
2362 }
2363
2364 // Notify that old coins are spent
2365 for (const CTxIn& txin : tx->vin) {
2366 CWalletTx &coin = mapWallet.at(txin.prevout.hash);
2367 coin.MarkDirty();
2369 }
2370
2372 // Don't submit tx to the mempool
2373 return;
2374 }
2375
2376 std::string err_string;
2377 if (!SubmitTxMemoryPoolAndRelay(*wtx, err_string, true)) {
2378 WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2379 // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
2380 }
2381}
2382
2384{
2385 LOCK(cs_wallet);
2386
2387 Assert(m_spk_managers.empty());
2388 Assert(m_wallet_flags == 0);
2389 DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
2390 if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2391 {
2392 if (GetDatabase().Rewrite("\x04pool"))
2393 {
2394 for (const auto& spk_man_pair : m_spk_managers) {
2395 spk_man_pair.second->RewriteDB();
2396 }
2397 }
2398 }
2399
2400 if (m_spk_managers.empty()) {
2403 }
2404
2405 return nLoadWalletRet;
2406}
2407
2408util::Result<void> CWallet::RemoveTxs(std::vector<uint256>& txs_to_remove)
2409{
2411 bilingual_str str_err; // future: make RunWithinTxn return a util::Result
2412 bool was_txn_committed = RunWithinTxn(GetDatabase(), /*process_desc=*/"remove transactions", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2413 util::Result<void> result{RemoveTxs(batch, txs_to_remove)};
2414 if (!result) str_err = util::ErrorString(result);
2415 return result.has_value();
2416 });
2417 if (!str_err.empty()) return util::Error{str_err};
2418 if (!was_txn_committed) return util::Error{_("Error starting/committing db txn for wallet transactions removal process")};
2419 return {}; // all good
2420}
2421
2422util::Result<void> CWallet::RemoveTxs(WalletBatch& batch, std::vector<uint256>& txs_to_remove)
2423{
2425 if (!batch.HasActiveTxn()) return util::Error{strprintf(_("The transactions removal process can only be executed within a db txn"))};
2426
2427 // Check for transaction existence and remove entries from disk
2428 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2429 std::vector<TxIterator> erased_txs;
2430 bilingual_str str_err;
2431 for (const uint256& hash : txs_to_remove) {
2432 auto it_wtx = mapWallet.find(hash);
2433 if (it_wtx == mapWallet.end()) {
2434 return util::Error{strprintf(_("Transaction %s does not belong to this wallet"), hash.GetHex())};
2435 }
2436 if (!batch.EraseTx(hash)) {
2437 return util::Error{strprintf(_("Failure removing transaction: %s"), hash.GetHex())};
2438 }
2439 erased_txs.emplace_back(it_wtx);
2440 }
2441
2442 // Register callback to update the memory state only when the db txn is actually dumped to disk
2443 batch.RegisterTxnListener({.on_commit=[&, erased_txs]() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
2444 // Update the in-memory state and notify upper layers about the removals
2445 for (const auto& it : erased_txs) {
2446 const uint256 hash{it->first};
2447 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2448 for (const auto& txin : it->second.tx->vin)
2449 mapTxSpends.erase(txin.prevout);
2450 mapWallet.erase(it);
2452 }
2453
2454 MarkDirty();
2455 }, .on_abort={}});
2456
2457 return {};
2458}
2459
2460bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& new_purpose)
2461{
2462 bool fUpdated = false;
2463 bool is_mine;
2464 std::optional<AddressPurpose> purpose;
2465 {
2466 LOCK(cs_wallet);
2467 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2468 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2469
2470 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2471 record.SetLabel(strName);
2472 is_mine = IsMine(address) != ISMINE_NO;
2473 if (new_purpose) { /* update purpose only if requested */
2474 record.purpose = new_purpose;
2475 }
2476 purpose = record.purpose;
2477 }
2478
2479 const std::string& encoded_dest = EncodeDestination(address);
2480 if (new_purpose && !batch.WritePurpose(encoded_dest, PurposeToString(*new_purpose))) {
2481 WalletLogPrintf("Error: fail to write address book 'purpose' entry\n");
2482 return false;
2483 }
2484 if (!batch.WriteName(encoded_dest, strName)) {
2485 WalletLogPrintf("Error: fail to write address book 'name' entry\n");
2486 return false;
2487 }
2488
2489 // In very old wallets, address purpose may not be recorded so we derive it from IsMine
2490 NotifyAddressBookChanged(address, strName, is_mine,
2491 purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND),
2492 (fUpdated ? CT_UPDATED : CT_NEW));
2493 return true;
2494}
2495
2496bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::optional<AddressPurpose>& purpose)
2497{
2498 WalletBatch batch(GetDatabase());
2499 return SetAddressBookWithDB(batch, address, strName, purpose);
2500}
2501
2503{
2504 return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){
2505 return DelAddressBookWithDB(batch, address);
2506 });
2507}
2508
2510{
2511 const std::string& dest = EncodeDestination(address);
2512 {
2513 LOCK(cs_wallet);
2514 // 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.
2515 // NOTE: This isn't a problem for sending addresses because they don't have any data that needs to be kept.
2516 // When adding new address data, it should be considered here whether to retain or delete it.
2517 if (IsMine(address)) {
2518 WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2519 return false;
2520 }
2521 // Delete data rows associated with this address
2522 if (!batch.EraseAddressData(address)) {
2523 WalletLogPrintf("Error: cannot erase address book entry data\n");
2524 return false;
2525 }
2526
2527 // Delete purpose entry
2528 if (!batch.ErasePurpose(dest)) {
2529 WalletLogPrintf("Error: cannot erase address book entry purpose\n");
2530 return false;
2531 }
2532
2533 // Delete name entry
2534 if (!batch.EraseName(dest)) {
2535 WalletLogPrintf("Error: cannot erase address book entry name\n");
2536 return false;
2537 }
2538
2539 // finally, remove it from the map
2540 m_address_book.erase(address);
2541 }
2542
2543 // All good, signal changes
2544 NotifyAddressBookChanged(address, "", /*is_mine=*/false, AddressPurpose::SEND, CT_DELETED);
2545 return true;
2546}
2547
2549{
2551
2552 auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2553 if (legacy_spk_man) {
2554 return legacy_spk_man->KeypoolCountExternalKeys();
2555 }
2556
2557 unsigned int count = 0;
2558 for (auto spk_man : m_external_spk_managers) {
2559 count += spk_man.second->GetKeyPoolSize();
2560 }
2561
2562 return count;
2563}
2564
2565unsigned int CWallet::GetKeyPoolSize() const
2566{
2568
2569 unsigned int count = 0;
2570 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2571 count += spk_man->GetKeyPoolSize();
2572 }
2573 return count;
2574}
2575
2576bool CWallet::TopUpKeyPool(unsigned int kpSize)
2577{
2578 LOCK(cs_wallet);
2579 bool res = true;
2580 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2581 res &= spk_man->TopUp(kpSize);
2582 }
2583 return res;
2584}
2585
2587{
2588 LOCK(cs_wallet);
2589 auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false);
2590 if (!spk_man) {
2591 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2592 }
2593
2594 auto op_dest = spk_man->GetNewDestination(type);
2595 if (op_dest) {
2596 SetAddressBook(*op_dest, label, AddressPurpose::RECEIVE);
2597 }
2598
2599 return op_dest;
2600}
2601
2603{
2604 LOCK(cs_wallet);
2605
2606 ReserveDestination reservedest(this, type);
2607 auto op_dest = reservedest.GetReservedDestination(true);
2608 if (op_dest) reservedest.KeepDestination();
2609
2610 return op_dest;
2611}
2612
2613std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
2614{
2615 LOCK(cs_wallet);
2616 if (m_spk_managers.empty()) {
2617 return std::nullopt;
2618 }
2619
2620 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2621 for (const auto& spk_man_pair : m_spk_managers) {
2622 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2623 }
2624 return oldest_key;
2625}
2626
2627void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2628 for (auto& entry : mapWallet) {
2629 CWalletTx& wtx = entry.second;
2630 if (wtx.m_is_cache_empty) continue;
2631 for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2632 CTxDestination dst;
2633 if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
2634 wtx.MarkDirty();
2635 break;
2636 }
2637 }
2638 }
2639}
2640
2642{
2644 for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2645 const auto& entry = item.second;
2646 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2647 }
2648}
2649
2650std::vector<CTxDestination> CWallet::ListAddrBookAddresses(const std::optional<AddrBookFilter>& _filter) const
2651{
2653 std::vector<CTxDestination> result;
2654 AddrBookFilter filter = _filter ? *_filter : AddrBookFilter();
2655 ForEachAddrBookEntry([&result, &filter](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) {
2656 // Filter by change
2657 if (filter.ignore_change && is_change) return;
2658 // Filter by label
2659 if (filter.m_op_label && *filter.m_op_label != label) return;
2660 // All good
2661 result.emplace_back(dest);
2662 });
2663 return result;
2664}
2665
2666std::set<std::string> CWallet::ListAddrBookLabels(const std::optional<AddressPurpose> purpose) const
2667{
2669 std::set<std::string> label_set;
2670 ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label,
2671 bool _is_change, const std::optional<AddressPurpose>& _purpose) {
2672 if (_is_change) return;
2673 if (!purpose || purpose == _purpose) {
2674 label_set.insert(_label);
2675 }
2676 });
2677 return label_set;
2678}
2679
2681{
2683 if (!m_spk_man) {
2684 return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
2685 }
2686
2687 if (nIndex == -1) {
2688 CKeyPool keypool;
2689 int64_t index;
2690 auto op_address = m_spk_man->GetReservedDestination(type, internal, index, keypool);
2691 if (!op_address) return op_address;
2692 nIndex = index;
2693 address = *op_address;
2694 fInternal = keypool.fInternal;
2695 }
2696 return address;
2697}
2698
2700{
2701 if (nIndex != -1) {
2703 }
2704 nIndex = -1;
2706}
2707
2709{
2710 if (nIndex != -1) {
2712 }
2713 nIndex = -1;
2715}
2716
2718{
2719 CScript scriptPubKey = GetScriptForDestination(dest);
2720 for (const auto& spk_man : GetScriptPubKeyMans(scriptPubKey)) {
2721 auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan *>(spk_man);
2722 if (signer_spk_man == nullptr) {
2723 continue;
2724 }
2726 return signer_spk_man->DisplayAddress(dest, signer);
2727 }
2728 return util::Error{_("There is no ScriptPubKeyManager for this address")};
2729}
2730
2731bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
2732{
2734 setLockedCoins.insert(output);
2735 if (batch) {
2736 return batch->WriteLockedUTXO(output);
2737 }
2738 return true;
2739}
2740
2741bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
2742{
2744 bool was_locked = setLockedCoins.erase(output);
2745 if (batch && was_locked) {
2746 return batch->EraseLockedUTXO(output);
2747 }
2748 return true;
2749}
2750
2752{
2754 bool success = true;
2755 WalletBatch batch(GetDatabase());
2756 for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2757 success &= batch.EraseLockedUTXO(*it);
2758 }
2759 setLockedCoins.clear();
2760 return success;
2761}
2762
2763bool CWallet::IsLockedCoin(const COutPoint& output) const
2764{
2766 return setLockedCoins.count(output) > 0;
2767}
2768
2769void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2770{
2772 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2773 it != setLockedCoins.end(); it++) {
2774 COutPoint outpt = (*it);
2775 vOutpts.push_back(outpt);
2776 }
2777}
2778 // end of Actions
2780
2781void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
2783 mapKeyBirth.clear();
2784
2785 // map in which we'll infer heights of other keys
2786 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2787 TxStateConfirmed max_confirm{uint256{}, /*height=*/-1, /*index=*/-1};
2788 max_confirm.confirmed_block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
2789 CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.confirmed_block_height, FoundBlock().hash(max_confirm.confirmed_block_hash)));
2790
2791 {
2793 assert(spk_man != nullptr);
2794 LOCK(spk_man->cs_KeyStore);
2795
2796 // get birth times for keys with metadata
2797 for (const auto& entry : spk_man->mapKeyMetadata) {
2798 if (entry.second.nCreateTime) {
2799 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2800 }
2801 }
2802
2803 // Prepare to infer birth heights for keys without metadata
2804 for (const CKeyID &keyid : spk_man->GetKeys()) {
2805 if (mapKeyBirth.count(keyid) == 0)
2806 mapKeyFirstBlock[keyid] = &max_confirm;
2807 }
2808
2809 // if there are no such keys, we're done
2810 if (mapKeyFirstBlock.empty())
2811 return;
2812
2813 // find first block that affects those keys, if there are any left
2814 for (const auto& entry : mapWallet) {
2815 // iterate over all wallet transactions...
2816 const CWalletTx &wtx = entry.second;
2817 if (auto* conf = wtx.state<TxStateConfirmed>()) {
2818 // ... which are already in a block
2819 for (const CTxOut &txout : wtx.tx->vout) {
2820 // iterate over all their outputs
2821 for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
2822 // ... and all their affected keys
2823 auto rit = mapKeyFirstBlock.find(keyid);
2824 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2825 rit->second = conf;
2826 }
2827 }
2828 }
2829 }
2830 }
2831 }
2832
2833 // Extract block timestamps for those keys
2834 for (const auto& entry : mapKeyFirstBlock) {
2835 int64_t block_time;
2836 CHECK_NONFATAL(chain().findBlock(entry.second->confirmed_block_hash, FoundBlock().time(block_time)));
2837 mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
2838 }
2839}
2840
2864unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
2865{
2866 std::optional<uint256> block_hash;
2867 if (auto* conf = wtx.state<TxStateConfirmed>()) {
2868 block_hash = conf->confirmed_block_hash;
2869 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
2870 block_hash = conf->conflicting_block_hash;
2871 }
2872
2873 unsigned int nTimeSmart = wtx.nTimeReceived;
2874 if (block_hash) {
2875 int64_t blocktime;
2876 int64_t block_max_time;
2877 if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) {
2878 if (rescanning_old_block) {
2879 nTimeSmart = block_max_time;
2880 } else {
2881 int64_t latestNow = wtx.nTimeReceived;
2882 int64_t latestEntry = 0;
2883
2884 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2885 int64_t latestTolerated = latestNow + 300;
2886 const TxItems& txOrdered = wtxOrdered;
2887 for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2888 CWalletTx* const pwtx = it->second;
2889 if (pwtx == &wtx) {
2890 continue;
2891 }
2892 int64_t nSmartTime;
2893 nSmartTime = pwtx->nTimeSmart;
2894 if (!nSmartTime) {
2895 nSmartTime = pwtx->nTimeReceived;
2896 }
2897 if (nSmartTime <= latestTolerated) {
2898 latestEntry = nSmartTime;
2899 if (nSmartTime > latestNow) {
2900 latestNow = nSmartTime;
2901 }
2902 break;
2903 }
2904 }
2905
2906 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2907 }
2908 } else {
2909 WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString());
2910 }
2911 }
2912 return nTimeSmart;
2913}
2914
2916{
2917 if (std::get_if<CNoDestination>(&dest))
2918 return false;
2919
2920 if (!used) {
2921 if (auto* data{common::FindKey(m_address_book, dest)}) data->previously_spent = false;
2922 return batch.WriteAddressPreviouslySpent(dest, false);
2923 }
2924
2926 return batch.WriteAddressPreviouslySpent(dest, true);
2927}
2928
2930{
2931 m_address_book[dest].previously_spent = true;
2932}
2933
2934void CWallet::LoadAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& request)
2935{
2936 m_address_book[dest].receive_requests[id] = request;
2937}
2938
2940{
2941 if (auto* data{common::FindKey(m_address_book, dest)}) return data->previously_spent;
2942 return false;
2943}
2944
2945std::vector<std::string> CWallet::GetAddressReceiveRequests() const
2946{
2947 std::vector<std::string> values;
2948 for (const auto& [dest, entry] : m_address_book) {
2949 for (const auto& [id, request] : entry.receive_requests) {
2950 values.emplace_back(request);
2951 }
2952 }
2953 return values;
2954}
2955
2956bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
2957{
2958 if (!batch.WriteAddressReceiveRequest(dest, id, value)) return false;
2959 m_address_book[dest].receive_requests[id] = value;
2960 return true;
2961}
2962
2963bool CWallet::EraseAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id)
2964{
2965 if (!batch.EraseAddressReceiveRequest(dest, id)) return false;
2966 m_address_book[dest].receive_requests.erase(id);
2967 return true;
2968}
2969
2971{
2972 // Do some checking on wallet path. It should be either a:
2973 //
2974 // 1. Path where a directory can be created.
2975 // 2. Path to an existing directory.
2976 // 3. Path to a symlink to a directory.
2977 // 4. For backwards compatibility, the name of a data file in -walletdir.
2979 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2980 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2981 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2982 (path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
2984 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2985 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2986 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2988 }
2989 return wallet_path;
2990}
2991
2992std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2993{
2994 const auto& wallet_path = GetWalletPath(name);
2995 if (!wallet_path) {
2996 error_string = util::ErrorString(wallet_path);
2998 return nullptr;
2999 }
3000 return MakeDatabase(*wallet_path, options, status, error_string);
3001}
3002
3003std::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)
3004{
3005 interfaces::Chain* chain = context.chain;
3006 ArgsManager& args = *Assert(context.args);
3007 const std::string& walletFile = database->Filename();
3008
3009 const auto start{SteadyClock::now()};
3010 // TODO: Can't use std::make_shared because we need a custom deleter but
3011 // should be possible to use std::allocate_shared.
3012 std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
3013 walletInstance->m_keypool_size = std::max(args.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{1});
3014 walletInstance->m_notify_tx_changed_script = args.GetArg("-walletnotify", "");
3015
3016 // Load wallet
3017 bool rescan_required = false;
3018 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
3019 if (nLoadWalletRet != DBErrors::LOAD_OK) {
3020 if (nLoadWalletRet == DBErrors::CORRUPT) {
3021 error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
3022 return nullptr;
3023 }
3024 else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
3025 {
3026 warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
3027 " or address metadata may be missing or incorrect."),
3028 walletFile));
3029 }
3030 else if (nLoadWalletRet == DBErrors::TOO_NEW) {
3031 error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, CLIENT_NAME);
3032 return nullptr;
3033 }
3034 else if (nLoadWalletRet == DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED) {
3035 error = strprintf(_("Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
3036 return nullptr;
3037 }
3038 else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
3039 {
3040 error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
3041 return nullptr;
3042 } else if (nLoadWalletRet == DBErrors::NEED_RESCAN) {
3043 warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
3044 " Rescanning wallet."), walletFile));
3045 rescan_required = true;
3046 } else if (nLoadWalletRet == DBErrors::UNKNOWN_DESCRIPTOR) {
3047 error = strprintf(_("Unrecognized descriptor found. Loading wallet %s\n\n"
3048 "The wallet might had been created on a newer version.\n"
3049 "Please try running the latest software version.\n"), walletFile);
3050 return nullptr;
3051 } else if (nLoadWalletRet == DBErrors::UNEXPECTED_LEGACY_ENTRY) {
3052 error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
3053 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3054 return nullptr;
3055 } else {
3056 error = strprintf(_("Error loading %s"), walletFile);
3057 return nullptr;
3058 }
3059 }
3060
3061 // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3062 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3063 !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
3064 !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
3065 if (fFirstRun)
3066 {
3067 // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
3068 walletInstance->SetMinVersion(FEATURE_LATEST);
3069
3070 walletInstance->InitWalletFlags(wallet_creation_flags);
3071
3072 // Only create LegacyScriptPubKeyMan when not descriptor wallet
3073 if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3074 walletInstance->SetupLegacyScriptPubKeyMan();
3075 }
3076
3077 if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
3078 LOCK(walletInstance->cs_wallet);
3079 if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3080 walletInstance->SetupDescriptorScriptPubKeyMans();
3081 // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
3082 } else {
3083 // Legacy wallets need SetupGeneration here.
3084 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3085 if (!spk_man->SetupGeneration()) {
3086 error = _("Unable to generate initial keys");
3087 return nullptr;
3088 }
3089 }
3090 }
3091 }
3092
3093 if (chain) {
3094 walletInstance->chainStateFlushed(ChainstateRole::NORMAL, chain->getTipLocator());
3095 }
3096 } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
3097 // Make it impossible to disable private keys after creation
3098 error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
3099 return nullptr;
3100 } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3101 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3102 if (spk_man->HavePrivateKeys()) {
3103 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3104 break;
3105 }
3106 }
3107 }
3108
3109 if (!args.GetArg("-addresstype", "").empty()) {
3110 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-addresstype", ""));
3111 if (!parsed) {
3112 error = strprintf(_("Unknown address type '%s'"), args.GetArg("-addresstype", ""));
3113 return nullptr;
3114 }
3115 walletInstance->m_default_address_type = parsed.value();
3116 }
3117
3118 if (!args.GetArg("-changetype", "").empty()) {
3119 std::optional<OutputType> parsed = ParseOutputType(args.GetArg("-changetype", ""));
3120 if (!parsed) {
3121 error = strprintf(_("Unknown change type '%s'"), args.GetArg("-changetype", ""));
3122 return nullptr;
3123 }
3124 walletInstance->m_default_change_type = parsed.value();
3125 }
3126
3127 if (const auto arg{args.GetArg("-mintxfee")}) {
3128 std::optional<CAmount> min_tx_fee = ParseMoney(*arg);
3129 if (!min_tx_fee) {
3130 error = AmountErrMsg("mintxfee", *arg);
3131 return nullptr;
3132 } else if (min_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3133 warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
3134 _("This is the minimum transaction fee you pay on every transaction."));
3135 }
3136
3137 walletInstance->m_min_fee = CFeeRate{min_tx_fee.value()};
3138 }
3139
3140 if (const auto arg{args.GetArg("-maxapsfee")}) {
3141 const std::string& max_aps_fee{*arg};
3142 if (max_aps_fee == "-1") {
3143 walletInstance->m_max_aps_fee = -1;
3144 } else if (std::optional<CAmount> max_fee = ParseMoney(max_aps_fee)) {
3145 if (max_fee.value() > HIGH_APS_FEE) {
3146 warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
3147 _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3148 }
3149 walletInstance->m_max_aps_fee = max_fee.value();
3150 } else {
3151 error = AmountErrMsg("maxapsfee", max_aps_fee);
3152 return nullptr;
3153 }
3154 }
3155
3156 if (const auto arg{args.GetArg("-fallbackfee")}) {
3157 std::optional<CAmount> fallback_fee = ParseMoney(*arg);
3158 if (!fallback_fee) {
3159 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-fallbackfee", *arg);
3160 return nullptr;
3161 } else if (fallback_fee.value() > HIGH_TX_FEE_PER_KB) {
3162 warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
3163 _("This is the transaction fee you may pay when fee estimates are not available."));
3164 }
3165 walletInstance->m_fallback_fee = CFeeRate{fallback_fee.value()};
3166 }
3167
3168 // Disable fallback fee in case value was set to 0, enable if non-null value
3169 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
3170
3171 if (const auto arg{args.GetArg("-discardfee")}) {
3172 std::optional<CAmount> discard_fee = ParseMoney(*arg);
3173 if (!discard_fee) {
3174 error = strprintf(_("Invalid amount for %s=<amount>: '%s'"), "-discardfee", *arg);
3175 return nullptr;
3176 } else if (discard_fee.value() > HIGH_TX_FEE_PER_KB) {
3177 warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
3178 _("This is the transaction fee you may discard if change is smaller than dust at this level"));
3179 }
3180 walletInstance->m_discard_rate = CFeeRate{discard_fee.value()};
3181 }
3182
3183 if (const auto arg{args.GetArg("-paytxfee")}) {
3184 warnings.push_back(_("-paytxfee is deprecated and will be fully removed in v31.0."));
3185
3186 std::optional<CAmount> pay_tx_fee = ParseMoney(*arg);
3187 if (!pay_tx_fee) {
3188 error = AmountErrMsg("paytxfee", *arg);
3189 return nullptr;
3190 } else if (pay_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
3191 warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
3192 _("This is the transaction fee you will pay if you send a transaction."));
3193 }
3194
3195 walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000};
3196
3197 if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
3198 error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3199 "-paytxfee", *arg, chain->relayMinFee().ToString());
3200 return nullptr;
3201 }
3202 }
3203
3204 if (const auto arg{args.GetArg("-maxtxfee")}) {
3205 std::optional<CAmount> max_fee = ParseMoney(*arg);
3206 if (!max_fee) {
3207 error = AmountErrMsg("maxtxfee", *arg);
3208 return nullptr;
3209 } else if (max_fee.value() > HIGH_MAX_TX_FEE) {
3210 warnings.push_back(strprintf(_("%s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee"));
3211 }
3212
3213 if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) {
3214 error = strprintf(_("Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3215 "-maxtxfee", *arg, chain->relayMinFee().ToString());
3216 return nullptr;
3217 }
3218
3219 walletInstance->m_default_max_tx_fee = max_fee.value();
3220 }
3221
3222 if (const auto arg{args.GetArg("-consolidatefeerate")}) {
3223 if (std::optional<CAmount> consolidate_feerate = ParseMoney(*arg)) {
3224 walletInstance->m_consolidate_feerate = CFeeRate(*consolidate_feerate);
3225 } else {
3226 error = AmountErrMsg("consolidatefeerate", *arg);
3227 return nullptr;
3228 }
3229 }
3230
3232 warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
3233 _("The wallet will avoid paying less than the minimum relay fee."));
3234 }
3235
3236 walletInstance->m_confirm_target = args.GetIntArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
3237 walletInstance->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
3238 walletInstance->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
3239
3240 walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3241
3242 // Try to top up keypool. No-op if the wallet is locked.
3243 walletInstance->TopUpKeyPool();
3244
3245 // Cache the first key time
3246 std::optional<int64_t> time_first_key;
3247 for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3248 int64_t time = spk_man->GetTimeFirstKey();
3249 if (!time_first_key || time < *time_first_key) time_first_key = time;
3250 }
3251 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3252
3253 if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
3254 walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
3255 return nullptr;
3256 }
3257
3258 {
3259 LOCK(walletInstance->cs_wallet);
3260 walletInstance->SetBroadcastTransactions(args.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
3261 walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3262 walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3263 walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3264 }
3265
3266 return walletInstance;
3267}
3268
3269bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
3270{
3271 LOCK(walletInstance->cs_wallet);
3272 // allow setting the chain if it hasn't been set already but prevent changing it
3273 assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
3274 walletInstance->m_chain = &chain;
3275
3276 // Unless allowed, ensure wallet files are not reused across chains:
3277 if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
3278 WalletBatch batch(walletInstance->GetDatabase());
3279 CBlockLocator locator;
3280 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
3281 // Wallet is assumed to be from another chain, if genesis block in the active
3282 // chain differs from the genesis block known to the wallet.
3283 if (chain.getBlockHash(0) != locator.vHave.back()) {
3284 error = Untranslated("Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3285 return false;
3286 }
3287 }
3288 }
3289
3290 // Register wallet with validationinterface. It's done before rescan to avoid
3291 // missing block connections during the rescan.
3292 // Because of the wallet lock being held, block connection notifications are going to
3293 // be pending on the validation-side until lock release. Blocks that are connected while the
3294 // rescan is ongoing will not be processed in the rescan but with the block connected notifications,
3295 // so the wallet will only be completeley synced after the notifications delivery.
3296 // chainStateFlushed notifications are ignored until the rescan is finished
3297 // so that in case of a shutdown event, the rescan will be repeated at the next start.
3298 // This is temporary until rescan and notifications delivery are unified under same
3299 // interface.
3300 walletInstance->m_attaching_chain = true; //ignores chainStateFlushed notifications
3301 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3302
3303 // If rescan_required = true, rescan_height remains equal to 0
3304 int rescan_height = 0;
3305 if (!rescan_required)
3306 {
3307 WalletBatch batch(walletInstance->GetDatabase());
3308 CBlockLocator locator;
3309 if (batch.ReadBestBlock(locator)) {
3310 if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
3311 rescan_height = *fork_height;
3312 }
3313 }
3314 }
3315
3316 const std::optional<int> tip_height = chain.getHeight();
3317 if (tip_height) {
3318 walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
3319 walletInstance->m_last_block_processed_height = *tip_height;
3320 } else {
3321 walletInstance->m_last_block_processed.SetNull();
3322 walletInstance->m_last_block_processed_height = -1;
3323 }
3324
3325 if (tip_height && *tip_height != rescan_height)
3326 {
3327 // No need to read and scan block if block was created before
3328 // our wallet birthday (as adjusted for block time variability)
3329 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3330 if (time_first_key) {
3331 FoundBlock found = FoundBlock().height(rescan_height);
3332 chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, found);
3333 if (!found.found) {
3334 // We were unable to find a block that had a time more recent than our earliest timestamp
3335 // or a height higher than the wallet was synced to, indicating that the wallet is newer than the
3336 // current chain tip. Skip rescanning in this case.
3337 rescan_height = *tip_height;
3338 }
3339 }
3340
3341 // Technically we could execute the code below in any case, but performing the
3342 // `while` loop below can make startup very slow, so only check blocks on disk
3343 // if necessary.
3345 int block_height = *tip_height;
3346 while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3347 --block_height;
3348 }
3349
3350 if (rescan_height != block_height) {
3351 // We can't rescan beyond blocks we don't have data for, stop and throw an error.
3352 // This might happen if a user uses an old wallet within a pruned node
3353 // or if they ran -disablewallet for a longer time, then decided to re-enable
3354 // Exit early and print an error.
3355 // It also may happen if an assumed-valid chain is in use and therefore not
3356 // all block data is available.
3357 // If a block is pruned after this check, we will load the wallet,
3358 // but fail the rescan with a generic error.
3359
3360 error = chain.havePruned() ?
3361 _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3362 strprintf(_(
3363 "Error loading wallet. Wallet requires blocks to be downloaded, "
3364 "and software does not currently support loading wallets while "
3365 "blocks are being downloaded out of order when using assumeutxo "
3366 "snapshots. Wallet should be able to load successfully after "
3367 "node sync reaches height %s"), block_height);
3368 return false;
3369 }
3370 }
3371
3372 chain.initMessage(_("Rescanning…"));
3373 walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3374
3375 {
3376 WalletRescanReserver reserver(*walletInstance);
3377 if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true).status)) {
3378 error = _("Failed to rescan the wallet during initialization");
3379 return false;
3380 }
3381 }
3382 walletInstance->m_attaching_chain = false;
3383 walletInstance->chainStateFlushed(ChainstateRole::NORMAL, chain.getTipLocator());
3384 walletInstance->GetDatabase().IncrementUpdateCounter();
3385 }
3386 walletInstance->m_attaching_chain = false;
3387
3388 return true;
3389}
3390
3391const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
3392{
3393 const auto& address_book_it = m_address_book.find(dest);
3394 if (address_book_it == m_address_book.end()) return nullptr;
3395 if ((!allow_change) && address_book_it->second.IsChange()) {
3396 return nullptr;
3397 }
3398 return &address_book_it->second;
3399}
3400
3401bool CWallet::UpgradeWallet(int version, bilingual_str& error)
3402{
3403 int prev_version = GetVersion();
3404 if (version == 0) {
3405 WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
3406 version = FEATURE_LATEST;
3407 } else {
3408 WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
3409 }
3410 if (version < prev_version) {
3411 error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3412 return false;
3413 }
3414
3415 LOCK(cs_wallet);
3416
3417 // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
3419 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);
3420 return false;
3421 }
3422
3423 // Permanently upgrade to the version
3425
3426 for (auto spk_man : GetActiveScriptPubKeyMans()) {
3427 if (!spk_man->Upgrade(prev_version, version, error)) {
3428 return false;
3429 }
3430 }
3431 return true;
3432}
3433
3435{
3436 // Add wallet transactions that aren't already in a block to mempool
3437 // Do this here as mempool requires genesis block to be loaded
3438 ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
3439
3440 // Update wallet transactions with current mempool transactions.
3441 WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
3442}
3443
3444bool CWallet::BackupWallet(const std::string& strDest) const
3445{
3446 if (m_chain) {
3447 CBlockLocator loc;
3448 WITH_LOCK(cs_wallet, chain().findBlock(m_last_block_processed, FoundBlock().locator(loc)));
3449 if (!loc.IsNull()) {
3450 WalletBatch batch(GetDatabase());
3451 batch.WriteBestBlock(loc);
3452 }
3453 }
3454 return GetDatabase().Backup(strDest);
3455}
3456
3458{
3459 nTime = GetTime();
3460 fInternal = false;
3461 m_pre_split = false;
3462}
3463
3464CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
3465{
3466 nTime = GetTime();
3467 vchPubKey = vchPubKeyIn;
3468 fInternal = internalIn;
3469 m_pre_split = false;
3470}
3471
3473{
3475 if (auto* conf = wtx.state<TxStateConfirmed>()) {
3476 assert(conf->confirmed_block_height >= 0);
3477 return GetLastBlockHeight() - conf->confirmed_block_height + 1;
3478 } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) {
3479 assert(conf->conflicting_block_height >= 0);
3480 return -1 * (GetLastBlockHeight() - conf->conflicting_block_height + 1);
3481 } else {
3482 return 0;
3483 }
3484}
3485
3487{
3489
3490 if (!wtx.IsCoinBase()) {
3491 return 0;
3492 }
3493 int chain_depth = GetTxDepthInMainChain(wtx);
3494 assert(chain_depth >= 0); // coinbase tx should not be conflicted
3495 return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
3496}
3497
3499{
3501
3502 // note GetBlocksToMaturity is 0 for non-coinbase tx
3503 return GetTxBlocksToMaturity(wtx) > 0;
3504}
3505
3507{
3508 return HasEncryptionKeys();
3509}
3510
3512{
3513 if (!IsCrypted()) {
3514 return false;
3515 }
3516 LOCK(cs_wallet);
3517 return vMasterKey.empty();
3518}
3519
3521{
3522 if (!IsCrypted())
3523 return false;
3524
3525 {
3527 if (!vMasterKey.empty()) {
3528 memory_cleanse(vMasterKey.data(), vMasterKey.size() * sizeof(decltype(vMasterKey)::value_type));
3529 vMasterKey.clear();
3530 }
3531 }
3532
3533 NotifyStatusChanged(this);
3534 return true;
3535}
3536
3537bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn)
3538{
3539 {
3540 LOCK(cs_wallet);
3541 for (const auto& spk_man_pair : m_spk_managers) {
3542 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3543 return false;
3544 }
3545 }
3546 vMasterKey = vMasterKeyIn;
3547 }
3548 NotifyStatusChanged(this);
3549 return true;
3550}
3551
3552std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
3553{
3554 std::set<ScriptPubKeyMan*> spk_mans;
3555 for (bool internal : {false, true}) {
3556 for (OutputType t : OUTPUT_TYPES) {
3557 auto spk_man = GetScriptPubKeyMan(t, internal);
3558 if (spk_man) {
3559 spk_mans.insert(spk_man);
3560 }
3561 }
3562 }
3563 return spk_mans;
3564}
3565
3567{
3568 for (const auto& [_, ext_spkm] : m_external_spk_managers) {
3569 if (ext_spkm == &spkm) return true;
3570 }
3571 for (const auto& [_, int_spkm] : m_internal_spk_managers) {
3572 if (int_spkm == &spkm) return true;
3573 }
3574 return false;
3575}
3576
3577std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
3578{
3579 std::set<ScriptPubKeyMan*> spk_mans;
3580 for (const auto& spk_man_pair : m_spk_managers) {
3581 spk_mans.insert(spk_man_pair.second.get());
3582 }
3583 return spk_mans;
3584}
3585
3587{
3588 const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
3589 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3590 if (it == spk_managers.end()) {
3591 return nullptr;
3592 }
3593 return it->second;
3594}
3595
3596std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script) const
3597{
3598 std::set<ScriptPubKeyMan*> spk_mans;
3599
3600 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3601 const auto& it = m_cached_spks.find(script);
3602 if (it != m_cached_spks.end()) {
3603 spk_mans.insert(it->second.begin(), it->second.end());
3604 }
3605 SignatureData sigdata;
3606 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3607
3608 // Legacy wallet
3610 if (spkm && spkm->CanProvide(script, sigdata)) spk_mans.insert(spkm);
3611
3612 return spk_mans;
3613}
3614
3616{
3617 if (m_spk_managers.count(id) > 0) {
3618 return m_spk_managers.at(id).get();
3619 }
3620 return nullptr;
3621}
3622
3623std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3624{
3625 SignatureData sigdata;
3626 return GetSolvingProvider(script, sigdata);
3627}
3628
3629std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3630{
3631 // Search the cache for relevant SPKMs instead of iterating m_spk_managers
3632 const auto& it = m_cached_spks.find(script);
3633 if (it != m_cached_spks.end()) {
3634 // All spkms for a given script must already be able to make a SigningProvider for the script, so just return the first one.
3635 Assume(it->second.at(0)->CanProvide(script, sigdata));
3636 return it->second.at(0)->GetSolvingProvider(script);
3637 }
3638
3639 // Legacy wallet
3641 if (spkm && spkm->CanProvide(script, sigdata)) return spkm->GetSolvingProvider(script);
3642
3643 return nullptr;
3644}
3645
3646std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const
3647{
3648 std::vector<WalletDescriptor> descs;
3649 for (const auto spk_man: GetScriptPubKeyMans(script)) {
3650 if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3651 LOCK(desc_spk_man->cs_desc_man);
3652 descs.push_back(desc_spk_man->GetWalletDescriptor());
3653 }
3654 }
3655 return descs;
3656}
3657
3659{
3661 return nullptr;
3662 }
3663 // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
3664 // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
3666 if (it == m_internal_spk_managers.end()) return nullptr;
3667 return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
3668}
3669
3671{
3673 return nullptr;
3674 }
3676 if (it == m_internal_spk_managers.end()) return nullptr;
3677 return dynamic_cast<LegacyDataSPKM*>(it->second);
3678}
3679
3681{
3683 return GetLegacyScriptPubKeyMan();
3684}
3685
3686void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man)
3687{
3688 // Add spkm_man to m_spk_managers before calling any method
3689 // that might access it.
3690 const auto& spkm = m_spk_managers[id] = std::move(spkm_man);
3691
3692 // Update birth time if needed
3693 MaybeUpdateBirthTime(spkm->GetTimeFirstKey());
3694}
3695
3697{
3699 return GetLegacyDataSPKM();
3700}
3701
3703{
3705 return;
3706 }
3707
3708 std::unique_ptr<ScriptPubKeyMan> spk_manager = m_database->Format() == "bdb_ro" ?
3709 std::make_unique<LegacyDataSPKM>(*this) :
3710 std::make_unique<LegacyScriptPubKeyMan>(*this, m_keypool_size);
3711
3712 for (const auto& type : LEGACY_OUTPUT_TYPES) {
3713 m_internal_spk_managers[type] = spk_manager.get();
3714 m_external_spk_managers[type] = spk_manager.get();
3715 }
3716 uint256 id = spk_manager->GetID();
3717 AddScriptPubKeyMan(id, std::move(spk_manager));
3718}
3719
3720bool CWallet::WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const
3721{
3722 LOCK(cs_wallet);
3723 return cb(vMasterKey);
3724}
3725
3727{
3728 return !mapMasterKeys.empty();
3729}
3730
3732{
3733 for (const auto& spkm : GetAllScriptPubKeyMans()) {
3734 if (spkm->HaveCryptedKeys()) return true;
3735 }
3736 return false;
3737}
3738
3740{
3741 for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3742 spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3743 spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3744 spk_man->NotifyFirstKeyTimeChanged.connect(std::bind(&CWallet::MaybeUpdateBirthTime, this, std::placeholders::_2));
3745 }
3746}
3747
3749{
3750 DescriptorScriptPubKeyMan* spk_manager;
3752 spk_manager = new ExternalSignerScriptPubKeyMan(*this, desc, m_keypool_size);
3753 } else {
3754 spk_manager = new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size);
3755 }
3756 AddScriptPubKeyMan(id, std::unique_ptr<ScriptPubKeyMan>(spk_manager));
3757 return *spk_manager;
3758}
3759
3760DescriptorScriptPubKeyMan& CWallet::SetupDescriptorScriptPubKeyMan(WalletBatch& batch, const CExtKey& master_key, const OutputType& output_type, bool internal)
3761{
3763 auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, m_keypool_size));
3764 if (IsCrypted()) {
3765 if (IsLocked()) {
3766 throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3767 }
3768 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3769 throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3770 }
3771 }
3772 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3773 DescriptorScriptPubKeyMan* out = spk_manager.get();
3774 uint256 id = spk_manager->GetID();
3775 AddScriptPubKeyMan(id, std::move(spk_manager));
3776 AddActiveScriptPubKeyManWithDb(batch, id, output_type, internal);
3777 return *out;
3778}
3779
3781{
3783 for (bool internal : {false, true}) {
3784 for (OutputType t : OUTPUT_TYPES) {
3785 SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
3786 }
3787 }
3788}
3789
3791{
3794 // Make a seed
3795 CKey seed_key = GenerateRandomKey();
3796 CPubKey seed = seed_key.GetPubKey();
3797 assert(seed_key.VerifyPubKey(seed));
3798
3799 // Get the extended key
3800 CExtKey master_key;
3801 master_key.SetSeed(seed_key);
3802
3803 SetupDescriptorScriptPubKeyMans(batch, master_key);
3804}
3805
3807{
3809
3811 if (!RunWithinTxn(GetDatabase(), /*process_desc=*/"setup descriptors", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet){
3813 return true;
3814 })) throw std::runtime_error("Error: cannot process db transaction for descriptors setup");
3815 } else {
3817
3818 // TODO: add account parameter
3819 int account = 0;
3820 UniValue signer_res = signer.GetDescriptors(account);
3821
3822 if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3823
3824 WalletBatch batch(GetDatabase());
3825 if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors import");
3826
3827 for (bool internal : {false, true}) {
3828 const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
3829 if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3830 for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
3831 const std::string& desc_str = desc_val.getValStr();
3833 std::string desc_error;
3834 auto descs = Parse(desc_str, keys, desc_error, false);
3835 if (descs.empty()) {
3836 throw std::runtime_error(std::string(__func__) + ": Invalid descriptor \"" + desc_str + "\" (" + desc_error + ")");
3837 }
3838 auto& desc = descs.at(0);
3839 if (!desc->GetOutputType()) {
3840 continue;
3841 }
3842 OutputType t = *desc->GetOutputType();
3843 auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, m_keypool_size));
3844 spk_manager->SetupDescriptor(batch, std::move(desc));
3845 uint256 id = spk_manager->GetID();
3846 AddScriptPubKeyMan(id, std::move(spk_manager));
3847 AddActiveScriptPubKeyManWithDb(batch, id, t, internal);
3848 }
3849 }
3850
3851 // Ensure imported descriptors are committed to disk
3852 if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors import");
3853 }
3854}
3855
3857{
3858 WalletBatch batch(GetDatabase());
3859 return AddActiveScriptPubKeyManWithDb(batch, id, type, internal);
3860}
3861
3863{
3864 if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
3865 throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
3866 }
3867 LoadActiveScriptPubKeyMan(id, type, internal);
3868}
3869
3871{
3872 // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
3873 // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
3875
3876 WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3877 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3878 auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
3879 auto spk_man = m_spk_managers.at(id).get();
3880 spk_mans[type] = spk_man;
3881
3882 const auto it = spk_mans_other.find(type);
3883 if (it != spk_mans_other.end() && it->second == spk_man) {
3884 spk_mans_other.erase(type);
3885 }
3886
3888}
3889
3891{
3892 auto spk_man = GetScriptPubKeyMan(type, internal);
3893 if (spk_man != nullptr && spk_man->GetID() == id) {
3894 WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
3895 WalletBatch batch(GetDatabase());
3896 if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3897 throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3898 }
3899
3900 auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3901 spk_mans.erase(type);
3902 }
3903
3905}
3906
3908{
3910}
3911
3913{
3914 for (auto& spk_man_pair : m_spk_managers) {
3915 // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
3916 DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
3917 if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3918 return spk_manager;
3919 }
3920 }
3921
3922 return nullptr;
3923}
3924
3925std::optional<bool> CWallet::IsInternalScriptPubKeyMan(ScriptPubKeyMan* spk_man) const
3926{
3927 // Legacy script pubkey man can't be either external or internal
3928 if (IsLegacy()) {
3929 return std::nullopt;
3930 }
3931
3932 // only active ScriptPubKeyMan can be internal
3933 if (!GetActiveScriptPubKeyMans().count(spk_man)) {
3934 return std::nullopt;
3935 }
3936
3937 const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
3938 if (!desc_spk_man) {
3939 throw std::runtime_error(std::string(__func__) + ": unexpected ScriptPubKeyMan type.");
3940 }
3941
3942 LOCK(desc_spk_man->cs_desc_man);
3943 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3944 assert(type.has_value());
3945
3946 return GetScriptPubKeyMan(*type, /* internal= */ true) == desc_spk_man;
3947}
3948
3949ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
3950{
3952
3954 WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
3955 return nullptr;
3956 }
3957
3958 auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3959 if (spk_man) {
3960 WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
3961 spk_man->UpdateWalletDescriptor(desc);
3962 } else {
3963 auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc, m_keypool_size));
3964 spk_man = new_spk_man.get();
3965
3966 // Save the descriptor to memory
3967 uint256 id = new_spk_man->GetID();
3968 AddScriptPubKeyMan(id, std::move(new_spk_man));
3969 }
3970
3971 // Add the private keys to the descriptor
3972 for (const auto& entry : signing_provider.keys) {
3973 const CKey& key = entry.second;
3974 spk_man->AddDescriptorKey(key, key.GetPubKey());
3975 }
3976
3977 // Top up key pool, the manager will generate new scriptPubKeys internally
3978 if (!spk_man->TopUp()) {
3979 WalletLogPrintf("Could not top up scriptPubKeys\n");
3980 return nullptr;
3981 }
3982
3983 // Apply the label if necessary
3984 // Note: we disable labels for ranged descriptors
3985 if (!desc.descriptor->IsRange()) {
3986 auto script_pub_keys = spk_man->GetScriptPubKeys();
3987 if (script_pub_keys.empty()) {
3988 WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
3989 return nullptr;
3990 }
3991
3992 if (!internal) {
3993 for (const auto& script : script_pub_keys) {
3994 CTxDestination dest;
3995 if (ExtractDestination(script, dest)) {
3997 }
3998 }
3999 }
4000 }
4001
4002 // Save the descriptor to DB
4003 spk_man->WriteDescriptor();
4004
4005 return spk_man;
4006}
4007
4009{
4011
4012 WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
4013
4014 if (m_database->Format() == "sqlite") {
4015 error = _("Error: This wallet already uses SQLite");
4016 return false;
4017 }
4018
4019 // Get all of the records for DB type migration
4020 std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
4021 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
4022 std::vector<std::pair<SerializeData, SerializeData>> records;
4023 if (!cursor) {
4024 error = _("Error: Unable to begin reading all records in the database");
4025 return false;
4026 }
4028 while (true) {
4029 DataStream ss_key{};
4030 DataStream ss_value{};
4031 status = cursor->Next(ss_key, ss_value);
4032 if (status != DatabaseCursor::Status::MORE) {
4033 break;
4034 }
4035 SerializeData key(ss_key.begin(), ss_key.end());
4036 SerializeData value(ss_value.begin(), ss_value.end());
4037 records.emplace_back(key, value);
4038 }
4039 cursor.reset();
4040 batch.reset();
4041 if (status != DatabaseCursor::Status::DONE) {
4042 error = _("Error: Unable to read all records in the database");
4043 return false;
4044 }
4045
4046 // Close this database and delete the file
4047 fs::path db_path = fs::PathFromString(m_database->Filename());
4048 m_database->Close();
4049 fs::remove(db_path);
4050
4051 // Generate the path for the location of the migrated wallet
4052 // Wallets that are plain files rather than wallet directories will be migrated to be wallet directories.
4054
4055 // Make new DB
4056 DatabaseOptions opts;
4057 opts.require_create = true;
4059 DatabaseStatus db_status;
4060 std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
4061 assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
4062 m_database.reset();
4063 m_database = std::move(new_db);
4064
4065 // Write existing records into the new DB
4066 batch = m_database->MakeBatch();
4067 bool began = batch->TxnBegin();
4068 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.
4069 for (const auto& [key, value] : records) {
4070 if (!batch->Write(std::span{key}, std::span{value})) {
4071 batch->TxnAbort();
4072 m_database->Close();
4073 fs::remove(m_database->Filename());
4074 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.
4075 }
4076 }
4077 bool committed = batch->TxnCommit();
4078 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.
4079 return true;
4080}
4081
4082std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& error) const
4083{
4085
4086 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
4087 if (!Assume(legacy_spkm)) {
4088 // This shouldn't happen
4089 error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
4090 return std::nullopt;
4091 }
4092
4093 std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
4094 if (res == std::nullopt) {
4095 error = _("Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4096 return std::nullopt;
4097 }
4098 return res;
4099}
4100
4102{
4104
4105 LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
4106 if (!Assume(legacy_spkm)) {
4107 // This shouldn't happen
4108 return util::Error{Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"))};
4109 }
4110
4111 // Get all invalid or non-watched scripts that will not be migrated
4112 std::set<CTxDestination> not_migrated_dests;
4113 for (const auto& script : legacy_spkm->GetNotMineScriptPubKeys()) {
4114 CTxDestination dest;
4115 if (ExtractDestination(script, dest)) not_migrated_dests.emplace(dest);
4116 }
4117
4118 // When the legacy wallet has no spendable scripts, the main wallet will be empty, leaving its script cache empty as well.
4119 // The watch-only and/or solvable wallet(s) will contain the scripts in their respective caches.
4120 if (!data.desc_spkms.empty()) Assume(!m_cached_spks.empty());
4121 if (!data.watch_descs.empty()) Assume(!data.watchonly_wallet->m_cached_spks.empty());
4122 if (!data.solvable_descs.empty()) Assume(!data.solvable_wallet->m_cached_spks.empty());
4123
4124 for (auto& desc_spkm : data.desc_spkms) {
4125 if (m_spk_managers.count(desc_spkm->GetID()) > 0) {
4126 return util::Error{_("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
4127 }
4128 uint256 id = desc_spkm->GetID();
4129 AddScriptPubKeyMan(id, std::move(desc_spkm));
4130 }
4131
4132 // Remove the LegacyScriptPubKeyMan from disk
4133 if (!legacy_spkm->DeleteRecordsWithDB(local_wallet_batch)) {
4134 return util::Error{_("Error: cannot remove legacy wallet records")};
4135 }
4136
4137 // Remove the LegacyScriptPubKeyMan from memory
4138 m_spk_managers.erase(legacy_spkm->GetID());
4141
4142 // Setup new descriptors
4143 SetWalletFlagWithDB(local_wallet_batch, WALLET_FLAG_DESCRIPTORS);
4145 // Use the existing master key if we have it
4146 if (data.master_key.key.IsValid()) {
4147 SetupDescriptorScriptPubKeyMans(local_wallet_batch, data.master_key);
4148 } else {
4149 // Setup with a new seed if we don't.
4150 SetupOwnDescriptorScriptPubKeyMans(local_wallet_batch);
4151 }
4152 }
4153
4154 // Get best block locator so that we can copy it to the watchonly and solvables
4155 CBlockLocator best_block_locator;
4156 if (!local_wallet_batch.ReadBestBlock(best_block_locator)) {
4157 return util::Error{_("Error: Unable to read wallet's best block locator record")};
4158 }
4159
4160 // Check if the transactions in the wallet are still ours. Either they belong here, or they belong in the watchonly wallet.
4161 // We need to go through these in the tx insertion order so that lookups to spends works.
4162 std::vector<uint256> txids_to_delete;
4163 std::unique_ptr<WalletBatch> watchonly_batch;
4164 if (data.watchonly_wallet) {
4165 watchonly_batch = std::make_unique<WalletBatch>(data.watchonly_wallet->GetDatabase());
4166 if (!watchonly_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.watchonly_wallet->GetName())};
4167 // Copy the next tx order pos to the watchonly wallet
4168 LOCK(data.watchonly_wallet->cs_wallet);
4169 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
4170 watchonly_batch->WriteOrderPosNext(data.watchonly_wallet->nOrderPosNext);
4171 // Write the best block locator to avoid rescanning on reload
4172 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4173 return util::Error{_("Error: Unable to write watchonly wallet best block locator record")};
4174 }
4175 }
4176 std::unique_ptr<WalletBatch> solvables_batch;
4177 if (data.solvable_wallet) {
4178 solvables_batch = std::make_unique<WalletBatch>(data.solvable_wallet->GetDatabase());
4179 if (!solvables_batch->TxnBegin()) return util::Error{strprintf(_("Error: database transaction cannot be executed for wallet %s"), data.solvable_wallet->GetName())};
4180 // Write the best block locator to avoid rescanning on reload
4181 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
4182 return util::Error{_("Error: Unable to write solvable wallet best block locator record")};
4183 }
4184 }
4185 for (const auto& [_pos, wtx] : wtxOrdered) {
4186 // Check it is the watchonly wallet's
4187 // solvable_wallet doesn't need to be checked because transactions for those scripts weren't being watched for
4188 bool is_mine = IsMine(*wtx->tx) || IsFromMe(*wtx->tx);
4189 if (data.watchonly_wallet) {
4190 LOCK(data.watchonly_wallet->cs_wallet);
4191 if (data.watchonly_wallet->IsMine(*wtx->tx) || data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4192 // Add to watchonly wallet
4193 const uint256& hash = wtx->GetHash();
4194 const CWalletTx& to_copy_wtx = *wtx;
4195 if (!data.watchonly_wallet->LoadToWallet(hash, [&](CWalletTx& ins_wtx, bool new_tx) EXCLUSIVE_LOCKS_REQUIRED(data.watchonly_wallet->cs_wallet) {
4196 if (!new_tx) return false;
4197 ins_wtx.SetTx(to_copy_wtx.tx);
4198 ins_wtx.CopyFrom(to_copy_wtx);
4199 return true;
4200 })) {
4201 return util::Error{strprintf(_("Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
4202 }
4203 watchonly_batch->WriteTx(data.watchonly_wallet->mapWallet.at(hash));
4204 // Mark as to remove from the migrated wallet only if it does not also belong to it
4205 if (!is_mine) {
4206 txids_to_delete.push_back(hash);
4207 }
4208 continue;
4209 }
4210 }
4211 if (!is_mine) {
4212 // Both not ours and not in the watchonly wallet
4213 return util::Error{strprintf(_("Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
4214 }
4215 }
4216
4217 // Do the removes
4218 if (txids_to_delete.size() > 0) {
4219 if (auto res = RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
4220 return util::Error{_("Error: Could not delete watchonly transactions. ") + util::ErrorString(res)};
4221 }
4222 }
4223
4224 // Pair external wallets with their corresponding db handler
4225 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4226 if (data.watchonly_wallet) wallets_vec.emplace_back(data.watchonly_wallet, std::move(watchonly_batch));
4227 if (data.solvable_wallet) wallets_vec.emplace_back(data.solvable_wallet, std::move(solvables_batch));
4228
4229 // Write address book entry to disk
4230 auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
4231 auto address{EncodeDestination(dest)};
4232 if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
4233 if (entry.label) batch.WriteName(address, *entry.label);
4234 for (const auto& [id, request] : entry.receive_requests) {
4235 batch.WriteAddressReceiveRequest(dest, id, request);
4236 }
4237 if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
4238 };
4239
4240 // Check the address book data in the same way we did for transactions
4241 std::vector<CTxDestination> dests_to_delete;
4242 for (const auto& [dest, record] : m_address_book) {
4243 // Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
4244 // Entries for everything else ("send") will be cloned to all wallets.
4245 bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
4246 bool copied = false;
4247 for (auto& [wallet, batch] : wallets_vec) {
4248 LOCK(wallet->cs_wallet);
4249 if (require_transfer && !wallet->IsMine(dest)) continue;
4250
4251 // Copy the entire address book entry
4252 wallet->m_address_book[dest] = record;
4253 func_store_addr(*batch, dest, record);
4254
4255 copied = true;
4256 // Only delete 'receive' records that are no longer part of the original wallet
4257 if (require_transfer) {
4258 dests_to_delete.push_back(dest);
4259 break;
4260 }
4261 }
4262
4263 // Fail immediately if we ever found an entry that was ours and cannot be transferred
4264 // to any of the created wallets (watch-only, solvable).
4265 // Means that no inferred descriptor maps to the stored entry. Which mustn't happen.
4266 if (require_transfer && !copied) {
4267
4268 // Skip invalid/non-watched scripts that will not be migrated
4269 if (not_migrated_dests.count(dest) > 0) {
4270 dests_to_delete.push_back(dest);
4271 continue;
4272 }
4273
4274 return util::Error{_("Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4275 }
4276 }
4277
4278 // Persist external wallets address book entries
4279 for (auto& [wallet, batch] : wallets_vec) {
4280 if (!batch->TxnCommit()) {
4281 return util::Error{strprintf(_("Error: Unable to write data to disk for wallet %s"), wallet->GetName())};
4282 }
4283 }
4284
4285 // Remove the things to delete in this wallet
4286 if (dests_to_delete.size() > 0) {
4287 for (const auto& dest : dests_to_delete) {
4288 if (!DelAddressBookWithDB(local_wallet_batch, dest)) {
4289 return util::Error{_("Error: Unable to remove watchonly address book data")};
4290 }
4291 }
4292 }
4293
4294 return {}; // all good
4295}
4296
4298{
4300}
4301
4303{
4304 AssertLockHeld(wallet.cs_wallet);
4305
4306 // Get all of the descriptors from the legacy wallet
4307 std::optional<MigrationData> data = wallet.GetDescriptorsForLegacy(error);
4308 if (data == std::nullopt) return false;
4309
4310 // Create the watchonly and solvable wallets if necessary
4311 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4312 DatabaseOptions options;
4313 options.require_existing = false;
4314 options.require_create = true;
4316
4317 WalletContext empty_context;
4318 empty_context.args = context.args;
4319
4320 // Make the wallets
4322 if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
4324 }
4325 if (wallet.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
4327 }
4328 if (data->watch_descs.size() > 0) {
4329 wallet.WalletLogPrintf("Making a new watchonly wallet containing the watched scripts\n");
4330
4331 DatabaseStatus status;
4332 std::vector<bilingual_str> warnings;
4333 std::string wallet_name = wallet.GetName() + "_watchonly";
4334 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4335 if (!database) {
4336 error = strprintf(_("Wallet file creation failed: %s"), error);
4337 return false;
4338 }
4339
4340 data->watchonly_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4341 if (!data->watchonly_wallet) {
4342 error = _("Error: Failed to create new watchonly wallet");
4343 return false;
4344 }
4345 res.watchonly_wallet = data->watchonly_wallet;
4346 LOCK(data->watchonly_wallet->cs_wallet);
4347
4348 // Parse the descriptors and add them to the new wallet
4349 for (const auto& [desc_str, creation_time] : data->watch_descs) {
4350 // Parse the descriptor
4352 std::string parse_err;
4353 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4354 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4355 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4356
4357 // Add to the wallet
4358 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4359 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4360 }
4361
4362 // Add the wallet to settings
4363 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4364 }
4365 if (data->solvable_descs.size() > 0) {
4366 wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
4367
4368 DatabaseStatus status;
4369 std::vector<bilingual_str> warnings;
4370 std::string wallet_name = wallet.GetName() + "_solvables";
4371 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4372 if (!database) {
4373 error = strprintf(_("Wallet file creation failed: %s"), error);
4374 return false;
4375 }
4376
4377 data->solvable_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4378 if (!data->solvable_wallet) {
4379 error = _("Error: Failed to create new watchonly wallet");
4380 return false;
4381 }
4382 res.solvables_wallet = data->solvable_wallet;
4383 LOCK(data->solvable_wallet->cs_wallet);
4384
4385 // Parse the descriptors and add them to the new wallet
4386 for (const auto& [desc_str, creation_time] : data->solvable_descs) {
4387 // Parse the descriptor
4389 std::string parse_err;
4390 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
4391 assert(descs.size() == 1); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor or a multipath descriptors
4392 assert(!descs.at(0)->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
4393
4394 // Add to the wallet
4395 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
4396 data->solvable_wallet->AddWalletDescriptor(w_desc, keys, "", false);
4397 }
4398
4399 // Add the wallet to settings
4400 UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
4401 }
4402 }
4403
4404 // Add the descriptors to wallet, remove LegacyScriptPubKeyMan, and cleanup txs and address book data
4405 return RunWithinTxn(wallet.GetDatabase(), /*process_desc=*/"apply migration process", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet){
4406 if (auto res_migration = wallet.ApplyMigrationData(batch, *data); !res_migration) {
4407 error = util::ErrorString(res_migration);
4408 return false;
4409 }
4410 wallet.WalletLogPrintf("Wallet migration complete.\n");
4411 return true;
4412 });
4413}
4414
4415util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context)
4416{
4417 std::vector<bilingual_str> warnings;
4418 bilingual_str error;
4419
4420 // If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
4421 bool was_loaded = false;
4422 if (auto wallet = GetWallet(context, wallet_name)) {
4423 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4424 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4425 }
4426
4427 // Flush chain state before unloading wallet
4428 CBlockLocator locator;
4429 WITH_LOCK(wallet->cs_wallet, context.chain->findBlock(wallet->GetLastBlockHash(), FoundBlock().locator(locator)));
4430 if (!locator.IsNull()) wallet->chainStateFlushed(ChainstateRole::NORMAL, locator);
4431
4432 if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
4433 return util::Error{_("Unable to unload the wallet before migrating")};
4434 }
4435 WaitForDeleteWallet(std::move(wallet));
4436 was_loaded = true;
4437 } else {
4438 // Check if the wallet is BDB
4439 const auto& wallet_path = GetWalletPath(wallet_name);
4440 if (!wallet_path) {
4441 return util::Error{util::ErrorString(wallet_path)};
4442 }
4443 if (!fs::exists(*wallet_path)) {
4444 return util::Error{_("Error: Wallet does not exist")};
4445 }
4446 if (!IsBDBFile(BDBDataFile(*wallet_path))) {
4447 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4448 }
4449 }
4450
4451 // Load the wallet but only in the context of this function.
4452 // No signals should be connected nor should anything else be aware of this wallet
4453 WalletContext empty_context;
4454 empty_context.args = context.args;
4455 DatabaseOptions options;
4456 options.require_existing = true;
4457 options.require_format = DatabaseFormat::BERKELEY_RO;
4458 DatabaseStatus status;
4459 std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
4460 if (!database) {
4461 return util::Error{Untranslated("Wallet file verification failed.") + Untranslated(" ") + error};
4462 }
4463
4464 // Make the local wallet
4465 std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
4466 if (!local_wallet) {
4467 return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
4468 }
4469
4470 return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, was_loaded);
4471}
4472
4473util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded)
4474{
4475 MigrationResult res;
4476 bilingual_str error;
4477 std::vector<bilingual_str> warnings;
4478
4479 DatabaseOptions options;
4480 options.require_existing = true;
4481 DatabaseStatus status;
4482
4483 const std::string wallet_name = local_wallet->GetName();
4484
4485 // Helper to reload as normal for some of our exit scenarios
4486 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4487 assert(to_reload.use_count() == 1);
4488 std::string name = to_reload->GetName();
4489 to_reload.reset();
4490 to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4491 return to_reload != nullptr;
4492 };
4493
4494 // Before anything else, check if there is something to migrate.
4495 if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4496 if (was_loaded) {
4497 reload_wallet(local_wallet);
4498 }
4499 return util::Error{_("Error: This wallet is already a descriptor wallet")};
4500 }
4501
4502 // Make a backup of the DB
4503 fs::path this_wallet_dir = fs::absolute(fs::PathFromString(local_wallet->GetDatabase().Filename())).parent_path();
4504 fs::path backup_filename = fs::PathFromString(strprintf("%s_%d.legacy.bak", (wallet_name.empty() ? "default_wallet" : wallet_name), GetTime()));
4505 fs::path backup_path = this_wallet_dir / backup_filename;
4506 if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4507 if (was_loaded) {
4508 reload_wallet(local_wallet);
4509 }
4510 return util::Error{_("Error: Unable to make a backup of your wallet")};
4511 }
4512 res.backup_path = backup_path;
4513
4514 bool success = false;
4515
4516 // Unlock the wallet if needed
4517 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4518 if (was_loaded) {
4519 reload_wallet(local_wallet);
4520 }
4521 if (passphrase.find('\0') == std::string::npos) {
4522 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4523 } else {
4524 return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4525 "The passphrase contains a null character (ie - a zero byte). "
4526 "If this passphrase was set with a version of this software prior to 25.0, "
4527 "please try again with only the characters up to — but not including — "
4528 "the first null character.")};
4529 }
4530 }
4531
4532 {
4533 LOCK(local_wallet->cs_wallet);
4534 // First change to using SQLite
4535 if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
4536
4537 // Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
4538 success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
4539 if (!success) {
4540 success = DoMigration(*local_wallet, context, error, res);
4541 } else {
4542 // Make sure that descriptors flag is actually set
4543 local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
4544 }
4545 }
4546
4547 // In case of reloading failure, we need to remember the wallet dirs to remove
4548 // Set is used as it may be populated with the same wallet directory paths multiple times,
4549 // both before and after reloading. This ensures the set is complete even if one of the wallets
4550 // fails to reload.
4551 std::set<fs::path> wallet_dirs;
4552 if (success) {
4553 // Migration successful, unload all wallets locally, then reload them.
4554 // Reload the main wallet
4555 wallet_dirs.insert(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4556 success = reload_wallet(local_wallet);
4557 res.wallet = local_wallet;
4558 res.wallet_name = wallet_name;
4559 if (success && res.watchonly_wallet) {
4560 // Reload watchonly
4561 wallet_dirs.insert(fs::PathFromString(res.watchonly_wallet->GetDatabase().Filename()).parent_path());
4562 success = reload_wallet(res.watchonly_wallet);
4563 }
4564 if (success && res.solvables_wallet) {
4565 // Reload solvables
4566 wallet_dirs.insert(fs::PathFromString(res.solvables_wallet->GetDatabase().Filename()).parent_path());
4567 success = reload_wallet(res.solvables_wallet);
4568 }
4569 }
4570 if (!success) {
4571 // Migration failed, cleanup
4572 // Before deleting the wallet's directory, copy the backup file to the top-level wallets dir
4573 fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
4574 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4575
4576 // Make list of wallets to cleanup
4577 std::vector<std::shared_ptr<CWallet>> created_wallets;
4578 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4579 if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
4580 if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
4581
4582 // Get the directories to remove after unloading
4583 for (std::shared_ptr<CWallet>& w : created_wallets) {
4584 wallet_dirs.emplace(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
4585 }
4586
4587 // Unload the wallets
4588 for (std::shared_ptr<CWallet>& w : created_wallets) {
4589 if (w->HaveChain()) {
4590 // Unloading for wallets that were loaded for normal use
4591 if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
4592 error += _("\nUnable to cleanup failed migration");
4593 return util::Error{error};
4594 }
4595 WaitForDeleteWallet(std::move(w));
4596 } else {
4597 // Unloading for wallets in local context
4598 assert(w.use_count() == 1);
4599 w.reset();
4600 }
4601 }
4602
4603 // Delete the wallet directories
4604 for (const fs::path& dir : wallet_dirs) {
4605 fs::remove_all(dir);
4606 }
4607
4608 // Restore the backup
4609 // Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.
4610 // Reload it into memory if the wallet was previously loaded.
4611 bilingual_str restore_error;
4612 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);
4613 if (!restore_error.empty()) {
4614 error += restore_error + _("\nUnable to restore backup of wallet.");
4615 return util::Error{error};
4616 }
4617
4618 // The wallet directory has been restored, but just in case, copy the previously created backup to the wallet dir
4619 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4620 fs::remove(temp_backup_location);
4621
4622 // Verify that there is no dangling wallet: when the wallet wasn't loaded before, expect null.
4623 // This check is performed after restoration to avoid an early error before saving the backup.
4624 bool wallet_reloaded = ptr_wallet != nullptr;
4625 assert(was_loaded == wallet_reloaded);
4626
4627 return util::Error{error};
4628 }
4629 return res;
4630}
4631
4632void CWallet::CacheNewScriptPubKeys(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4633{
4634 for (const auto& script : spks) {
4635 m_cached_spks[script].push_back(spkm);
4636 }
4637}
4638
4639void CWallet::TopUpCallback(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)
4640{
4641 // Update scriptPubKey cache
4642 CacheNewScriptPubKeys(spks, spkm);
4643}
4644
4645std::set<CExtPubKey> CWallet::GetActiveHDPubKeys() const
4646{
4647 AssertLockHeld(cs_wallet);
4648
4649 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
4650
4651 std::set<CExtPubKey> active_xpubs;
4652 for (const auto& spkm : GetActiveScriptPubKeyMans()) {
4653 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4654 assert(desc_spkm);
4655 LOCK(desc_spkm->cs_desc_man);
4656 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
4657
4658 std::set<CPubKey> desc_pubkeys;
4659 std::set<CExtPubKey> desc_xpubs;
4660 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4661 active_xpubs.merge(std::move(desc_xpubs));
4662 }
4663 return active_xpubs;
4664}
4665
4666std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const
4667{
4668 Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
4669
4670 for (const auto& spkm : GetAllScriptPubKeyMans()) {
4671 const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
4672 assert(desc_spkm);
4673 LOCK(desc_spkm->cs_desc_man);
4674 if (std::optional<CKey> key = desc_spkm->GetKey(keyid)) {
4675 return key;
4676 }
4677 }
4678 return std::nullopt;
4679}
4680} // 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
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
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:3506
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:3566
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:3658
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:3856
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:3870
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:3623
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3498
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
Definition: wallet.cpp:3862
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
Definition: wallet.cpp:3552
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3391
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
Definition: wallet.cpp:3434
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:3472
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:2956
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:3670
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:3912
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:3748
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:3907
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:4082
bool HaveCryptedKeys() const
Definition: wallet.cpp:3731
LegacyDataSPKM * GetOrCreateLegacyDataSPKM()
Definition: wallet.cpp:3696
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:3537
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:4008
bool BackupWallet(const std::string &strDest) const
Definition: wallet.cpp:3444
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:2915
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:2945
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
Definition: wallet.cpp:3646
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:3486
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:3726
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:3003
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:4297
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
Definition: wallet.cpp:3925
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:4101
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:2963
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:2934
void AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
Definition: wallet.cpp:3686
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
Definition: wallet.cpp:3890
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Definition: wallet.cpp:3401
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:3511
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:3577
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:2864
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:3949
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:3586
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2939
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Pass the encryption key to cb().
Definition: wallet.cpp:3720
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2781
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:3739
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:3702
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:3269
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:3680
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:3790
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:3806
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:3760
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:2929
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
Definition: wallet.cpp:3596
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:1387
bool EraseName(const std::string &strAddress)
Definition: walletdb.cpp:77
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:1171
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:181
void RegisterTxnListener(const DbTxnListener &l)
Registers db txn callback functions.
Definition: walletdb.cpp:1400
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:187
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:99
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:150
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:224
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:1369
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
Definition: walletdb.cpp:1329
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
Definition: walletdb.cpp:1340
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:1374
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition: walletdb.cpp:72
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition: walletdb.cpp:84
bool WriteWalletFlags(const uint64_t flags)
Definition: walletdb.cpp:1357
bool EraseAddressData(const CTxDestination &dest)
Definition: walletdb.cpp:1345
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:204
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:94
bool ErasePurpose(const std::string &strAddress)
Definition: walletdb.cpp:89
bool EraseLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:314
bool WriteLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:309
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition: walletdb.cpp:229
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
Definition: walletdb.cpp:235
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
Definition: walletdb.cpp:1335
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:2627
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
Definition: wallet.cpp:2496
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:2576
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:2214
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2741
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2565
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
Definition: wallet.cpp:2699
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2763
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
Definition: wallet.cpp:2180
DBErrors LoadWallet()
Definition: wallet.cpp:2383
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:2650
void ReturnDestination()
Return reserved address.
Definition: wallet.cpp:2708
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
Definition: wallet.cpp:2586
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:2408
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2548
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2731
std::optional< int64_t > GetOldestKeyPoolTime() const
Definition: wallet.cpp:2613
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Definition: wallet.cpp:2268
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
Definition: wallet.cpp:2460
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
Definition: wallet.cpp:2509
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:2666
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
Definition: wallet.cpp:2281
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2769
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:2342
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2751
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
Definition: wallet.cpp:2602
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2641
bool DelAddressBook(const CTxDestination &address)
Definition: wallet.cpp:2502
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
Definition: wallet.cpp:2680
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2717
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:1721
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:1811
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:1584
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:1781
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:1715
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:1834
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:1801
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1748
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:1735
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:1743
void ResubmitWalletTransactions(bool relay, bool force)
Definition: wallet.cpp:2128
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:1702
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:1894
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
Definition: wallet.cpp:1753
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2075
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:1691
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
Definition: wallet.cpp:1463
static NodeClock::time_point GetDefaultNextResend()
Definition: wallet.cpp:2102
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
Definition: wallet.cpp:2085
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:1765
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
Definition: wallet.cpp:1729
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:1601
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:1791
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition: wallet.cpp:1850
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1623
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
Definition: wallet.cpp:1674
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:2045
@ 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:1406
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
Definition: wallet.cpp:2165
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:1273
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:4473
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
std::underlying_type_t< isminetype > isminefilter
used for bitflags of isminetype
Definition: wallet.h:48
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
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:2992
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:4302
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:2970
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(std::span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition: random.cpp: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(std::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