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