47#include <boost/algorithm/string/replace.hpp>
53 "You need to rescan the blockchain in order to correctly mark used "
54 "destinations in the past. Until this is done, some destinations may "
55 "be considered unused, even if the opposite is the case."
64 if (value.isStr() && value.get_str() == wallet_name)
return true;
73 if (!setting_value.
isArray())
return true;
76 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
78 if (new_value.
size() == setting_value.
size())
return true;
83 const std::string& wallet_name,
84 std::optional<bool> load_on_startup,
85 std::vector<bilingual_str>& warnings)
87 if (!load_on_startup)
return;
89 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
91 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
109 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
110 if (i != context.wallets.end())
return false;
111 context.wallets.push_back(
wallet);
112 wallet->ConnectScriptPubKeyManNotifiers();
113 wallet->NotifyCanGetAddressesChanged();
125 wallet->m_chain_notifications_handler.reset();
127 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
128 if (i == context.wallets.end())
return false;
129 context.wallets.erase(i);
139 std::vector<bilingual_str> warnings;
146 return context.wallets;
152 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
161 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
175 wallet->WalletLogPrintf(
"Releasing wallet\n");
181 if (g_unloading_wallet_set.erase(
name) == 0) {
195 auto it = g_unloading_wallet_set.insert(
name);
207 while (g_unloading_wallet_set.count(
name) == 1) {
231 wallet->postInitProcess();
237 }
catch (
const std::runtime_error& e) {
248 if (!result.second) {
253 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status,
error, warnings);
269 if (!passphrase.empty()) {
275 error =
Untranslated(
"Private keys must be disabled when using an external signer");
282 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
297 error =
Untranslated(
"Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
313 if (!
wallet->EncryptWallet(passphrase)) {
320 if (!
wallet->Unlock(passphrase)) {
330 wallet->SetupDescriptorScriptPubKeyMans();
332 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
333 if (!spk_man->SetupGeneration()) {
347 wallet->postInitProcess();
364 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
365 if (it == mapWallet.end())
367 return &(it->second);
381 spk_man->UpgradeKeyMetadata();
405 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
407 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
409 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
411 if (
Unlock(_vMasterKey, accept_no_keys)) {
435 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
437 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
442 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
443 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(
GetTimeMillis() - nStartTime))));
446 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
447 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
449 if (pMasterKey.second.nDeriveIterations < 25000)
450 pMasterKey.second.nDeriveIterations = 25000;
452 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
454 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
456 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
478 if (nWalletVersion >= nVersion)
480 nWalletVersion = nVersion;
484 if (nWalletVersion > 40000)
493 std::set<uint256> result;
496 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
497 if (it == mapWallet.end())
501 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
503 for (
const CTxIn& txin : wtx.
tx->vin)
505 if (mapTxSpends.count(txin.
prevout) <= 1)
507 range = mapTxSpends.equal_range(txin.
prevout);
508 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
509 result.insert(_it->second);
517 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
518 return (iter != mapTxSpends.end() && iter->first.hash == txid);
537 int nMinOrderPos = std::numeric_limits<int>::max();
539 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
540 const CWalletTx* wtx = &mapWallet.at(it->second);
552 for (TxSpends::iterator it = range.first; it != range.second; ++it)
554 const uint256& hash = it->second;
556 if (copyFrom == copyTo)
continue;
557 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
577 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
578 range = mapTxSpends.equal_range(outpoint);
580 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
582 const uint256& wtxid = it->second;
583 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
584 if (mit != mapWallet.end()) {
586 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
595 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
604 std::pair<TxSpends::iterator, TxSpends::iterator> range;
605 range = mapTxSpends.equal_range(outpoint);
612 auto it = mapWallet.find(wtxid);
613 assert(it != mapWallet.end());
618 for (
const CTxIn& txin : thisTx.
tx->vin)
661 delete encrypted_batch;
662 encrypted_batch =
nullptr;
668 auto spk_man = spk_man_pair.second.get();
669 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
671 delete encrypted_batch;
672 encrypted_batch =
nullptr;
683 delete encrypted_batch;
684 encrypted_batch =
nullptr;
690 delete encrypted_batch;
691 encrypted_batch =
nullptr;
694 Unlock(strWalletPassphrase);
701 if (spk_man->IsHDEnabled()) {
702 if (!spk_man->SetupGeneration(
true)) {
733 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
736 for (
auto& entry : mapWallet)
743 std::vector<int64_t> nOrderPosOffsets;
744 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
751 nOrderPos = nOrderPosNext++;
752 nOrderPosOffsets.push_back(nOrderPos);
759 int64_t nOrderPosOff = 0;
760 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
762 if (nOrderPos >= nOffsetStart)
765 nOrderPos += nOrderPosOff;
766 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
784 int64_t nRet = nOrderPosNext++;
797 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
798 item.second.MarkDirty();
806 auto mi = mapWallet.find(originalHash);
809 assert(mi != mapWallet.end());
845 tx_destinations.insert(dst);
868 assert(spk_man !=
nullptr);
869 for (
const auto& keyid :
GetAffectedKeys(srctx->
tx->vout[n].scriptPubKey, *spk_man)) {
898 std::set<CTxDestination> tx_destinations;
900 for (
const CTxIn& txin : tx->vin) {
909 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx));
911 bool fInsertedNew = ret.second;
912 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
940 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
947 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
950 if (fInsertedNew || fUpdated)
962 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
966 boost::replace_all(strCmd,
"%s", hash.
GetHex());
967 if (confirm.
status == CWalletTx::Status::CONFIRMED)
972 boost::replace_all(strCmd,
"%b",
"unconfirmed");
973 boost::replace_all(strCmd,
"%h",
"-1");
983 std::thread t(runCommand, strCmd);
993 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr));
995 if (!fill_wtx(wtx, ins.second)) {
1023 for (
const CTxIn& txin : wtx.
tx->vin) {
1025 if (it != mapWallet.end()) {
1043 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1044 while (range.first != range.second) {
1045 if (range.first->second != tx.
GetHash()) {
1046 WalletLogPrintf(
"Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.
GetHash().
ToString(), confirm.
hashBlock.
ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1054 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1055 if (fExisted && !fUpdate)
return false;
1067 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1088 for (
const CTxIn& txin : tx->vin) {
1090 if (it != mapWallet.end()) {
1091 it->second.MarkDirty();
1102 std::set<uint256> todo;
1103 std::set<uint256> done;
1106 auto it = mapWallet.find(hashTx);
1107 assert(it != mapWallet.end());
1113 todo.insert(hashTx);
1115 while (!todo.empty()) {
1119 auto it = mapWallet.find(now);
1120 assert(it != mapWallet.end());
1124 assert(currentconfirm <= 0);
1134 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1135 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1136 if (!done.count(iter->second)) {
1137 todo.insert(iter->second);
1154 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1159 if (conflictconfirms >= 0)
1165 std::set<uint256> todo;
1166 std::set<uint256> done;
1168 todo.insert(hashTx);
1170 while (!todo.empty()) {
1174 auto it = mapWallet.find(now);
1175 assert(it != mapWallet.end());
1178 if (conflictconfirms < currentconfirm) {
1188 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1189 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1190 if (!done.count(iter->second)) {
1191 todo.insert(iter->second);
1217 auto it = mapWallet.find(tx->GetHash());
1218 if (it != mapWallet.end()) {
1225 auto it = mapWallet.find(tx->GetHash());
1226 if (it != mapWallet.end()) {
1265 m_last_block_processed_height = height;
1266 m_last_block_processed = block_hash;
1267 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1268 SyncTransaction(block.
vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1281 m_last_block_processed_height = height - 1;
1294void CWallet::BlockUntilSyncedToCurrentChain()
const {
1310 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1311 if (mi != mapWallet.end())
1339 result = std::max(result, spk_man_pair.second->IsMine(script));
1365 throw std::runtime_error(std::string(__func__) +
": value out of range");
1373 bool result =
false;
1375 if (!spk_man->IsHDEnabled())
return false;
1387 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1399 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1413 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1444 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1470 for (
const auto& txout : txouts)
1476 const std::unique_ptr<SigningProvider> provider =
GetSolvingProvider(txout.scriptPubKey);
1477 if (!provider || !
DummySignInput(*provider, txin, txout, use_max_sig)) {
1494 LOCK(spk_man->cs_KeyStore);
1495 return spk_man->ImportScripts(scripts, timestamp);
1504 LOCK(spk_man->cs_KeyStore);
1505 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1508bool CWallet::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)
1514 LOCK(spk_man->cs_KeyStore);
1515 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1518bool CWallet::ImportScriptPubKeys(
const std::string& label,
const std::set<CScript>& script_pub_keys,
const bool have_solving_data,
const bool apply_label,
const int64_t timestamp)
1524 LOCK(spk_man->cs_KeyStore);
1525 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1530 for (
const CScript& script : script_pub_keys) {
1554 int start_height = 0;
1599 uint256 block_hash = start_block;
1611 double progress_current = progress_begin;
1612 int block_height = start_height;
1614 if (progress_end - progress_begin > 0.0) {
1615 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1619 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1624 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1633 bool block_still_active =
false;
1634 bool next_block =
false;
1640 if (!block_still_active) {
1647 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1648 SyncTransaction(block.
vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate,
true);
1658 if (max_height && block_height >= *max_height) {
1669 block_hash = next_block_hash;
1674 const uint256 prev_tip_hash = tip_hash;
1676 if (!max_height && prev_tip_hash != tip_hash) {
1684 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1686 }
else if (block_height &&
chain().shutdownRequested()) {
1687 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1700 std::map<int64_t, CWalletTx*> mapSorted;
1703 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1704 const uint256& wtxid = item.first;
1711 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1716 for (
const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1718 std::string unused_err_string;
1753 std::set<uint256> result;
1757 result.erase(myHash);
1775 if (!
chain().isReadyToBroadcast())
return;
1785 int submitted_tx_count = 0;
1791 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1797 std::string unused_err_string;
1802 if (submitted_tx_count > 0) {
1803 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
1811 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
1812 pwallet->ResendWalletTransactions();
1827 std::map<COutPoint, Coin> coins;
1828 for (
auto& input : tx.
vin) {
1829 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
1830 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
1836 std::map<int, bilingual_str> input_errors;
1846 if (spk_man->SignTransaction(tx, coins,
sighash, input_errors)) {
1863 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
1864 const CTxIn& txin = psbtx.
tx->vin[i];
1874 const auto it = mapWallet.find(txhash);
1875 if (it != mapWallet.end()) {
1886 int n_signed_this_spkm = 0;
1887 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
1893 (*n_signed) += n_signed_this_spkm;
1899 for (
const auto& input : psbtx.
inputs) {
1911 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
1912 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
1922 return *change_type;
1933 for (
const auto& recipient : vecSend) {
1935 int witnessversion = 0;
1936 std::vector<unsigned char> witnessprogram;
1937 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
1962 wtx.
mapValue = std::move(mapValue);
1970 for (
const CTxIn& txin : tx->vin) {
1978 CWalletTx& wtx = mapWallet.at(tx->GetHash());
1985 std::string err_string;
1987 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2002 spk_man_pair.second->RewriteDB();
2012 return nLoadWalletRet;
2019 for (
const uint256& hash : vHashOut) {
2020 const auto& it = mapWallet.find(hash);
2021 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2022 for (
const auto& txin : it->second.tx->vin)
2023 mapTxSpends.erase(txin.prevout);
2024 mapWallet.erase(it);
2033 spk_man_pair.second->RewriteDB();
2039 return nZapSelectTxRet;
2048 bool fUpdated =
false;
2052 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2053 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2054 m_address_book[address].SetLabel(strName);
2055 if (!strPurpose.empty())
2056 m_address_book[address].purpose = strPurpose;
2087 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
2091 m_address_book.erase(address);
2106 if (legacy_spk_man) {
2107 return legacy_spk_man->KeypoolCountExternalKeys();
2110 unsigned int count = 0;
2112 count += spk_man.second->GetKeyPoolSize();
2122 unsigned int count = 0;
2124 count += spk_man->GetKeyPoolSize();
2134 res &= spk_man->TopUp(kpSize);
2143 bool result =
false;
2147 result = spk_man->GetNewDestination(type, dest,
error);
2175 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2177 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2183 for (
auto& entry : mapWallet) {
2186 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2199 std::set<CTxDestination> result;
2200 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
2202 if (item.second.IsChange())
continue;
2204 const std::string& strName = item.second.GetLabel();
2205 if (strName == label)
2206 result.insert(address);
2256 if (spk_man ==
nullptr) {
2260 if (signer_spk_man ==
nullptr) {
2264 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2270 setLockedCoins.insert(output);
2280 bool was_locked = setLockedCoins.erase(output);
2281 if (batch && was_locked) {
2290 bool success =
true;
2292 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2295 setLockedCoins.clear();
2304 return (setLockedCoins.count(outpt) > 0);
2310 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2311 it != setLockedCoins.end(); it++) {
2313 vOutpts.push_back(outpt);
2321 mapKeyBirth.clear();
2324 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
2331 assert(spk_man !=
nullptr);
2335 for (
const auto& entry : spk_man->mapKeyMetadata) {
2336 if (entry.second.nCreateTime) {
2337 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2343 if (mapKeyBirth.count(keyid) == 0)
2344 mapKeyFirstBlock[keyid] = &max_confirm;
2348 if (mapKeyFirstBlock.empty())
2352 for (
const auto& entry : mapWallet) {
2357 for (
const CTxOut &txout : wtx.
tx->vout) {
2361 auto rit = mapKeyFirstBlock.find(keyid);
2372 for (
const auto& entry : mapKeyFirstBlock) {
2407 int64_t block_max_time;
2409 if (rescanning_old_block) {
2410 nTimeSmart = block_max_time;
2413 int64_t latestEntry = 0;
2416 int64_t latestTolerated = latestNow + 300;
2418 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2428 if (nSmartTime <= latestTolerated) {
2429 latestEntry = nSmartTime;
2430 if (nSmartTime > latestNow) {
2431 latestNow = nSmartTime;
2437 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2448 const std::string key{
"used"};
2449 if (std::get_if<CNoDestination>(&dest))
2453 if (
auto* data =
util::FindKey(m_address_book, dest)) data->destdata.erase(key);
2457 const std::string value{
"1"};
2458 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2464 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2469 const std::string key{
"used"};
2470 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
2471 if(i != m_address_book.end())
2473 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2474 if(j != i->second.destdata.end())
2484 const std::string
prefix{
"rr"};
2485 std::vector<std::string>
values;
2486 for (
const auto& address : m_address_book) {
2487 for (
const auto& data : address.second.destdata) {
2489 values.emplace_back(data.second);
2498 const std::string key{
"rr" +
id};
2500 if (value.empty()) {
2519 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2520 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
2521 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
2524 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2525 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2526 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2531 return MakeDatabase(wallet_path, options, status, error_string);
2538 const std::string& walletFile = database->Filename();
2544 bool rescan_required =
false;
2545 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2548 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2553 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
2554 " or address book entries might be missing or incorrect."),
2566 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect."
2567 " Rescanning wallet."), walletFile));
2568 rescan_required =
true;
2577 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2585 walletInstance->AddWalletFlags(wallet_creation_flags);
2589 walletInstance->SetupLegacyScriptPubKeyMan();
2593 LOCK(walletInstance->cs_wallet);
2595 walletInstance->SetupDescriptorScriptPubKeyMans();
2599 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2600 if (!spk_man->SetupGeneration()) {
2601 error =
_(
"Unable to generate initial keys");
2613 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
2616 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2617 if (spk_man->HavePrivateKeys()) {
2618 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2624 if (!args.
GetArg(
"-addresstype",
"").empty()) {
2630 walletInstance->m_default_address_type = parsed.value();
2633 if (!args.
GetArg(
"-changetype",
"").empty()) {
2639 walletInstance->m_default_change_type = parsed.value();
2643 std::optional<CAmount> min_tx_fee =
ParseMoney(args.
GetArg(
"-mintxfee",
""));
2644 if (!min_tx_fee || min_tx_fee.value() == 0) {
2649 _(
"This is the minimum transaction fee you pay on every transaction."));
2652 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
2656 const std::string max_aps_fee{args.
GetArg(
"-maxapsfee",
"")};
2657 if (max_aps_fee ==
"-1") {
2658 walletInstance->m_max_aps_fee = -1;
2659 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
2662 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2664 walletInstance->m_max_aps_fee = max_fee.value();
2671 if (args.
IsArgSet(
"-fallbackfee")) {
2672 std::optional<CAmount> fallback_fee =
ParseMoney(args.
GetArg(
"-fallbackfee",
""));
2673 if (!fallback_fee) {
2674 error =
strprintf(
_(
"Invalid amount for -fallbackfee=<amount>: '%s'"), args.
GetArg(
"-fallbackfee",
""));
2678 _(
"This is the transaction fee you may pay when fee estimates are not available."));
2680 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
2684 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
2686 if (args.
IsArgSet(
"-discardfee")) {
2687 std::optional<CAmount> discard_fee =
ParseMoney(args.
GetArg(
"-discardfee",
""));
2689 error =
strprintf(
_(
"Invalid amount for -discardfee=<amount>: '%s'"), args.
GetArg(
"-discardfee",
""));
2693 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
2695 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
2699 std::optional<CAmount> pay_tx_fee =
ParseMoney(args.
GetArg(
"-paytxfee",
""));
2705 _(
"This is the transaction fee you will pay if you send a transaction."));
2708 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
2711 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
2723 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
2727 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
2732 walletInstance->m_default_max_tx_fee = max_fee.value();
2735 if (args.
IsArgSet(
"-consolidatefeerate")) {
2736 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(args.
GetArg(
"-consolidatefeerate",
""))) {
2737 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
2746 _(
"The wallet will avoid paying less than the minimum relay fee."));
2753 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
GetTimeMillis() - nStart);
2756 walletInstance->TopUpKeyPool();
2758 LOCK(walletInstance->cs_wallet);
2766 for (
auto& load_wallet : context.wallet_load_fns) {
2774 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
2775 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
2776 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
2779 return walletInstance;
2784 LOCK(walletInstance->cs_wallet);
2786 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
2787 walletInstance->m_chain = &
chain;
2797 walletInstance->m_chain_notifications_handler = walletInstance->chain().
handleNotifications(walletInstance);
2800 int rescan_height = 0;
2801 if (!rescan_required)
2807 rescan_height = *fork_height;
2815 walletInstance->m_last_block_processed_height = *tip_height;
2817 walletInstance->m_last_block_processed.
SetNull();
2818 walletInstance->m_last_block_processed_height = -1;
2821 if (tip_height && *tip_height != rescan_height)
2824 int block_height = *tip_height;
2825 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
2829 if (rescan_height != block_height) {
2836 error =
_(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
2842 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
2846 std::optional<int64_t> time_first_key;
2847 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
2848 int64_t time = spk_man->GetTimeFirstKey();
2849 if (!time_first_key || time < *time_first_key) time_first_key = time;
2851 if (time_first_key) {
2858 error =
_(
"Failed to rescan the wallet during initialization");
2863 walletInstance->GetDatabase().IncrementUpdateCounter();
2871 const auto& address_book_it = m_address_book.find(dest);
2872 if (address_book_it == m_address_book.end())
return nullptr;
2873 if ((!allow_change) && address_book_it->second.IsChange()) {
2876 return &address_book_it->second;
2888 if (version < prev_version) {
2889 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
2897 error =
strprintf(
_(
"Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified."), prev_version, version,
FEATURE_PRE_SPLIT_KEYPOOL);
2905 if (!spk_man->Upgrade(prev_version, version,
error)) {
2957 assert(chain_depth >= 0);
2978 return vMasterKey.empty();
3000 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
3004 vMasterKey = vMasterKeyIn;
3012 std::set<ScriptPubKeyMan*> spk_mans;
3013 for (
bool internal : {
false,
true}) {
3017 spk_mans.insert(spk_man);
3026 std::set<ScriptPubKeyMan*> spk_mans;
3028 spk_mans.insert(spk_man_pair.second.get());
3036 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3037 if (it == spk_managers.end()) {
3045 std::set<ScriptPubKeyMan*> spk_mans;
3047 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3048 spk_mans.insert(spk_man_pair.second.get());
3058 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3059 return spk_man_pair.second.get();
3082 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3083 return spk_man_pair.second->GetSolvingProvider(script);
3165 for (
bool internal : {
false,
true}) {
3175 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3177 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3178 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3181 spk_manager->SetupDescriptorGeneration(master_key, t,
internal);
3182 uint256 id = spk_manager->GetID();
3194 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3195 for (
bool internal : {
false,
true}) {
3196 const UniValue& descriptor_vals =
find_value(signer_res,
internal ?
"internal" :
"receive");
3197 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3199 std::string desc_str = desc_val.getValStr();
3201 std::string dummy_error;
3202 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, dummy_error,
false);
3203 if (!desc->GetOutputType()) {
3208 spk_manager->SetupDescriptor(std::move(desc));
3209 uint256 id = spk_manager->GetID();
3221 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3232 WalletLogPrintf(
"Setting spkMan to active: id = %s, type = %d, internal = %d\n",
id.
ToString(),
static_cast<int>(type),
static_cast<int>(
internal));
3236 spk_mans[type] = spk_man;
3238 const auto it = spk_mans_other.find(type);
3239 if (it != spk_mans_other.end() && it->second == spk_man) {
3240 spk_mans_other.erase(type);
3249 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3250 WalletLogPrintf(
"Deactivate spkMan: id = %s, type = %d, internal = %d\n",
id.
ToString(),
static_cast<int>(type),
static_cast<int>(
internal));
3253 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3257 spk_mans.erase(type);
3269 return spk_man !=
nullptr;
3290 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3297 spk_man->UpdateWalletDescriptor(desc);
3300 spk_man = new_spk_man.get();
3307 for (
const auto& entry : signing_provider.
keys) {
3308 const CKey& key = entry.second;
3309 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3313 if (!spk_man->TopUp()) {
3321 auto script_pub_keys = spk_man->GetScriptPubKeys();
3322 if (script_pub_keys.empty()) {
3323 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3334 spk_man->WriteDescriptor();
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
#define PACKAGE_BUGREPORT
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
#define Assert(val)
Identity function.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
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
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
FlatSigningProvider m_external_provider
SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs.
bool IsExternalSelected(const COutPoint &output) const
Encryption/decryption context with key information.
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Fee rate in satoshis per kilobyte: CAmount / kB.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
An encapsulated 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< unsigned char > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
std::vector< unsigned char > vchCryptedKey
unsigned int nDeriveIterations
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
const uint256 & GetHash() const
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An input of a transaction.
An output of a transaction.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
std::atomic< int64_t > m_best_block_time
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.
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.
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
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
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
RecursiveMutex cs_wallet
Main wallet lock.
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.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
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.
int GetTxBlocksToMaturity(const CWalletTx &wtx) const
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
OutputType m_default_address_type
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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
WalletFlags set on this wallet.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
int64_t nNextResend
The next scheduled rebroadcast of wallet transactions.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
bool BackupWallet(const std::string &strDest) const
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, const bool rescan_required, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
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::multimap< int64_t, CWalletTx * > TxItems
bool IsLocked() const override
WalletDatabase & GetDatabase() const override
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::atomic< double > m_scanning_progress
bool SetAddressUsed(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetTxDepthInMainChain(const CWalletTx &wtx) const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static std::shared_ptr< CWallet > Create(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool HasEncryptionKeys() const override
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
bool IsAddressUsed(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CAmount 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
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
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::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
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
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, const CCoinControl *coin_control=nullptr) const
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)
const CKeyingMaterial & GetEncryptionKey() const override
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.
void SetTx(CTransactionRef arg)
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
bool isConflicted() const
const uint256 & GetHash() 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
void UpgradeDescriptorCache()
Enables interaction with an external signing device or service, such as a hardware wallet.
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
static ExternalSigner GetExternalSigner()
RecursiveMutex cs_KeyStore
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. Based on type when GetReservedDestination is called.
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.
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool, bilingual_str &error)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
An interface to be implemented by keystores that support signing.
const std::vector< UniValue > & getValues() const
bool push_back(const UniValue &val)
const UniValue & get_array() 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 std::string &strAddress, const std::string &strName)
bool WriteMinVersion(int nVersion)
bool ErasePurpose(const std::string &strAddress)
bool EraseLockedUTXO(const COutPoint &output)
bool WriteWalletFlags(const uint64_t flags)
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
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 WriteBestBlock(const CBlockLocator &locator)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
bool EraseName(const std::string &strAddress)
DBErrors LoadWallet(CWallet *pwallet)
bool WriteLockedUTXO(const COutPoint &output)
virtual void ReloadDbEnv()=0
virtual void Flush()=0
Make sure all changes are flushed to database file.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
virtual void Close()=0
Flush to the database file and close the 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 prepare application code for transition from boost::filesystem library to std::...
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 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 uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height,...
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual bool havePruned()=0
Check if any block has been pruned.
virtual int64_t getAdjustedTime()=0
Get adjusted time.
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual void requestMempoolTransactions(Notifications ¬ifications)=0
Synchronously send transactionAddedToMempool notifications about all current mempool transactions to ...
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
Helper for findBlock to selectively return pieces of block data.
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
const unsigned int WALLET_CRYPTO_SALT_SIZE
const unsigned int WALLET_CRYPTO_KEY_SIZE
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, bilingual_str &error)
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) 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. Do not return it's key to the keypool when this object goes out of scope.
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)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
bool GetReservedDestination(CTxDestination &pubkey, bool internal, bilingual_str &error)
Reserve an address.
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)
Fetch the inputs and sign with SIGHASH_ALL.
void ReturnDestination()
Return reserved address.
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=1, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr) const
Fills out a PSBT with information from the wallet.
bool TopUpKeyPool(unsigned int kpSize=0)
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string > > orderForm)
Submit the transaction to the node's mempool and then relay to peers.
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
int64_t GetOldestKeyPoolTime() const
bool DelAddressBook(const CTxDestination &address)
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, bilingual_str &error)
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool AddWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t returns false if unknown, non-tolerable flags are present
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)
void blockConnected(const CBlock &block, int height) override
void Flush()
Flush wallet (bitdb flush)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const NO_THREAD_SAFETY_ANALYSIS
bool HasWalletSpend(const uint256 &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 MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction (e.g., BIP 125).
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_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...
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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)
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
ScanResult ScanForWalletTransactions(const uint256 &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 DummySignInput(const SigningProvider &provider, CTxIn &tx_in, const CTxOut &txout, bool use_max_sig)
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
bool IsSpent(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
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
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
bool AbandonTransaction(const uint256 &hashTx)
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block=false)
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EncryptWallet(const SecureString &strWalletPassphrase)
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void updatedBlockTip() override
bool SubmitTxMemoryPoolAndRelay(const CWalletTx &wtx, std::string &err_string, bool relay) const
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
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.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
DBErrors ReorderTransactions()
bool IsSpentKey(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockDisconnected(const CBlock &block, int height) override
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
void Close()
Close wallet database.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
void ResendWalletTransactions()
void chainStateFlushed(const CBlockLocator &loc) override
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
std::string EncodeDestination(const CTxDestination &dest)
@ PRIVATE_KEY_NOT_AVAILABLE
std::optional< CAmount > ParseMoney(const std::string &money_string)
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)
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
static unsigned const char sighash[]
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
std::optional< OutputType > ParseOutputType(const std::string &type)
const std::string & FormatOutputType(OutputType type)
static constexpr auto OUTPUT_TYPES
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
void GetStrongRandBytes(unsigned char *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
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, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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 uint8_t > seed)
A mutable version of CTransaction.
std::optional< int > last_scanned_height
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
enum CWallet::ScanResult::@17 status
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
std::optional< DatabaseFormat > require_format
SecureString create_passphrase
std::map< CKeyID, CKey > keys
A version of CTransaction with the PSBT format.
std::vector< PSBTInput > inputs
std::optional< CMutableTransaction > tx
WalletContext struct containing references to state shared between CWallet instances,...
interfaces::Chain * chain
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool error(const char *fmt, const Args &... args)
int64_t GetTimeMillis()
Returns the system time (not mockable)
int64_t GetTime()
DEPRECATED Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
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.
const UniValue & find_value(const UniValue &obj, const std::string &name)
std::string ShellEscape(const std::string &arg)
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
std::map< std::string, std::string > mapValue_t
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
static void ReleaseWallet(CWallet *wallet)
static Mutex g_wallet_release_mutex
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
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
static void RefreshMempoolStatus(CWalletTx &tx, interfaces::Chain &chain)
Refresh mempool status so the wallet is in an internally consistent state and immediately knows the t...
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
static std::condition_variable g_wallet_release_cv
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
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.
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
static Mutex g_loading_wallet_mutex
static std::set< std::string > g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex)
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
static constexpr uint64_t KNOWN_WALLET_FLAGS
static const bool DEFAULT_WALLETBROADCAST
static const bool DEFAULT_WALLET_RBF
-walletrbf default
DBErrors
Error statuses for the wallet database.
fs::path GetWalletDir()
Get the path of the wallet directory.
WalletFeature GetClosestWalletFeature(int version)
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
@ 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_LAST_HARDENED_XPUB_CACHED
@ 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