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