8 #if defined(HAVE_CONFIG_H)
12 #include <blockfilter.h>
76 #include <condition_variable>
95 if (value.isStr() && value.get_str() == wallet_name)
return true;
104 if (!setting_value.
isArray())
return true;
107 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
109 if (new_value.
size() == setting_value.
size())
return true;
114 const std::string& wallet_name,
115 std::optional<bool> load_on_startup,
116 std::vector<bilingual_str>& warnings)
118 if (!load_on_startup)
return;
120 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
122 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
144 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
145 if (i != context.wallets.end())
return false;
146 context.wallets.push_back(
wallet);
147 wallet->ConnectScriptPubKeyManNotifiers();
148 wallet->NotifyCanGetAddressesChanged();
160 wallet->m_chain_notifications_handler.reset();
162 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
163 if (i == context.wallets.end())
return false;
164 context.wallets.erase(i);
174 std::vector<bilingual_str> warnings;
181 return context.wallets;
187 count = context.wallets.size();
188 return count == 1 ? context.wallets[0] :
nullptr;
194 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
203 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
210 for (
auto& load_wallet : context.wallet_load_fns) {
225 wallet->WalletLogPrintf(
"Releasing wallet\n");
231 if (g_unloading_wallet_set.erase(
name) == 0) {
245 auto it = g_unloading_wallet_set.insert(
name);
257 while (g_unloading_wallet_set.count(
name) == 1) {
264 std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context,
const std::string&
name, std::optional<bool> load_on_start,
const DatabaseOptions& options,
DatabaseStatus& status,
bilingual_str& error, std::vector<bilingual_str>& warnings)
273 context.chain->initMessage(
_(
"Loading wallet…").translated);
274 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), options.create_flags, error, warnings);
283 warnings.push_back(
_(
"Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet."));
288 wallet->postInitProcess();
294 }
catch (
const std::runtime_error& e) {
301 class FastWalletRescanFilter
310 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
311 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
312 assert(desc_spkm !=
nullptr);
313 AddScriptPubKeys(desc_spkm);
315 if (desc_spkm->IsHDEnabled()) {
321 void UpdateIfNeeded()
325 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
326 assert(desc_spkm !=
nullptr);
327 int32_t current_range_end{desc_spkm->GetEndRange()};
328 if (current_range_end > last_range_end) {
329 AddScriptPubKeys(desc_spkm, last_range_end);
335 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const
351 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
353 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
354 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
363 if (!result.second) {
368 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status, error, warnings);
384 if (!passphrase.empty()) {
390 error =
Untranslated(
"Private keys must be disabled when using an external signer");
397 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
404 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.");
419 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), wallet_creation_flags, error, warnings);
428 if (!
wallet->EncryptWallet(passphrase)) {
429 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
435 if (!
wallet->Unlock(passphrase)) {
436 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
445 wallet->SetupDescriptorScriptPubKeyMans();
447 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
448 if (!spk_man->SetupGeneration()) {
449 error =
Untranslated(
"Unable to generate initial keys");
464 wallet->postInitProcess();
471 warnings.push_back(
_(
"Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future."));
485 auto wallet_file = wallet_path /
"wallet.dat";
486 std::shared_ptr<CWallet>
wallet;
501 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
503 wallet =
LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
504 }
catch (
const std::exception& e) {
510 fs::remove_all(wallet_path);
524 const auto it = mapWallet.find(hash);
525 if (it == mapWallet.end())
527 return &(it->second);
541 spk_man->UpgradeKeyMetadata();
565 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
567 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
569 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
571 if (
Unlock(_vMasterKey)) {
595 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
597 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
602 auto start{SteadyClock::now()};
603 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
604 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
606 start = SteadyClock::now();
607 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
608 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
610 if (pMasterKey.second.nDeriveIterations < 25000)
611 pMasterKey.second.nDeriveIterations = 25000;
613 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
615 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
617 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
644 if (nWalletVersion >= nVersion)
647 nWalletVersion = nVersion;
651 if (nWalletVersion > 40000)
660 std::set<uint256> result;
663 const auto it = mapWallet.find(txid);
664 if (it == mapWallet.end())
668 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
670 for (
const CTxIn& txin : wtx.
tx->vin)
672 if (mapTxSpends.count(txin.
prevout) <= 1)
674 range = mapTxSpends.equal_range(txin.
prevout);
675 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
676 result.insert(_it->second);
684 const Txid& txid = tx->GetHash();
685 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
709 int nMinOrderPos = std::numeric_limits<int>::max();
711 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
712 const CWalletTx* wtx = &mapWallet.at(it->second);
724 for (TxSpends::iterator it = range.first; it != range.second; ++it)
726 const uint256& hash = it->second;
728 if (copyFrom == copyTo)
continue;
729 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
748 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
749 range = mapTxSpends.equal_range(outpoint);
751 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
752 const uint256& wtxid = it->second;
753 const auto mit = mapWallet.find(wtxid);
754 if (mit != mapWallet.end()) {
755 const auto& wtx = mit->second;
756 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
765 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
774 std::pair<TxSpends::iterator, TxSpends::iterator> range;
775 range = mapTxSpends.equal_range(outpoint);
785 for (
const CTxIn& txin : wtx.
tx->vin)
806 auto start{SteadyClock::now()};
808 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
810 start = SteadyClock::now();
829 delete encrypted_batch;
830 encrypted_batch =
nullptr;
836 auto spk_man = spk_man_pair.second.get();
837 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
839 delete encrypted_batch;
840 encrypted_batch =
nullptr;
851 delete encrypted_batch;
852 encrypted_batch =
nullptr;
858 delete encrypted_batch;
859 encrypted_batch =
nullptr;
862 Unlock(strWalletPassphrase);
869 if (spk_man->IsHDEnabled()) {
870 if (!spk_man->SetupGeneration(
true)) {
901 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
904 for (
auto& entry : mapWallet)
911 std::vector<int64_t> nOrderPosOffsets;
912 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
919 nOrderPos = nOrderPosNext++;
920 nOrderPosOffsets.push_back(nOrderPos);
927 int64_t nOrderPosOff = 0;
928 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
930 if (nOrderPos >= nOffsetStart)
933 nOrderPos += nOrderPosOff;
934 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
952 int64_t nRet = nOrderPosNext++;
965 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
966 item.second.MarkDirty();
974 auto mi = mapWallet.find(originalHash);
977 assert(mi != mapWallet.end());
1013 tx_destinations.insert(dst);
1033 assert(spk_man !=
nullptr);
1062 std::set<CTxDestination> tx_destinations;
1064 for (
const CTxIn& txin : tx->vin) {
1073 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1075 bool fInsertedNew =
ret.second;
1076 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1090 if (state.index() != wtx.
m_state.index()) {
1102 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1110 std::vector<CWalletTx*> txs{&wtx};
1114 while (!txs.empty()) {
1117 desc_tx->
m_state = inactive_state;
1122 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1124 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1125 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1126 const auto wit = mapWallet.find(it->second);
1127 if (wit != mapWallet.end()) {
1128 txs.push_back(&wit->second);
1139 if (fInsertedNew || fUpdated)
1153 if (!strCmd.empty())
1158 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1172 std::thread
t(runCommand, strCmd);
1182 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1184 if (!fill_wtx(wtx, ins.second)) {
1196 for (
const CTxIn& txin : wtx.
tx->vin) {
1198 if (it != mapWallet.end()) {
1218 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1220 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1221 while (range.first != range.second) {
1222 if (range.first->second != tx.
GetHash()) {
1223 WalletLogPrintf(
"Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.
GetHash().
ToString(), conf->confirmed_block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1224 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1231 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1232 if (fExisted && !fUpdate)
return false;
1244 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1246 if (!dest.internal.has_value()) {
1251 if (!dest.internal.has_value())
continue;
1265 TxState tx_state = std::visit([](
auto&& s) ->
TxState {
return s; }, state);
1270 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1287 for (
const CTxIn& txin : tx->vin) {
1289 if (it != mapWallet.end()) {
1290 it->second.MarkDirty();
1300 auto it = mapWallet.find(hashTx);
1301 assert(it != mapWallet.end());
1309 assert(!wtx.isConfirmed());
1310 assert(!wtx.InMempool());
1312 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1338 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1341 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1342 if (conflictconfirms >= 0)
1363 RecursiveUpdateTxState(&batch, tx_hash, try_updating_state);
1367 std::set<uint256> todo;
1368 std::set<uint256> done;
1370 todo.insert(tx_hash);
1372 while (!todo.empty()) {
1376 auto it = mapWallet.find(now);
1377 assert(it != mapWallet.end());
1380 TxUpdate update_state = try_updating_state(wtx);
1381 if (update_state != TxUpdate::UNCHANGED) {
1383 if (batch) batch->WriteTx(wtx);
1385 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); ++i) {
1386 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(
Txid::FromUint256(now), i));
1387 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1388 if (!done.count(iter->second)) {
1389 todo.insert(iter->second);
1394 if (update_state == TxUpdate::NOTIFY_CHANGED) {
1400 MarkInputsDirty(wtx.
tx);
1420 auto it = mapWallet.find(tx->GetHash());
1421 if (it != mapWallet.end()) {
1425 const Txid& txid = tx->GetHash();
1427 for (
const CTxIn& tx_in : tx->vin) {
1429 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1430 const uint256& spent_id = range.first->second;
1432 if (spent_id == txid)
continue;
1442 auto it = mapWallet.find(tx->GetHash());
1443 if (it != mapWallet.end()) {
1476 const Txid& txid = tx->GetHash();
1478 for (
const CTxIn& tx_in : tx->vin) {
1482 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1483 const uint256& spent_id = range.first->second;
1500 m_last_block_processed_height = block.
height;
1501 m_last_block_processed = block.
hash;
1508 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1523 m_last_block_processed_height = block.
height - 1;
1526 int disconnect_height = block.
height;
1531 for (
const CTxIn& tx_in : ptx->vin) {
1533 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1535 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1538 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1539 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1543 auto try_updating_state = [&](
CWalletTx& tx) {
1563 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1579 const auto mi = mapWallet.find(txin.
prevout.
hash);
1580 if (mi != mapWallet.end())
1611 for (
const auto& spkm : it->second) {
1612 res = std::max(res, spkm->IsMine(script));
1640 if (outpoint.
n >= wtx->tx->vout.size()) {
1643 return IsMine(wtx->tx->vout[outpoint.
n]);
1658 throw std::runtime_error(std::string(__func__) +
": value out of range");
1666 bool result =
false;
1668 if (!spk_man->IsHDEnabled())
return false;
1680 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1687 void CWallet::SetWalletFlag(uint64_t
flags)
1692 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1706 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1741 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1753 LOCK(spk_man->cs_KeyStore);
1754 return spk_man->ImportScripts(scripts, timestamp);
1763 LOCK(spk_man->cs_KeyStore);
1764 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1767 bool 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)
1773 LOCK(spk_man->cs_KeyStore);
1774 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1777 bool 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)
1783 LOCK(spk_man->cs_KeyStore);
1784 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1789 for (
const CScript& script : script_pub_keys) {
1803 if (time < birthtime) {
1821 int start_height = 0;
1862 constexpr
auto INTERVAL_TIME{60s};
1863 auto current_time{reserver.
now()};
1864 auto start_time{reserver.
now()};
1868 uint256 block_hash = start_block;
1871 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1875 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1884 double progress_current = progress_begin;
1885 int block_height = start_height;
1887 if (progress_end - progress_begin > 0.0) {
1888 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1892 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1896 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1897 if (next_interval) {
1898 current_time = reserver.
now();
1899 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1902 bool fetch_block{
true};
1903 if (fast_rescan_filter) {
1904 fast_rescan_filter->UpdateIfNeeded();
1905 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1906 if (matches_block.has_value()) {
1907 if (*matches_block) {
1912 fetch_block =
false;
1915 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.
ToString());
1921 bool block_still_active =
false;
1922 bool next_block =
false;
1933 if (!block_still_active) {
1940 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1947 if (save_progress && next_interval) {
1962 if (max_height && block_height >= *max_height) {
1973 block_hash = next_block_hash;
1978 const uint256 prev_tip_hash = tip_hash;
1980 if (!max_height && prev_tip_hash != tip_hash) {
1992 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1994 }
else if (block_height &&
chain().shutdownRequested()) {
1995 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1998 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
2039 result.erase(myHash);
2051 if (!
chain().isReadyToBroadcast())
return false;
2092 int submitted_tx_count = 0;
2099 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2100 for (
auto& [txid, wtx] : mapWallet) {
2102 if (!wtx.isUnconfirmed())
continue;
2107 to_submit.insert(&wtx);
2110 for (
auto wtx : to_submit) {
2111 std::string unused_err_string;
2116 if (submitted_tx_count > 0) {
2117 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2125 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2126 if (!pwallet->ShouldResend())
continue;
2127 pwallet->ResubmitWalletTransactions(
true,
false);
2128 pwallet->SetNextResend();
2143 std::map<COutPoint, Coin> coins;
2144 for (
auto& input : tx.
vin) {
2145 const auto mi = mapWallet.find(input.prevout.hash);
2146 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2151 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2153 std::map<int, bilingual_str> input_errors;
2163 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2179 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2180 const CTxIn& txin = psbtx.
tx->vin[i];
2190 const auto it = mapWallet.find(txhash);
2191 if (it != mapWallet.end()) {
2204 int n_signed_this_spkm = 0;
2205 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize);
2211 (*n_signed) += n_signed_this_spkm;
2219 for (
const auto& input : psbtx.
inputs) {
2231 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2233 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2243 return *change_type;
2252 bool any_wpkh{
false};
2254 bool any_pkh{
false};
2256 for (
const auto& recipient : vecSend) {
2257 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2259 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2261 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2263 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2269 if (has_bech32m_spkman && any_tr) {
2274 if (has_bech32_spkman && any_wpkh) {
2279 if (has_p2sh_segwit_spkman && any_sh) {
2285 if (has_legacy_spkman && any_pkh) {
2290 if (has_bech32m_spkman) {
2293 if (has_bech32_spkman) {
2310 wtx.
mapValue = std::move(mapValue);
2319 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2323 for (
const CTxIn& txin : tx->vin) {
2334 std::string err_string;
2336 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2353 spk_man_pair.second->RewriteDB();
2363 return nLoadWalletRet;
2370 if (!batch.
TxnBegin())
return util::Error{
_(
"Error starting db txn for wallet transactions removal")};
2373 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2374 std::vector<TxIterator> erased_txs;
2376 for (
const uint256& hash : txs_to_remove) {
2377 auto it_wtx = mapWallet.find(hash);
2378 if (it_wtx == mapWallet.end()) {
2379 str_err =
strprintf(
_(
"Transaction %s does not belong to this wallet"), hash.GetHex());
2383 str_err =
strprintf(
_(
"Failure removing transaction: %s"), hash.GetHex());
2386 erased_txs.emplace_back(it_wtx);
2390 if (!str_err.
empty()) {
2396 if (!batch.
TxnCommit())
return util::Error{
_(
"Error committing db txn for wallet transactions removal")};
2399 for (
const auto& it : erased_txs) {
2400 const uint256 hash{it->first};
2401 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2402 for (
const auto& txin : it->second.tx->vin)
2403 mapTxSpends.erase(txin.prevout);
2404 mapWallet.erase(it);
2415 bool fUpdated =
false;
2417 std::optional<AddressPurpose> purpose;
2420 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2421 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2423 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2434 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2437 if (!batch.
WriteName(encoded_dest, strName)) {
2493 m_address_book.erase(address);
2506 if (legacy_spk_man) {
2507 return legacy_spk_man->KeypoolCountExternalKeys();
2510 unsigned int count = 0;
2512 count += spk_man.second->GetKeyPoolSize();
2522 unsigned int count = 0;
2524 count += spk_man->GetKeyPoolSize();
2534 res &= spk_man->TopUp(kpSize);
2547 auto op_dest = spk_man->GetNewDestination(type);
2570 return std::nullopt;
2573 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2575 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2581 for (
auto& entry : mapWallet) {
2584 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2597 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2598 const auto& entry = item.second;
2599 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2606 std::vector<CTxDestination> result;
2614 result.emplace_back(dest);
2622 std::set<std::string> label_set;
2624 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2625 if (_is_change)
return;
2626 if (!purpose || purpose == _purpose) {
2627 label_set.insert(_label);
2644 if (!op_address)
return op_address;
2675 if (signer_spk_man ==
nullptr) {
2679 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2687 setLockedCoins.insert(output);
2697 bool was_locked = setLockedCoins.erase(output);
2698 if (batch && was_locked) {
2707 bool success =
true;
2709 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2712 setLockedCoins.clear();
2719 return setLockedCoins.count(output) > 0;
2725 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2726 it != setLockedCoins.end(); it++) {
2728 vOutpts.push_back(outpt);
2736 mapKeyBirth.clear();
2739 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2746 assert(spk_man !=
nullptr);
2750 for (
const auto& entry : spk_man->mapKeyMetadata) {
2751 if (entry.second.nCreateTime) {
2752 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2758 if (mapKeyBirth.count(keyid) == 0)
2759 mapKeyFirstBlock[keyid] = &max_confirm;
2763 if (mapKeyFirstBlock.empty())
2767 for (
const auto& entry : mapWallet) {
2772 for (
const CTxOut &txout : wtx.
tx->vout) {
2776 auto rit = mapKeyFirstBlock.find(keyid);
2777 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2787 for (
const auto& entry : mapKeyFirstBlock) {
2819 std::optional<uint256> block_hash;
2821 block_hash = conf->confirmed_block_hash;
2823 block_hash = conf->conflicting_block_hash;
2829 int64_t block_max_time;
2830 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2831 if (rescanning_old_block) {
2832 nTimeSmart = block_max_time;
2835 int64_t latestEntry = 0;
2838 int64_t latestTolerated = latestNow + 300;
2840 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2850 if (nSmartTime <= latestTolerated) {
2851 latestEntry = nSmartTime;
2852 if (nSmartTime > latestNow) {
2853 latestNow = nSmartTime;
2859 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2870 if (std::get_if<CNoDestination>(&dest))
2874 if (
auto* data{
common::FindKey(m_address_book, dest)}) data->previously_spent =
false;
2884 m_address_book[dest].previously_spent =
true;
2889 m_address_book[dest].receive_requests[id] = request;
2894 if (
auto* data{
common::FindKey(m_address_book, dest)})
return data->previously_spent;
2900 std::vector<std::string>
values;
2901 for (
const auto& [dest, entry] : m_address_book) {
2902 for (
const auto& [
id, request] : entry.receive_requests) {
2903 values.emplace_back(request);
2912 m_address_book[dest].receive_requests[id] = value;
2919 m_address_book[dest].receive_requests.erase(
id);
2932 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2933 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2934 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2937 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2938 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2939 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2944 return MakeDatabase(wallet_path, options, status, error_string);
2951 const std::string& walletFile = database->Filename();
2953 const auto start{SteadyClock::now()};
2958 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
2961 bool rescan_required =
false;
2962 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2965 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2970 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
2971 " or address metadata may be missing or incorrect."),
2979 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2987 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect."
2988 " Rescanning wallet."), walletFile));
2989 rescan_required =
true;
2991 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n"
2992 "The wallet might had been created on a newer version.\n"
2993 "Please try running the latest software version.\n"), walletFile);
2996 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
2997 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3000 error =
strprintf(
_(
"Error loading %s"), walletFile);
3006 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3014 walletInstance->InitWalletFlags(wallet_creation_flags);
3018 walletInstance->SetupLegacyScriptPubKeyMan();
3022 LOCK(walletInstance->cs_wallet);
3024 walletInstance->SetupDescriptorScriptPubKeyMans();
3028 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3029 if (!spk_man->SetupGeneration()) {
3030 error =
_(
"Unable to generate initial keys");
3042 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3045 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3046 if (spk_man->HavePrivateKeys()) {
3047 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3053 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
3059 walletInstance->m_default_address_type = parsed.value();
3062 if (!
args.
GetArg(
"-changetype",
"").empty()) {
3068 walletInstance->m_default_change_type = parsed.value();
3078 _(
"This is the minimum transaction fee you pay on every transaction."));
3081 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
3085 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
3086 if (max_aps_fee ==
"-1") {
3087 walletInstance->m_max_aps_fee = -1;
3088 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
3091 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3093 walletInstance->m_max_aps_fee = max_fee.value();
3102 if (!fallback_fee) {
3103 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-fallbackfee",
args.
GetArg(
"-fallbackfee",
""));
3107 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3109 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3113 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3118 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-discardfee",
args.
GetArg(
"-discardfee",
""));
3122 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3124 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3134 _(
"This is the transaction fee you will pay if you send a transaction."));
3137 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3140 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3152 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3156 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3161 walletInstance->m_default_max_tx_fee = max_fee.value();
3165 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3166 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3175 _(
"The wallet will avoid paying less than the minimum relay fee."));
3182 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3185 walletInstance->TopUpKeyPool();
3188 std::optional<int64_t> time_first_key;
3189 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3190 int64_t time = spk_man->GetTimeFirstKey();
3191 if (!time_first_key || time < *time_first_key) time_first_key = time;
3193 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3196 walletInstance->m_chain_notifications_handler.reset();
3201 LOCK(walletInstance->cs_wallet);
3203 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3204 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3205 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3208 return walletInstance;
3213 LOCK(walletInstance->cs_wallet);
3215 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3216 walletInstance->m_chain = &
chain;
3226 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3242 walletInstance->m_attaching_chain =
true;
3243 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3246 int rescan_height = 0;
3247 if (!rescan_required)
3253 rescan_height = *fork_height;
3261 walletInstance->m_last_block_processed_height = *tip_height;
3263 walletInstance->m_last_block_processed.
SetNull();
3264 walletInstance->m_last_block_processed_height = -1;
3267 if (tip_height && *tip_height != rescan_height)
3271 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3272 if (time_first_key) {
3279 rescan_height = *tip_height;
3287 int block_height = *tip_height;
3288 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3292 if (rescan_height != block_height) {
3303 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3305 "Error loading wallet. Wallet requires blocks to be downloaded, "
3306 "and software does not currently support loading wallets while "
3307 "blocks are being downloaded out of order when using assumeutxo "
3308 "snapshots. Wallet should be able to load successfully after "
3309 "node sync reaches height %s"), block_height);
3315 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3320 error =
_(
"Failed to rescan the wallet during initialization");
3324 walletInstance->m_attaching_chain =
false;
3326 walletInstance->GetDatabase().IncrementUpdateCounter();
3328 walletInstance->m_attaching_chain =
false;
3335 const auto& address_book_it = m_address_book.find(dest);
3336 if (address_book_it == m_address_book.end())
return nullptr;
3337 if ((!allow_change) && address_book_it->second.IsChange()) {
3340 return &address_book_it->second;
3352 if (version < prev_version) {
3353 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3361 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);
3369 if (!spk_man->Upgrade(prev_version, version, error)) {
3410 assert(conf->confirmed_block_height >= 0);
3413 assert(conf->conflicting_block_height >= 0);
3428 assert(chain_depth >= 0);
3451 return vMasterKey.empty();
3461 if (!vMasterKey.empty()) {
3462 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3476 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3480 vMasterKey = vMasterKeyIn;
3488 std::set<ScriptPubKeyMan*> spk_mans;
3489 for (
bool internal : {
false,
true}) {
3493 spk_mans.insert(spk_man);
3503 if (ext_spkm == &spkm)
return true;
3506 if (int_spkm == &spkm)
return true;
3513 std::set<ScriptPubKeyMan*> spk_mans;
3515 spk_mans.insert(spk_man_pair.second.get());
3523 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3524 if (it == spk_managers.end()) {
3532 std::set<ScriptPubKeyMan*> spk_mans;
3537 spk_mans.insert(it->second.begin(), it->second.end());
3540 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](
ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3568 Assume(it->second.at(0)->CanProvide(script, sigdata));
3569 return it->second.at(0)->GetSolvingProvider(script);
3580 std::vector<WalletDescriptor> descs;
3583 LOCK(desc_spk_man->cs_desc_man);
3584 descs.push_back(desc_spk_man->GetWalletDescriptor());
3629 uint256 id = spk_manager->GetID();
3636 return cb(vMasterKey);
3662 return *spk_manager;
3671 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3673 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3674 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3677 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type,
internal);
3679 uint256 id = spk_manager->GetID();
3691 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors setup");
3693 for (
bool internal : {
false,
true}) {
3700 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors setup");
3725 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3728 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3730 for (
bool internal : {
false,
true}) {
3731 const UniValue& descriptor_vals = signer_res.
find_value(
internal ?
"internal" :
"receive");
3732 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3734 const std::string& desc_str = desc_val.getValStr();
3736 std::string desc_error;
3737 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, desc_error,
false);
3738 if (desc ==
nullptr) {
3739 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3741 if (!desc->GetOutputType()) {
3746 spk_manager->SetupDescriptor(batch, std::move(desc));
3747 uint256 id = spk_manager->GetID();
3754 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3767 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3782 spk_mans[type] = spk_man;
3784 const auto it = spk_mans_other.find(type);
3785 if (it != spk_mans_other.end() && it->second == spk_man) {
3786 spk_mans_other.erase(type);
3795 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3799 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3803 spk_mans.erase(type);
3815 return spk_man !=
nullptr;
3835 return std::nullopt;
3840 return std::nullopt;
3844 if (!desc_spk_man) {
3845 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3848 LOCK(desc_spk_man->cs_desc_man);
3849 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3850 assert(type.has_value());
3860 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3867 spk_man->UpdateWalletDescriptor(desc);
3870 spk_man = new_spk_man.get();
3873 uint256 id = new_spk_man->GetID();
3878 for (
const auto& entry : signing_provider.
keys) {
3879 const CKey& key = entry.second;
3880 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3884 if (!spk_man->TopUp()) {
3892 auto script_pub_keys = spk_man->GetScriptPubKeys();
3893 if (script_pub_keys.empty()) {
3894 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3899 for (
const auto& script : script_pub_keys) {
3909 spk_man->WriteDescriptor();
3918 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3921 error =
_(
"Error: This wallet already uses SQLite");
3926 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3927 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3928 std::vector<std::pair<SerializeData, SerializeData>> records;
3930 error =
_(
"Error: Unable to begin reading all records in the database");
3937 status = cursor->Next(ss_key, ss_value);
3943 records.emplace_back(key, value);
3948 error =
_(
"Error: Unable to read all records in the database");
3955 fs::remove(db_path);
3966 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status, error);
3973 bool began = batch->TxnBegin();
3975 for (
const auto& [key, value] : records) {
3976 if (!batch->Write(
Span{key},
Span{value})) {
3983 bool committed = batch->TxnCommit();
3993 if (!
Assume(legacy_spkm)) {
3996 return std::nullopt;
4000 if (res == std::nullopt) {
4001 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4002 return std::nullopt;
4012 if (!
Assume(legacy_spkm)) {
4019 std::set<CTxDestination> not_migrated_dests;
4029 error =
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
4032 uint256 id = desc_spkm->GetID();
4061 error =
_(
"Error: Unable to read wallet's best block locator record");
4067 std::vector<uint256> txids_to_delete;
4068 std::unique_ptr<WalletBatch> watchonly_batch;
4070 watchonly_batch = std::make_unique<WalletBatch>(data.
watchonly_wallet->GetDatabase());
4076 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4077 error =
_(
"Error: Unable to write watchonly wallet best block locator record");
4084 error =
_(
"Error: Unable to write solvable wallet best block locator record");
4096 const uint256& hash = wtx->GetHash();
4099 if (!new_tx) return false;
4100 ins_wtx.SetTx(to_copy_wtx.tx);
4101 ins_wtx.CopyFrom(to_copy_wtx);
4104 error =
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex());
4110 txids_to_delete.push_back(hash);
4117 error =
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
4121 watchonly_batch.reset();
4123 if (txids_to_delete.size() > 0) {
4124 if (
auto res =
RemoveTxs(txids_to_delete); !res) {
4125 error =
_(
"Error: Could not delete watchonly transactions. ") +
util::ErrorString(res);
4131 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4133 if (!ext_wallet)
continue;
4135 std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
4136 if (!batch->TxnBegin()) {
4137 error =
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
4140 wallets_vec.emplace_back(ext_wallet, std::move(batch));
4147 if (entry.label) batch.
WriteName(address, *entry.label);
4148 for (
const auto& [
id, request] : entry.receive_requests) {
4155 std::vector<CTxDestination> dests_to_delete;
4156 for (
const auto& [dest, record] : m_address_book) {
4160 bool copied =
false;
4161 for (
auto& [
wallet, batch] : wallets_vec) {
4163 if (require_transfer && !
wallet->IsMine(dest))
continue;
4166 wallet->m_address_book[dest] = record;
4167 func_store_addr(*batch, dest, record);
4171 if (require_transfer) {
4172 dests_to_delete.push_back(dest);
4180 if (require_transfer && !copied) {
4183 if (not_migrated_dests.count(dest) > 0) {
4184 dests_to_delete.push_back(dest);
4188 error =
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets");
4194 for (
auto& [
wallet, batch] : wallets_vec) {
4196 error =
strprintf(
_(
"Error: address book copy failed for wallet %s"),
wallet->GetName());
4204 if (dests_to_delete.size() > 0) {
4205 for (
const auto& dest : dests_to_delete) {
4207 error =
_(
"Error: Unable to remove watchonly address book data");
4233 std::optional<MigrationData> data =
wallet.GetDescriptorsForLegacy(error);
4234 if (data == std::nullopt)
return false;
4237 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4244 empty_context.
args = context.args;
4254 if (data->watch_descs.size() > 0) {
4255 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4258 std::vector<bilingual_str> warnings;
4259 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4260 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4262 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4267 if (!data->watchonly_wallet) {
4268 error =
_(
"Error: Failed to create new watchonly wallet");
4271 res.watchonly_wallet = data->watchonly_wallet;
4272 LOCK(data->watchonly_wallet->cs_wallet);
4275 for (
const auto& [desc_str, creation_time] : data->watch_descs) {
4278 std::string parse_err;
4279 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4281 assert(!desc->IsRange());
4285 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4291 if (data->solvable_descs.size() > 0) {
4292 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4295 std::vector<bilingual_str> warnings;
4296 std::string wallet_name =
wallet.GetName() +
"_solvables";
4297 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4299 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4304 if (!data->solvable_wallet) {
4305 error =
_(
"Error: Failed to create new watchonly wallet");
4308 res.solvables_wallet = data->solvable_wallet;
4309 LOCK(data->solvable_wallet->cs_wallet);
4312 for (
const auto& [desc_str, creation_time] : data->solvable_descs) {
4315 std::string parse_err;
4316 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4318 assert(!desc->IsRange());
4322 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4331 if (!
wallet.ApplyMigrationData(*data, error)) {
4341 std::vector<bilingual_str> warnings;
4344 bool was_loaded =
false;
4347 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4360 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4366 std::shared_ptr<CWallet> local_wallet =
CWallet::Create(empty_context, wallet_name, std::move(database), options.
create_flags, error, warnings);
4367 if (!local_wallet) {
4372 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4373 assert(to_reload.use_count() == 1);
4374 std::string
name = to_reload->GetName();
4376 to_reload =
LoadWallet(context,
name, std::nullopt, options, status, error, warnings);
4377 return to_reload !=
nullptr;
4383 reload_wallet(local_wallet);
4385 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4391 fs::path backup_path = this_wallet_dir / backup_filename;
4394 reload_wallet(local_wallet);
4396 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4400 bool success =
false;
4403 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4405 reload_wallet(local_wallet);
4407 if (passphrase.find(
'\0') == std::string::npos) {
4408 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4410 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4411 "The passphrase contains a null character (ie - a zero byte). "
4412 "If this passphrase was set with a version of this software prior to 25.0, "
4413 "please try again with only the characters up to — but not including — "
4414 "the first null character.")};
4419 LOCK(local_wallet->cs_wallet);
4421 if (!local_wallet->MigrateToSQLite(error))
return util::Error{error};
4426 success =
DoMigration(*local_wallet, context, error, res);
4437 std::set<fs::path> wallet_dirs;
4441 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4442 success = reload_wallet(local_wallet);
4443 res.
wallet = local_wallet;
4460 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4463 std::vector<std::shared_ptr<CWallet>> created_wallets;
4464 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4469 for (std::shared_ptr<CWallet>& w : created_wallets) {
4474 for (std::shared_ptr<CWallet>& w : created_wallets) {
4475 if (w->HaveChain()) {
4478 error +=
_(
"\nUnable to cleanup failed migration");
4484 assert(w.use_count() == 1);
4490 for (
const fs::path& dir : wallet_dirs) {
4491 fs::remove_all(dir);
4496 std::vector<bilingual_str> warnings;
4497 if (!
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status, error, warnings)) {
4498 error +=
_(
"\nUnable to restore backup of wallet.");
4503 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4504 fs::remove(temp_backup_location);
4513 for (
const auto& script : spks) {
4530 std::set<CExtPubKey> active_xpubs;
4537 std::set<CPubKey> desc_pubkeys;
4538 std::set<CExtPubKey> desc_xpubs;
4539 w_desc.
descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4540 active_xpubs.merge(std::move(desc_xpubs));
4542 return active_xpubs;
4553 if (std::optional<CKey> key = desc_spkm->
GetKey(keyid)) {
4557 return std::nullopt;
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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)
Identity function.
#define Assert(val)
Identity function.
#define STR_INTERNAL_BUG(msg)
#define Assume(val)
Assume is the 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
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
An encapsulated private key.
bool IsValid() const
Check whether this private key is valid.
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.
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 Txid & GetHash() const LIFETIMEBOUND
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An input of a transaction.
An output of a transaction.
Double ended buffer combining vector and stream-like interfaces.
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.
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
RecursiveMutex cs_KeyStore
std::unordered_set< Element, ByteVectorHash > ElementSet
Different type to mark Mutex at global scope.
A Span is an object that can refer to a contiguous sequence of objects.
void push_back(UniValue val)
const UniValue & find_value(std::string_view key) const
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
std::string ToString() const
constexpr unsigned char * begin()
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 CBlockLocator getActiveChainLocator(const uint256 &block_hash)=0
Return a locator that refers to a block in the active chain.
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height,...
virtual bool havePruned()=0
Check if any block has been pruned.
virtual common::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual 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 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 bool updateRwSetting(const std::string &name, const common::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
Helper for findBlock to selectively return pieces of block data.
FoundBlock & height(int &height)
std::string ToString() const
static transaction_identifier FromUint256(const uint256 &id)
Encryption/decryption context with key information.
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
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)
A key from a CWallet's keypool.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
CPubKey vchPubKey
The public key.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
std::vector< unsigned char > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
std::vector< unsigned char > vchCryptedKey
unsigned int nDeriveIterations
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
std::atomic< bool > fAbortRescan
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
bool HaveChain() const
Interface to assert chain access.
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool IsActiveScriptPubKeyMan(const ScriptPubKeyMan &spkm) const
OutputType m_default_address_type
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
std::function< void(const CTxDestination &dest, const std::string &label, bool is_change, const std::optional< AddressPurpose > purpose)> ListAddrBookFunc
Walk-through the address book entries.
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
void TopUpCallback(const std::set< CScript > &spks, ScriptPubKeyMan *spkm) override
Callback function for after TopUp completes containing any scripts that were added by a SPKMan.
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
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...
unsigned int nMasterKeyMaxID
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
std::atomic< double > m_scanning_progress
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
WalletDatabase & GetDatabase() const override
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
bool IsLegacy() const
Determine if we are a legacy wallet.
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
bool Unlock(const CKeyingMaterial &vMasterKeyIn)
bool MigrateToSQLite(bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Move all records from the BDB database to a new SQLite database for storage.
bool BackupWallet(const std::string &strDest) const
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
std::string m_name
Wallet name: relative directory name or "" for default wallet.
bool SetAddressPreviouslySpent(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
RecursiveMutex m_relock_mutex
std::string m_notify_tx_changed_script
Notify external script when a wallet transaction comes in or is updated (handled by -walletnotify)
std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
std::atomic< bool > m_attaching_chain
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
void CacheNewScriptPubKeys(const std::set< CScript > &spks, ScriptPubKeyMan *spkm)
Add scriptPubKeys for this ScriptPubKeyMan into the scriptPubKey cache.
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool HasEncryptionKeys() const override
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)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
bool CanGrindR() const
Whether the (external) signer performs R-value signature grinding.
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
MasterKeyMap mapMasterKeys
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
std::optional< CKey > GetKey(const CKeyID &keyid) const
Find the private key for the given key id from the wallet's descriptors, if available Returns nullopt...
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
void LoadAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &request) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Appends payment request to destination.
void AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
interfaces::Chain * m_chain
Interface for accessing chain state.
std::set< CExtPubKey > GetActiveHDPubKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve the xpubs in use by the active descriptors.
bool IsLocked() const override
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
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.
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Pass the encryption key to cb().
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process,...
RecursiveMutex cs_wallet
Main wallet lock.
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
std::atomic< int64_t > m_best_block_time
std::unordered_map< CScript, std::vector< ScriptPubKeyMan * >, SaltedSipHasher > m_cached_spks
Cache of descriptor ScriptPubKeys used for IsMine. Maps ScriptPubKey to set of spkms.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
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...
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, AddressPurpose purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
std::multimap< int64_t, CWalletTx * > TxItems
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
DescriptorScriptPubKeyMan & SetupDescriptorScriptPubKeyMan(WalletBatch &batch, const CExtKey &master_key, const OutputType &output_type, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMan and add it to the wallet.
bool ApplyMigrationData(MigrationData &data, bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan,...
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
std::function< TxUpdate(CWalletTx &wtx)> TryUpdatingStateFn
std::atomic< int64_t > m_birth_time
void LoadAddressPreviouslySpent(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks destination as previously spent.
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
interfaces::Chain & chain() const
Interface for accessing chain state.
A transaction with a bunch of additional info that only the owner cares about.
bool isBlockConflicted() const
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
std::vector< std::pair< std::string, std::string > > vOrderForm
const Txid & GetHash() const LIFETIMEBOUND
std::set< Txid > mempool_conflicts
mapValue_t mapValue
Key/value map with information about the transaction.
void updateState(interfaces::Chain &chain)
Update transaction state when attaching to a chain, filling in heights of conflicted and confirmed bl...
int64_t nOrderPos
position in ordered transaction list
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
unsigned int nTimeReceived
time received by this node
void SetTx(CTransactionRef arg)
unsigned int fTimeReceivedIsTxTime
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
int64_t GetTxTime() const
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
void MarkDirty()
make sure balances are recalculated
void UpgradeDescriptorCache()
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
std::optional< CKey > GetKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet,...
bool HasWalletDescriptor(const WalletDescriptor &desc) const
RecursiveMutex cs_desc_man
static ExternalSigner GetExternalSigner()
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
uint256 GetID() const override
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid,...
std::set< CKeyID > GetKeys() const override
isminetype IsMine(const CScript &script) const override
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
A wrapper to reserve an address from a wallet.
const CWallet *const pwallet
The wallet to reserve from.
CTxDestination address
The destination.
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.
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
virtual util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool)
Access to the wallet database.
bool TxnAbort()
Abort current transaction.
bool EraseName(const std::string &strAddress)
DBErrors LoadWallet(CWallet *pwallet)
bool WriteBestBlock(const CBlockLocator &locator)
bool ReadBestBlock(CBlockLocator &locator)
bool EraseTx(uint256 hash)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteMinVersion(int nVersion)
bool TxnBegin()
Begin a new transaction.
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool WriteWalletFlags(const uint64_t flags)
bool EraseAddressData(const CTxDestination &dest)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool WriteTx(const CWalletTx &wtx)
bool ErasePurpose(const std::string &strAddress)
bool EraseLockedUTXO(const COutPoint &output)
bool WriteLockedUTXO(const COutPoint &output)
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
virtual void ReloadDbEnv()=0
virtual void Close()=0
Flush to the database file and close the database.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
virtual void Flush()=0
Make sure all changes are flushed to database file.
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
Clock::time_point now() const
bool reserve(bool with_passphrase=false)
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
std::string ShellEscape(const std::string &arg)
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
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 ...
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
bool TopUpKeyPool(unsigned int kpSize=0)
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
void ReturnDestination()
Return reserved address.
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
util::Result< void > RemoveTxs(std::vector< uint256 > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::optional< int64_t > GetOldestKeyPoolTime() const
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
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::optional< AddressPurpose > &strPurpose)
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
std::set< std::string > ListAddrBookLabels(const std::optional< AddressPurpose > purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DelAddressBook(const CTxDestination &address)
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
bool HasWalletSpend(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet.
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_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)
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 updatedBlockTip() override
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockConnected(ChainstateRole role, const interfaces::BlockInfo &block) override
void MaybeUpdateBirthTime(int64_t time)
Updates wallet birth time if 'time' is below it.
void Flush()
Flush wallet (bitdb flush)
void blockDisconnected(const interfaces::BlockInfo &block) override
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
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 UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void ResubmitWalletTransactions(bool relay, bool force)
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void RecursiveUpdateTxState(const uint256 &tx_hash, const TryUpdatingStateFn &try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction (and its in-wallet descendants) as a particular tx state.
bool CanGetAddresses(bool internal=false) const
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate, const bool save_progress)
Scan the block chain (starting in start_block) for transactions from or to us.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
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 transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
static NodeClock::time_point GetDefaultNextResend()
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool AbandonTransaction(const uint256 &hashTx)
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
bool EncryptWallet(const SecureString &strWalletPassphrase)
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
DBErrors ReorderTransactions()
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, const SyncTxState &state, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx) override
void Close()
Close wallet database.
bool SubmitTxMemoryPoolAndRelay(CWalletTx &wtx, std::string &err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
CKey GenerateRandomKey(bool compressed) noexcept
std::string EncodeDestination(const CTxDestination &dest)
#define LogPrint(category,...)
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.
@ PRIVATE_KEY_NOT_AVAILABLE
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
static path absolute(const path &p)
static path u8path(const std::string &utf8_str)
static auto quoted(const std::string &s)
static bool exists(const path &p)
static bool copy_file(const path &from, const path &to, copy_options options)
static std::string PathToString(const path &path)
Convert path object to a 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< Handler > MakeCleanupHandler(std::function< void()> cleanup)
Return handler wrapping a cleanup function.
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
bilingual_str ErrorString(const Result< T > &result)
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
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)
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
std::map< std::string, std::string > mapValue_t
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
DBErrors
Error statuses for the wallet database.
@ UNEXPECTED_LEGACY_ENTRY
@ EXTERNAL_SIGNER_SUPPORT_REQUIRED
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
static GlobalMutex g_wallet_release_mutex
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
const unsigned int WALLET_CRYPTO_KEY_SIZE
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...
static std::set< std::string > g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex)
static const bool DEFAULT_WALLETCROSSCHAIN
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
fs::path GetWalletDir()
Get the path of the wallet directory.
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
static void ReleaseWallet(CWallet *wallet)
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
static const bool DEFAULT_WALLET_RBF
-walletrbf default
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
static std::condition_variable g_wallet_release_cv
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
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
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
std::string PurposeToString(AddressPurpose p)
static const bool DEFAULT_WALLETBROADCAST
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
bool DoMigration(CWallet &wallet, WalletContext &context, bilingual_str &error, MigrationResult &res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
WalletFeature
(client) version numbers for particular wallet features
@ FEATURE_PRE_SPLIT_KEYPOOL
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
static constexpr uint64_t KNOWN_WALLET_FLAGS
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_loading_wallet_mutex
const unsigned int WALLET_CRYPTO_SALT_SIZE
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)
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
@ WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
@ WALLET_FLAG_KEY_ORIGIN_METADATA
@ WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
WalletFeature GetClosestWalletFeature(int version)
@ FAILED_INVALID_BACKUP_FILE
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
std::shared_ptr< CWallet > wallet
const std::string & FormatOutputType(OutputType type)
std::optional< OutputType > ParseOutputType(const std::string &type)
static constexpr auto OUTPUT_TYPES
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
void RemoveUnnecessaryTransactions(PartiallySignedTransaction &psbtx, const int &sighash_type)
Reduces the size of the PSBT by dropping unnecessary non_witness_utxos (i.e.
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
void GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
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...
std::vector< uint256 > vHave
void SetSeed(Span< const std::byte > seed)
A mutable version of CTransaction.
std::map< CKeyID, CKey > keys
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
A version of CTransaction with the PSBT format.
std::vector< PSBTInput > inputs
std::optional< CMutableTransaction > tx
Block data sent with blockConnected, blockDisconnected notifications.
const uint256 * prev_hash
unsigned int chain_time_max
std::optional< AddressPurpose > purpose
Address purpose which was originally recorded for payment protocol support but now serves as a cached...
void SetLabel(std::string name)
std::optional< std::string > m_op_label
std::optional< int > last_scanned_height
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
enum wallet::CWallet::ScanResult::@18 status
SecureString create_passphrase
std::optional< DatabaseFormat > require_format
struct containing information needed for migrating legacy wallets to descriptor wallets
std::vector< std::unique_ptr< DescriptorScriptPubKeyMan > > desc_spkms
std::shared_ptr< CWallet > watchonly_wallet
std::shared_ptr< CWallet > solvable_wallet
std::shared_ptr< CWallet > watchonly_wallet
std::shared_ptr< CWallet > solvables_wallet
std::shared_ptr< CWallet > wallet
State of rejected transaction that conflicts with a confirmed block.
int conflicting_block_height
State of transaction confirmed in a block.
int confirmed_block_height
State of transaction added to mempool.
State of transaction not confirmed or conflicting with a known block and not in the mempool.
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
GCSFilter::ElementSet m_filter_set
std::map< uint256, int32_t > m_last_range_ends
Map for keeping track of each range descriptor's last seen end range.
static void NotifyTransactionChanged(WalletModel *walletmodel, const uint256 &hash, ChangeType status)
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.