Bitcoin ABC 0.34.3
P2P Digital Currency
Loading...
Searching...
No Matches
wallet.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2019 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 <chain.h>
9#include <chainparams.h>
10#include <common/args.h>
11#include <common/messages.h>
12#include <common/signmessage.h>
13#include <config.h>
14#include <consensus/amount.h>
15#include <consensus/consensus.h>
17#include <interfaces/wallet.h>
18#include <kernel/chain.h>
19#include <key.h>
20#include <key_io.h>
21#include <policy/policy.h>
23#include <random.h>
24#include <script/descriptor.h>
25#include <script/script.h>
26#include <script/sighashtype.h>
27#include <script/sign.h>
29#include <script/solver.h>
30#include <support/cleanse.h>
31#include <txmempool.h>
32#include <univalue.h>
33#include <util/bip32.h>
34#include <util/check.h>
35#include <util/fs.h>
36#include <util/fs_helpers.h>
37#include <util/moneystr.h>
38#include <util/string.h>
39#include <util/translation.h>
40#include <wallet/coincontrol.h>
41#include <wallet/context.h>
42#include <wallet/fees.h>
43
44#include <variant>
45
51using util::ToString;
52
53const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
55 "You need to rescan the blockchain in order to correctly mark used "
56 "destinations in the past. Until this is done, some destinations may "
57 "be considered unused, even if the opposite is the case."},
58};
59
61 const std::string &wallet_name) {
62 util::SettingsValue setting_value = chain.getRwSetting("wallet");
63 if (!setting_value.isArray()) {
64 setting_value.setArray();
65 }
66 for (const util::SettingsValue &value : setting_value.getValues()) {
67 if (value.isStr() && value.get_str() == wallet_name) {
68 return true;
69 }
70 }
71 setting_value.push_back(wallet_name);
72 return chain.updateRwSetting("wallet", setting_value);
73}
74
76 const std::string &wallet_name) {
77 util::SettingsValue setting_value = chain.getRwSetting("wallet");
78 if (!setting_value.isArray()) {
79 return true;
80 }
82 for (const util::SettingsValue &value : setting_value.getValues()) {
83 if (!value.isStr() || value.get_str() != wallet_name) {
84 new_value.push_back(value);
85 }
86 }
87 if (new_value.size() == setting_value.size()) {
88 return true;
89 }
90 return chain.updateRwSetting("wallet", new_value);
91}
92
94 const std::string &wallet_name,
95 std::optional<bool> load_on_startup,
96 std::vector<bilingual_str> &warnings) {
97 if (!load_on_startup) {
98 return;
99 }
100 if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
101 warnings.emplace_back(
102 Untranslated("Wallet load on startup setting could not be updated, "
103 "so wallet may not be loaded next node startup."));
104 } else if (!load_on_startup.value() &&
105 !RemoveWalletSetting(chain, wallet_name)) {
106 warnings.emplace_back(
107 Untranslated("Wallet load on startup setting could not be updated, "
108 "so wallet may still be loaded next node startup."));
109 }
110}
111
112bool AddWallet(WalletContext &context, const std::shared_ptr<CWallet> &wallet) {
113 LOCK(context.wallets_mutex);
114 assert(wallet);
115 std::vector<std::shared_ptr<CWallet>>::const_iterator i =
116 std::find(context.wallets.begin(), context.wallets.end(), wallet);
117 if (i != context.wallets.end()) {
118 return false;
119 }
120 context.wallets.push_back(wallet);
121 wallet->ConnectScriptPubKeyManNotifiers();
122 wallet->NotifyCanGetAddressesChanged();
123 return true;
124}
125
127 const std::shared_ptr<CWallet> &wallet,
128 std::optional<bool> load_on_start,
129 std::vector<bilingual_str> &warnings) {
130 assert(wallet);
131
132 interfaces::Chain &chain = wallet->chain();
133 std::string name = wallet->GetName();
134
135 // Unregister with the validation interface which also drops shared ponters.
136 wallet->m_chain_notifications_handler.reset();
137 {
138 LOCK(context.wallets_mutex);
139 std::vector<std::shared_ptr<CWallet>>::iterator i =
140 std::find(context.wallets.begin(), context.wallets.end(), wallet);
141 if (i == context.wallets.end()) {
142 return false;
143 }
144 context.wallets.erase(i);
145 }
146 // Notify unload so that upper layers release the shared pointer.
147 wallet->NotifyUnload();
148
149 // Write the wallet setting
150 UpdateWalletSetting(chain, name, load_on_start, warnings);
151
152 return true;
153}
154
156 const std::shared_ptr<CWallet> &wallet,
157 std::optional<bool> load_on_start) {
158 std::vector<bilingual_str> warnings;
159 return RemoveWallet(context, wallet, load_on_start, warnings);
160}
161
162std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext &context) {
163 LOCK(context.wallets_mutex);
164 return context.wallets;
165}
166
167std::shared_ptr<CWallet> GetWallet(WalletContext &context,
168 const std::string &name) {
169 LOCK(context.wallets_mutex);
170 for (const std::shared_ptr<CWallet> &wallet : context.wallets) {
171 if (wallet->GetName() == name) {
172 return wallet;
173 }
174 }
175 return nullptr;
176}
177
178std::unique_ptr<interfaces::Handler>
180 LOCK(context.wallets_mutex);
181 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(),
182 std::move(load_wallet));
183 return interfaces::MakeHandler([&context, it] {
184 LOCK(context.wallets_mutex);
185 context.wallet_load_fns.erase(it);
186 });
187}
188
190 const std::shared_ptr<CWallet> &wallet) {
191 LOCK(context.wallets_mutex);
192 for (auto &load_wallet : context.wallet_load_fns) {
193 load_wallet(interfaces::MakeWallet(context, wallet));
194 }
195}
196
199static std::condition_variable g_wallet_release_cv;
200static std::set<std::string>
201 g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
202static std::set<std::string>
203 g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
204
205// Custom deleter for shared_ptr<CWallet>.
207 const std::string name = wallet->GetName();
208 wallet->WalletLogPrintf("Releasing wallet %s..\n", name);
209 wallet->Flush();
210 delete wallet;
211 // Wallet is now released, notify UnloadWallet, if any.
212 {
214 if (g_unloading_wallet_set.erase(name) == 0) {
215 // UnloadWallet was not called for this wallet, all done.
216 return;
217 }
218 }
219 g_wallet_release_cv.notify_all();
220}
221
222void WaitForDeleteWallet(std::shared_ptr<CWallet> &&wallet) {
223 // Mark wallet for unloading.
224 const std::string name = wallet->GetName();
225 {
227 g_unloading_wallet_set.insert(name);
228 // Do not expect to be the only one removing this wallet.
229 // Multiple threads could simultaneously be waiting for deletion.
230 }
231
232 // Time to ditch our shared_ptr and wait for FlushAndDeleteWallet call.
233 wallet.reset();
234 {
236 while (g_unloading_wallet_set.count(name) == 1) {
237 g_wallet_release_cv.wait(lock);
238 }
239 }
240}
241
242namespace {
243std::shared_ptr<CWallet>
244LoadWalletInternal(WalletContext &context, const std::string &name,
245 std::optional<bool> load_on_start,
246 const DatabaseOptions &options, DatabaseStatus &status,
247 bilingual_str &error, std::vector<bilingual_str> &warnings) {
248 try {
249 std::unique_ptr<WalletDatabase> database =
250 MakeWalletDatabase(name, options, status, error);
251 if (!database) {
252 error = Untranslated("Wallet file verification failed.") +
253 Untranslated(" ") + error;
254 return nullptr;
255 }
256
257 context.chain->initMessage(_("Loading wallet…").translated);
258 std::shared_ptr<CWallet> wallet =
259 CWallet::Create(context, name, std::move(database),
260 options.create_flags, error, warnings);
261 if (!wallet) {
262 error = Untranslated("Wallet loading failed.") + Untranslated(" ") +
263 error;
265 return nullptr;
266 }
267
268 NotifyWalletLoaded(context, wallet);
269 AddWallet(context, wallet);
270 wallet->postInitProcess();
271
272 // Write the wallet setting
273 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
274
275 return wallet;
276 } catch (const std::runtime_error &e) {
277 error = Untranslated(e.what());
279 return nullptr;
280 }
281}
282} // namespace
283
284std::shared_ptr<CWallet>
285LoadWallet(WalletContext &context, const std::string &name,
286 std::optional<bool> load_on_start, const DatabaseOptions &options,
287 DatabaseStatus &status, bilingual_str &error,
288 std::vector<bilingual_str> &warnings) {
289 auto result = WITH_LOCK(g_loading_wallet_mutex,
290 return g_loading_wallet_set.insert(name));
291 if (!result.second) {
292 error = Untranslated("Wallet already being loading.");
294 return nullptr;
295 }
296 auto wallet = LoadWalletInternal(context, name, load_on_start, options,
297 status, error, warnings);
298 WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
299 return wallet;
300}
301
302std::shared_ptr<CWallet>
303CreateWallet(WalletContext &context, const std::string &name,
304 std::optional<bool> load_on_start, DatabaseOptions &options,
305 DatabaseStatus &status, bilingual_str &error,
306 std::vector<bilingual_str> &warnings) {
307 uint64_t wallet_creation_flags = options.create_flags;
308 const SecureString &passphrase = options.create_passphrase;
309
310 // Indicate that the wallet is actually supposed to be blank and not just
311 // blank to make it encrypted
312 bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
313
314 // Born encrypted wallets need to be created blank first.
315 if (!passphrase.empty()) {
316 wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
317 }
318
319 // Wallet::Verify will check if we're trying to create a wallet with a
320 // duplicate name.
321 std::unique_ptr<WalletDatabase> database =
322 MakeWalletDatabase(name, options, status, error);
323 if (!database) {
324 error = Untranslated("Wallet file verification failed.") +
325 Untranslated(" ") + error;
327 return nullptr;
328 }
329
330 // Do not allow a passphrase when private keys are disabled
331 if (!passphrase.empty() &&
332 (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
333 error = Untranslated(
334 "Passphrase provided but private keys are disabled. A passphrase "
335 "is only used to encrypt private keys, so cannot be used for "
336 "wallets with private keys disabled.");
338 return nullptr;
339 }
340
341 // Make the wallet
342 context.chain->initMessage(_("Loading wallet…").translated);
343 std::shared_ptr<CWallet> wallet =
344 CWallet::Create(context, name, std::move(database),
345 wallet_creation_flags, error, warnings);
346 if (!wallet) {
347 error =
348 Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
350 return nullptr;
351 }
352
353 // Encrypt the wallet
354 if (!passphrase.empty() &&
355 !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
356 if (!wallet->EncryptWallet(passphrase)) {
357 error =
358 Untranslated("Error: Wallet created but failed to encrypt.");
360 return nullptr;
361 }
362 if (!create_blank) {
363 // Unlock the wallet
364 if (!wallet->Unlock(passphrase)) {
365 error = Untranslated(
366 "Error: Wallet was encrypted but could not be unlocked");
368 return nullptr;
369 }
370
371 // Set a seed for the wallet
372 {
373 LOCK(wallet->cs_wallet);
374 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
375 wallet->SetupDescriptorScriptPubKeyMans();
376 } else {
377 for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
378 if (!spk_man->SetupGeneration()) {
379 error =
380 Untranslated("Unable to generate initial keys");
382 return nullptr;
383 }
384 }
385 }
386 }
387
388 // Relock the wallet
389 wallet->Lock();
390 }
391 }
392
393 NotifyWalletLoaded(context, wallet);
394 AddWallet(context, wallet);
395 wallet->postInitProcess();
396
397 // Write the wallet settings
398 UpdateWalletSetting(*context.chain, name, load_on_start, warnings);
399
401 return wallet;
402}
403
404std::shared_ptr<CWallet>
405RestoreWallet(WalletContext &context, const fs::path &backup_file,
406 const std::string &wallet_name, std::optional<bool> load_on_start,
407 DatabaseStatus &status, bilingual_str &error,
408 std::vector<bilingual_str> &warnings) {
409 DatabaseOptions options;
410 options.require_existing = true;
411
412 const fs::path wallet_path =
414 auto wallet_file = wallet_path / "wallet.dat";
415 std::shared_ptr<CWallet> wallet;
416
417 try {
418 if (!fs::exists(backup_file)) {
419 error = Untranslated("Backup file does not exist");
421 return nullptr;
422 }
423
424 if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) {
425 error = Untranslated(strprintf(
426 "Failed to create database path '%s'. Database already exists.",
427 fs::PathToString(wallet_path)));
429 return nullptr;
430 }
431
432 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
433
434 wallet = LoadWallet(context, wallet_name, load_on_start, options,
435 status, error, warnings);
436 } catch (const std::exception &e) {
437 assert(!wallet);
438 if (!error.empty()) {
439 error += Untranslated("\n");
440 }
441 error += strprintf(Untranslated("Unexpected exception: %s"), e.what());
442 }
443 if (!wallet) {
444 fs::remove_all(wallet_path);
445 }
446
447 return wallet;
448}
449
456 // Get CChainParams from interfaces::Chain, unless wallet doesn't have a
457 // chain (i.e. bitcoin-wallet), in which case return global Params()
458 return m_chain ? m_chain->params() : Params();
459}
460
461const CWalletTx *CWallet::GetWalletTx(const TxId &txid) const {
463 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
464 if (it == mapWallet.end()) {
465 return nullptr;
466 }
467
468 return &(it->second);
469}
470
473 return;
474 }
475
476 auto spk_man = GetLegacyScriptPubKeyMan();
477 if (!spk_man) {
478 return;
479 }
480
481 spk_man->UpgradeKeyMetadata();
483}
484
485bool CWallet::Unlock(const SecureString &strWalletPassphrase,
486 bool accept_no_keys) {
487 CCrypter crypter;
488 CKeyingMaterial _vMasterKey;
489
490 {
492 for (const MasterKeyMap::value_type &pMasterKey : mapMasterKeys) {
493 if (!crypter.SetKeyFromPassphrase(
494 strWalletPassphrase, pMasterKey.second.vchSalt,
495 pMasterKey.second.nDeriveIterations,
496 pMasterKey.second.nDerivationMethod)) {
497 return false;
498 }
499 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey,
500 _vMasterKey)) {
501 // try another master key
502 continue;
503 }
504 if (Unlock(_vMasterKey, accept_no_keys)) {
505 // Now that we've unlocked, upgrade the key metadata
507 return true;
508 }
509 }
510 }
511
512 return false;
513}
514
516 const SecureString &strOldWalletPassphrase,
517 const SecureString &strNewWalletPassphrase) {
518 bool fWasLocked = IsLocked();
519
521 Lock();
522
523 CCrypter crypter;
524 CKeyingMaterial _vMasterKey;
525 for (MasterKeyMap::value_type &pMasterKey : mapMasterKeys) {
526 if (!crypter.SetKeyFromPassphrase(
527 strOldWalletPassphrase, pMasterKey.second.vchSalt,
528 pMasterKey.second.nDeriveIterations,
529 pMasterKey.second.nDerivationMethod)) {
530 return false;
531 }
532
533 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey)) {
534 return false;
535 }
536
537 if (Unlock(_vMasterKey)) {
538 constexpr MillisecondsDouble target{100};
539 auto start{SteadyClock::now()};
540 crypter.SetKeyFromPassphrase(strNewWalletPassphrase,
541 pMasterKey.second.vchSalt,
542 pMasterKey.second.nDeriveIterations,
543 pMasterKey.second.nDerivationMethod);
544 pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(
545 pMasterKey.second.nDeriveIterations * target /
546 (SteadyClock::now() - start));
547
548 start = SteadyClock::now();
549 crypter.SetKeyFromPassphrase(strNewWalletPassphrase,
550 pMasterKey.second.vchSalt,
551 pMasterKey.second.nDeriveIterations,
552 pMasterKey.second.nDerivationMethod);
553 pMasterKey.second.nDeriveIterations =
554 (pMasterKey.second.nDeriveIterations +
555 static_cast<unsigned int>(pMasterKey.second.nDeriveIterations *
556 target /
557 (SteadyClock::now() - start))) /
558 2;
559
560 if (pMasterKey.second.nDeriveIterations < 25000) {
561 pMasterKey.second.nDeriveIterations = 25000;
562 }
563
565 "Wallet passphrase changed to an nDeriveIterations of %i\n",
566 pMasterKey.second.nDeriveIterations);
567
568 if (!crypter.SetKeyFromPassphrase(
569 strNewWalletPassphrase, pMasterKey.second.vchSalt,
570 pMasterKey.second.nDeriveIterations,
571 pMasterKey.second.nDerivationMethod)) {
572 return false;
573 }
574
575 if (!crypter.Encrypt(_vMasterKey,
576 pMasterKey.second.vchCryptedKey)) {
577 return false;
578 }
579
580 WalletBatch(*database).WriteMasterKey(pMasterKey.first,
581 pMasterKey.second);
582 if (fWasLocked) {
583 Lock();
584 }
585
586 return true;
587 }
588 }
589
590 return false;
591}
592
594 // Don't update the best block until the chain is attached so that in case
595 // of a shutdown, the rescan will be restarted at next startup.
597 return;
598 }
599 WalletBatch batch(*database);
600 batch.WriteBestBlock(loc);
601}
602
604 bool fExplicit) {
606 if (nWalletVersion >= nVersion) {
607 return;
608 }
609
610 // When doing an explicit upgrade, if we pass the max version permitted,
611 // upgrade all the way.
612 if (fExplicit && nVersion > nWalletMaxVersion) {
613 nVersion = FEATURE_LATEST;
614 }
615
616 nWalletVersion = nVersion;
617
618 if (nVersion > nWalletMaxVersion) {
619 nWalletMaxVersion = nVersion;
620 }
621
622 WalletBatch *batch = batch_in ? batch_in : new WalletBatch(*database);
623 if (nWalletVersion > 40000) {
624 batch->WriteMinVersion(nWalletVersion);
625 }
626 if (!batch_in) {
627 delete batch;
628 }
629}
630
631bool CWallet::SetMaxVersion(int nVersion) {
633
634 // Cannot downgrade below current version
635 if (nWalletVersion > nVersion) {
636 return false;
637 }
638
639 nWalletMaxVersion = nVersion;
640
641 return true;
642}
643
644std::set<TxId> CWallet::GetConflicts(const TxId &txid) const {
645 std::set<TxId> result;
647
648 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
649 if (it == mapWallet.end()) {
650 return result;
651 }
652
653 const CWalletTx &wtx = it->second;
654
655 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
656
657 for (const CTxIn &txin : wtx.tx->vin) {
658 if (mapTxSpends.count(txin.prevout) <= 1) {
659 // No conflict if zero or one spends.
660 continue;
661 }
662
663 range = mapTxSpends.equal_range(txin.prevout);
664 for (TxSpends::const_iterator _it = range.first; _it != range.second;
665 ++_it) {
666 result.insert(_it->second);
667 }
668 }
669
670 return result;
671}
672
673bool CWallet::HasWalletSpend(const TxId &txid) const {
675 auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
676 return (iter != mapTxSpends.end() && iter->first.GetTxId() == txid);
677}
678
680 database->Flush();
681}
682
684 database->Close();
685}
686
688 std::pair<TxSpends::iterator, TxSpends::iterator> range) {
689 // We want all the wallet transactions in range to have the same metadata as
690 // the oldest (smallest nOrderPos).
691 // So: find smallest nOrderPos:
692
693 int nMinOrderPos = std::numeric_limits<int>::max();
694 const CWalletTx *copyFrom = nullptr;
695 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
696 const CWalletTx *wtx = &mapWallet.at(it->second);
697 if (wtx->nOrderPos < nMinOrderPos) {
698 nMinOrderPos = wtx->nOrderPos;
699 copyFrom = wtx;
700 }
701 }
702
703 if (!copyFrom) {
704 return;
705 }
706
707 // Now copy data from copyFrom to rest:
708 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
709 const TxId &txid = it->second;
710 CWalletTx *copyTo = &mapWallet.at(txid);
711 if (copyFrom == copyTo) {
712 continue;
713 }
714
715 assert(
716 copyFrom &&
717 "Oldest wallet transaction in range assumed to have been found.");
718
719 if (!copyFrom->IsEquivalentTo(*copyTo)) {
720 continue;
721 }
722
723 copyTo->mapValue = copyFrom->mapValue;
724 copyTo->vOrderForm = copyFrom->vOrderForm;
725 // fTimeReceivedIsTxTime not copied on purpose nTimeReceived not copied
726 // on purpose.
727 copyTo->nTimeSmart = copyFrom->nTimeSmart;
728 copyTo->fFromMe = copyFrom->fFromMe;
729 // nOrderPos not copied on purpose cached members not copied on purpose.
730 }
731}
732
736bool CWallet::IsSpent(const COutPoint &outpoint) const {
738
739 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range =
740 mapTxSpends.equal_range(outpoint);
741
742 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
743 const TxId &wtxid = it->second;
744 std::map<TxId, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
745 if (mit != mapWallet.end()) {
746 int depth = GetTxDepthInMainChain(mit->second);
747 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) {
748 // Spent
749 return true;
750 }
751 }
752 }
753
754 return false;
755}
756
757void CWallet::AddToSpends(const COutPoint &outpoint, const TxId &wtxid) {
758 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
759
760 setLockedCoins.erase(outpoint);
761
762 std::pair<TxSpends::iterator, TxSpends::iterator> range;
763 range = mapTxSpends.equal_range(outpoint);
764 SyncMetaData(range);
765}
766
767void CWallet::AddToSpends(const TxId &wtxid) {
768 auto it = mapWallet.find(wtxid);
769 assert(it != mapWallet.end());
770 const CWalletTx &thisTx = it->second;
771 // Coinbases don't spend anything!
772 if (thisTx.IsCoinBase()) {
773 return;
774 }
775
776 for (const CTxIn &txin : thisTx.tx->vin) {
777 AddToSpends(txin.prevout, wtxid);
778 }
779}
780
781bool CWallet::EncryptWallet(const SecureString &strWalletPassphrase) {
782 if (IsCrypted()) {
783 return false;
784 }
785
786 CKeyingMaterial _vMasterKey;
787
788 _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
789 GetStrongRandBytes(_vMasterKey);
790
791 CMasterKey kMasterKey;
792
793 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
794 GetStrongRandBytes(kMasterKey.vchSalt);
795
796 CCrypter crypter;
797 constexpr MillisecondsDouble target{100};
798 auto start{SteadyClock::now()};
799 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000,
800 kMasterKey.nDerivationMethod);
801 kMasterKey.nDeriveIterations = static_cast<unsigned int>(
802 25000 * target / (SteadyClock::now() - start));
803
804 start = SteadyClock::now();
805 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt,
806 kMasterKey.nDeriveIterations,
807 kMasterKey.nDerivationMethod);
808 kMasterKey.nDeriveIterations =
809 (kMasterKey.nDeriveIterations +
810 static_cast<unsigned int>(kMasterKey.nDeriveIterations * target /
811 (SteadyClock::now() - start))) /
812 2;
813
814 if (kMasterKey.nDeriveIterations < 25000) {
815 kMasterKey.nDeriveIterations = 25000;
816 }
817
818 WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n",
819 kMasterKey.nDeriveIterations);
820
821 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt,
822 kMasterKey.nDeriveIterations,
823 kMasterKey.nDerivationMethod)) {
824 return false;
825 }
826
827 if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) {
828 return false;
829 }
830
831 {
833 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
834 WalletBatch *encrypted_batch = new WalletBatch(*database);
835 if (!encrypted_batch->TxnBegin()) {
836 delete encrypted_batch;
837 encrypted_batch = nullptr;
838 return false;
839 }
840 encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
841
842 for (const auto &spk_man_pair : m_spk_managers) {
843 auto spk_man = spk_man_pair.second.get();
844 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
845 encrypted_batch->TxnAbort();
846 delete encrypted_batch;
847 encrypted_batch = nullptr;
848 // We now probably have half of our keys encrypted in memory,
849 // and half not... die and let the user reload the unencrypted
850 // wallet.
851 assert(false);
852 }
853 }
854
855 // Encryption was introduced in version 0.4.0
856 SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true);
857
858 if (!encrypted_batch->TxnCommit()) {
859 delete encrypted_batch;
860 encrypted_batch = nullptr;
861 // We now have keys encrypted in memory, but not on disk...
862 // die to avoid confusion and let the user reload the unencrypted
863 // wallet.
864 assert(false);
865 }
866
867 delete encrypted_batch;
868 encrypted_batch = nullptr;
869
870 Lock();
871 Unlock(strWalletPassphrase);
872
873 // If we are using descriptors, make new descriptors with a new seed
877 } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
878 // if we are using HD, replace the HD seed with a new one
879 if (spk_man->IsHDEnabled()) {
880 if (!spk_man->SetupGeneration(true)) {
881 return false;
882 }
883 }
884 }
885 Lock();
886
887 // Need to completely rewrite the wallet file; if we don't, bdb might
888 // keep bits of the unencrypted private key in slack space in the
889 // database file.
890 database->Rewrite();
891
892 // BDB seems to have a bad habit of writing old data into
893 // slack space in .dat files; that is bad if the old data is
894 // unencrypted private keys. So:
895 database->ReloadDbEnv();
896 }
897
899 return true;
900}
901
904 WalletBatch batch(*database);
905
906 // Old wallets didn't have any defined order for transactions. Probably a
907 // bad idea to change the output of this.
908
909 // First: get all CWalletTx into a sorted-by-time
910 // multimap.
911 TxItems txByTime;
912
913 for (auto &entry : mapWallet) {
914 CWalletTx *wtx = &entry.second;
915 txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
916 }
917
918 nOrderPosNext = 0;
919 std::vector<int64_t> nOrderPosOffsets;
920 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) {
921 CWalletTx *const pwtx = (*it).second;
922 int64_t &nOrderPos = pwtx->nOrderPos;
923
924 if (nOrderPos == -1) {
925 nOrderPos = nOrderPosNext++;
926 nOrderPosOffsets.push_back(nOrderPos);
927
928 if (!batch.WriteTx(*pwtx)) {
929 return DBErrors::LOAD_FAIL;
930 }
931 } else {
932 int64_t nOrderPosOff = 0;
933 for (const int64_t &nOffsetStart : nOrderPosOffsets) {
934 if (nOrderPos >= nOffsetStart) {
935 ++nOrderPosOff;
936 }
937 }
938
939 nOrderPos += nOrderPosOff;
940 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
941
942 if (!nOrderPosOff) {
943 continue;
944 }
945
946 // Since we're changing the order, write it back.
947 if (!batch.WriteTx(*pwtx)) {
948 return DBErrors::LOAD_FAIL;
949 }
950 }
951 }
952
953 batch.WriteOrderPosNext(nOrderPosNext);
954
955 return DBErrors::LOAD_OK;
956}
957
960 int64_t nRet = nOrderPosNext++;
961 if (batch) {
962 batch->WriteOrderPosNext(nOrderPosNext);
963 } else {
964 WalletBatch(*database).WriteOrderPosNext(nOrderPosNext);
965 }
966
967 return nRet;
968}
969
972 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
973 item.second.MarkDirty();
974 }
975}
976
978 unsigned int n, bool used,
979 std::set<CTxDestination> &tx_destinations) {
981 const CWalletTx *srctx = GetWalletTx(txid);
982 if (!srctx) {
983 return;
984 }
985
986 CTxDestination dst;
987 if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
988 if (IsMine(dst)) {
989 if (used && !GetDestData(dst, "used", nullptr)) {
990 // p for "present", opposite of absent (null)
991 if (AddDestData(batch, dst, "used", "p")) {
992 tx_destinations.insert(dst);
993 }
994 } else if (!used && GetDestData(dst, "used", nullptr)) {
995 EraseDestData(batch, dst, "used");
996 }
997 }
998 }
999}
1000
1001bool CWallet::IsSpentKey(const TxId &txid, unsigned int n) const {
1003 const CWalletTx *srctx = GetWalletTx(txid);
1004 if (srctx) {
1005 assert(srctx->tx->vout.size() > n);
1006 CTxDestination dest;
1007 if (!ExtractDestination(srctx->tx->vout[n].scriptPubKey, dest)) {
1008 return false;
1009 }
1010 if (GetDestData(dest, "used", nullptr)) {
1011 return true;
1012 }
1013 if (IsLegacy()) {
1015 assert(spk_man != nullptr);
1016 for (const auto &keyid :
1017 GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
1018 PKHash pkh_dest(keyid);
1019 if (GetDestData(pkh_dest, "used", nullptr)) {
1020 return true;
1021 }
1022 }
1023 }
1024 }
1025 return false;
1026}
1027
1029 const CWalletTx::Confirmation &confirm,
1030 const UpdateWalletTxFn &update_wtx,
1031 bool fFlushOnClose) {
1032 LOCK(cs_wallet);
1033
1034 WalletBatch batch(*database, fFlushOnClose);
1035
1036 const TxId &txid = tx->GetId();
1037
1039 // Mark used destinations
1040 std::set<CTxDestination> tx_destinations;
1041
1042 for (const CTxIn &txin : tx->vin) {
1043 const COutPoint &op = txin.prevout;
1044 SetSpentKeyState(batch, op.GetTxId(), op.GetN(), true,
1045 tx_destinations);
1046 }
1047
1048 MarkDestinationsDirty(tx_destinations);
1049 }
1050
1051 // Inserts only if not already there, returns tx inserted or tx found.
1052 auto ret =
1053 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
1054 std::forward_as_tuple(tx));
1055 CWalletTx &wtx = (*ret.first).second;
1056 bool fInsertedNew = ret.second;
1057 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1058 if (fInsertedNew) {
1059 wtx.m_confirm = confirm;
1060 wtx.nTimeReceived = GetTime();
1061 wtx.nOrderPos = IncOrderPosNext(&batch);
1062 wtx.m_it_wtxOrdered =
1063 wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1064 wtx.nTimeSmart = ComputeTimeSmart(wtx);
1065 AddToSpends(txid);
1066 }
1067
1068 if (!fInsertedNew) {
1069 if (confirm.status != wtx.m_confirm.status) {
1070 wtx.m_confirm.status = confirm.status;
1071 wtx.m_confirm.nIndex = confirm.nIndex;
1072 wtx.m_confirm.hashBlock = confirm.hashBlock;
1073 wtx.m_confirm.block_height = confirm.block_height;
1074 fUpdated = true;
1075 } else {
1076 assert(wtx.m_confirm.nIndex == confirm.nIndex);
1077 assert(wtx.m_confirm.hashBlock == confirm.hashBlock);
1078 assert(wtx.m_confirm.block_height == confirm.block_height);
1079 }
1080 }
1081
1083 WalletLogPrintf("AddToWallet %s %s%s\n", txid.ToString(),
1084 (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
1085
1086 // Write to disk
1087 if ((fInsertedNew || fUpdated) && !batch.WriteTx(wtx)) {
1088 return nullptr;
1089 }
1090
1091 // Break debit/credit balance caches:
1092 wtx.MarkDirty();
1093
1094 // Notify UI of new or updated transaction.
1095 NotifyTransactionChanged(this, txid, fInsertedNew ? CT_NEW : CT_UPDATED);
1096
1097#if defined(HAVE_SYSTEM)
1098 // Notify an external script when a wallet transaction comes in or is
1099 // updated.
1100 std::string strCmd = gArgs.GetArg("-walletnotify", "");
1101
1102 if (!strCmd.empty()) {
1103 ReplaceAll(strCmd, "%s", txid.GetHex());
1104 if (confirm.status == CWalletTx::Status::CONFIRMED) {
1105 ReplaceAll(strCmd, "%b", confirm.hashBlock.GetHex());
1106 ReplaceAll(strCmd, "%h", ToString(confirm.block_height));
1107 } else {
1108 ReplaceAll(strCmd, "%b", "unconfirmed");
1109 ReplaceAll(strCmd, "%h", "-1");
1110 }
1111#ifndef WIN32
1112 // Substituting the wallet name isn't currently supported on windows
1113 // because windows shell escaping has not been implemented yet:
1114 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
1115 // A few ways it could be implemented in the future are described in:
1116 // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
1117 ReplaceAll(strCmd, "%w", ShellEscape(GetName()));
1118#endif
1119
1120 std::thread t(runCommand, strCmd);
1121 // Thread runs free.
1122 t.detach();
1123 }
1124#endif
1125
1126 return &wtx;
1127}
1128
1129bool CWallet::LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) {
1130 const auto &ins =
1131 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
1132 std::forward_as_tuple(nullptr));
1133 CWalletTx &wtx = ins.first->second;
1134 if (!fill_wtx(wtx, ins.second)) {
1135 return false;
1136 }
1137 // If wallet doesn't have a chain (e.g wallet-tool), don't bother to update
1138 // txn.
1139 if (HaveChain()) {
1140 bool active;
1141 int height;
1142 if (chain().findBlock(
1143 wtx.m_confirm.hashBlock,
1144 FoundBlock().inActiveChain(active).height(height)) &&
1145 active) {
1146 // Update cached block height variable since it not stored in the
1147 // serialized transaction.
1148 wtx.m_confirm.block_height = height;
1149 } else if (wtx.isConflicted() || wtx.isConfirmed()) {
1150 // If tx block (or conflicting block) was reorged out of chain
1151 // while the wallet was shutdown, change tx status to UNCONFIRMED
1152 // and reset block height, hash, and index. ABANDONED tx don't have
1153 // associated blocks and don't need to be updated. The case where a
1154 // transaction was reorged out while online and then reconfirmed
1155 // while offline is covered by the rescan logic.
1156 wtx.setUnconfirmed();
1158 wtx.m_confirm.block_height = 0;
1159 wtx.m_confirm.nIndex = 0;
1160 }
1161 }
1162 if (/* insertion took place */ ins.second) {
1163 wtx.m_it_wtxOrdered =
1164 wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1165 }
1166 AddToSpends(txid);
1167 for (const CTxIn &txin : wtx.tx->vin) {
1168 auto it = mapWallet.find(txin.prevout.GetTxId());
1169 if (it != mapWallet.end()) {
1170 CWalletTx &prevtx = it->second;
1171 if (prevtx.isConflicted()) {
1173 prevtx.m_confirm.block_height, wtx.GetId());
1174 }
1175 }
1176 }
1177 return true;
1178}
1179
1182 bool fUpdate) {
1184
1185 const TxId &txid = ptx->GetId();
1186
1187 if (!confirm.hashBlock.IsNull()) {
1188 for (const CTxIn &txin : ptx->vin) {
1189 std::pair<TxSpends::const_iterator, TxSpends::const_iterator>
1190 range = mapTxSpends.equal_range(txin.prevout);
1191 while (range.first != range.second) {
1192 if (range.first->second != txid) {
1194 "Transaction %s (in block %s) conflicts with wallet "
1195 "transaction %s (both spend %s:%i)\n",
1196 txid.ToString(), confirm.hashBlock.ToString(),
1197 range.first->second.ToString(),
1198 range.first->first.GetTxId().ToString(),
1199 range.first->first.GetN());
1200 MarkConflicted(confirm.hashBlock, confirm.block_height,
1201 range.first->second);
1202 }
1203 range.first++;
1204 }
1205 }
1206 }
1207
1208 bool fExisted = mapWallet.count(txid) != 0;
1209 if (fExisted && !fUpdate) {
1210 return false;
1211 }
1212 if (fExisted || IsMine(*ptx) || IsFromMe(*ptx)) {
1221 // loop though all outputs
1222 for (const CTxOut &txout : ptx->vout) {
1223 for (const auto &spk_man_pair : m_spk_managers) {
1224 spk_man_pair.second->MarkUnusedAddresses(txout.scriptPubKey);
1225 }
1226 }
1227
1228 // Block disconnection override an abandoned tx as unconfirmed
1229 // which means user may have to call abandontransaction again
1230 return AddToWallet(ptx, confirm,
1231 /* update_wtx= */ nullptr,
1232 /* fFlushOnClose= */ false);
1233 }
1234 return false;
1235}
1236
1238 LOCK(cs_wallet);
1239 const CWalletTx *wtx = GetWalletTx(txid);
1240 return wtx && !wtx->isAbandoned() && GetTxDepthInMainChain(*wtx) == 0 &&
1241 !wtx->InMempool();
1242}
1243
1245 for (const CTxIn &txin : tx->vin) {
1246 auto it = mapWallet.find(txin.prevout.GetTxId());
1247 if (it != mapWallet.end()) {
1248 it->second.MarkDirty();
1249 }
1250 }
1251}
1252
1254 LOCK(cs_wallet);
1255
1256 WalletBatch batch(*database);
1257
1258 std::set<TxId> todo;
1259 std::set<TxId> done;
1260
1261 // Can't mark abandoned if confirmed or in mempool
1262 auto it = mapWallet.find(txid);
1263 assert(it != mapWallet.end());
1264 const CWalletTx &origtx = it->second;
1265 if (GetTxDepthInMainChain(origtx) != 0 || origtx.InMempool()) {
1266 return false;
1267 }
1268
1269 todo.insert(txid);
1270
1271 while (!todo.empty()) {
1272 const TxId now = *todo.begin();
1273 todo.erase(now);
1274 done.insert(now);
1275 it = mapWallet.find(now);
1276 assert(it != mapWallet.end());
1277 CWalletTx &wtx = it->second;
1278 int currentconfirm = GetTxDepthInMainChain(wtx);
1279 // If the orig tx was not in block, none of its spends can be.
1280 assert(currentconfirm <= 0);
1281 // If (currentconfirm < 0) {Tx and spends are already conflicted, no
1282 // need to abandon}
1283 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1284 // If the orig tx was not in block/mempool, none of its spends can
1285 // be in mempool.
1286 assert(!wtx.InMempool());
1287 wtx.setAbandoned();
1288 wtx.MarkDirty();
1289 batch.WriteTx(wtx);
1291 // Iterate over all its outputs, and mark transactions in the wallet
1292 // that spend them abandoned too.
1293 TxSpends::const_iterator iter =
1294 mapTxSpends.lower_bound(COutPoint(now, 0));
1295 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1296 if (!done.count(iter->second)) {
1297 todo.insert(iter->second);
1298 }
1299 iter++;
1300 }
1301
1302 // If a transaction changes 'conflicted' state, that changes the
1303 // balance available of the outputs it spends. So force those to be
1304 // recomputed.
1305 MarkInputsDirty(wtx.tx);
1306 }
1307 }
1308
1309 return true;
1310}
1311
1312void CWallet::MarkConflicted(const BlockHash &hashBlock, int conflicting_height,
1313 const TxId &txid) {
1314 LOCK(cs_wallet);
1315
1316 int conflictconfirms =
1317 (m_last_block_processed_height - conflicting_height + 1) * -1;
1318
1319 // If number of conflict confirms cannot be determined, this means that the
1320 // block is still unknown or not yet part of the main chain, for example
1321 // when loading the wallet during a reindex. Do nothing in that case.
1322 if (conflictconfirms >= 0) {
1323 return;
1324 }
1325
1326 // Do not flush the wallet here for performance reasons.
1327 WalletBatch batch(*database, false);
1328
1329 std::set<TxId> todo;
1330 std::set<TxId> done;
1331
1332 todo.insert(txid);
1333
1334 while (!todo.empty()) {
1335 const TxId now = *todo.begin();
1336 todo.erase(now);
1337 done.insert(now);
1338 auto it = mapWallet.find(now);
1339 assert(it != mapWallet.end());
1340 CWalletTx &wtx = it->second;
1341 int currentconfirm = GetTxDepthInMainChain(wtx);
1342 if (conflictconfirms < currentconfirm) {
1343 // Block is 'more conflicted' than current confirm; update.
1344 // Mark transaction as conflicted with this block.
1345 wtx.m_confirm.nIndex = 0;
1346 wtx.m_confirm.hashBlock = hashBlock;
1347 wtx.m_confirm.block_height = conflicting_height;
1348 wtx.setConflicted();
1349 wtx.MarkDirty();
1350 batch.WriteTx(wtx);
1351 // Iterate over all its outputs, and mark transactions in the wallet
1352 // that spend them conflicted too.
1353 TxSpends::const_iterator iter =
1354 mapTxSpends.lower_bound(COutPoint(now, 0));
1355 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1356 if (!done.count(iter->second)) {
1357 todo.insert(iter->second);
1358 }
1359 iter++;
1360 }
1361 // If a transaction changes 'conflicted' state, that changes the
1362 // balance available of the outputs it spends. So force those to be
1363 // recomputed.
1364 MarkInputsDirty(wtx.tx);
1365 }
1366 }
1367}
1368
1370 CWalletTx::Confirmation confirm, bool update_tx) {
1371 if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx)) {
1372 // Not one of ours
1373 return;
1374 }
1375
1376 // If a transaction changes 'conflicted' state, that changes the balance
1377 // available of the outputs it spends. So force those to be
1378 // recomputed, also:
1379 MarkInputsDirty(ptx);
1380}
1381
1383 uint64_t mempool_sequence) {
1384 LOCK(cs_wallet);
1385
1386 SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block_height */ 0,
1387 BlockHash(), /* nIndex */ 0});
1388
1389 auto it = mapWallet.find(tx->GetId());
1390 if (it != mapWallet.end()) {
1391 it->second.fInMempool = true;
1392 }
1393}
1394
1396 MemPoolRemovalReason reason,
1397 uint64_t mempool_sequence) {
1398 LOCK(cs_wallet);
1399 auto it = mapWallet.find(tx->GetId());
1400 if (it != mapWallet.end()) {
1401 it->second.fInMempool = false;
1402 }
1403 // Handle transactions that were removed from the mempool because they
1404 // conflict with transactions in a newly connected block.
1405 if (reason == MemPoolRemovalReason::CONFLICT) {
1406 // Call SyncNotifications, so external -walletnotify notifications will
1407 // be triggered for these transactions. Set Status::UNCONFIRMED instead
1408 // of Status::CONFLICTED for a few reasons:
1409 //
1410 // 1. The transactionRemovedFromMempool callback does not currently
1411 // provide the conflicting block's hash and height, and for backwards
1412 // compatibility reasons it may not be not safe to store conflicted
1413 // wallet transactions with a null block hash. See
1414 // https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1415 // 2. For most of these transactions, the wallet's internal conflict
1416 // detection in the blockConnected handler will subsequently call
1417 // MarkConflicted and update them with CONFLICTED status anyway. This
1418 // applies to any wallet transaction that has inputs spent in the
1419 // block, or that has ancestors in the wallet with inputs spent by
1420 // the block.
1421 // 3. Longstanding behavior since the sync implementation in
1422 // https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1423 // implementation before that was to mark these transactions
1424 // unconfirmed rather than conflicted.
1425 //
1426 // Nothing described above should be seen as an unchangeable requirement
1427 // when improving this code in the future. The wallet's heuristics for
1428 // distinguishing between conflicted and unconfirmed transactions are
1429 // imperfect, and could be improved in general, see
1430 // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1431 SyncTransaction(tx,
1432 {CWalletTx::Status::UNCONFIRMED, /* block height */ 0,
1433 BlockHash(), /* index */ 0});
1434 }
1435}
1436
1438 int height) {
1439 if (role == ChainstateRole::BACKGROUND) {
1440 return;
1441 }
1442 const BlockHash &block_hash = block.GetHash();
1443 LOCK(cs_wallet);
1444
1445 m_last_block_processed_height = height;
1446 m_last_block_processed = block_hash;
1447 for (size_t index = 0; index < block.vtx.size(); index++) {
1448 SyncTransaction(block.vtx[index], {CWalletTx::Status::CONFIRMED, height,
1449 block_hash, int(index)});
1452 0 /* mempool_sequence */);
1453 }
1454}
1455
1456void CWallet::blockDisconnected(const CBlock &block, int height) {
1457 LOCK(cs_wallet);
1458
1459 // At block disconnection, this will change an abandoned transaction to
1460 // be unconfirmed, whether or not the transaction is added back to the
1461 // mempool. User may have to call abandontransaction again. It may be
1462 // addressed in the future with a stickier abandoned state or even removing
1463 // abandontransaction call.
1464 m_last_block_processed_height = height - 1;
1465 m_last_block_processed = block.hashPrevBlock;
1466 for (const CTransactionRef &ptx : block.vtx) {
1467 SyncTransaction(ptx,
1468 {CWalletTx::Status::UNCONFIRMED, /* block_height */ 0,
1469 BlockHash(), /* nIndex */ 0});
1470 }
1471}
1472
1476
1477void CWallet::BlockUntilSyncedToCurrentChain() const {
1479 // Skip the queue-draining stuff if we know we're caught up with
1480 // chain().Tip(), otherwise put a callback in the validation interface
1481 // queue and wait for the queue to drain enough to execute it (indicating we
1482 // are caught up at least with the time we entered this function).
1483 const BlockHash last_block_hash =
1484 WITH_LOCK(cs_wallet, return m_last_block_processed);
1485 chain().waitForNotificationsIfTipChanged(last_block_hash);
1486}
1487
1488// Note that this function doesn't distinguish between a 0-valued input, and a
1489// not-"is mine" (according to the filter) input.
1490Amount CWallet::GetDebit(const CTxIn &txin, const isminefilter &filter) const {
1491 LOCK(cs_wallet);
1492 std::map<TxId, CWalletTx>::const_iterator mi =
1493 mapWallet.find(txin.prevout.GetTxId());
1494 if (mi != mapWallet.end()) {
1495 const CWalletTx &prev = (*mi).second;
1496 if (txin.prevout.GetN() < prev.tx->vout.size()) {
1497 if (IsMine(prev.tx->vout[txin.prevout.GetN()]) & filter) {
1498 return prev.tx->vout[txin.prevout.GetN()].nValue;
1499 }
1500 }
1501 }
1502
1503 return Amount::zero();
1504}
1505
1506isminetype CWallet::IsMine(const CTxOut &txout) const {
1508 return IsMine(txout.scriptPubKey);
1509}
1510
1515
1516isminetype CWallet::IsMine(const CScript &script) const {
1518 isminetype result = ISMINE_NO;
1519 for (const auto &spk_man_pair : m_spk_managers) {
1520 result = std::max(result, spk_man_pair.second->IsMine(script));
1521 }
1522 return result;
1523}
1524
1525bool CWallet::IsMine(const CTransaction &tx) const {
1527 for (const CTxOut &txout : tx.vout) {
1528 if (IsMine(txout)) {
1529 return true;
1530 }
1531 }
1532
1533 return false;
1534}
1535
1536bool CWallet::IsFromMe(const CTransaction &tx) const {
1537 return GetDebit(tx, ISMINE_ALL) > Amount::zero();
1538}
1539
1540Amount CWallet::GetDebit(const CTransaction &tx,
1541 const isminefilter &filter) const {
1542 Amount nDebit = Amount::zero();
1543 for (const CTxIn &txin : tx.vin) {
1544 nDebit += GetDebit(txin, filter);
1545 if (!MoneyRange(nDebit)) {
1546 throw std::runtime_error(std::string(__func__) +
1547 ": value out of range");
1548 }
1549 }
1550
1551 return nDebit;
1552}
1553
1555 // All Active ScriptPubKeyMans must be HD for this to be true
1556 bool result = true;
1557 for (const auto &spk_man : GetActiveScriptPubKeyMans()) {
1558 result &= spk_man->IsHDEnabled();
1559 }
1560 return result;
1561}
1562
1563bool CWallet::CanGetAddresses(bool internal) const {
1564 LOCK(cs_wallet);
1565 if (m_spk_managers.empty()) {
1566 return false;
1567 }
1568 for (OutputType t : OUTPUT_TYPES) {
1569 auto spk_man = GetScriptPubKeyMan(t, internal);
1570 if (spk_man && spk_man->CanGetAddresses(internal)) {
1571 return true;
1572 }
1573 }
1574 return false;
1575}
1576
1578 LOCK(cs_wallet);
1580 if (!WalletBatch(*database).WriteWalletFlags(m_wallet_flags)) {
1581 throw std::runtime_error(std::string(__func__) +
1582 ": writing wallet flags failed");
1583 }
1584}
1585
1586void CWallet::UnsetWalletFlag(uint64_t flag) {
1587 WalletBatch batch(*database);
1588 UnsetWalletFlagWithDB(batch, flag);
1589}
1590
1591void CWallet::UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag) {
1592 LOCK(cs_wallet);
1593 m_wallet_flags &= ~flag;
1594 if (!batch.WriteWalletFlags(m_wallet_flags)) {
1595 throw std::runtime_error(std::string(__func__) +
1596 ": writing wallet flags failed");
1597 }
1598}
1599
1603
1604bool CWallet::IsWalletFlagSet(uint64_t flag) const {
1605 return (m_wallet_flags & flag);
1606}
1607
1609 LOCK(cs_wallet);
1610 if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1611 // contains unknown non-tolerable wallet flags
1612 return false;
1613 }
1615
1616 return true;
1617}
1618
1620 LOCK(cs_wallet);
1621 // We should never be writing unknown non-tolerable wallet flags
1622 assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1623 if (!WalletBatch(*database).WriteWalletFlags(flags)) {
1624 throw std::runtime_error(std::string(__func__) +
1625 ": writing wallet flags failed");
1626 }
1627
1628 return LoadWalletFlags(flags);
1629}
1630
1631// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1632// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
1633bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout,
1634 bool use_max_sig) const {
1635 // Fill in dummy signatures for fee calculation.
1636 const CScript &scriptPubKey = txout.scriptPubKey;
1637 SignatureData sigdata;
1638
1639 std::unique_ptr<SigningProvider> provider =
1640 GetSolvingProvider(scriptPubKey);
1641 if (!provider) {
1642 // We don't know about this scriptpbuKey;
1643 return false;
1644 }
1645
1646 if (!ProduceSignature(*provider,
1649 scriptPubKey, sigdata)) {
1650 return false;
1651 }
1652
1653 UpdateInput(tx_in, sigdata);
1654 return true;
1655}
1656
1657// Helper for producing a bunch of max-sized low-S low-R signatures (eg 71
1658// bytes)
1660 const std::vector<CTxOut> &txouts,
1661 bool use_max_sig) const {
1662 // Fill in dummy signatures for fee calculation.
1663 int nIn = 0;
1664 for (const auto &txout : txouts) {
1665 if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
1666 return false;
1667 }
1668
1669 nIn++;
1670 }
1671 return true;
1672}
1673
1674bool CWallet::ImportScripts(const std::set<CScript> scripts,
1675 int64_t timestamp) {
1676 auto spk_man = GetLegacyScriptPubKeyMan();
1677 if (!spk_man) {
1678 return false;
1679 }
1680 LOCK(spk_man->cs_KeyStore);
1681 return spk_man->ImportScripts(scripts, timestamp);
1682}
1683
1684bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey> &privkey_map,
1685 const int64_t timestamp) {
1686 auto spk_man = GetLegacyScriptPubKeyMan();
1687 if (!spk_man) {
1688 return false;
1689 }
1690 LOCK(spk_man->cs_KeyStore);
1691 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1692}
1693
1695 const std::vector<CKeyID> &ordered_pubkeys,
1696 const std::map<CKeyID, CPubKey> &pubkey_map,
1697 const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
1698 const bool add_keypool, const bool internal, const int64_t timestamp) {
1699 auto spk_man = GetLegacyScriptPubKeyMan();
1700 if (!spk_man) {
1701 return false;
1702 }
1703 LOCK(spk_man->cs_KeyStore);
1704 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins,
1705 add_keypool, internal, timestamp);
1706}
1707
1708bool CWallet::ImportScriptPubKeys(const std::string &label,
1709 const std::set<CScript> &script_pub_keys,
1710 const bool have_solving_data,
1711 const bool apply_label,
1712 const int64_t timestamp) {
1713 auto spk_man = GetLegacyScriptPubKeyMan();
1714 if (!spk_man) {
1715 return false;
1716 }
1717 LOCK(spk_man->cs_KeyStore);
1718 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data,
1719 timestamp)) {
1720 return false;
1721 }
1722 if (apply_label) {
1723 WalletBatch batch(*database);
1724 for (const CScript &script : script_pub_keys) {
1725 CTxDestination dest;
1727 if (IsValidDestination(dest)) {
1728 SetAddressBookWithDB(batch, dest, label, "receive");
1729 }
1730 }
1731 }
1732 return true;
1733}
1734
1743int64_t CWallet::RescanFromTime(int64_t startTime,
1744 const WalletRescanReserver &reserver,
1745 bool update) {
1746 // Find starting block. May be null if nCreateTime is greater than the
1747 // highest blockchain timestamp, in which case there is nothing that needs
1748 // to be scanned.
1749 int start_height = 0;
1750 BlockHash start_block;
1752 startTime - TIMESTAMP_WINDOW, 0,
1753 FoundBlock().hash(start_block).height(start_height));
1754 WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__,
1755 start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) -
1756 start_height + 1
1757 : 0);
1758
1759 if (start) {
1760 // TODO: this should take into account failure by ScanResult::USER_ABORT
1762 start_block, start_height, {} /* max_height */, reserver, update);
1763 if (result.status == ScanResult::FAILURE) {
1764 int64_t time_max;
1765 CHECK_NONFATAL(chain().findBlock(result.last_failed_block,
1766 FoundBlock().maxTime(time_max)));
1767 return time_max + TIMESTAMP_WINDOW + 1;
1768 }
1769 }
1770 return startTime;
1771}
1772
1795 const BlockHash &start_block, int start_height,
1796 std::optional<int> max_height, const WalletRescanReserver &reserver,
1797 bool fUpdate) {
1798 int64_t nNow = GetTime();
1799 int64_t start_time = GetTimeMillis();
1800
1801 assert(reserver.isReserved());
1802
1803 BlockHash block_hash = start_block;
1804 ScanResult result;
1805
1806 WalletLogPrintf("Rescan started from block %s...\n",
1807 start_block.ToString());
1808
1809 fAbortRescan = false;
1810 // Show rescan progress in GUI as dialog or on splashscreen, if -rescan on
1811 // startup.
1813 strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0);
1814 BlockHash tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1815 BlockHash end_hash = tip_hash;
1816 if (max_height) {
1817 chain().findAncestorByHeight(tip_hash, *max_height,
1818 FoundBlock().hash(end_hash));
1819 }
1820 double progress_begin = chain().guessVerificationProgress(block_hash);
1821 double progress_end = chain().guessVerificationProgress(end_hash);
1822 double progress_current = progress_begin;
1823 int block_height = start_height;
1824 while (!fAbortRescan && !chain().shutdownRequested()) {
1825 if (progress_end - progress_begin > 0.0) {
1826 m_scanning_progress = (progress_current - progress_begin) /
1827 (progress_end - progress_begin);
1828 } else {
1829 // avoid divide-by-zero for single block scan range (i.e. start and
1830 // stop hashes are equal)
1832 }
1833 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1835 strprintf("%s " + _("Rescanning...").translated,
1836 GetDisplayName()),
1837 std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1838 }
1839 if (GetTime() >= nNow + 60) {
1840 nNow = GetTime();
1841 WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n",
1842 block_height, progress_current);
1843 }
1844
1845 // Read block data
1846 CBlock block;
1847 chain().findBlock(block_hash, FoundBlock().data(block));
1848
1849 // Find next block separately from reading data above, because reading
1850 // is slow and there might be a reorg while it is read.
1851 bool block_still_active = false;
1852 bool next_block = false;
1853 BlockHash next_block_hash;
1854 chain().findBlock(block_hash,
1855 FoundBlock()
1856 .inActiveChain(block_still_active)
1857 .nextBlock(FoundBlock()
1858 .inActiveChain(next_block)
1859 .hash(next_block_hash)));
1860
1861 if (!block.IsNull()) {
1862 LOCK(cs_wallet);
1863 if (!block_still_active) {
1864 // Abort scan if current block is no longer active, to prevent
1865 // marking transactions as coming from the wrong block.
1866 result.last_failed_block = block_hash;
1867 result.status = ScanResult::FAILURE;
1868 break;
1869 }
1870 for (size_t posInBlock = 0; posInBlock < block.vtx.size();
1871 ++posInBlock) {
1873 block_height, block_hash,
1874 posInBlock);
1875 SyncTransaction(block.vtx[posInBlock],
1876 {CWalletTx::Status::CONFIRMED, block_height,
1877 block_hash, int(posInBlock)},
1878 fUpdate);
1879 }
1880 // scan succeeded, record block as most recent successfully
1881 // scanned
1882 result.last_scanned_block = block_hash;
1883 result.last_scanned_height = block_height;
1884 } else {
1885 // could not scan block, keep scanning but record this block as
1886 // the most recent failure
1887 result.last_failed_block = block_hash;
1888 result.status = ScanResult::FAILURE;
1889 }
1890 if (max_height && block_height >= *max_height) {
1891 break;
1892 }
1893 {
1894 if (!next_block) {
1895 // break successfully when rescan has reached the tip, or
1896 // previous block is no longer on the chain due to a reorg
1897 break;
1898 }
1899
1900 // increment block and verification progress
1901 block_hash = next_block_hash;
1902 ++block_height;
1903 progress_current = chain().guessVerificationProgress(block_hash);
1904
1905 // handle updated tip hash
1906 const BlockHash prev_tip_hash = tip_hash;
1907 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1908 if (!max_height && prev_tip_hash != tip_hash) {
1909 // in case the tip has changed, update progress max
1910 progress_end = chain().guessVerificationProgress(tip_hash);
1911 }
1912 }
1913 }
1914
1915 // Hide progress dialog in GUI.
1917 strprintf("%s " + _("Rescanning...").translated, GetDisplayName()),
1918 100);
1919 if (block_height && fAbortRescan) {
1920 WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n",
1921 block_height, progress_current);
1923 } else if (block_height && chain().shutdownRequested()) {
1925 "Rescan interrupted by shutdown request at block %d. Progress=%f\n",
1926 block_height, progress_current);
1928 } else {
1929 WalletLogPrintf("Rescan completed in %15dms\n",
1930 GetTimeMillis() - start_time);
1931 }
1932 return result;
1933}
1934
1937
1938 // If transactions aren't being broadcasted, don't let them into local
1939 // mempool either.
1941 return;
1942 }
1943
1944 std::map<int64_t, CWalletTx *> mapSorted;
1945
1946 // Sort pending wallet transactions based on their initial wallet insertion
1947 // order.
1948 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1949 const TxId &wtxid = item.first;
1950 CWalletTx &wtx = item.second;
1951 assert(wtx.GetId() == wtxid);
1952
1953 int nDepth = GetTxDepthInMainChain(wtx);
1954
1955 if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
1956 mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
1957 }
1958 }
1959
1960 // Try to add wallet transactions to memory pool.
1961 for (const std::pair<const int64_t, CWalletTx *> &item : mapSorted) {
1962 CWalletTx &wtx = *(item.second);
1963 std::string unused_err_string;
1964 SubmitTxMemoryPoolAndRelay(wtx, unused_err_string, false);
1965 }
1966}
1967
1969 std::string &err_string,
1970 bool relay) const {
1972
1973 // Can't relay if wallet is not broadcasting
1974 if (!GetBroadcastTransactions()) {
1975 return false;
1976 }
1977 // Don't relay abandoned transactions
1978 if (wtx.isAbandoned()) {
1979 return false;
1980 }
1981 // Don't try to submit coinbase transactions. These would fail anyway but
1982 // would cause log spam.
1983 if (wtx.IsCoinBase()) {
1984 return false;
1985 }
1986 // Don't try to submit conflicted or confirmed transactions.
1987 if (GetTxDepthInMainChain(wtx) != 0) {
1988 return false;
1989 }
1990
1991 // Submit transaction to mempool for relay
1992 WalletLogPrintf("Submitting wtx %s to mempool for relay\n",
1993 wtx.GetId().ToString());
1994 // We must set fInMempool here - while it will be re-set to true by the
1995 // entered-mempool callback, if we did not there would be a race where a
1996 // user could call sendmoney in a loop and hit spurious out of funds errors
1997 // because we think that this newly generated transaction's change is
1998 // unavailable as we're not yet aware that it is in the mempool.
1999 //
2000 // Irrespective of the failure reason, un-marking fInMempool
2001 // out-of-order is incorrect - it should be unmarked when
2002 // TransactionRemovedFromMempool fires.
2003 bool ret = chain().broadcastTransaction(
2004 GetConfig(), wtx.tx, m_default_max_tx_fee, relay, err_string);
2005 wtx.fInMempool |= ret;
2006 return ret;
2007}
2008
2009std::set<TxId> CWallet::GetTxConflicts(const CWalletTx &wtx) const {
2011
2012 std::set<TxId> result;
2013 const TxId &txid = wtx.GetId();
2014 result = GetConflicts(txid);
2015 result.erase(txid);
2016
2017 return result;
2018}
2019
2020// Rebroadcast transactions from the wallet. We do this on a random timer
2021// to slightly obfuscate which transactions come from our wallet.
2022//
2023// Ideally, we'd only resend transactions that we think should have been
2024// mined in the most recent block. Any transaction that wasn't in the top
2025// blockweight of transactions in the mempool shouldn't have been mined,
2026// and so is probably just sitting in the mempool waiting to be confirmed.
2027// Rebroadcasting does nothing to speed up confirmation and only damages
2028// privacy.
2030 // During reindex, importing and IBD, old wallet transactions become
2031 // unconfirmed. Don't resend them as that would spam other nodes.
2032 if (!chain().isReadyToBroadcast()) {
2033 return;
2034 }
2035
2036 // Do this infrequently and randomly to avoid giving away that these are our
2037 // transactions.
2039 return;
2040 }
2041
2042 bool fFirst = (nNextResend == 0);
2043 // resend 12-36 hours from now, ~1 day on average.
2044 nNextResend = GetTime() + (12 * 60 * 60) +
2045 FastRandomContext().randrange(24 * 60 * 60);
2046 if (fFirst) {
2047 return;
2048 }
2049
2050 int submitted_tx_count = 0;
2051
2052 { // cs_wallet scope
2053 LOCK(cs_wallet);
2054
2055 // Relay transactions
2056 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
2057 CWalletTx &wtx = item.second;
2058 // Attempt to rebroadcast all txes more than 5 minutes older than
2059 // the last block. SubmitTxMemoryPoolAndRelay() will not rebroadcast
2060 // any confirmed or conflicting txs.
2061 if (wtx.nTimeReceived > m_best_block_time - 5 * 60) {
2062 continue;
2063 }
2064 std::string unused_err_string;
2065 if (SubmitTxMemoryPoolAndRelay(wtx, unused_err_string, true)) {
2066 ++submitted_tx_count;
2067 }
2068 }
2069 } // cs_wallet
2070
2071 if (submitted_tx_count > 0) {
2072 WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__,
2073 submitted_tx_count);
2074 }
2075}
2076
// end of mapWallet
2078
2080 for (const std::shared_ptr<CWallet> &pwallet : GetWallets(context)) {
2081 pwallet->ResendWalletTransactions();
2082 }
2083}
2084
2093
2094 // Build coins map
2095 std::map<COutPoint, Coin> coins;
2096 for (auto &input : tx.vin) {
2097 auto mi = mapWallet.find(input.prevout.GetTxId());
2098 if (mi == mapWallet.end() ||
2099 input.prevout.GetN() >= mi->second.tx->vout.size()) {
2100 return false;
2101 }
2102 const CWalletTx &wtx = mi->second;
2103 coins[input.prevout] =
2104 Coin(wtx.tx->vout[input.prevout.GetN()], wtx.m_confirm.block_height,
2105 wtx.IsCoinBase());
2106 }
2107 std::map<int, std::string> input_errors;
2108 return SignTransaction(tx, coins, SigHashType().withForkId(), input_errors);
2109}
2110
2112 const std::map<COutPoint, Coin> &coins,
2113 SigHashType sighash,
2114 std::map<int, std::string> &input_errors) const {
2115 // Try to sign with all ScriptPubKeyMans
2116 for (ScriptPubKeyMan *spk_man : GetAllScriptPubKeyMans()) {
2117 // spk_man->SignTransaction will return true if the transaction is
2118 // complete, so we can exit early and return true if that happens
2119 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2120 return true;
2121 }
2122 }
2123
2124 // At this point, one input was not fully signed otherwise we would have
2125 // exited already
2126
2127 // When there are no available providers for the remaining inputs, use the
2128 // legacy provider so we can get proper error messages.
2129 auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2130 if (legacy_spk_man &&
2131 legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2132 return true;
2133 }
2134
2135 return false;
2136}
2137
2138std::optional<PSBTError> CWallet::FillPSBT(PartiallySignedTransaction &psbtx,
2139 bool &complete,
2140 SigHashType sighash_type, bool sign,
2141 bool bip32derivs,
2142 bool finalize) const {
2143 LOCK(cs_wallet);
2144 // Get all of the previous transactions
2145 for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
2146 const CTxIn &txin = psbtx.tx->vin[i];
2147 PSBTInput &input = psbtx.inputs.at(i);
2148
2149 if (PSBTInputSigned(input)) {
2150 continue;
2151 }
2152
2153 // If we have no utxo, grab it from the wallet.
2154 if (input.utxo.IsNull()) {
2155 const TxId &txid = txin.prevout.GetTxId();
2156 const auto it = mapWallet.find(txid);
2157 if (it != mapWallet.end()) {
2158 const CWalletTx &wtx = it->second;
2159 if (txin.prevout.GetN() >= wtx.tx->vout.size()) {
2160 return PSBTError::MISSING_INPUTS;
2161 }
2162 // Update UTXOs from the wallet.
2163 input.utxo = wtx.tx->vout[txin.prevout.GetN()];
2164 }
2165 }
2166 }
2167
2168 // Fill in information from ScriptPubKeyMans
2169 for (ScriptPubKeyMan *spk_man : GetAllScriptPubKeyMans()) {
2170 const auto error{spk_man->FillPSBT(psbtx, sighash_type, sign,
2171 bip32derivs, finalize)};
2172 if (error) {
2173 return error;
2174 }
2175 }
2176
2177 // Complete if every input is now signed
2178 complete = true;
2179 for (const auto &input : psbtx.inputs) {
2180 complete &= PSBTInputSigned(input);
2181 }
2182
2183 return {};
2184}
2185
2186SigningResult CWallet::SignMessage(const std::string &message,
2187 const PKHash &pkhash,
2188 std::string &str_sig) const {
2189 SignatureData sigdata;
2190 CScript script_pub_key = GetScriptForDestination(pkhash);
2191 for (const auto &spk_man_pair : m_spk_managers) {
2192 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2193 LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which
2194 // can lock cs_wallet in a deadlocking order
2195 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2196 }
2197 }
2199}
2200
2202CWallet::TransactionChangeType(const std::optional<OutputType> &change_type,
2203 const std::vector<CRecipient> &vecSend) const {
2204 // If -changetype is specified, always use that change type.
2205 if (change_type) {
2206 return *change_type;
2207 }
2208
2209 // if m_default_address_type is legacy, use legacy address as change.
2211 return OutputType::LEGACY;
2212 }
2213
2214 // else use m_default_address_type for change
2216}
2217
2219 CTransactionRef tx, mapValue_t mapValue,
2220 std::vector<std::pair<std::string, std::string>> orderForm,
2221 bool broadcast) {
2222 LOCK(cs_wallet);
2223
2224 WalletLogPrintfToBeContinued("CommitTransaction:\n%s", tx->ToString());
2225
2226 // Add tx to wallet, because if it has change it's also ours, otherwise just
2227 // for transaction history.
2228 AddToWallet(tx, {}, [&](CWalletTx &wtx, bool new_tx) {
2229 CHECK_NONFATAL(wtx.mapValue.empty());
2230 CHECK_NONFATAL(wtx.vOrderForm.empty());
2231 wtx.mapValue = std::move(mapValue);
2232 wtx.vOrderForm = std::move(orderForm);
2233 wtx.fTimeReceivedIsTxTime = true;
2234 wtx.fFromMe = true;
2235 return true;
2236 });
2237
2238 // Notify that old coins are spent.
2239 for (const CTxIn &txin : tx->vin) {
2240 CWalletTx &coin = mapWallet.at(txin.prevout.GetTxId());
2241 coin.MarkDirty();
2243 }
2244
2245 // Get the inserted-CWalletTx from mapWallet so that the
2246 // fInMempool flag is cached properly
2247 CWalletTx &wtx = mapWallet.at(tx->GetId());
2248
2249 if (!broadcast || !fBroadcastTransactions) {
2250 // Don't submit tx to the mempool if the flag is unset for this single
2251 // transaction, or if the wallet doesn't broadcast transactions at all.
2252 return;
2253 }
2254
2255 std::string err_string;
2256 if (!SubmitTxMemoryPoolAndRelay(wtx, err_string, true)) {
2257 WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast "
2258 "immediately, %s\n",
2259 err_string);
2260 // TODO: if we expect the failure to be long term or permanent, instead
2261 // delete wtx from the wallet and return failure.
2262 }
2263}
2264
2266 LOCK(cs_wallet);
2267
2268 DBErrors nLoadWalletRet = WalletBatch(*database).LoadWallet(this);
2269 if (nLoadWalletRet == DBErrors::NEED_REWRITE) {
2270 if (database->Rewrite("\x04pool")) {
2271 for (const auto &spk_man_pair : m_spk_managers) {
2272 spk_man_pair.second->RewriteDB();
2273 }
2274 }
2275 }
2276
2277 if (m_spk_managers.empty()) {
2280 }
2281
2282 if (nLoadWalletRet != DBErrors::LOAD_OK) {
2283 return nLoadWalletRet;
2284 }
2285
2286 return DBErrors::LOAD_OK;
2287}
2288
2289DBErrors CWallet::ZapSelectTx(std::vector<TxId> &txIdsIn,
2290 std::vector<TxId> &txIdsOut) {
2292 DBErrors nZapSelectTxRet =
2293 WalletBatch(*database).ZapSelectTx(txIdsIn, txIdsOut);
2294 for (const TxId &txid : txIdsOut) {
2295 const auto &it = mapWallet.find(txid);
2296 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2297 for (const auto &txin : it->second.tx->vin) {
2298 mapTxSpends.erase(txin.prevout);
2299 }
2300 mapWallet.erase(it);
2302 }
2303
2304 if (nZapSelectTxRet == DBErrors::NEED_REWRITE) {
2305 if (database->Rewrite("\x04pool")) {
2306 for (const auto &spk_man_pair : m_spk_managers) {
2307 spk_man_pair.second->RewriteDB();
2308 }
2309 }
2310 }
2311
2312 if (nZapSelectTxRet != DBErrors::LOAD_OK) {
2313 return nZapSelectTxRet;
2314 }
2315
2316 MarkDirty();
2317
2318 return DBErrors::LOAD_OK;
2319}
2320
2322 const CTxDestination &address,
2323 const std::string &strName,
2324 const std::string &strPurpose) {
2325 bool fUpdated = false;
2326 bool is_mine;
2327 {
2328 LOCK(cs_wallet);
2329 std::map<CTxDestination, CAddressBookData>::iterator mi =
2330 m_address_book.find(address);
2331 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2332 m_address_book[address].SetLabel(strName);
2333 // Update purpose only if requested.
2334 if (!strPurpose.empty()) {
2335 m_address_book[address].purpose = strPurpose;
2336 }
2337 is_mine = IsMine(address) != ISMINE_NO;
2338 }
2339
2340 NotifyAddressBookChanged(this, address, strName, is_mine, strPurpose,
2341 (fUpdated ? CT_UPDATED : CT_NEW));
2342 if (!strPurpose.empty() && !batch.WritePurpose(address, strPurpose)) {
2343 return false;
2344 }
2345 return batch.WriteName(address, strName);
2346}
2347
2349 const std::string &strName,
2350 const std::string &strPurpose) {
2351 WalletBatch batch(*database);
2352 return SetAddressBookWithDB(batch, address, strName, strPurpose);
2353}
2354
2356 bool is_mine;
2357 WalletBatch batch(*database);
2358 {
2359 LOCK(cs_wallet);
2360 // If we want to delete receiving addresses, we need to take care that
2361 // DestData "used" (and possibly newer DestData) gets preserved (and the
2362 // "deleted" address transformed into a change entry instead of actually
2363 // being deleted)
2364 // NOTE: This isn't a problem for sending addresses because they never
2365 // have any DestData yet! When adding new DestData, it should be
2366 // considered here whether to retain or delete it (or move it?).
2367 if (IsMine(address)) {
2369 "%s called with IsMine address, NOT SUPPORTED. Please "
2370 "report this bug! %s\n",
2371 __func__, PACKAGE_BUGREPORT);
2372 return false;
2373 }
2374 // Delete destdata tuples associated with address
2375 for (const std::pair<const std::string, std::string> &item :
2376 m_address_book[address].destdata) {
2377 batch.EraseDestData(address, item.first);
2378 }
2379 m_address_book.erase(address);
2380 is_mine = IsMine(address) != ISMINE_NO;
2381 }
2382
2383 NotifyAddressBookChanged(this, address, "", is_mine, "", CT_DELETED);
2384
2385 batch.ErasePurpose(address);
2386 return batch.EraseName(address);
2387}
2388
2391
2392 unsigned int count = 0;
2393 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2394 count += spk_man->KeypoolCountExternalKeys();
2395 }
2396
2397 return count;
2398}
2399
2400unsigned int CWallet::GetKeyPoolSize() const {
2402
2403 unsigned int count = 0;
2404 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2405 count += spk_man->GetKeyPoolSize();
2406 }
2407 return count;
2408}
2409
2410bool CWallet::TopUpKeyPool(unsigned int kpSize) {
2411 LOCK(cs_wallet);
2412 bool res = true;
2413 for (auto spk_man : GetActiveScriptPubKeyMans()) {
2414 res &= spk_man->TopUp(kpSize);
2415 }
2416 return res;
2417}
2418
2420CWallet::GetNewDestination(const OutputType type, const std::string &label) {
2421 LOCK(cs_wallet);
2422 auto spk_man = GetScriptPubKeyMan(type, /*internal=*/false);
2423 if (!spk_man) {
2424 return util::Error{strprintf(_("Error: No %s addresses available."),
2425 FormatOutputType(type))};
2426 }
2427 spk_man->TopUp();
2428 auto op_dest = spk_man->GetNewDestination(type);
2429 if (op_dest) {
2430 SetAddressBook(*op_dest, label, "receive");
2431 }
2432
2433 return op_dest;
2434}
2435
2438 LOCK(cs_wallet);
2439
2440 CTxDestination dest;
2441 ReserveDestination reservedest(this, type);
2442 if (!reservedest.GetReservedDestination(dest, true)) {
2443 return util::Error{
2444 _("Error: Keypool ran out, please call keypoolrefill first")};
2445 }
2446
2447 reservedest.KeepDestination();
2448 return dest;
2449}
2450
2452 LOCK(cs_wallet);
2453 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2454 for (const auto &spk_man_pair : m_spk_managers) {
2455 oldestKey =
2456 std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2457 }
2458 return oldestKey;
2459}
2460
2462 const std::set<CTxDestination> &destinations) {
2463 for (auto &entry : mapWallet) {
2464 CWalletTx &wtx = entry.second;
2465 if (wtx.m_is_cache_empty) {
2466 continue;
2467 }
2468
2469 for (size_t i = 0; i < wtx.tx->vout.size(); i++) {
2470 CTxDestination dst;
2471
2472 if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) &&
2473 destinations.count(dst)) {
2474 wtx.MarkDirty();
2475 break;
2476 }
2477 }
2478 }
2479}
2480
2481std::set<CTxDestination>
2482CWallet::GetLabelAddresses(const std::string &label) const {
2484 std::set<CTxDestination> result;
2485 for (const std::pair<const CTxDestination, CAddressBookData> &item :
2486 m_address_book) {
2487 if (item.second.IsChange()) {
2488 continue;
2489 }
2490 const CTxDestination &address = item.first;
2491 const std::string &strName = item.second.GetLabel();
2492 if (strName == label) {
2493 result.insert(address);
2494 }
2495 }
2496
2497 return result;
2498}
2499
2501 bool internal) {
2503 if (!m_spk_man) {
2504 return false;
2505 }
2506
2507 if (nIndex == -1) {
2508 m_spk_man->TopUp();
2509
2510 CKeyPool keypool;
2512 keypool)) {
2513 return false;
2514 }
2515 fInternal = keypool.fInternal;
2516 }
2517 dest = address;
2518 return true;
2519}
2520
2522 if (nIndex != -1) {
2524 }
2525
2526 nIndex = -1;
2528}
2529
2537
2538void CWallet::LockCoin(const COutPoint &output) {
2540 setLockedCoins.insert(output);
2541}
2542
2543void CWallet::UnlockCoin(const COutPoint &output) {
2545 setLockedCoins.erase(output);
2546}
2547
2550 setLockedCoins.clear();
2551}
2552
2553bool CWallet::IsLockedCoin(const COutPoint &outpoint) const {
2555
2556 return setLockedCoins.count(outpoint) > 0;
2557}
2558
2559void CWallet::ListLockedCoins(std::vector<COutPoint> &vOutpts) const {
2561 for (COutPoint outpoint : setLockedCoins) {
2562 vOutpts.push_back(outpoint);
2563 }
2564}
2565
// end of Actions
2567
2568void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
2570 mapKeyBirth.clear();
2571
2572 // map in which we'll infer heights of other keys
2573 std::map<CKeyID, const CWalletTx::Confirmation *> mapKeyFirstBlock;
2574 CWalletTx::Confirmation max_confirm;
2575 // the tip can be reorganized; use a 144-block safety margin
2576 max_confirm.block_height =
2577 GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0;
2578 CHECK_NONFATAL(chain().findAncestorByHeight(
2579 GetLastBlockHash(), max_confirm.block_height,
2580 FoundBlock().hash(max_confirm.hashBlock)));
2581
2582 {
2584 assert(spk_man != nullptr);
2585 LOCK(spk_man->cs_KeyStore);
2586
2587 // Get birth times for keys with metadata.
2588 for (const auto &entry : spk_man->mapKeyMetadata) {
2589 if (entry.second.nCreateTime) {
2590 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2591 }
2592 }
2593
2594 // Prepare to infer birth heights for keys without metadata.
2595 for (const CKeyID &keyid : spk_man->GetKeys()) {
2596 if (mapKeyBirth.count(keyid) == 0) {
2597 mapKeyFirstBlock[keyid] = &max_confirm;
2598 }
2599 }
2600
2601 // If there are no such keys, we're done.
2602 if (mapKeyFirstBlock.empty()) {
2603 return;
2604 }
2605
2606 // Find first block that affects those keys, if there are any left.
2607 for (const auto &entry : mapWallet) {
2608 // iterate over all wallet transactions...
2609 const CWalletTx &wtx = entry.second;
2611 // ... which are already in a block
2612 for (const CTxOut &txout : wtx.tx->vout) {
2613 // Iterate over all their outputs...
2614 for (const auto &keyid :
2615 GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
2616 // ... and all their affected keys.
2617 auto rit = mapKeyFirstBlock.find(keyid);
2618 if (rit != mapKeyFirstBlock.end() &&
2620 rit->second->block_height) {
2621 rit->second = &wtx.m_confirm;
2622 }
2623 }
2624 }
2625 }
2626 }
2627 }
2628
2629 // Extract block timestamps for those keys.
2630 for (const auto &entry : mapKeyFirstBlock) {
2631 int64_t block_time;
2632 CHECK_NONFATAL(chain().findBlock(entry.second->hashBlock,
2633 FoundBlock().time(block_time)));
2634 // block times can be 2h off
2635 mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW;
2636 }
2637}
2638
2660unsigned int CWallet::ComputeTimeSmart(const CWalletTx &wtx) const {
2661 unsigned int nTimeSmart = wtx.nTimeReceived;
2662 if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
2663 int64_t blocktime;
2664 if (chain().findBlock(wtx.m_confirm.hashBlock,
2665 FoundBlock().time(blocktime))) {
2666 int64_t latestNow = wtx.nTimeReceived;
2667 int64_t latestEntry = 0;
2668
2669 // Tolerate times up to the last timestamp in the wallet not more
2670 // than 5 minutes into the future
2671 int64_t latestTolerated = latestNow + 300;
2672 const TxItems &txOrdered = wtxOrdered;
2673 for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2674 CWalletTx *const pwtx = it->second;
2675 if (pwtx == &wtx) {
2676 continue;
2677 }
2678 int64_t nSmartTime;
2679 nSmartTime = pwtx->nTimeSmart;
2680 if (!nSmartTime) {
2681 nSmartTime = pwtx->nTimeReceived;
2682 }
2683 if (nSmartTime <= latestTolerated) {
2684 latestEntry = nSmartTime;
2685 if (nSmartTime > latestNow) {
2686 latestNow = nSmartTime;
2687 }
2688 break;
2689 }
2690 }
2691
2692 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2693 } else {
2694 WalletLogPrintf("%s: found %s in block %s not in index\n", __func__,
2695 wtx.GetId().ToString(),
2697 }
2698 }
2699 return nTimeSmart;
2700}
2701
2703 const std::string &key, const std::string &value) {
2704 if (std::get_if<CNoDestination>(&dest)) {
2705 return false;
2706 }
2707
2708 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2709 return batch.WriteDestData(dest, key, value);
2710}
2711
2713 const std::string &key) {
2714 if (!m_address_book[dest].destdata.erase(key)) {
2715 return false;
2716 }
2717
2718 return batch.EraseDestData(dest, key);
2719}
2720
2721void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key,
2722 const std::string &value) {
2723 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2724}
2725
2726bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key,
2727 std::string *value) const {
2728 std::map<CTxDestination, CAddressBookData>::const_iterator i =
2729 m_address_book.find(dest);
2730 if (i != m_address_book.end()) {
2731 CAddressBookData::StringMap::const_iterator j =
2732 i->second.destdata.find(key);
2733 if (j != i->second.destdata.end()) {
2734 if (value) {
2735 *value = j->second;
2736 }
2737
2738 return true;
2739 }
2740 }
2741 return false;
2742}
2743
2744std::vector<std::string>
2745CWallet::GetDestValues(const std::string &prefix) const {
2746 std::vector<std::string> values;
2747 for (const auto &address : m_address_book) {
2748 for (const auto &data : address.second.destdata) {
2749 if (!data.first.compare(0, prefix.size(), prefix)) {
2750 values.emplace_back(data.second);
2751 }
2752 }
2753 }
2754 return values;
2755}
2756
2757std::unique_ptr<WalletDatabase>
2758MakeWalletDatabase(const std::string &name, const DatabaseOptions &options,
2759 DatabaseStatus &status, bilingual_str &error_string) {
2760 // Do some checking on wallet path. It should be either a:
2761 //
2762 // 1. Path where a directory can be created.
2763 // 2. Path to an existing directory.
2764 // 3. Path to a symlink to a directory.
2765 // 4. For backwards compatibility, the name of a data file in -walletdir.
2766 const fs::path wallet_path =
2768 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2769 if (!(path_type == fs::file_type::not_found ||
2770 path_type == fs::file_type::directory ||
2771 (path_type == fs::file_type::symlink &&
2772 fs::is_directory(wallet_path)) ||
2773 (path_type == fs::file_type::regular &&
2774 fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
2775 error_string = Untranslated(
2776 strprintf("Invalid -wallet path '%s'. -wallet path should point to "
2777 "a directory where wallet.dat and "
2778 "database/log.?????????? files can be stored, a location "
2779 "where such a directory could be created, "
2780 "or (for backwards compatibility) the name of an "
2781 "existing data file in -walletdir (%s)",
2784 return nullptr;
2785 }
2786 return MakeDatabase(wallet_path, options, status, error_string);
2787}
2788
2789std::shared_ptr<CWallet>
2790CWallet::Create(WalletContext &context, const std::string &name,
2791 std::unique_ptr<WalletDatabase> database,
2792 uint64_t wallet_creation_flags, bilingual_str &error,
2793 std::vector<bilingual_str> &warnings) {
2794 interfaces::Chain *chain = context.chain;
2795 const std::string &walletFile = database->Filename();
2796
2797 int64_t nStart = GetTimeMillis();
2798 // TODO: Can't use std::make_shared because we need a custom deleter but
2799 // should be possible to use std::allocate_shared.
2800 std::shared_ptr<CWallet> walletInstance(
2801 new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet);
2802 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2803 if (nLoadWalletRet != DBErrors::LOAD_OK) {
2804 if (nLoadWalletRet == DBErrors::CORRUPT) {
2805 error =
2806 strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
2807 return nullptr;
2808 }
2809
2810 if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR) {
2811 warnings.push_back(
2812 strprintf(_("Error reading %s! All keys read correctly, but "
2813 "transaction data or address book entries might be "
2814 "missing or incorrect."),
2815 walletFile));
2816 } else if (nLoadWalletRet == DBErrors::TOO_NEW) {
2817 error = strprintf(
2818 _("Error loading %s: Wallet requires newer version of %s"),
2819 walletFile, PACKAGE_NAME);
2820 return nullptr;
2821 } else if (nLoadWalletRet == DBErrors::NEED_REWRITE) {
2822 error = strprintf(
2823 _("Wallet needed to be rewritten: restart %s to complete"),
2824 PACKAGE_NAME);
2825 return nullptr;
2826 } else {
2827 error = strprintf(_("Error loading %s"), walletFile);
2828 return nullptr;
2829 }
2830 }
2831
2832 // This wallet is in its first run if there are no ScriptPubKeyMans and it
2833 // isn't blank or no privkeys
2834 const bool fFirstRun =
2835 walletInstance->m_spk_managers.empty() &&
2836 !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
2837 !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
2838 if (fFirstRun) {
2839 // Ensure this wallet.dat can only be opened by clients supporting
2840 // HD with chain split and expects no default key.
2841 walletInstance->SetMinVersion(FEATURE_LATEST);
2842
2843 walletInstance->AddWalletFlags(wallet_creation_flags);
2844
2845 // Only create LegacyScriptPubKeyMan when not descriptor wallet
2846 if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2847 walletInstance->SetupLegacyScriptPubKeyMan();
2848 }
2849
2850 if (!(wallet_creation_flags &
2852 LOCK(walletInstance->cs_wallet);
2853 if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2854 walletInstance->SetupDescriptorScriptPubKeyMans();
2855 // SetupDescriptorScriptPubKeyMans already calls SetupGeneration
2856 // for us so we don't need to call SetupGeneration separately
2857 } else {
2858 // Legacy wallets need SetupGeneration here.
2859 for (auto spk_man :
2860 walletInstance->GetActiveScriptPubKeyMans()) {
2861 if (!spk_man->SetupGeneration()) {
2862 error = _("Unable to generate initial keys");
2863 return nullptr;
2864 }
2865 }
2866 }
2867 }
2868
2869 if (chain) {
2870 walletInstance->chainStateFlushed(ChainstateRole::NORMAL,
2871 chain->getTipLocator());
2872 }
2873 } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
2874 // Make it impossible to disable private keys after creation
2875 error = strprintf(_("Error loading %s: Private keys can only be "
2876 "disabled during creation"),
2877 walletFile);
2878 return nullptr;
2879 } else if (walletInstance->IsWalletFlagSet(
2881 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2882 if (spk_man->HavePrivateKeys()) {
2883 warnings.push_back(
2884 strprintf(_("Warning: Private keys detected in wallet {%s} "
2885 "with disabled private keys"),
2886 walletFile));
2887 }
2888 }
2889 }
2890
2891 if (gArgs.IsArgSet("-mintxfee")) {
2892 Amount n = Amount::zero();
2893 if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) ||
2894 n == Amount::zero()) {
2895 error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""));
2896 return nullptr;
2897 }
2898 if (n > HIGH_TX_FEE_PER_KB) {
2899 warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
2900 _("This is the minimum transaction fee you pay "
2901 "on every transaction."));
2902 }
2903 walletInstance->m_min_fee = CFeeRate(n);
2904 }
2905
2906 if (gArgs.IsArgSet("-maxapsfee")) {
2907 const std::string max_aps_fee{gArgs.GetArg("-maxapsfee", "")};
2908 Amount n = Amount::zero();
2909 if (max_aps_fee == "-1") {
2910 n = -1 * SATOSHI;
2911 } else if (!ParseMoney(max_aps_fee, n)) {
2912 error = AmountErrMsg("maxapsfee", max_aps_fee);
2913 return nullptr;
2914 }
2915 if (n > HIGH_APS_FEE) {
2916 warnings.push_back(
2917 AmountHighWarn("-maxapsfee") + Untranslated(" ") +
2918 _("This is the maximum transaction fee you pay (in addition to"
2919 " the normal fee) to prioritize partial spend avoidance over"
2920 " regular coin selection."));
2921 }
2922 walletInstance->m_max_aps_fee = n;
2923 }
2924
2925 if (gArgs.IsArgSet("-fallbackfee")) {
2926 Amount nFeePerK = Amount::zero();
2927 if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
2928 error =
2929 strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"),
2930 gArgs.GetArg("-fallbackfee", ""));
2931 return nullptr;
2932 }
2933 if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2934 warnings.push_back(AmountHighWarn("-fallbackfee") +
2935 Untranslated(" ") +
2936 _("This is the transaction fee you may pay when "
2937 "fee estimates are not available."));
2938 }
2939 walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
2940 }
2941 // Disable fallback fee in case value was set to 0, enable if non-null value
2942 walletInstance->m_allow_fallback_fee =
2943 walletInstance->m_fallback_fee.GetFeePerK() != Amount::zero();
2944
2945 if (gArgs.IsArgSet("-paytxfee")) {
2946 Amount nFeePerK = Amount::zero();
2947 if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
2948 error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""));
2949 return nullptr;
2950 }
2951 if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2952 warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
2953 _("This is the transaction fee you will pay if "
2954 "you send a transaction."));
2955 }
2956 walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
2957 if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
2958 error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' "
2959 "(must be at least %s)"),
2960 gArgs.GetArg("-paytxfee", ""),
2962 return nullptr;
2963 }
2964 }
2965
2966 if (gArgs.IsArgSet("-maxtxfee")) {
2967 Amount nMaxFee = Amount::zero();
2968 if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
2969 error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", ""));
2970 return nullptr;
2971 }
2972 if (nMaxFee > HIGH_MAX_TX_FEE) {
2973 warnings.push_back(_("-maxtxfee is set very high! Fees this large "
2974 "could be paid on a single transaction."));
2975 }
2976 if (chain && CFeeRate(nMaxFee, 1000) < chain->relayMinFee()) {
2977 error = strprintf(
2978 _("Invalid amount for -maxtxfee=<amount>: '%s' (must be at "
2979 "least the minrelay fee of %s to prevent stuck "
2980 "transactions)"),
2981 gArgs.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
2982 return nullptr;
2983 }
2984 walletInstance->m_default_max_tx_fee = nMaxFee;
2985 }
2986
2988 warnings.push_back(
2989 AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
2990 _("The wallet will avoid paying less than the minimum relay fee."));
2991 }
2992
2993 walletInstance->m_spend_zero_conf_change =
2994 gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
2995
2996 walletInstance->m_default_address_type = DEFAULT_ADDRESS_TYPE;
2997
2998 walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n",
2999 GetTimeMillis() - nStart);
3000
3001 // Try to top up keypool. No-op if the wallet is locked.
3002 walletInstance->TopUpKeyPool();
3003
3004 if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
3005 // Reset this pointer so that the wallet will actually be unloaded
3006 walletInstance->m_chain_notifications_handler.reset();
3007 return nullptr;
3008 }
3009
3010 {
3011 LOCK(walletInstance->cs_wallet);
3012 walletInstance->SetBroadcastTransactions(
3013 gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
3014 walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n",
3015 walletInstance->GetKeyPoolSize());
3016 walletInstance->WalletLogPrintf("mapWallet.size() = %u\n",
3017 walletInstance->mapWallet.size());
3018 walletInstance->WalletLogPrintf("m_address_book.size() = %u\n",
3019 walletInstance->m_address_book.size());
3020 }
3021
3022 return walletInstance;
3023}
3024
3025bool CWallet::AttachChain(const std::shared_ptr<CWallet> &walletInstance,
3026 interfaces::Chain &chain, bilingual_str &error,
3027 std::vector<bilingual_str> &warnings) {
3028 LOCK(walletInstance->cs_wallet);
3029 // allow setting the chain if it hasn't been set already but prevent
3030 // changing it
3031 assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
3032 walletInstance->m_chain = &chain;
3033
3034 // Register wallet with validationinterface. It's done before rescan to
3035 // avoid missing block connections between end of rescan and validation
3036 // subscribing. Because of wallet lock being hold, block connection
3037 // notifications are going to be pending on the validation-side until lock
3038 // release. It's likely to have block processing duplicata (if rescan block
3039 // range overlaps with notification one) but we guarantee at least than
3040 // wallet state is correct after notifications delivery.
3041 // However, chainStateFlushed notifications are ignored until the rescan
3042 // is finished so that in case of a shutdown event, the rescan will be
3043 // repeated at the next start.
3044 // This is temporary until rescan and notifications delivery are unified
3045 // under same interface.
3046 walletInstance->m_attaching_chain = true;
3047 walletInstance->m_chain_notifications_handler =
3048 walletInstance->chain().handleNotifications(walletInstance);
3049
3050 int rescan_height = 0;
3051 if (!gArgs.GetBoolArg("-rescan", false)) {
3052 WalletBatch batch(*walletInstance->database);
3053 CBlockLocator locator;
3054 if (batch.ReadBestBlock(locator)) {
3055 if (const std::optional<int> fork_height =
3056 chain.findLocatorFork(locator)) {
3057 rescan_height = *fork_height;
3058 }
3059 }
3060 }
3061
3062 const std::optional<int> tip_height = chain.getHeight();
3063 if (tip_height) {
3064 walletInstance->m_last_block_processed =
3065 chain.getBlockHash(*tip_height);
3066 walletInstance->m_last_block_processed_height = *tip_height;
3067 } else {
3068 walletInstance->m_last_block_processed.SetNull();
3069 walletInstance->m_last_block_processed_height = -1;
3070 }
3071
3072 if (tip_height && *tip_height != rescan_height) {
3073 // Technically we could execute the code below in any case, but
3074 // performing the `while` loop below can make startup very slow, so only
3075 // check blocks on disk if necessary.
3077 int block_height = *tip_height;
3078 while (block_height > 0 &&
3079 chain.haveBlockOnDisk(block_height - 1) &&
3080 rescan_height != block_height) {
3081 --block_height;
3082 }
3083
3084 if (rescan_height != block_height) {
3085 // We can't rescan beyond blocks we don't have data for, stop
3086 // and throw an error. This might happen if a user uses an old
3087 // wallet within a pruned node or if they ran -disablewallet
3088 // for a longer time, then decided to re-enable
3089 // Exit early and print an error.
3090 // It also may happen if an assumed-valid chain is in use and
3091 // therefore not all block data is available.
3092 // If a block is pruned after this check, we will load
3093 // the wallet, but fail the rescan with a generic error.
3094
3095 error =
3097 ? _("Prune: last wallet synchronisation goes beyond "
3098 "pruned data. You need to -reindex (download the "
3099 "whole blockchain again in case of pruned node)")
3100 : strprintf(_("Error loading wallet. Wallet requires "
3101 "blocks to be downloaded, "
3102 "and software does not currently support "
3103 "loading wallets while "
3104 "blocks are being downloaded out of "
3105 "order when using assumeutxo "
3106 "snapshots. Wallet should be able to "
3107 "load successfully after "
3108 "node sync reaches height %s"),
3109 block_height);
3110 return false;
3111 }
3112 }
3113
3114 chain.initMessage(_("Rescanning...").translated);
3115 walletInstance->WalletLogPrintf(
3116 "Rescanning last %i blocks (from block %i)...\n",
3117 *tip_height - rescan_height, rescan_height);
3118
3119 // No need to read and scan block if block was created before our wallet
3120 // birthday (as adjusted for block time variability)
3121 std::optional<int64_t> time_first_key;
3122 for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3123 int64_t time = spk_man->GetTimeFirstKey();
3124 if (!time_first_key || time < *time_first_key) {
3125 time_first_key = time;
3126 }
3127 }
3128 if (time_first_key) {
3130 *time_first_key - TIMESTAMP_WINDOW, rescan_height,
3131 FoundBlock().height(rescan_height));
3132 }
3133
3134 {
3135 WalletRescanReserver reserver(*walletInstance);
3136 if (!reserver.reserve() ||
3138 walletInstance
3139 ->ScanForWalletTransactions(
3140 chain.getBlockHash(rescan_height), rescan_height,
3141 {} /* max height */, reserver, true /* update */)
3142 .status)) {
3143 error = _("Failed to rescan the wallet during initialization");
3144 return false;
3145 }
3146 }
3147 // The flag must be reset before calling chainStateFlushed
3148 walletInstance->m_attaching_chain = false;
3149 walletInstance->chainStateFlushed(ChainstateRole::NORMAL,
3151 walletInstance->database->IncrementUpdateCounter();
3152 }
3153 walletInstance->m_attaching_chain = false;
3154
3155 return true;
3156}
3157
3158const CAddressBookData *
3160 bool allow_change) const {
3161 const auto &address_book_it = m_address_book.find(dest);
3162 if (address_book_it == m_address_book.end()) {
3163 return nullptr;
3164 }
3165 if ((!allow_change) && address_book_it->second.IsChange()) {
3166 return nullptr;
3167 }
3168 return &address_book_it->second;
3169}
3170
3171bool CWallet::UpgradeWallet(int version, bilingual_str &error) {
3172 int prev_version = GetVersion();
3173 int nMaxVersion = version;
3174 // The -upgradewallet without argument case
3175 if (nMaxVersion == 0) {
3176 WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
3177 nMaxVersion = FEATURE_LATEST;
3178 // permanently upgrade the wallet immediately
3180 } else {
3181 WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
3182 }
3183
3184 if (nMaxVersion < GetVersion()) {
3185 error = _("Cannot downgrade wallet");
3186 return false;
3187 }
3188
3189 SetMaxVersion(nMaxVersion);
3190
3191 LOCK(cs_wallet);
3192
3193 // Do not upgrade versions to any version between HD_SPLIT and
3194 // FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
3195 int max_version = GetVersion();
3197 max_version >= FEATURE_HD_SPLIT &&
3198 max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
3199 error = _("Cannot upgrade a non HD split wallet without upgrading to "
3200 "support pre split keypool. Please use version 200300 or no "
3201 "version specified.");
3202 return false;
3203 }
3204
3205 for (auto spk_man : GetActiveScriptPubKeyMans()) {
3206 if (!spk_man->Upgrade(prev_version, error)) {
3207 return false;
3208 }
3209 }
3210
3211 return true;
3212}
3213
3215 LOCK(cs_wallet);
3216
3217 // Add wallet transactions that aren't already in a block to mempool.
3218 // Do this here as mempool requires genesis block to be loaded.
3220
3221 // Update wallet transactions with current mempool transactions.
3223}
3224
3225bool CWallet::BackupWallet(const std::string &strDest) const {
3226 if (m_chain) {
3227 CBlockLocator loc;
3228 WITH_LOCK(cs_wallet, chain().findBlock(m_last_block_processed,
3229 FoundBlock().locator(loc)));
3230 if (!loc.IsNull()) {
3231 WalletBatch batch(*database);
3232 batch.WriteBestBlock(loc);
3233 }
3234 }
3235 return database->Backup(strDest);
3236}
3237
3239 nTime = GetTime();
3240 fInternal = false;
3241 m_pre_split = false;
3242}
3243
3244CKeyPool::CKeyPool(const CPubKey &vchPubKeyIn, bool internalIn) {
3245 nTime = GetTime();
3246 vchPubKey = vchPubKeyIn;
3247 fInternal = internalIn;
3248 m_pre_split = false;
3249}
3250
3253 if (wtx.isUnconfirmed() || wtx.isAbandoned()) {
3254 return 0;
3255 }
3256
3257 return (GetLastBlockHeight() - wtx.m_confirm.block_height + 1) *
3258 (wtx.isConflicted() ? -1 : 1);
3259}
3260
3263
3264 if (!wtx.IsCoinBase()) {
3265 return 0;
3266 }
3267 int chain_depth = GetTxDepthInMainChain(wtx);
3268 // coinbase tx should not be conflicted
3269 assert(chain_depth >= 0);
3270 return std::max(0, (COINBASE_MATURITY + 1) - chain_depth);
3271}
3272
3275
3276 // note GetBlocksToMaturity is 0 for non-coinbase tx
3277 return GetTxBlocksToMaturity(wtx) > 0;
3278}
3279
3281 return HasEncryptionKeys();
3282}
3283
3284bool CWallet::IsLocked() const {
3285 if (!IsCrypted()) {
3286 return false;
3287 }
3288 LOCK(cs_wallet);
3289 return vMasterKey.empty();
3290}
3291
3293 if (!IsCrypted()) {
3294 return false;
3295 }
3296
3297 {
3298 LOCK(cs_wallet);
3299 if (!vMasterKey.empty()) {
3300 memory_cleanse(vMasterKey.data(),
3301 vMasterKey.size() *
3302 sizeof(decltype(vMasterKey)::value_type));
3303 vMasterKey.clear();
3304 }
3305 }
3306
3307 NotifyStatusChanged(this);
3308 return true;
3309}
3310
3311bool CWallet::Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys) {
3312 {
3313 LOCK(cs_wallet);
3314 for (const auto &spk_man_pair : m_spk_managers) {
3315 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn,
3316 accept_no_keys)) {
3317 return false;
3318 }
3319 }
3320 vMasterKey = vMasterKeyIn;
3321 }
3322 NotifyStatusChanged(this);
3323 return true;
3324}
3325
3326std::set<ScriptPubKeyMan *> CWallet::GetActiveScriptPubKeyMans() const {
3327 std::set<ScriptPubKeyMan *> spk_mans;
3328 for (bool internal : {false, true}) {
3329 for (OutputType t : OUTPUT_TYPES) {
3330 auto spk_man = GetScriptPubKeyMan(t, internal);
3331 if (spk_man) {
3332 spk_mans.insert(spk_man);
3333 }
3334 }
3335 }
3336 return spk_mans;
3337}
3338
3339std::set<ScriptPubKeyMan *> CWallet::GetAllScriptPubKeyMans() const {
3340 std::set<ScriptPubKeyMan *> spk_mans;
3341 for (const auto &spk_man_pair : m_spk_managers) {
3342 spk_mans.insert(spk_man_pair.second.get());
3343 }
3344 return spk_mans;
3345}
3346
3348 bool internal) const {
3349 const std::map<OutputType, ScriptPubKeyMan *> &spk_managers =
3351 std::map<OutputType, ScriptPubKeyMan *>::const_iterator it =
3352 spk_managers.find(type);
3353 if (it == spk_managers.end()) {
3355 "%s scriptPubKey Manager for output type %d does not exist\n",
3356 internal ? "Internal" : "External", static_cast<int>(type));
3357 return nullptr;
3358 }
3359 return it->second;
3360}
3361
3362std::set<ScriptPubKeyMan *>
3364 SignatureData &sigdata) const {
3365 std::set<ScriptPubKeyMan *> spk_mans;
3366 for (const auto &spk_man_pair : m_spk_managers) {
3367 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3368 spk_mans.insert(spk_man_pair.second.get());
3369 }
3370 }
3371 return spk_mans;
3372}
3373
3375 SignatureData sigdata;
3376 for (const auto &spk_man_pair : m_spk_managers) {
3377 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3378 return spk_man_pair.second.get();
3379 }
3380 }
3381 return nullptr;
3382}
3383
3385 if (m_spk_managers.count(id) > 0) {
3386 return m_spk_managers.at(id).get();
3387 }
3388 return nullptr;
3389}
3390
3391std::unique_ptr<SigningProvider>
3393 SignatureData sigdata;
3394 return GetSolvingProvider(script, sigdata);
3395}
3396
3397std::unique_ptr<SigningProvider>
3399 SignatureData &sigdata) const {
3400 for (const auto &spk_man_pair : m_spk_managers) {
3401 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3402 return spk_man_pair.second->GetSolvingProvider(script);
3403 }
3404 }
3405 return nullptr;
3406}
3407
3410 return nullptr;
3411 }
3412 // Legacy wallets only have one ScriptPubKeyMan which is a
3413 // LegacyScriptPubKeyMan. Everything in m_internal_spk_managers and
3414 // m_external_spk_managers point to the same legacyScriptPubKeyMan.
3416 if (it == m_internal_spk_managers.end()) {
3417 return nullptr;
3418 }
3419 return dynamic_cast<LegacyScriptPubKeyMan *>(it->second);
3420}
3421
3426
3428 if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() ||
3430 return;
3431 }
3432
3433 auto spk_manager =
3434 std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this));
3435 for (const auto &type : OUTPUT_TYPES) {
3436 m_internal_spk_managers[type] = spk_manager.get();
3437 m_external_spk_managers[type] = spk_manager.get();
3438 }
3439 m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
3440}
3441
3443 const std::function<bool(const CKeyingMaterial &)> &cb) const {
3444 LOCK(cs_wallet);
3445 return cb(vMasterKey);
3446}
3447
3449 return !mapMasterKeys.empty();
3450}
3451
3453 for (const auto &spk_man : GetActiveScriptPubKeyMans()) {
3454 spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3455 spk_man->NotifyCanGetAddressesChanged.connect(
3457 }
3458}
3459
3461 WalletDescriptor &desc) {
3462 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(
3463 new DescriptorScriptPubKeyMan(*this, desc));
3464 m_spk_managers[id] = std::move(spk_manager);
3465}
3466
3469
3470 // Make a seed
3471 CKey seed_key;
3472 seed_key.MakeNewKey(true);
3473 CPubKey seed = seed_key.GetPubKey();
3474 assert(seed_key.VerifyPubKey(seed));
3475
3476 // Get the extended key
3477 CExtKey master_key;
3478 master_key.SetSeed(seed_key);
3479
3480 for (bool internal : {false, true}) {
3481 for (OutputType t : OUTPUT_TYPES) {
3482 auto spk_manager =
3483 std::make_unique<DescriptorScriptPubKeyMan>(*this, internal);
3484 if (IsCrypted()) {
3485 if (IsLocked()) {
3486 throw std::runtime_error(
3487 std::string(__func__) +
3488 ": Wallet is locked, cannot setup new descriptors");
3489 }
3490 if (!spk_manager->CheckDecryptionKey(vMasterKey) &&
3491 !spk_manager->Encrypt(vMasterKey, nullptr)) {
3492 throw std::runtime_error(
3493 std::string(__func__) +
3494 ": Could not encrypt new descriptors");
3495 }
3496 }
3497 spk_manager->SetupDescriptorGeneration(master_key, t);
3498 uint256 id = spk_manager->GetID();
3499 m_spk_managers[id] = std::move(spk_manager);
3500 AddActiveScriptPubKeyMan(id, t, internal);
3501 }
3502 }
3503}
3504
3506 bool internal) {
3507 WalletBatch batch(*database);
3508 if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id,
3509 internal)) {
3510 throw std::runtime_error(std::string(__func__) +
3511 ": writing active ScriptPubKeyMan id failed");
3512 }
3513 LoadActiveScriptPubKeyMan(id, type, internal);
3514}
3515
3517 bool internal) {
3518 // Activating ScriptPubKeyManager for a given output and change type is
3519 // incompatible with legacy wallets.
3520 // Legacy wallets have only one ScriptPubKeyManager and it's active for all
3521 // output and change types.
3523
3525 "Setting spkMan to active: id = %s, type = %d, internal = %d\n",
3526 id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3527 auto &spk_mans =
3529 auto &spk_mans_other =
3531 auto spk_man = m_spk_managers.at(id).get();
3532 spk_man->SetInternal(internal);
3533 spk_mans[type] = spk_man;
3534
3535 const auto it = spk_mans_other.find(type);
3536 if (it != spk_mans_other.end() && it->second == spk_man) {
3537 spk_mans_other.erase(type);
3538 }
3539
3541}
3542
3544 bool internal) {
3545 auto spk_man = GetScriptPubKeyMan(type, internal);
3546 if (spk_man != nullptr && spk_man->GetID() == id) {
3548 "Deactivate spkMan: id = %s, type = %d, internal = %d\n",
3549 id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3550 WalletBatch batch(GetDatabase());
3551 if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type),
3552 internal)) {
3553 throw std::runtime_error(
3554 std::string(__func__) +
3555 ": erasing active ScriptPubKeyMan id failed");
3556 }
3557
3558 auto &spk_mans =
3560 spk_mans.erase(type);
3561 }
3562
3564}
3565
3566bool CWallet::IsLegacy() const {
3568 return false;
3569 }
3570 auto spk_man = dynamic_cast<LegacyScriptPubKeyMan *>(
3572 return spk_man != nullptr;
3573}
3574
3577 for (auto &spk_man_pair : m_spk_managers) {
3578 // Try to downcast to DescriptorScriptPubKeyMan then check if the
3579 // descriptors match
3580 DescriptorScriptPubKeyMan *spk_manager =
3581 dynamic_cast<DescriptorScriptPubKeyMan *>(
3582 spk_man_pair.second.get());
3583 if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3584 return spk_manager;
3585 }
3586 }
3587
3588 return nullptr;
3589}
3590
3593 const FlatSigningProvider &signing_provider,
3594 const std::string &label, bool internal) {
3596
3599 "Cannot add WalletDescriptor to a non-descriptor wallet\n");
3600 return nullptr;
3601 }
3602
3603 auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3604 if (spk_man) {
3605 WalletLogPrintf("Update existing descriptor: %s\n",
3606 desc.descriptor->ToString());
3607 spk_man->UpdateWalletDescriptor(desc);
3608 } else {
3609 auto new_spk_man =
3610 std::make_unique<DescriptorScriptPubKeyMan>(*this, desc);
3611 spk_man = new_spk_man.get();
3612
3613 // Save the descriptor to memory
3614 m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
3615 }
3616
3617 // Add the private keys to the descriptor
3618 for (const auto &entry : signing_provider.keys) {
3619 const CKey &key = entry.second;
3620 spk_man->AddDescriptorKey(key, key.GetPubKey());
3621 }
3622
3623 // Top up key pool, the manager will generate new scriptPubKeys internally
3624 if (!spk_man->TopUp()) {
3625 WalletLogPrintf("Could not top up scriptPubKeys\n");
3626 return nullptr;
3627 }
3628
3629 // Apply the label if necessary
3630 // Note: we disable labels for ranged descriptors
3631 if (!desc.descriptor->IsRange()) {
3632 auto script_pub_keys = spk_man->GetScriptPubKeys();
3633 if (script_pub_keys.empty()) {
3635 "Could not generate scriptPubKeys (cache is empty)\n");
3636 return nullptr;
3637 }
3638
3639 CTxDestination dest;
3640 if (!internal && ExtractDestination(script_pub_keys.at(0), dest)) {
3641 SetAddressBook(dest, label, "receive");
3642 }
3643 }
3644
3645 // Save the descriptor to DB
3646 spk_man->WriteDescriptor();
3647
3648 return spk_man;
3649}
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition addresstype.h:54
bool MoneyRange(const Amount nValue)
Definition amount.h:177
static constexpr Amount SATOSHI
Definition amount.h:153
ArgsManager gArgs
Definition args.cpp:39
int flags
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:36
const CChainParams & Params()
Return the currently selected parameters.
#define CHECK_NONFATAL(condition)
Identity function.
Definition check.h:83
#define Assert(val)
Identity function.
Definition check.h:87
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition args.cpp:371
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition args.cpp:462
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition args.cpp:524
Address book data.
Definition wallet.h:215
BlockHash GetHash() const
Definition block.cpp:11
BlockHash hashPrevBlock
Definition block.h:27
bool IsNull() const
Definition block.h:49
Definition block.h:60
std::vector< CTransactionRef > vtx
Definition block.h:63
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition chainparams.h:86
Encryption/decryption context with key information.
Definition crypter.h:64
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
Definition crypter.cpp:79
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition crypter.cpp:41
bool Decrypt(const std::vector< uint8_t > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition crypter.cpp:100
Fee rate in satoshis per virtualbyte: Amount / vB the feerate is represented internally as FeeFrac.
Definition feerate.h:24
std::string ToString() const
Definition feerate.cpp:43
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition feerate.h:55
An encapsulated secp256k1 private key.
Definition key.h:28
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition key.cpp:182
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:209
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition key.cpp:301
A reference to a CKey: the Hash160 of its serialized public key.
Definition pubkey.h:22
A key from a CWallet's keypool.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
CPubKey vchPubKey
The public key.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
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:31
std::vector< uint8_t > vchSalt
Definition crypter.h:34
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
Definition crypter.h:37
unsigned int nDeriveIterations
Definition crypter.h:38
std::vector< uint8_t > vchCryptedKey
Definition crypter.h:33
A mutable version of CTransaction.
std::vector< CTxIn > vin
An encapsulated public key.
Definition pubkey.h:31
An output of a transaction.
CScript scriptPubKey
bool IsNull() const
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition wallet.h:270
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
Definition wallet.cpp:3392
std::atomic< int64_t > m_best_block_time
Definition wallet.h:298
bool Lock()
Definition wallet.cpp:3292
BlockHash GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.h:1059
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script, SignatureData &sigdata) const
Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e....
Definition wallet.cpp:3363
bool HaveChain() const
Interface to assert chain access.
Definition wallet.h:452
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3261
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
Definition wallet.h:727
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
Definition wallet.cpp:3452
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
Definition wallet.cpp:3505
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
Definition wallet.cpp:3427
bool AddDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, and saves it to disk When adding new fields,...
Definition wallet.cpp:2702
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Definition wallet.h:895
MasterKeyMap mapMasterKeys
Definition wallet.h:431
TxItems wtxOrdered
Definition wallet.h:457
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:3251
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3273
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition wallet.h:889
RecursiveMutex cs_wallet
Definition wallet.h:416
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
Definition wallet.cpp:3311
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
Definition wallet.h:904
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition wallet.h:997
interfaces::Chain & chain() const
Interface for accessing chain state.
Definition wallet.h:475
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
Definition wallet.cpp:3467
WalletDatabase & GetDatabase() override
Definition wallet.h:423
interfaces::Chain * m_chain
Interface for accessing chain state.
Definition wallet.h:369
std::atomic< bool > m_attaching_chain
Definition wallet.h:280
bool WithEncryptionKey(const std::function< bool(const CKeyingMaterial &)> &cb) const override
Pass the encryption key to cb().
Definition wallet.cpp:3442
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition wallet.cpp:3422
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
Definition wallet.h:394
void DeactivateScriptPubKeyMan(const uint256 &id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
Definition wallet.cpp:3543
bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Look up a destination data tuple in the store, return true if found false otherwise.
Definition wallet.cpp:2726
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition wallet.cpp:3566
std::atomic< bool > fAbortRescan
Definition wallet.h:277
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
Definition wallet.h:400
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
Definition wallet.cpp:3516
boost::signals2::signal< void(CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition wallet.h:877
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition wallet.h:1054
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
Definition wallet.h:901
OutputType m_default_address_type
Definition wallet.h:770
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
Definition wallet.cpp:3576
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, 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:3025
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
Definition wallet.cpp:3460
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition wallet.cpp:3408
std::atomic< uint64_t > m_wallet_flags
Definition wallet.h:356
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition wallet.h:428
int64_t nNextResend
Definition wallet.h:294
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we are allowed to upgrade (or already support) to the named feature
Definition wallet.h:513
bool BackupWallet(const std::string &strDest) const
Definition wallet.cpp:3225
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
Definition wallet.cpp:2660
void WalletLogPrintfToBeContinued(std::string fmt, Params... parameters) const
Definition wallet.h:1002
std::unique_ptr< WalletDatabase > database
Internal database handle.
Definition wallet.h:375
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:3592
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
Definition wallet.cpp:3326
std::vector< std::string > GetDestValues(const std::string &prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all destination values matching a prefix.
Definition wallet.cpp:2745
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
Definition wallet.h:892
bool IsLocked() const override
Definition wallet.cpp:3284
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
Definition wallet.h:395
std::atomic< double > m_scanning_progress
Definition wallet.h:283
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition wallet.h:846
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2568
bool EraseDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases a destination data tuple in the store and on disk.
Definition wallet.cpp:2712
boost::signals2::signal< void(CWallet *wallet, const TxId &txid, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition wallet.h:885
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)
Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error.
Definition wallet.cpp:2790
bool HasEncryptionKeys() const override
Definition wallet.cpp:3448
Amount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
Definition wallet.h:782
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Definition wallet.cpp:3171
bool fBroadcastTransactions
Definition wallet.h:295
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition wallet.cpp:3347
bool IsCrypted() const
Definition wallet.cpp:3280
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
Definition wallet.cpp:3339
std::multimap< int64_t, CWalletTx * > TxItems
Definition wallet.h:456
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:986
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
Definition wallet.cpp:2721
unsigned int nMasterKeyMaxID
Definition wallet.h:432
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
Definition wallet.h:623
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
Definition wallet.cpp:3214
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:3159
A transaction with a bunch of additional info that only the owner cares about.
Definition transaction.h:65
bool isAbandoned() const
mapValue_t mapValue
Key/value map with information about the transaction.
Definition transaction.h:99
CTransactionRef tx
bool isUnconfirmed() const
void setConflicted()
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
bool IsEquivalentTo(const CWalletTx &tx) const
bool isConflicted() const
Confirmation m_confirm
TxId GetId() const
std::vector< std::pair< std::string, std::string > > vOrderForm
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
void setAbandoned()
void setUnconfirmed()
bool fInMempool
unsigned int fTimeReceivedIsTxTime
bool isConfirmed() const
void MarkDirty()
make sure balances are recalculated
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool InMempool() const
bool IsCoinBase() const
unsigned int nTimeReceived
time received by this node
int64_t nOrderPos
position in ordered transaction list
A UTXO entry.
Definition coins.h:31
bool HasWalletDescriptor(const WalletDescriptor &desc) const
Fast randomness source.
Definition random.h:411
Different type to mark Mutex at global scope.
Definition sync.h:144
std::set< CKeyID > GetKeys() const override
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
Definition random.h:266
A wrapper to reserve an address from a wallet.
Definition wallet.h:177
bool fInternal
Whether this is from the internal (change output) keypool.
Definition wallet.h:190
OutputType const type
Definition wallet.h:184
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from.
Definition wallet.h:183
int64_t nIndex
The index of the address's key in the keypool.
Definition wallet.h:186
CTxDestination address
The destination.
Definition wallet.h:188
const CWallet *const pwallet
The wallet to reserve from.
Definition wallet.h:180
A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool)
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
Signature hash type wrapper class.
Definition sighashtype.h:37
void push_back(UniValue val)
Definition univalue.cpp:96
bool isArray() const
Definition univalue.h:110
void setArray()
Definition univalue.cpp:86
size_t size() const
Definition univalue.h:92
const std::vector< UniValue > & getValues() const
Access to the wallet database.
Definition walletdb.h:175
bool TxnCommit()
Commit current transaction.
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition walletdb.cpp:214
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition walletdb.cpp:155
bool WriteName(const CTxDestination &address, const std::string &strName)
Definition walletdb.cpp:61
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
Definition walletdb.cpp:82
bool WriteMinVersion(int nVersion)
Definition walletdb.cpp:210
bool ErasePurpose(const CTxDestination &address)
Definition walletdb.cpp:92
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
bool WriteWalletFlags(const uint64_t flags)
bool ReadBestBlock(CBlockLocator &locator)
Definition walletdb.cpp:187
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition walletdb.cpp:194
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
Definition walletdb.cpp:221
bool WriteTx(const CWalletTx &wtx)
Definition walletdb.cpp:100
bool TxnBegin()
Begin a new transaction.
bool TxnAbort()
Abort current transaction.
bool EraseName(const CTxDestination &address)
Definition walletdb.cpp:71
bool WriteBestBlock(const CBlockLocator &locator)
Definition walletdb.cpp:180
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut)
DBErrors LoadWallet(CWallet *pwallet)
Definition walletdb.cpp:775
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
Descriptor with some wallet metadata.
Definition walletutil.h:80
std::shared_ptr< Descriptor > descriptor
Definition walletutil.h:82
RAII object to check and reserve a wallet rescan.
Definition wallet.h:1132
bool isReserved() const
Definition wallet.h:1151
constexpr bool IsNull() const
Definition uint256.h:44
constexpr uint8_t * begin()
Definition uint256.h:122
std::string ToString() const
Definition uint256.h:117
constexpr void SetNull()
Definition uint256.h:49
std::string GetHex() const
Definition uint256.cpp:10
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition fs.h:30
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition chain.h:136
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 BlockHash getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findBlock(const BlockHash &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual std::unique_ptr< Handler > handleNotifications(std::shared_ptr< Notifications > notifications)=0
Register handler for notifications.
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
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 broadcastTransaction(const Config &config, const CTransactionRef &tx, const Amount &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 util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual double guessVerificationProgress(const BlockHash &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual const CChainParams & params() const =0
This Chain's parameters.
virtual bool havePruned()=0
Check if any block has been pruned.
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
virtual bool findAncestorByHeight(const BlockHash &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual void initMessage(const std::string &message)=0
Send init message.
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 void requestMempoolTransactions(Notifications &notifications)=0
Synchronously send transactionAddedToMempool notifications about all current mempool transactions to ...
virtual void waitForNotificationsIfTipChanged(const BlockHash &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee settings).
Helper for findBlock to selectively return pieces of block data.
Definition chain.h:55
FoundBlock & height(int &height)
Definition chain.h:61
256-bit opaque blob.
Definition uint256.h:199
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition cleanse.cpp:14
const Config & GetConfig()
Definition config.cpp:40
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
Definition consensus.h:32
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition crypter.h:13
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
Definition crypter.h:57
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition crypter.h:12
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2538
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:2461
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2389
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string &label)
Definition wallet.cpp:2420
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
Definition wallet.cpp:2437
void KeepDestination()
Keep the address.
Definition wallet.cpp:2521
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2559
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2400
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2482
bool IsLockedCoin(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2553
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Definition wallet.cpp:2186
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2543
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition wallet.cpp:2348
DBErrors LoadWallet()
Definition wallet.cpp:2265
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
Definition wallet.cpp:2202
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2091
void ReturnDestination()
Return reserved address.
Definition wallet.cpp:2530
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2548
bool TopUpKeyPool(unsigned int kpSize=0)
Definition wallet.cpp:2410
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
Definition wallet.cpp:2321
bool GetReservedDestination(CTxDestination &pubkey, bool internal)
Reserve an address.
Definition wallet.cpp:2500
int64_t GetOldestKeyPoolTime() const
Definition wallet.cpp:2451
bool DelAddressBook(const CTxDestination &address)
Definition wallet.cpp:2355
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2289
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string > > orderForm, bool broadcast=true)
Add the transaction to the wallet and maybe attempt to broadcast it.
Definition wallet.cpp:2218
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, SigHashType sighash_type=SigHashType().withForkId(), bool sign=true, bool bip32derivs=true, bool finalize=true) const
Fills out a PSBT with information from the wallet.
Definition wallet.cpp:2138
bool AddWalletFlags(uint64_t flags)
Overwrite all flags by the given uint64_t.
Definition wallet.cpp:1619
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1694
bool LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1129
void MarkConflicted(const BlockHash &hashBlock, int conflicting_height, const TxId &txid)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
Definition wallet.cpp:1312
void Flush()
Flush wallet (bitdb flush)
Definition wallet.cpp:679
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition wallet.cpp:471
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
Definition wallet.cpp:631
std::set< TxId > GetConflicts(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
Definition wallet.cpp:644
void MarkDirty()
Definition wallet.cpp:970
bool SubmitTxMemoryPoolAndRelay(const 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:1968
void AddToSpends(const COutPoint &outpoint, const TxId &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:757
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
Definition wallet.cpp:1369
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1674
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
Definition wallet.cpp:1028
bool HasWalletSpend(const TxId &txid) 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:673
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition wallet.cpp:515
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:1577
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
Definition wallet.cpp:1536
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1684
void blockConnected(ChainstateRole role, const CBlock &block, int height) override
Definition wallet.cpp:1437
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1511
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
Definition wallet.cpp:1608
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:1708
bool CanGetAddresses(bool internal=false) const
Returns true if the wallet can give out new addresses.
Definition wallet.cpp:1563
ScanResult ScanForWalletTransactions(const BlockHash &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate)
Scan the block chain (starting in start_block) for transactions from or to us.
Definition wallet.cpp:1794
bool IsSpentKey(const TxId &txid, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1001
bool TransactionCanBeAbandoned(const TxId &txid) const
Return whether transaction can be abandoned.
Definition wallet.cpp:1237
const CChainParams & GetChainParams() const override
Definition wallet.cpp:455
Amount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
Definition wallet.cpp:1490
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:1244
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
Definition wallet.cpp:1180
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction, spends it:
Definition wallet.cpp:736
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:1935
bool IsHDEnabled() const
Definition wallet.cpp:1554
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
Definition wallet.cpp:1591
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:687
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition wallet.cpp:781
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
Definition wallet.cpp:593
void updatedBlockTip() override
Definition wallet.cpp:1473
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
Definition wallet.cpp:1586
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
Definition wallet.cpp:1395
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
Definition wallet.cpp:1604
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition wallet.cpp:1743
bool AbandonTransaction(const TxId &txid)
Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent.
Definition wallet.cpp:1253
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
Definition wallet.cpp:1600
void SetSpentKeyState(WalletBatch &batch, const TxId &txid, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:977
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
Definition wallet.cpp:1382
DBErrors ReorderTransactions()
Definition wallet.cpp:902
void blockDisconnected(const CBlock &block, int height) override
Definition wallet.cpp:1456
void Close()
Close wallet database.
Definition wallet.cpp:683
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
Definition wallet.cpp:958
const CWalletTx * GetWalletTx(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:461
void ResendWalletTransactions()
Definition wallet.cpp:2029
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false) override
signify that a particular wallet feature is now used.
Definition wallet.cpp:603
std::set< TxId > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition wallet.cpp:2009
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
Definition wallet.cpp:1633
uint8_t isminefilter
Definition wallet.h:46
isminetype
IsMine() return codes.
Definition ismine.h:18
@ ISMINE_ALL
Definition ismine.h:23
@ ISMINE_NO
Definition ismine.h:19
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
Definition chain.h:14
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
Definition moneystr.cpp:41
PSBTError
Definition types.h:17
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
Definition messages.cpp:73
bilingual_str AmountHighWarn(const std::string &optname)
Definition messages.cpp:69
static path u8path(const std::string &utf8_str)
Definition fs.h:90
static auto quoted(const std::string &s)
Definition fs.h:112
static bool exists(const path &p)
Definition fs.h:107
static bool copy_file(const path &from, const path &to, copy_options options)
Definition fs.h:124
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition fs.h:147
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition fs.h:170
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition fs.cpp:39
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
Definition handler.cpp:48
void ReplaceAll(std::string &in_out, std::string_view search, std::string_view substitute)
Replace every non-overlapping occurrence of search with substitute, treating both literally; the repl...
Definition string.cpp:11
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition string.h:156
const std::string & FormatOutputType(OutputType type)
const std::array< OutputType, 1 > OUTPUT_TYPES
OutputType
Definition outputtype.h:16
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
Definition psbt.cpp:160
void GetStrongRandBytes(Span< uint8_t > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition random.cpp:695
const char * prefix
Definition rest.cpp:1078
const char * name
Definition rest.cpp:46
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition secure.h:55
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition sign.cpp:210
void UpdateInput(CTxIn &input, const SignatureData &data)
Definition sign.cpp:343
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
Definition sign.cpp:433
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
Definition sign.cpp:431
SigningResult
Definition signmessage.h:47
@ PRIVATE_KEY_NOT_AVAILABLE
static constexpr Amount zero() noexcept
Definition amount.h:36
A BlockHash is a unqiue identifier for a block.
Definition blockhash.h:13
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition block.h:108
bool IsNull() const
Definition block.h:135
Definition key.h:167
void SetSeed(Span< const std::byte > seed)
Definition key.cpp:381
std::optional< int > last_scanned_height
Definition wallet.h:647
BlockHash last_scanned_block
Hash and height of most recent block that was successfully scanned.
Definition wallet.h:646
BlockHash last_failed_block
Hash of the most recent block that could not be scanned due to read errors or pruning.
Definition wallet.h:653
enum CWallet::ScanResult::@19 status
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
uint64_t create_flags
Definition db.h:220
bool require_existing
Definition db.h:218
SecureString create_passphrase
Definition db.h:221
std::map< CKeyID, CKey > keys
A structure for PSBTs which contain per-input information.
Definition psbt.h:44
CTxOut utxo
Definition psbt.h:45
A version of CTransaction with the PSBT format.
Definition psbt.h:336
std::vector< PSBTInput > inputs
Definition psbt.h:338
std::optional< CMutableTransaction > tx
Definition psbt.h:337
A TxId is the identifier of a transaction.
Definition txid.h:14
WalletContext struct containing references to state shared between CWallet instances,...
Definition context.h:35
Mutex wallets_mutex
Definition context.h:42
interfaces::Chain * chain
Definition context.h:36
Bilingual messages:
Definition translation.h:17
bool empty() const
Definition translation.h:27
#define WAIT_LOCK(cs, name)
Definition sync.h:304
#define AssertLockNotHeld(cs)
Definition sync.h:163
#define LOCK(cs)
Definition sync.h:295
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition sync.h:343
#define AssertLockHeld(cs)
Definition sync.h:146
std::string ShellEscape(const std::string &arg)
Definition system.cpp:46
static int count
#define GUARDED_BY(x)
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition time.cpp:76
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition time.cpp:80
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
Definition time.h:99
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
bilingual_str _(const char *psz)
Translation function.
Definition translation.h:68
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition translation.h:36
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
Definition txmempool.h:159
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
@ CT_UPDATED
@ CT_DELETED
@ CT_NEW
assert(!tx.IsCoinBase())
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
Definition context.h:23
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
DatabaseStatus
Definition db.h:225
@ FAILED_INVALID_BACKUP_FILE
std::map< std::string, std::string > mapValue_t
Definition transaction.h:21
constexpr Amount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
Definition wallet.h:126
constexpr OutputType DEFAULT_ADDRESS_TYPE
Default for -addresstype.
Definition wallet.h:142
constexpr Amount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
Definition wallet.h:129
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
Definition wallet.h:120
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition wallet.h:144
static const bool DEFAULT_WALLETBROADCAST
Definition wallet.h:121
constexpr Amount HIGH_APS_FEE
discourage APS fee higher than this amount
Definition wallet.h:116
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
Definition wallet.cpp:179
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
Definition wallet.cpp:2758
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition wallet.cpp:53
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:126
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
Definition wallet.cpp:2079
static std::condition_variable g_wallet_release_cv
Definition wallet.cpp:199
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:112
static void FlushAndDeleteWallet(CWallet *wallet)
Definition wallet.cpp:206
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition wallet.cpp:222
static GlobalMutex g_loading_wallet_mutex
Definition wallet.cpp:197
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition wallet.cpp:162
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:60
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:405
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:75
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition wallet.cpp:167
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:93
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:303
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:285
static GlobalMutex g_wallet_release_mutex
Definition wallet.cpp:198
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:189
DBErrors
Error statuses for the wallet database.
Definition walletdb.h:45
@ NONCRITICAL_ERROR
fs::path GetWalletDir()
Get the path of the wallet directory.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition walletutil.h:55
@ WALLET_FLAG_AVOID_REUSE
Definition walletutil.h:47
@ WALLET_FLAG_KEY_ORIGIN_METADATA
Definition walletutil.h:51
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition walletutil.h:70
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition walletutil.h:67
WalletFeature
(client) version numbers for particular wallet features
Definition walletutil.h:14
@ FEATURE_HD_SPLIT
Definition walletutil.h:28
@ FEATURE_WALLETCRYPT
Definition walletutil.h:20
@ FEATURE_PRE_SPLIT_KEYPOOL
Definition walletutil.h:34
@ FEATURE_LATEST
Definition walletutil.h:36