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