9#include <chainparams.h>
47 "You need to rescan the blockchain in order to correctly mark used "
48 "destinations in the past. Until this is done, some destinations may "
49 "be considered unused, even if the opposite is the case."},
57 const std::string &wallet_name) {
63 if (value.isStr() && value.get_str() == wallet_name) {
72 const std::string &wallet_name) {
79 if (!value.isStr() || value.get_str() != wallet_name) {
83 if (new_value.
size() == setting_value.
size()) {
90 const std::string &wallet_name,
91 std::optional<bool> load_on_startup,
92 std::vector<bilingual_str> &warnings) {
93 if (!load_on_startup) {
97 warnings.emplace_back(
98 Untranslated(
"Wallet load on startup setting could not be updated, "
99 "so wallet may not be loaded next node startup."));
100 }
else if (!load_on_startup.value() &&
102 warnings.emplace_back(
103 Untranslated(
"Wallet load on startup setting could not be updated, "
104 "so wallet may still be loaded next node startup."));
111 std::vector<std::shared_ptr<CWallet>>::const_iterator i =
112 std::find(vpwallets.begin(), vpwallets.end(),
wallet);
113 if (i != vpwallets.end()) {
116 vpwallets.push_back(
wallet);
117 wallet->ConnectScriptPubKeyManNotifiers();
118 wallet->NotifyCanGetAddressesChanged();
123 std::optional<bool> load_on_start,
124 std::vector<bilingual_str> &warnings) {
131 wallet->m_chain_notifications_handler.reset();
133 std::vector<std::shared_ptr<CWallet>>::iterator i =
134 std::find(vpwallets.begin(), vpwallets.end(),
wallet);
135 if (i == vpwallets.end()) {
147 std::optional<bool> load_on_start) {
148 std::vector<bilingual_str> warnings;
159 for (
const std::shared_ptr<CWallet> &
wallet : vpwallets) {
167std::unique_ptr<interfaces::Handler>
170 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(),
171 std::move(load_wallet));
174 g_load_wallet_fns.erase(it);
181static std::set<std::string>
183static std::set<std::string>
189 wallet->WalletLogPrintf(
"Releasing wallet\n");
195 if (g_unloading_wallet_set.erase(
name) == 0) {
208 auto it = g_unloading_wallet_set.insert(
name);
220 while (g_unloading_wallet_set.count(
name) == 1) {
227std::shared_ptr<CWallet>
229 std::optional<bool> load_on_start,
233 std::unique_ptr<WalletDatabase> database =
242 std::shared_ptr<CWallet>
wallet =
252 wallet->postInitProcess();
258 }
catch (
const std::runtime_error &e) {
266std::shared_ptr<CWallet>
270 std::vector<bilingual_str> &warnings) {
272 return g_loading_wallet_set.insert(
name));
273 if (!result.second) {
278 auto wallet = LoadWalletInternal(chain,
name, load_on_start, options,
279 status,
error, warnings);
284std::shared_ptr<CWallet>
288 std::vector<bilingual_str> &warnings) {
297 if (!passphrase.empty()) {
303 std::unique_ptr<WalletDatabase> database =
313 if (!passphrase.empty() &&
316 "Passphrase provided but private keys are disabled. A passphrase "
317 "is only used to encrypt private keys, so cannot be used for "
318 "wallets with private keys disabled.");
325 std::shared_ptr<CWallet>
wallet =
327 wallet_creation_flags,
error, warnings);
336 if (!passphrase.empty() &&
338 if (!
wallet->EncryptWallet(passphrase)) {
340 Untranslated(
"Error: Wallet created but failed to encrypt.");
346 if (!
wallet->Unlock(passphrase)) {
348 "Error: Wallet was encrypted but could not be unlocked");
357 wallet->SetupDescriptorScriptPubKeyMans();
359 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
360 if (!spk_man->SetupGeneration()) {
375 wallet->postInitProcess();
397 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
398 if (it == mapWallet.end()) {
402 return &(it->second);
415 spk_man->UpgradeKeyMetadata();
420 bool accept_no_keys) {
426 for (
const MasterKeyMap::value_type &pMasterKey :
mapMasterKeys) {
428 strWalletPassphrase, pMasterKey.second.vchSalt,
429 pMasterKey.second.nDeriveIterations,
430 pMasterKey.second.nDerivationMethod)) {
433 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey,
438 if (
Unlock(_vMasterKey, accept_no_keys)) {
461 strOldWalletPassphrase, pMasterKey.second.vchSalt,
462 pMasterKey.second.nDeriveIterations,
463 pMasterKey.second.nDerivationMethod)) {
467 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey)) {
471 if (
Unlock(_vMasterKey)) {
474 pMasterKey.second.vchSalt,
475 pMasterKey.second.nDeriveIterations,
476 pMasterKey.second.nDerivationMethod);
477 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(
478 pMasterKey.second.nDeriveIterations *
483 pMasterKey.second.vchSalt,
484 pMasterKey.second.nDeriveIterations,
485 pMasterKey.second.nDerivationMethod);
486 pMasterKey.second.nDeriveIterations =
487 (pMasterKey.second.nDeriveIterations +
488 static_cast<unsigned int>(
489 pMasterKey.second.nDeriveIterations * 100 /
493 if (pMasterKey.second.nDeriveIterations < 25000) {
494 pMasterKey.second.nDeriveIterations = 25000;
498 "Wallet passphrase changed to an nDeriveIterations of %i\n",
499 pMasterKey.second.nDeriveIterations);
502 strNewWalletPassphrase, pMasterKey.second.vchSalt,
503 pMasterKey.second.nDeriveIterations,
504 pMasterKey.second.nDerivationMethod)) {
508 if (!crypter.
Encrypt(_vMasterKey,
509 pMasterKey.second.vchCryptedKey)) {
539 if (nWalletVersion >= nVersion) {
545 if (fExplicit && nVersion > nWalletMaxVersion) {
549 nWalletVersion = nVersion;
551 if (nVersion > nWalletMaxVersion) {
552 nWalletMaxVersion = nVersion;
556 if (nWalletVersion > 40000) {
568 if (nWalletVersion > nVersion) {
572 nWalletMaxVersion = nVersion;
578 std::set<TxId> result;
581 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
582 if (it == mapWallet.end()) {
588 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
590 for (
const CTxIn &txin : wtx.
tx->vin) {
591 if (mapTxSpends.count(txin.prevout) <= 1) {
596 range = mapTxSpends.equal_range(txin.prevout);
597 for (TxSpends::const_iterator _it = range.first; _it != range.second;
599 result.insert(_it->second);
608 auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
609 return (iter != mapTxSpends.end() && iter->first.GetTxId() == txid);
621 std::pair<TxSpends::iterator, TxSpends::iterator> range) {
626 int nMinOrderPos = std::numeric_limits<int>::max();
628 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
629 const CWalletTx *wtx = &mapWallet.at(it->second);
641 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
642 const TxId &txid = it->second;
644 if (copyFrom == copyTo) {
650 "Oldest wallet transaction in range assumed to have been found.");
672 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range =
673 mapTxSpends.equal_range(outpoint);
675 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
676 const TxId &wtxid = it->second;
677 std::map<TxId, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
678 if (mit != mapWallet.end()) {
680 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) {
691 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
693 setLockedCoins.erase(outpoint);
695 std::pair<TxSpends::iterator, TxSpends::iterator> range;
696 range = mapTxSpends.equal_range(outpoint);
701 auto it = mapWallet.find(wtxid);
702 assert(it != mapWallet.end());
709 for (
const CTxIn &txin : thisTx.
tx->vin) {
768 delete encrypted_batch;
769 encrypted_batch =
nullptr;
775 auto spk_man = spk_man_pair.second.get();
776 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
778 delete encrypted_batch;
779 encrypted_batch =
nullptr;
791 delete encrypted_batch;
792 encrypted_batch =
nullptr;
799 delete encrypted_batch;
800 encrypted_batch =
nullptr;
803 Unlock(strWalletPassphrase);
811 if (spk_man->IsHDEnabled()) {
812 if (!spk_man->SetupGeneration(
true)) {
845 for (
auto &entry : mapWallet) {
851 std::vector<int64_t> nOrderPosOffsets;
852 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) {
856 if (nOrderPos == -1) {
857 nOrderPos = nOrderPosNext++;
858 nOrderPosOffsets.push_back(nOrderPos);
864 int64_t nOrderPosOff = 0;
865 for (
const int64_t &nOffsetStart : nOrderPosOffsets) {
866 if (nOrderPos >= nOffsetStart) {
871 nOrderPos += nOrderPosOff;
872 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
892 int64_t nRet = nOrderPosNext++;
904 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
905 item.second.MarkDirty();
910 unsigned int n,
bool used,
911 std::set<CTxDestination> &tx_destinations) {
924 tx_destinations.insert(dst);
926 }
else if (!used &&
GetDestData(dst,
"used",
nullptr)) {
947 assert(spk_man !=
nullptr);
948 for (
const auto &keyid :
963 bool fFlushOnClose) {
968 const TxId &txid = tx->GetId();
972 std::set<CTxDestination> tx_destinations;
974 for (
const CTxIn &txin : tx->vin) {
975 const COutPoint &op = txin.prevout;
985 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
986 std::forward_as_tuple(tx));
988 bool fInsertedNew = ret.second;
989 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1000 if (!fInsertedNew) {
1016 (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
1019 if ((fInsertedNew || fUpdated) && !batch.
WriteTx(wtx)) {
1029#if defined(HAVE_SYSTEM)
1032 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
1034 if (!strCmd.empty()) {
1045 std::thread t(runCommand, strCmd);
1056 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
1057 std::forward_as_tuple(
nullptr));
1059 if (!fill_wtx(wtx, ins.second)) {
1067 if (
chain().findBlock(
1069 FoundBlock().inActiveChain(active).height(height)) &&
1092 for (
const CTxIn &txin : wtx.
tx->vin) {
1093 auto it = mapWallet.find(txin.prevout.GetTxId());
1094 if (it != mapWallet.end()) {
1110 const TxId &txid = ptx->GetId();
1113 for (
const CTxIn &txin : ptx->vin) {
1114 std::pair<TxSpends::const_iterator, TxSpends::const_iterator>
1115 range = mapTxSpends.equal_range(txin.prevout);
1116 while (range.first != range.second) {
1117 if (range.first->second != txid) {
1119 "Transaction %s (in block %s) conflicts with wallet "
1120 "transaction %s (both spend %s:%i)\n",
1122 range.first->second.ToString(),
1123 range.first->first.GetTxId().ToString(),
1124 range.first->first.GetN());
1126 range.first->second);
1133 bool fExisted = mapWallet.count(txid) != 0;
1134 if (fExisted && !fUpdate) {
1147 for (
const CTxOut &txout : ptx->vout) {
1149 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1170 for (
const CTxIn &txin : tx->vin) {
1171 auto it = mapWallet.find(txin.prevout.GetTxId());
1172 if (it != mapWallet.end()) {
1173 it->second.MarkDirty();
1183 std::set<TxId> todo;
1184 std::set<TxId> done;
1187 auto it = mapWallet.find(txid);
1188 assert(it != mapWallet.end());
1196 while (!todo.empty()) {
1200 it = mapWallet.find(now);
1201 assert(it != mapWallet.end());
1205 assert(currentconfirm <= 0);
1218 TxSpends::const_iterator iter =
1219 mapTxSpends.lower_bound(COutPoint(now, 0));
1220 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1221 if (!done.count(iter->second)) {
1222 todo.insert(iter->second);
1241 int conflictconfirms =
1242 (m_last_block_processed_height - conflicting_height + 1) * -1;
1247 if (conflictconfirms >= 0) {
1254 std::set<TxId> todo;
1255 std::set<TxId> done;
1259 while (!todo.empty()) {
1263 auto it = mapWallet.find(now);
1264 assert(it != mapWallet.end());
1267 if (conflictconfirms < currentconfirm) {
1278 TxSpends::const_iterator iter =
1279 mapTxSpends.lower_bound(COutPoint(now, 0));
1280 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1281 if (!done.count(iter->second)) {
1282 todo.insert(iter->second);
1308 uint64_t mempool_sequence) {
1314 auto it = mapWallet.find(tx->GetId());
1315 if (it != mapWallet.end()) {
1316 it->second.fInMempool =
true;
1322 uint64_t mempool_sequence) {
1324 auto it = mapWallet.find(tx->GetId());
1325 if (it != mapWallet.end()) {
1326 it->second.fInMempool =
false;
1357 {CWalletTx::Status::UNCONFIRMED, 0,
1370 m_last_block_processed_height = height;
1371 m_last_block_processed = block_hash;
1372 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1374 block_hash, int(index)});
1389 m_last_block_processed_height = height - 1;
1393 {CWalletTx::Status::UNCONFIRMED, 0,
1402void CWallet::BlockUntilSyncedToCurrentChain()
const {
1417 std::map<TxId, CWalletTx>::const_iterator mi =
1418 mapWallet.find(txin.prevout.GetTxId());
1419 if (mi != mapWallet.end()) {
1421 if (txin.prevout.GetN() < prev.
tx->vout.size()) {
1422 if (
IsMine(prev.
tx->vout[txin.prevout.GetN()]) & filter) {
1423 return prev.
tx->vout[txin.prevout.GetN()].nValue;
1445 result = std::max(result, spk_man_pair.second->IsMine(script));
1452 for (
const CTxOut &txout : tx.vout) {
1468 for (
const CTxIn &txin : tx.vin) {
1471 throw std::runtime_error(std::string(__func__) +
1472 ": value out of range");
1483 result &= spk_man->IsHDEnabled();
1495 if (spk_man && spk_man->CanGetAddresses(internal)) {
1506 throw std::runtime_error(std::string(__func__) +
1507 ": writing wallet flags failed");
1520 throw std::runtime_error(std::string(__func__) +
1521 ": writing wallet flags failed");
1549 throw std::runtime_error(std::string(__func__) +
1550 ": writing wallet flags failed");
1559 bool use_max_sig)
const {
1564 std::unique_ptr<SigningProvider> provider =
1574 scriptPubKey, sigdata)) {
1585 const std::vector<CTxOut> &txouts,
1586 bool use_max_sig)
const {
1589 for (
const auto &txout : txouts) {
1600 int64_t timestamp) {
1605 LOCK(spk_man->cs_KeyStore);
1606 return spk_man->ImportScripts(scripts, timestamp);
1610 const int64_t timestamp) {
1615 LOCK(spk_man->cs_KeyStore);
1616 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1620 const std::vector<CKeyID> &ordered_pubkeys,
1621 const std::map<CKeyID, CPubKey> &pubkey_map,
1622 const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
1623 const bool add_keypool,
const bool internal,
const int64_t timestamp) {
1628 LOCK(spk_man->cs_KeyStore);
1629 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins,
1630 add_keypool, internal, timestamp);
1634 const std::set<CScript> &script_pub_keys,
1635 const bool have_solving_data,
1636 const bool apply_label,
1637 const int64_t timestamp) {
1642 LOCK(spk_man->cs_KeyStore);
1643 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data,
1649 for (
const CScript &script : script_pub_keys) {
1674 int start_height = 0;
1678 FoundBlock().hash(start_block).height(start_height));
1687 start_block, start_height, {} , reserver, update);
1720 const BlockHash &start_block,
int start_height,
1747 double progress_current = progress_begin;
1748 int block_height = start_height;
1750 if (progress_end - progress_begin > 0.0) {
1752 (progress_end - progress_begin);
1758 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1760 strprintf(
"%s " +
_(
"Rescanning...").translated,
1767 block_height, progress_current);
1776 bool block_still_active =
false;
1777 bool next_block =
false;
1781 .inActiveChain(block_still_active)
1783 .inActiveChain(next_block)
1784 .hash(next_block_hash)));
1788 if (!block_still_active) {
1795 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size();
1798 block_height, block_hash,
1801 {CWalletTx::Status::CONFIRMED, block_height,
1802 block_hash, int(posInBlock)},
1815 if (max_height && block_height >= *max_height) {
1826 block_hash = next_block_hash;
1831 const BlockHash prev_tip_hash = tip_hash;
1833 if (!max_height && prev_tip_hash != tip_hash) {
1846 block_height, progress_current);
1848 }
else if (block_height &&
chain().shutdownRequested()) {
1850 "Rescan interrupted by shutdown request at block %d. Progress=%f\n",
1851 block_height, progress_current);
1869 std::map<int64_t, CWalletTx *> mapSorted;
1873 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1874 const TxId &wtxid = item.first;
1881 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1886 for (
const std::pair<const int64_t, CWalletTx *> &item : mapSorted) {
1888 std::string unused_err_string;
1894 std::string &err_string,
1937 std::set<TxId> result;
1957 if (!
chain().isReadyToBroadcast()) {
1974 int submitted_tx_count = 0;
1980 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1988 std::string unused_err_string;
1990 ++submitted_tx_count;
1995 if (submitted_tx_count > 0) {
1996 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__,
1997 submitted_tx_count);
2004 for (
const std::shared_ptr<CWallet> &pwallet :
GetWallets()) {
2005 pwallet->ResendWalletTransactions();
2019 std::map<COutPoint, Coin> coins;
2020 for (
auto &input : tx.
vin) {
2021 auto mi = mapWallet.find(input.prevout.GetTxId());
2022 if (mi == mapWallet.end() ||
2023 input.prevout.GetN() >= mi->second.tx->vout.size()) {
2027 coins[input.prevout] =
2031 std::map<int, std::string> input_errors;
2036 const std::map<COutPoint, Coin> &coins,
2038 std::map<int, std::string> &input_errors)
const {
2043 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2054 if (legacy_spk_man &&
2055 legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2064 bool sign,
bool bip32derivs)
const {
2067 for (
size_t i = 0; i < psbtx.
tx->vin.size(); ++i) {
2068 const CTxIn &txin = psbtx.
tx->vin[i];
2077 const TxId &txid = txin.prevout.GetTxId();
2078 const auto it = mapWallet.find(txid);
2079 if (it != mapWallet.end()) {
2081 CTxOut utxo = wtx.
tx->vout[txin.prevout.GetN()];
2091 spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
2099 for (
const auto &input : psbtx.
inputs) {
2108 std::string &str_sig)
const {
2112 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2113 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2121 const std::vector<CRecipient> &vecSend)
const {
2124 return *change_type;
2138 std::vector<std::pair<std::string, std::string>> orderForm,
2149 wtx.
mapValue = std::move(mapValue);
2157 for (
const CTxIn &txin : tx->vin) {
2158 CWalletTx &coin = mapWallet.at(txin.prevout.GetTxId());
2165 CWalletTx &wtx = mapWallet.at(tx->GetId());
2173 std::string err_string;
2175 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast "
2176 "immediately, %s\n",
2188 if (
database->Rewrite(
"\x04pool")) {
2190 spk_man_pair.second->RewriteDB();
2201 return nLoadWalletRet;
2208 std::vector<TxId> &txIdsOut) {
2212 for (
const TxId &txid : txIdsOut) {
2213 const auto &it = mapWallet.find(txid);
2214 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2215 for (
const auto &txin : it->second.tx->vin) {
2216 mapTxSpends.erase(txin.prevout);
2218 mapWallet.erase(it);
2223 if (
database->Rewrite(
"\x04pool")) {
2225 spk_man_pair.second->RewriteDB();
2231 return nZapSelectTxRet;
2241 const std::string &strName,
2242 const std::string &strPurpose) {
2243 bool fUpdated =
false;
2247 std::map<CTxDestination, CAddressBookData>::iterator mi =
2248 m_address_book.find(address);
2249 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2250 m_address_book[address].SetLabel(strName);
2252 if (!strPurpose.empty()) {
2253 m_address_book[address].purpose = strPurpose;
2260 if (!strPurpose.empty() && !batch.
WritePurpose(address, strPurpose)) {
2263 return batch.
WriteName(address, strName);
2267 const std::string &strName,
2268 const std::string &strPurpose) {
2287 "%s called with IsMine address, NOT SUPPORTED. Please "
2288 "report this bug! %s\n",
2289 __func__, PACKAGE_BUGREPORT);
2293 for (
const std::pair<const std::string, std::string> &item :
2294 m_address_book[address].destdata) {
2297 m_address_book.erase(address);
2310 unsigned int count = 0;
2312 count += spk_man->KeypoolCountExternalKeys();
2321 unsigned int count = 0;
2323 count += spk_man->GetKeyPoolSize();
2332 res &= spk_man->TopUp(kpSize);
2341 bool result =
false;
2345 result = spk_man->GetNewDestination(type, dest,
error);
2359 std::string &
error) {
2365 error =
_(
"Error: Keypool ran out, please call keypoolrefill first")
2376 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2379 std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2385 const std::set<CTxDestination> &destinations) {
2386 for (
auto &entry : mapWallet) {
2392 for (
size_t i = 0; i < wtx.
tx->vout.size(); i++) {
2396 destinations.count(dst)) {
2404std::set<CTxDestination>
2407 std::set<CTxDestination> result;
2408 for (
const std::pair<const CTxDestination, CAddressBookData> &item :
2410 if (item.second.IsChange()) {
2414 const std::string &strName = item.second.GetLabel();
2415 if (strName == label) {
2416 result.insert(address);
2463 setLockedCoins.insert(output);
2468 setLockedCoins.erase(output);
2473 setLockedCoins.clear();
2479 return setLockedCoins.count(outpoint) > 0;
2484 for (COutPoint outpoint : setLockedCoins) {
2485 vOutpts.push_back(outpoint);
2493 mapKeyBirth.clear();
2496 std::map<CKeyID, const CWalletTx::Confirmation *> mapKeyFirstBlock;
2507 assert(spk_man !=
nullptr);
2511 for (
const auto &entry : spk_man->mapKeyMetadata) {
2512 if (entry.second.nCreateTime) {
2513 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2519 if (mapKeyBirth.count(keyid) == 0) {
2520 mapKeyFirstBlock[keyid] = &max_confirm;
2525 if (mapKeyFirstBlock.empty()) {
2530 for (
const auto &entry : mapWallet) {
2535 for (
const CTxOut &txout : wtx.
tx->vout) {
2537 for (
const auto &keyid :
2540 auto rit = mapKeyFirstBlock.find(keyid);
2541 if (rit != mapKeyFirstBlock.end() &&
2543 rit->second->block_height) {
2553 for (
const auto &entry : mapKeyFirstBlock) {
2590 int64_t latestEntry = 0;
2594 int64_t latestTolerated = latestNow + 300;
2596 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2606 if (nSmartTime <= latestTolerated) {
2607 latestEntry = nSmartTime;
2608 if (nSmartTime > latestNow) {
2609 latestNow = nSmartTime;
2615 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2626 const std::string &key,
const std::string &value) {
2627 if (std::get_if<CNoDestination>(&dest)) {
2631 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2636 const std::string &key) {
2637 if (!m_address_book[dest].destdata.erase(key)) {
2645 const std::string &value) {
2646 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2650 std::string *value)
const {
2651 std::map<CTxDestination, CAddressBookData>::const_iterator i =
2652 m_address_book.find(dest);
2653 if (i != m_address_book.end()) {
2654 CAddressBookData::StringMap::const_iterator j =
2655 i->second.destdata.find(key);
2656 if (j != i->second.destdata.end()) {
2667std::vector<std::string>
2669 std::vector<std::string> values;
2670 for (
const auto &address : m_address_book) {
2671 for (
const auto &data : address.second.destdata) {
2673 values.emplace_back(data.second);
2680std::unique_ptr<WalletDatabase>
2691 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2692 if (!(path_type == fs::file_type::not_found ||
2693 path_type == fs::file_type::directory ||
2694 (path_type == fs::file_type::symlink &&
2695 fs::is_directory(wallet_path)) ||
2696 (path_type == fs::file_type::regular &&
2699 strprintf(
"Invalid -wallet path '%s'. -wallet path should point to "
2700 "a directory where wallet.dat and "
2701 "database/log.?????????? files can be stored, a location "
2702 "where such a directory could be created, "
2703 "or (for backwards compatibility) the name of an "
2704 "existing data file in -walletdir (%s)",
2709 return MakeDatabase(wallet_path, options, status, error_string);
2712std::shared_ptr<CWallet>
2714 std::unique_ptr<WalletDatabase> database,
2716 std::vector<bilingual_str> &warnings) {
2717 const std::string &walletFile =
database->Filename();
2722 std::shared_ptr<CWallet> walletInstance(
2724 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2728 strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2734 strprintf(
_(
"Error reading %s! All keys read correctly, but "
2735 "transaction data or address book entries might be "
2736 "missing or incorrect."),
2740 _(
"Error loading %s: Wallet requires newer version of %s"),
2741 walletFile, PACKAGE_NAME);
2745 _(
"Wallet needed to be rewritten: restart %s to complete"),
2756 const bool fFirstRun =
2757 walletInstance->m_spk_managers.empty() &&
2765 walletInstance->AddWalletFlags(wallet_creation_flags);
2769 walletInstance->SetupLegacyScriptPubKeyMan();
2772 if (!(wallet_creation_flags &
2774 LOCK(walletInstance->cs_wallet);
2776 walletInstance->SetupDescriptorScriptPubKeyMans();
2782 walletInstance->GetActiveScriptPubKeyMans()) {
2783 if (!spk_man->SetupGeneration()) {
2784 error =
_(
"Unable to generate initial keys");
2798 "disabled during creation"),
2801 }
else if (walletInstance->IsWalletFlagSet(
2803 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2804 if (spk_man->HavePrivateKeys()) {
2806 strprintf(
_(
"Warning: Private keys detected in wallet {%s} "
2807 "with disabled private keys"),
2822 _(
"This is the minimum transaction fee you pay "
2823 "on every transaction."));
2825 walletInstance->m_min_fee =
CFeeRate(n);
2829 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
2831 if (max_aps_fee ==
"-1") {
2840 _(
"This is the maximum transaction fee you pay (in addition to"
2841 " the normal fee) to prioritize partial spend avoidance over"
2842 " regular coin selection."));
2844 walletInstance->m_max_aps_fee = n;
2851 strprintf(
_(
"Invalid amount for -fallbackfee=<amount>: '%s'"),
2858 _(
"This is the transaction fee you may pay when "
2859 "fee estimates are not available."));
2861 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
2864 walletInstance->m_allow_fallback_fee =
2865 walletInstance->m_fallback_fee.GetFeePerK() !=
Amount::zero();
2875 _(
"This is the transaction fee you will pay if "
2876 "you send a transaction."));
2878 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
2881 "(must be at least %s)"),
2895 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large "
2896 "could be paid on a single transaction."));
2900 _(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at "
2901 "least the minrelay fee of %s to prevent stuck "
2906 walletInstance->m_default_max_tx_fee = nMaxFee;
2912 _(
"The wallet will avoid paying less than the minimum relay fee."));
2915 walletInstance->m_spend_zero_conf_change =
2920 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
2924 walletInstance->TopUpKeyPool();
2926 LOCK(walletInstance->cs_wallet);
2934 for (
auto &load_wallet : g_load_wallet_fns) {
2939 walletInstance->SetBroadcastTransactions(
2943 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n",
2944 walletInstance->GetKeyPoolSize());
2945 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n",
2946 walletInstance->mapWallet.size());
2947 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n",
2948 walletInstance->m_address_book.size());
2951 return walletInstance;
2956 std::vector<bilingual_str> &warnings) {
2957 LOCK(walletInstance->cs_wallet);
2960 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
2961 walletInstance->m_chain = &
chain;
2975 walletInstance->m_attaching_chain =
true;
2976 walletInstance->m_chain_notifications_handler =
2979 int rescan_height = 0;
2984 if (
const std::optional<int> fork_height =
2986 rescan_height = *fork_height;
2993 walletInstance->m_last_block_processed =
2995 walletInstance->m_last_block_processed_height = *tip_height;
2997 walletInstance->m_last_block_processed.
SetNull();
2998 walletInstance->m_last_block_processed_height = -1;
3001 if (tip_height && *tip_height != rescan_height) {
3006 int block_height = *tip_height;
3007 while (block_height > 0 &&
3009 rescan_height != block_height) {
3013 if (rescan_height != block_height) {
3026 ?
_(
"Prune: last wallet synchronisation goes beyond "
3027 "pruned data. You need to -reindex (download the "
3028 "whole blockchain again in case of pruned node)")
3029 :
strprintf(
_(
"Error loading wallet. Wallet requires "
3030 "blocks to be downloaded, "
3031 "and software does not currently support "
3032 "loading wallets while "
3033 "blocks are being downloaded out of "
3034 "order when using assumeutxo "
3035 "snapshots. Wallet should be able to "
3036 "load successfully after "
3037 "node sync reaches height %s"),
3044 walletInstance->WalletLogPrintf(
3045 "Rescanning last %i blocks (from block %i)...\n",
3046 *tip_height - rescan_height, rescan_height);
3050 std::optional<int64_t> time_first_key;
3051 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3052 int64_t time = spk_man->GetTimeFirstKey();
3053 if (!time_first_key || time < *time_first_key) {
3054 time_first_key = time;
3057 if (time_first_key) {
3068 ->ScanForWalletTransactions(
3070 {} , reserver,
true )
3072 error =
_(
"Failed to rescan the wallet during initialization");
3077 walletInstance->m_attaching_chain =
false;
3080 walletInstance->database->IncrementUpdateCounter();
3082 walletInstance->m_attaching_chain =
false;
3089 bool allow_change)
const {
3090 const auto &address_book_it = m_address_book.find(dest);
3091 if (address_book_it == m_address_book.end()) {
3094 if ((!allow_change) && address_book_it->second.IsChange()) {
3097 return &address_book_it->second;
3102 int nMaxVersion = version;
3104 if (nMaxVersion == 0) {
3114 error =
_(
"Cannot downgrade wallet");
3128 error =
_(
"Cannot upgrade a non HD split wallet without upgrading to "
3129 "support pre split keypool. Please use version 200300 or no "
3130 "version specified.");
3135 if (!spk_man->Upgrade(prev_version,
error)) {
3198 assert(chain_depth >= 0);
3218 return vMasterKey.empty();
3228 if (!vMasterKey.empty()) {
3231 sizeof(
decltype(vMasterKey)::value_type));
3244 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn,
3249 vMasterKey = vMasterKeyIn;
3256 std::set<ScriptPubKeyMan *> spk_mans;
3257 for (
bool internal : {
false,
true}) {
3261 spk_mans.insert(spk_man);
3269 std::set<ScriptPubKeyMan *> spk_mans;
3271 spk_mans.insert(spk_man_pair.second.get());
3277 bool internal)
const {
3278 const std::map<OutputType, ScriptPubKeyMan *> &spk_managers =
3280 std::map<OutputType, ScriptPubKeyMan *>::const_iterator it =
3281 spk_managers.find(type);
3282 if (it == spk_managers.end()) {
3284 "%s scriptPubKey Manager for output type %d does not exist\n",
3285 internal ?
"Internal" :
"External",
static_cast<int>(type));
3291std::set<ScriptPubKeyMan *>
3294 std::set<ScriptPubKeyMan *> spk_mans;
3296 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3297 spk_mans.insert(spk_man_pair.second.get());
3306 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3307 return spk_man_pair.second.get();
3320std::unique_ptr<SigningProvider>
3326std::unique_ptr<SigningProvider>
3330 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3331 return spk_man_pair.second->GetSolvingProvider(script);
3374 return cb(vMasterKey);
3384 spk_man->NotifyCanGetAddressesChanged.connect(
3391 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(
3409 for (
bool internal : {
false,
true}) {
3412 std::make_unique<DescriptorScriptPubKeyMan>(*
this, internal);
3415 throw std::runtime_error(
3416 std::string(__func__) +
3417 ": Wallet is locked, cannot setup new descriptors");
3419 if (!spk_manager->CheckDecryptionKey(vMasterKey) &&
3420 !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3421 throw std::runtime_error(
3422 std::string(__func__) +
3423 ": Could not encrypt new descriptors");
3426 spk_manager->SetupDescriptorGeneration(master_key, t);
3427 uint256 id = spk_manager->GetID();
3439 throw std::runtime_error(std::string(__func__) +
3440 ": writing active ScriptPubKeyMan id failed");
3454 "Setting spkMan to active: id = %s, type = %d, internal = %d\n",
3455 id.
ToString(),
static_cast<int>(type),
static_cast<int>(internal));
3458 auto &spk_mans_other =
3461 spk_man->SetInternal(internal);
3462 spk_mans[type] = spk_man;
3464 const auto it = spk_mans_other.find(type);
3465 if (it != spk_mans_other.end() && it->second == spk_man) {
3466 spk_mans_other.erase(type);
3475 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3477 "Deactivate spkMan: id = %s, type = %d, internal = %d\n",
3478 id.
ToString(),
static_cast<int>(type),
static_cast<int>(internal));
3482 throw std::runtime_error(
3483 std::string(__func__) +
3484 ": erasing active ScriptPubKeyMan id failed");
3489 spk_mans.erase(type);
3501 return spk_man !=
nullptr;
3511 spk_man_pair.second.get());
3523 const std::string &label,
bool internal) {
3528 "Cannot add WalletDescriptor to a non-descriptor wallet\n");
3536 spk_man->UpdateWalletDescriptor(desc);
3539 std::make_unique<DescriptorScriptPubKeyMan>(*
this, desc);
3540 spk_man = new_spk_man.get();
3547 for (
const auto &entry : signing_provider.
keys) {
3548 const CKey &key = entry.second;
3549 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3553 if (!spk_man->TopUp()) {
3561 auto script_pub_keys = spk_man->GetScriptPubKeys();
3562 if (script_pub_keys.empty()) {
3564 "Could not generate scriptPubKeys (cache is empty)\n");
3575 spk_man->WriteDescriptor();
bool MoneyRange(const Amount nValue)
static constexpr Amount SATOSHI
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
const CChainParams & Params()
Return the currently selected parameters.
#define CHECK_NONFATAL(condition)
Identity function.
#define Assert(val)
Identity function.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::vector< CTransactionRef > vtx
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Encryption/decryption context with key information.
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
bool Decrypt(const std::vector< uint8_t > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Fee rate in satoshis per kilobyte: Amount / kB.
std::string ToString() const
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
An encapsulated secp256k1 private key.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
A reference to a CKey: the Hash160 of its serialized public key.
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.
std::vector< uint8_t > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
unsigned int nDeriveIterations
std::vector< uint8_t > vchCryptedKey
A mutable version of CTransaction.
An encapsulated public key.
An output of a transaction.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
std::atomic< int64_t > m_best_block_time
BlockHash GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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....
bool HaveChain() const
Interface to assert chain access.
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
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,...
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
MasterKeyMap mapMasterKeys
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...
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
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.
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
interfaces::Chain & chain() const
Interface for accessing chain state.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
WalletDatabase & GetDatabase() override
interfaces::Chain * m_chain
Interface for accessing chain state.
std::atomic< bool > m_attaching_chain
bool WithEncryptionKey(const std::function< bool(const CKeyingMaterial &)> &cb) const override
Pass the encryption key to cb().
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
void DeactivateScriptPubKeyMan(const uint256 &id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
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.
bool IsLegacy() const
Determine if we are a legacy wallet.
std::atomic< bool > fAbortRescan
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
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.
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
OutputType m_default_address_type
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
std::atomic< uint64_t > m_wallet_flags
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
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
bool BackupWallet(const std::string &strDest) const
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
void WalletLogPrintfToBeContinued(std::string fmt, Params... parameters) const
std::unique_ptr< WalletDatabase > database
Internal database handle.
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.
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
std::vector< std::string > GetDestValues(const std::string &prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all destination values matching a prefix.
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
bool IsLocked() const override
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
std::atomic< double > m_scanning_progress
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
boost::signals2::signal< void(CWallet *wallet, const TxId &txid, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
bool HasEncryptionKeys() const override
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > _database)
Construct wallet with specified name and database implementation.
Amount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
bool fBroadcastTransactions
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
std::multimap< int64_t, CWalletTx * > TxItems
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.
unsigned int nMasterKeyMaxID
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
A transaction with a bunch of additional info that only the owner cares about.
mapValue_t mapValue
Key/value map with information about the transaction.
bool isUnconfirmed() const
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
bool IsEquivalentTo(const CWalletTx &tx) const
bool isConflicted() const
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,...
unsigned int fTimeReceivedIsTxTime
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
unsigned int nTimeReceived
time received by this node
int64_t nOrderPos
position in ordered transaction list
bool HasWalletDescriptor(const WalletDescriptor &desc) const
RecursiveMutex cs_KeyStore
Different type to mark Mutex at global scope.
std::set< CKeyID > GetKeys() const override
A wrapper to reserve an address from a wallet.
bool fInternal
Whether this is from the internal (change output) keypool.
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from.
int64_t nIndex
The index of the address's key in the keypool.
CTxDestination address
The destination.
const CWallet *const pwallet
The wallet to reserve from.
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.
void push_back(UniValue val)
const std::vector< UniValue > & getValues() const
Access to the wallet database.
bool TxnCommit()
Commit current transaction.
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteName(const CTxDestination &address, const std::string &strName)
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
bool WriteMinVersion(int nVersion)
bool ErasePurpose(const CTxDestination &address)
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)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool WriteTx(const CWalletTx &wtx)
bool TxnBegin()
Begin a new transaction.
bool TxnAbort()
Abort current transaction.
bool EraseName(const CTxDestination &address)
bool WriteBestBlock(const CBlockLocator &locator)
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut)
DBErrors LoadWallet(CWallet *pwallet)
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.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
std::string ToString() const
std::string GetHex() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual BlockHash getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findBlock(const BlockHash &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual std::unique_ptr< Handler > handleNotifications(std::shared_ptr< Notifications > notifications)=0
Register handler for notifications.
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height,...
virtual bool broadcastTransaction(const Config &config, const CTransactionRef &tx, const Amount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual double guessVerificationProgress(const BlockHash &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual const CChainParams & params() const =0
This Chain's parameters.
virtual bool havePruned()=0
Check if any block has been pruned.
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
virtual bool findAncestorByHeight(const BlockHash &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual void requestMempoolTransactions(Notifications ¬ifications)=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.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
const Config & GetConfig()
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
const unsigned int WALLET_CRYPTO_SALT_SIZE
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
const unsigned int WALLET_CRYPTO_KEY_SIZE
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 ...
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void KeepDestination()
Keep the address.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsLockedCoin(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ReturnDestination()
Return reserved address.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool TopUpKeyPool(unsigned int kpSize=0)
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
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.
bool GetReservedDestination(CTxDestination &pubkey, bool internal)
Reserve an address.
int64_t GetOldestKeyPoolTime() const
bool DelAddressBook(const CTxDestination &address)
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, std::string &error)
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
bool AddWalletFlags(uint64_t flags)
Overwrite all flags by the given uint64_t.
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)
bool LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
void Flush()
Flush wallet (bitdb flush)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
std::set< TxId > GetConflicts(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
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.
void AddToSpends(const COutPoint &outpoint, const TxId &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
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.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
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...
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockConnected(ChainstateRole role, const CBlock &block, int height) override
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
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)
bool CanGetAddresses(bool internal=false) const
Returns true if the wallet can give out new addresses.
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.
bool IsSpentKey(const TxId &txid, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool TransactionCanBeAbandoned(const TxId &txid) const
Return whether transaction can be abandoned.
const CChainParams & GetChainParams() const override
Amount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction, spends it:
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EncryptWallet(const SecureString &strWalletPassphrase)
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
void updatedBlockTip() override
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
bool AbandonTransaction(const TxId &txid)
Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void SetSpentKeyState(WalletBatch &batch, const TxId &txid, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
DBErrors ReorderTransactions()
void blockDisconnected(const CBlock &block, int height) override
void Close()
Close wallet database.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
const CWalletTx * GetWalletTx(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ResendWalletTransactions()
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false) override
signify that a particular wallet feature is now used.
std::set< TxId > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
isminetype
IsMine() return codes.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
bool error(const char *fmt, const Args &...args)
@ PRIVATE_KEY_NOT_AVAILABLE
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
static auto quoted(const std::string &s)
static std::string PathToString(const path &path)
Convert path object to byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
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.
const std::string & FormatOutputType(OutputType type)
const std::array< OutputType, 1 > OUTPUT_TYPES
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
void GetStrongRandBytes(Span< uint8_t > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
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...
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
void UpdateInput(CTxIn &input, const SignatureData &data)
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr Amount zero() noexcept
A BlockHash is a unqiue identifier for a block.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
void SetSeed(Span< const std::byte > seed)
std::optional< int > last_scanned_height
BlockHash last_scanned_block
Hash and height of most recent block that was successfully scanned.
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.
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
SecureString create_passphrase
std::map< CKeyID, CKey > keys
A version of CTransaction with the PSBT format.
std::vector< PSBTInput > inputs
std::optional< CMutableTransaction > tx
A TxId is the identifier of a transaction.
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::string ShellEscape(const std::string &arg)
int64_t GetTimeMillis()
Returns the system time (not mockable)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
std::map< std::string, std::string > mapValue_t
constexpr Amount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
constexpr OutputType DEFAULT_ADDRESS_TYPE
Default for -addresstype.
constexpr Amount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
static constexpr uint64_t KNOWN_WALLET_FLAGS
static const bool DEFAULT_WALLETBROADCAST
constexpr Amount HIGH_APS_FEE
discourage APS fee higher than this amount
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
static void ReleaseWallet(CWallet *wallet)
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
static std::vector< std::shared_ptr< CWallet > > vpwallets GUARDED_BY(cs_wallets)
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
static std::condition_variable g_wallet_release_cv
static GlobalMutex g_loading_wallet_mutex
RecursiveMutex cs_wallets
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
static GlobalMutex g_wallet_release_mutex
std::shared_ptr< CWallet > GetWallet(const std::string &name)
std::vector< std::shared_ptr< CWallet > > GetWallets()
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
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)
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)
DBErrors
Error statuses for the wallet database.
fs::path GetWalletDir()
Get the path of the wallet directory.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_KEY_ORIGIN_METADATA
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
WalletFeature
(client) version numbers for particular wallet features
@ FEATURE_PRE_SPLIT_KEYPOOL