8#include <bitcoin-build-config.h>
10#include <blockfilter.h>
75#include <condition_variable>
97 if (!setting_value.isArray()) setting_value.setArray();
98 for (
const auto& value : setting_value.getValues()) {
101 setting_value.push_back(wallet_name);
112 for (
const auto& value : setting_value.getValues()) {
113 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
116 setting_value = std::move(new_value);
123 const std::string& wallet_name,
124 std::optional<bool> load_on_startup,
125 std::vector<bilingual_str>& warnings)
127 if (!load_on_startup)
return;
129 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
131 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
153 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
154 if (i != context.wallets.end())
return false;
155 context.wallets.push_back(
wallet);
156 wallet->ConnectScriptPubKeyManNotifiers();
157 wallet->NotifyCanGetAddressesChanged();
170 wallet->m_chain_notifications_handler.reset();
173 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
174 if (i == context.wallets.end())
return false;
175 context.wallets.erase(i);
188 std::vector<bilingual_str> warnings;
195 return context.wallets;
201 count = context.wallets.size();
202 return count == 1 ? context.wallets[0] :
nullptr;
208 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
217 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
224 for (
auto& load_wallet : context.wallet_load_fns) {
239 wallet->WalletLogPrintf(
"Releasing wallet %s..\n",
name);
244 if (g_unloading_wallet_set.erase(
name) == 0) {
258 g_unloading_wallet_set.insert(
name);
267 while (g_unloading_wallet_set.count(
name) == 1) {
274std::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)
283 context.chain->initMessage(
_(
"Loading wallet…"));
284 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), options.create_flags, error, warnings);
293 warnings.emplace_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."));
298 wallet->postInitProcess();
304 }
catch (
const std::runtime_error& e) {
311class FastWalletRescanFilter
317 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
318 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
319 assert(desc_spkm !=
nullptr);
320 AddScriptPubKeys(desc_spkm);
322 if (desc_spkm->IsHDEnabled()) {
328 void UpdateIfNeeded()
332 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
333 assert(desc_spkm !=
nullptr);
334 int32_t current_range_end{desc_spkm->GetEndRange()};
335 if (current_range_end > last_range_end) {
336 AddScriptPubKeys(desc_spkm, last_range_end);
342 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const
358 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
360 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
361 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
370 if (!result.second) {
375 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status, error, warnings);
387 error =
Untranslated(
"Legacy wallets can no longer be created");
396 if (!passphrase.empty()) {
402 error =
Untranslated(
"Private keys must be disabled when using an external signer");
409 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
416 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.");
431 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), wallet_creation_flags, error, warnings);
440 if (!
wallet->EncryptWallet(passphrase)) {
441 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
447 if (!
wallet->Unlock(passphrase)) {
448 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
457 wallet->SetupDescriptorScriptPubKeyMans();
459 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
460 if (!spk_man->SetupGeneration()) {
461 error =
Untranslated(
"Unable to generate initial keys");
476 wallet->postInitProcess();
483 warnings.emplace_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."));
499 auto wallet_file = wallet_path /
"wallet.dat";
500 std::shared_ptr<CWallet>
wallet;
515 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
517 if (load_after_restore) {
518 wallet =
LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
520 }
catch (
const std::exception& e) {
527 if (load_after_restore && !
wallet) {
528 fs::remove_all(wallet_path);
542 const auto it = mapWallet.find(hash);
543 if (it == mapWallet.end())
545 return &(it->second);
566 auto start{SteadyClock::now()};
572 start = SteadyClock::now();
614 if (
Unlock(plain_master_key)) {
635 if (!
DecryptMasterKey(strOldWalletPassphrase, master_key, plain_master_key)) {
638 if (
Unlock(plain_master_key))
640 if (!
EncryptMasterKey(strNewWalletPassphrase, plain_master_key, master_key)) {
643 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", master_key.nDeriveIterations);
660 m_last_block_processed = block_hash;
661 m_last_block_processed_height = block_height;
675 if (nWalletVersion >= nVersion)
678 nWalletVersion = nVersion;
682 if (nWalletVersion > 40000)
691 std::set<Txid> result;
694 const auto it = mapWallet.find(txid);
695 if (it == mapWallet.end())
699 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
701 for (
const CTxIn& txin : wtx.
tx->vin)
703 if (mapTxSpends.count(txin.
prevout) <= 1)
705 range = mapTxSpends.equal_range(txin.
prevout);
706 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
707 result.insert(_it->second);
715 const Txid& txid = tx->GetHash();
716 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
735 int nMinOrderPos = std::numeric_limits<int>::max();
737 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
738 const CWalletTx* wtx = &mapWallet.at(it->second);
750 for (TxSpends::iterator it = range.first; it != range.second; ++it)
752 const Txid& hash = it->second;
754 if (copyFrom == copyTo)
continue;
755 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
773 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
774 range = mapTxSpends.equal_range(outpoint);
776 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
777 const Txid& txid = it->second;
778 const auto mit = mapWallet.find(txid);
779 if (mit != mapWallet.end()) {
780 const auto& wtx = mit->second;
781 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
790 mapTxSpends.insert(std::make_pair(outpoint, txid));
799 std::pair<TxSpends::iterator, TxSpends::iterator> range;
800 range = mapTxSpends.equal_range(outpoint);
810 for (
const CTxIn& txin : wtx.
tx->vin)
839 delete encrypted_batch;
840 encrypted_batch =
nullptr;
846 auto spk_man = spk_man_pair.second.get();
847 if (!spk_man->Encrypt(plain_master_key, encrypted_batch)) {
849 delete encrypted_batch;
850 encrypted_batch =
nullptr;
861 delete encrypted_batch;
862 encrypted_batch =
nullptr;
868 delete encrypted_batch;
869 encrypted_batch =
nullptr;
872 Unlock(strWalletPassphrase);
898 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
901 for (
auto& entry : mapWallet)
908 std::vector<int64_t> nOrderPosOffsets;
909 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
916 nOrderPos = nOrderPosNext++;
917 nOrderPosOffsets.push_back(nOrderPos);
924 int64_t nOrderPosOff = 0;
925 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
927 if (nOrderPos >= nOffsetStart)
930 nOrderPos += nOrderPosOff;
931 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
949 int64_t nRet = nOrderPosNext++;
962 for (
auto& [
_, wtx] : mapWallet)
971 auto mi = mapWallet.find(originalHash);
974 assert(mi != mapWallet.end());
1010 tx_destinations.insert(dst);
1037 Txid hash = tx->GetHash();
1041 std::set<CTxDestination> tx_destinations;
1043 for (
const CTxIn& txin : tx->vin) {
1052 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1054 bool fInsertedNew =
ret.second;
1055 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1069 if (state.index() != wtx.
m_state.index()) {
1081 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1089 std::vector<CWalletTx*> txs{&wtx};
1093 while (!txs.empty()) {
1096 desc_tx->
m_state = inactive_state;
1101 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1103 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1104 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1105 const auto wit = mapWallet.find(it->second);
1106 if (wit != mapWallet.end()) {
1107 txs.push_back(&wit->second);
1118 if (fInsertedNew || fUpdated)
1132 if (!strCmd.empty())
1137 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1151 std::thread
t(runCommand, strCmd);
1161 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1163 if (!fill_wtx(wtx, ins.second)) {
1175 for (
const CTxIn& txin : wtx.
tx->vin) {
1177 if (it != mapWallet.end()) {
1197 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1199 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1200 while (range.first != range.second) {
1201 if (range.first->second != tx.
GetHash()) {
1202 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);
1203 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1210 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1211 if (fExisted && !fUpdate)
return false;
1223 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1225 if (!dest.internal.has_value()) {
1230 if (!dest.internal.has_value())
continue;
1244 TxState tx_state = std::visit([](
auto&&
s) ->
TxState {
return s; }, state);
1249 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1266 for (
const CTxIn& txin : tx->vin) {
1268 if (it != mapWallet.end()) {
1269 it->second.MarkDirty();
1277 auto it = mapWallet.find(hashTx);
1278 assert(it != mapWallet.end());
1291 assert(!wtx.isConfirmed());
1292 assert(!wtx.InMempool());
1294 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1320 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1323 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1324 if (conflictconfirms >= 0)
1348 std::set<Txid> todo;
1349 std::set<Txid> done;
1351 todo.insert(tx_hash);
1353 while (!todo.empty()) {
1357 auto it = mapWallet.find(now);
1358 assert(it != mapWallet.end());
1361 TxUpdate update_state = try_updating_state(wtx);
1364 if (batch) batch->
WriteTx(wtx);
1366 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); ++i) {
1367 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(now, i));
1368 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1369 if (!done.count(iter->second)) {
1370 todo.insert(iter->second);
1402 auto it = mapWallet.find(tx->GetHash());
1403 if (it != mapWallet.end()) {
1407 const Txid& txid = tx->GetHash();
1409 for (
const CTxIn& tx_in : tx->vin) {
1411 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1412 const Txid& spent_id = range.first->second;
1414 if (spent_id == txid)
continue;
1424 auto it = mapWallet.find(tx->GetHash());
1425 if (it != mapWallet.end()) {
1458 const Txid& txid = tx->GetHash();
1460 for (
const CTxIn& tx_in : tx->vin) {
1464 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1465 const Txid& spent_id = range.first->second;
1491 bool wallet_updated =
false;
1492 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1498 if (wallet_updated || block.
height % 144 == 0) {
1512 int disconnect_height = block.
height;
1514 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1520 for (
const CTxIn& tx_in : ptx->vin) {
1522 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1524 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1527 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1528 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1532 auto try_updating_state = [&](
CWalletTx& tx) {
1555void CWallet::BlockUntilSyncedToCurrentChain()
const {
1571 const auto mi = mapWallet.find(txin.
prevout.
hash);
1572 if (mi != mapWallet.end())
1603 for (
const auto& spkm : it->second) {
1604 res = std::max(res, spkm->IsMine(
script));
1629 if (outpoint.
n >= wtx->tx->vout.size()) {
1632 return IsMine(wtx->tx->vout[outpoint.
n]);
1647 throw std::runtime_error(std::string(__func__) +
": value out of range");
1655 bool result =
false;
1657 if (!spk_man->IsHDEnabled())
return false;
1669 if (spk_man && spk_man->CanGetAddresses(internal)) {
1687 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1701 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1736 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1745 if (time < birthtime) {
1763 int start_height = 0;
1804 constexpr auto INTERVAL_TIME{60
s};
1805 auto current_time{reserver.
now()};
1806 auto start_time{reserver.
now()};
1810 uint256 block_hash = start_block;
1813 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1817 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1826 double progress_current = progress_begin;
1827 int block_height = start_height;
1829 if (progress_end - progress_begin > 0.0) {
1830 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1834 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1838 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1839 if (next_interval) {
1840 current_time = reserver.
now();
1841 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1844 bool fetch_block{
true};
1845 if (fast_rescan_filter) {
1846 fast_rescan_filter->UpdateIfNeeded();
1847 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1848 if (matches_block.has_value()) {
1849 if (*matches_block) {
1854 fetch_block =
false;
1857 LogDebug(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.
ToString());
1863 bool block_still_active =
false;
1864 bool next_block =
false;
1875 if (!block_still_active) {
1882 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1889 if (save_progress && next_interval) {
1904 if (max_height && block_height >= *max_height) {
1923 block_hash = next_block_hash;
1928 const uint256 prev_tip_hash = tip_hash;
1930 if (!max_height && prev_tip_hash != tip_hash) {
1942 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1944 }
else if (block_height &&
chain().shutdownRequested()) {
1945 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1948 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
1989 result.erase(myHash);
2001 if (!
chain().isReadyToBroadcast())
return false;
2042 int submitted_tx_count = 0;
2049 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2050 for (
auto& [txid, wtx] : mapWallet) {
2052 if (!wtx.isUnconfirmed())
continue;
2057 to_submit.insert(&wtx);
2060 for (
auto wtx : to_submit) {
2061 std::string unused_err_string;
2066 if (submitted_tx_count > 0) {
2067 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2075 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2076 if (!pwallet->ShouldResend())
continue;
2077 pwallet->ResubmitWalletTransactions(
true,
false);
2078 pwallet->SetNextResend();
2088 std::map<COutPoint, Coin> coins;
2089 for (
auto& input : tx.
vin) {
2090 const auto mi = mapWallet.find(input.prevout.hash);
2091 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2096 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2098 std::map<int, bilingual_str> input_errors;
2108 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2124 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2125 const CTxIn& txin = psbtx.
tx->vin[i];
2135 const auto it = mapWallet.find(txhash);
2136 if (it != mapWallet.end()) {
2149 int n_signed_this_spkm = 0;
2150 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type,
sign, bip32derivs, &n_signed_this_spkm, finalize)};
2156 (*n_signed) += n_signed_this_spkm;
2164 for (
size_t i = 0; i < psbtx.
inputs.size(); ++i) {
2176 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2178 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2188 return *change_type;
2197 bool any_wpkh{
false};
2199 bool any_pkh{
false};
2201 for (
const auto& recipient : vecSend) {
2202 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2204 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2206 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2208 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2214 if (has_bech32m_spkman && any_tr) {
2219 if (has_bech32_spkman && any_wpkh) {
2224 if (has_p2sh_segwit_spkman && any_sh) {
2230 if (has_legacy_spkman && any_pkh) {
2235 if (has_bech32m_spkman) {
2238 if (has_bech32_spkman) {
2255 wtx.
mapValue = std::move(mapValue);
2263 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2267 for (
const CTxIn& txin : tx->vin) {
2278 std::string err_string;
2280 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2297 spk_man_pair.second->RewriteDB();
2307 return nLoadWalletRet;
2317 return result.has_value();
2320 if (!was_txn_committed)
return util::Error{
_(
"Error starting/committing db txn for wallet transactions removal process")};
2330 std::vector<
decltype(mapWallet)::const_iterator> erased_txs;
2332 for (
const Txid& hash : txs_to_remove) {
2333 auto it_wtx = mapWallet.find(hash);
2334 if (it_wtx == mapWallet.end()) {
2340 erased_txs.emplace_back(it_wtx);
2346 for (
const auto& it : erased_txs) {
2347 const Txid hash{it->first};
2348 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2349 for (
const auto& txin : it->second.tx->vin)
2350 mapTxSpends.erase(txin.prevout);
2351 mapWallet.erase(it);
2363 bool fUpdated =
false;
2365 std::optional<AddressPurpose> purpose;
2368 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2369 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2371 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2382 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2385 if (!batch.
WriteName(encoded_dest, strName)) {
2419 WalletLogPrintf(
"%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2441 m_address_book.erase(address);
2453 unsigned int count = 0;
2455 count += spk_man.second->GetKeyPoolSize();
2465 unsigned int count = 0;
2467 count += spk_man->GetKeyPoolSize();
2477 res &= spk_man->TopUp(kpSize);
2490 auto op_dest = spk_man->GetNewDestination(type);
2510 for (
auto& entry : mapWallet) {
2513 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2526 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2527 const auto& entry = item.second;
2528 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2535 std::vector<CTxDestination> result;
2543 result.emplace_back(dest);
2551 std::set<std::string> label_set;
2553 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2554 if (_is_change)
return;
2555 if (!purpose || purpose == _purpose) {
2556 label_set.insert(_label);
2572 if (!op_address)
return op_address;
2602 if (signer_spk_man ==
nullptr) {
2606 return signer_spk_man->DisplayAddress(dest,
signer);
2608 return util::Error{
_(
"There is no ScriptPubKeyManager for this address")};
2614 setLockedCoins.insert(output);
2624 bool was_locked = setLockedCoins.erase(output);
2625 if (batch && was_locked) {
2634 bool success =
true;
2636 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2639 setLockedCoins.clear();
2646 return setLockedCoins.count(output) > 0;
2652 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2653 it != setLockedCoins.end(); it++) {
2655 vOutpts.push_back(outpt);
2684 std::optional<uint256> block_hash;
2686 block_hash = conf->confirmed_block_hash;
2688 block_hash = conf->conflicting_block_hash;
2694 int64_t block_max_time;
2695 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2696 if (rescanning_old_block) {
2697 nTimeSmart = block_max_time;
2700 int64_t latestEntry = 0;
2703 int64_t latestTolerated = latestNow + 300;
2705 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2715 if (nSmartTime <= latestTolerated) {
2716 latestEntry = nSmartTime;
2717 if (nSmartTime > latestNow) {
2718 latestNow = nSmartTime;
2724 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2735 if (std::get_if<CNoDestination>(&dest))
2749 m_address_book[dest].previously_spent =
true;
2754 m_address_book[dest].receive_requests[id] = request;
2765 std::vector<std::string>
values;
2766 for (
const auto& [dest, entry] : m_address_book) {
2767 for (
const auto& [
id, request] : entry.receive_requests) {
2768 values.emplace_back(request);
2777 m_address_book[dest].receive_requests[id] = value;
2784 m_address_book[dest].receive_requests.erase(
id);
2797 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2798 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2799 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2802 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2803 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2804 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2818 return MakeDatabase(*wallet_path, options, status, error_string);
2825 const std::string& walletFile = database->Filename();
2827 const auto start{SteadyClock::now()};
2832 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
2835 bool rescan_required =
false;
2836 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2839 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2844 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
2845 " or address metadata may be missing or incorrect."),
2849 error =
strprintf(
_(
"Error loading %s: Wallet requires newer version of %s"), walletFile, CLIENT_NAME);
2853 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2858 error =
strprintf(
_(
"Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
2861 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect."
2862 " Rescanning wallet."), walletFile));
2863 rescan_required =
true;
2865 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n"
2866 "The wallet might had been created on a newer version.\n"
2867 "Please try running the latest software version.\n"), walletFile);
2870 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
2871 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
2874 error =
strprintf(
_(
"Error loading %s: Wallet is a legacy wallet. Please migrate to a descriptor wallet using the migration tool (migratewallet RPC)."), walletFile);
2877 error =
strprintf(
_(
"Error loading %s"), walletFile);
2883 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2888 LOCK(walletInstance->cs_wallet);
2893 walletInstance->InitWalletFlags(wallet_creation_flags);
2900 walletInstance->SetupDescriptorScriptPubKeyMans();
2904 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2905 if (!spk_man->SetupGeneration()) {
2906 error =
_(
"Unable to generate initial keys");
2916 walletInstance->SetLastBlockProcessed(*tip_height,
chain->
getBlockHash(*tip_height));
2921 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
2924 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2925 if (spk_man->HavePrivateKeys()) {
2926 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2932 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
2938 walletInstance->m_default_address_type = parsed.value();
2941 if (!
args.
GetArg(
"-changetype",
"").empty()) {
2947 walletInstance->m_default_change_type = parsed.value();
2950 if (
const auto arg{
args.
GetArg(
"-mintxfee")}) {
2951 std::optional<CAmount> min_tx_fee =
ParseMoney(*arg);
2957 _(
"This is the minimum transaction fee you pay on every transaction."));
2960 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
2963 if (
const auto arg{
args.
GetArg(
"-maxapsfee")}) {
2964 const std::string& max_aps_fee{*arg};
2965 if (max_aps_fee ==
"-1") {
2966 walletInstance->m_max_aps_fee = -1;
2967 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
2970 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2972 walletInstance->m_max_aps_fee = max_fee.value();
2979 if (
const auto arg{
args.
GetArg(
"-fallbackfee")}) {
2980 std::optional<CAmount> fallback_fee =
ParseMoney(*arg);
2981 if (!fallback_fee) {
2982 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-fallbackfee", *arg);
2986 _(
"This is the transaction fee you may pay when fee estimates are not available."));
2988 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
2992 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
2994 if (
const auto arg{
args.
GetArg(
"-discardfee")}) {
2995 std::optional<CAmount> discard_fee =
ParseMoney(*arg);
2997 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-discardfee", *arg);
3001 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3003 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3006 if (
const auto arg{
args.
GetArg(
"-paytxfee")}) {
3007 warnings.push_back(
_(
"-paytxfee is deprecated and will be fully removed in v31.0."));
3009 std::optional<CAmount> pay_tx_fee =
ParseMoney(*arg);
3015 _(
"This is the transaction fee you will pay if you send a transaction."));
3018 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3021 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3027 if (
const auto arg{
args.
GetArg(
"-maxtxfee")}) {
3028 std::optional<CAmount> max_fee =
ParseMoney(*arg);
3033 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3037 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3042 walletInstance->m_default_max_tx_fee = max_fee.value();
3045 if (
const auto arg{
args.
GetArg(
"-consolidatefeerate")}) {
3046 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(*arg)) {
3047 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3056 _(
"The wallet will avoid paying less than the minimum relay fee."));
3063 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3066 walletInstance->TopUpKeyPool();
3069 std::optional<int64_t> time_first_key;
3070 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3071 int64_t time = spk_man->GetTimeFirstKey();
3072 if (!time_first_key || time < *time_first_key) time_first_key = time;
3074 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3077 walletInstance->m_chain_notifications_handler.reset();
3082 LOCK(walletInstance->cs_wallet);
3084 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3085 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3086 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3089 return walletInstance;
3094 LOCK(walletInstance->cs_wallet);
3096 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3097 walletInstance->m_chain = &
chain;
3107 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3119 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3122 int rescan_height = 0;
3123 if (!rescan_required)
3129 rescan_height = *fork_height;
3137 walletInstance->m_last_block_processed_height = *tip_height;
3139 walletInstance->m_last_block_processed.
SetNull();
3140 walletInstance->m_last_block_processed_height = -1;
3143 if (tip_height && *tip_height != rescan_height)
3147 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3148 if (time_first_key) {
3155 rescan_height = *tip_height;
3163 int block_height = *tip_height;
3164 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3168 if (rescan_height != block_height) {
3179 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3181 "Error loading wallet. Wallet requires blocks to be downloaded, "
3182 "and software does not currently support loading wallets while "
3183 "blocks are being downloaded out of order when using assumeutxo "
3184 "snapshots. Wallet should be able to load successfully after "
3185 "node sync reaches height %s"), block_height);
3191 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3196 error =
_(
"Failed to acquire rescan reserver during wallet initialization");
3199 ScanResult scan_res = walletInstance->ScanForWalletTransactions(
chain.
getBlockHash(rescan_height), rescan_height, {}, reserver,
true,
true);
3201 error =
_(
"Failed to rescan the wallet during initialization");
3216 const auto& address_book_it = m_address_book.find(dest);
3217 if (address_book_it == m_address_book.end())
return nullptr;
3218 if ((!allow_change) && address_book_it->second.IsChange()) {
3221 return &address_book_it->second;
3233 if (version < prev_version) {
3234 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3242 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);
3250 if (!spk_man->Upgrade(prev_version, version, error)) {
3277 assert(conf->confirmed_block_height >= 0);
3280 assert(conf->conflicting_block_height >= 0);
3295 assert(chain_depth >= 0);
3318 return vMasterKey.empty();
3328 if (!vMasterKey.empty()) {
3329 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(
decltype(vMasterKey)::value_type));
3343 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3347 vMasterKey = vMasterKeyIn;
3355 std::set<ScriptPubKeyMan*> spk_mans;
3356 for (
bool internal : {
false,
true}) {
3360 spk_mans.insert(spk_man);
3370 if (ext_spkm == &spkm)
return true;
3373 if (int_spkm == &spkm)
return true;
3380 std::set<ScriptPubKeyMan*> spk_mans;
3382 spk_mans.insert(spk_man_pair.second.get());
3390 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3391 if (it == spk_managers.end()) {
3399 std::set<ScriptPubKeyMan*> spk_mans;
3404 spk_mans.insert(it->second.begin(), it->second.end());
3407 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&
script, &sigdata](
ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3433 return it->second.at(0)->GetSolvingProvider(
script);
3441 std::vector<WalletDescriptor> descs;
3444 LOCK(desc_spk_man->cs_desc_man);
3445 descs.push_back(desc_spk_man->GetWalletDescriptor());
3484 std::unique_ptr<ScriptPubKeyMan> spk_manager = std::make_unique<LegacyDataSPKM>(*
this);
3490 uint256 id = spk_manager->GetID();
3497 return cb(vMasterKey);
3508 if (spkm->HaveCryptedKeys())
return true;
3530 return *spk_manager;
3539 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3541 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3542 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3545 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3547 uint256 id = spk_manager->GetID();
3556 for (
bool internal : {
false,
true}) {
3587 }))
throw std::runtime_error(
"Error: cannot process db transaction for descriptors setup");
3595 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3598 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3600 for (
bool internal : {
false,
true}) {
3601 const UniValue& descriptor_vals = signer_res.
find_value(internal ?
"internal" :
"receive");
3602 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3604 const std::string& desc_str = desc_val.getValStr();
3606 std::string desc_error;
3607 auto descs =
Parse(desc_str, keys, desc_error,
false);
3608 if (descs.empty()) {
3609 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3611 auto& desc = descs.at(0);
3612 if (!desc->GetOutputType()) {
3617 spk_manager->SetupDescriptor(batch, std::move(desc));
3618 uint256 id = spk_manager->GetID();
3625 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3638 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3653 spk_mans[type] = spk_man;
3655 const auto it = spk_mans_other.find(type);
3656 if (it != spk_mans_other.end() && it->second == spk_man) {
3657 spk_mans_other.erase(type);
3666 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3670 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3674 spk_mans.erase(type);
3699 return std::nullopt;
3703 if (!desc_spk_man) {
3704 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3707 LOCK(desc_spk_man->cs_desc_man);
3708 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3709 assert(type.has_value());
3719 return util::Error{
_(
"Cannot add WalletDescriptor to a non-descriptor wallet")};
3725 if (
auto spkm_res = spk_man->UpdateWalletDescriptor(desc); !spkm_res) {
3730 spk_man = new_spk_man.get();
3733 uint256 id = new_spk_man->GetID();
3738 for (
const auto& entry : signing_provider.
keys) {
3739 const CKey& key = entry.second;
3740 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3744 if (!spk_man->TopUp()) {
3745 return util::Error{
_(
"Could not top up scriptPubKeys")};
3751 auto script_pub_keys = spk_man->GetScriptPubKeys();
3752 if (script_pub_keys.empty()) {
3753 return util::Error{
_(
"Could not generate scriptPubKeys (cache is empty)")};
3757 for (
const auto&
script : script_pub_keys) {
3767 spk_man->WriteDescriptor();
3769 return std::reference_wrapper(*spk_man);
3776 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3779 error =
_(
"Error: This wallet already uses SQLite");
3784 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3785 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3786 std::vector<std::pair<SerializeData, SerializeData>> records;
3788 error =
_(
"Error: Unable to begin reading all records in the database");
3795 status = cursor->Next(ss_key, ss_value);
3801 records.emplace_back(key, value);
3806 error =
_(
"Error: Unable to read all records in the database");
3813 fs::remove(db_path);
3824 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status, error);
3831 bool began = batch->TxnBegin();
3833 for (
const auto& [key, value] : records) {
3834 if (!batch->Write(std::span{key}, std::span{value})) {
3841 bool committed = batch->TxnCommit();
3851 if (!
Assume(legacy_spkm)) {
3854 return std::nullopt;
3858 if (res == std::nullopt) {
3859 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
3860 return std::nullopt;
3870 if (!
Assume(legacy_spkm)) {
3876 std::set<CTxDestination> not_migrated_dests;
3885 if (!
data.watch_descs.empty())
Assume(!
data.watchonly_wallet->m_cached_spks.empty());
3886 if (!
data.solvable_descs.empty())
Assume(!
data.solvable_wallet->m_cached_spks.empty());
3888 for (
auto& desc_spkm :
data.desc_spkms) {
3890 return util::Error{
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
3892 uint256 id = desc_spkm->GetID();
3898 return util::Error{
_(
"Error: cannot remove legacy wallet records")};
3910 if (
data.master_key.key.IsValid()) {
3920 if (!local_wallet_batch.
ReadBestBlock(best_block_locator)) {
3921 return util::Error{
_(
"Error: Unable to read wallet's best block locator record")};
3926 std::vector<Txid> txids_to_delete;
3927 std::unique_ptr<WalletBatch> watchonly_batch;
3928 if (
data.watchonly_wallet) {
3929 watchonly_batch = std::make_unique<WalletBatch>(
data.watchonly_wallet->GetDatabase());
3930 if (!watchonly_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.watchonly_wallet->GetName())};
3932 LOCK(
data.watchonly_wallet->cs_wallet);
3933 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
3934 watchonly_batch->WriteOrderPosNext(
data.watchonly_wallet->nOrderPosNext);
3936 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
3937 return util::Error{
_(
"Error: Unable to write watchonly wallet best block locator record")};
3940 std::unique_ptr<WalletBatch> solvables_batch;
3941 if (
data.solvable_wallet) {
3942 solvables_batch = std::make_unique<WalletBatch>(
data.solvable_wallet->GetDatabase());
3943 if (!solvables_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.solvable_wallet->GetName())};
3945 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
3946 return util::Error{
_(
"Error: Unable to write solvable wallet best block locator record")};
3953 if (
data.watchonly_wallet) {
3954 LOCK(
data.watchonly_wallet->cs_wallet);
3955 if (
data.watchonly_wallet->IsMine(*wtx->tx) ||
data.watchonly_wallet->IsFromMe(*wtx->tx)) {
3957 const Txid& hash = wtx->GetHash();
3960 if (!new_tx) return false;
3961 ins_wtx.SetTx(to_copy_wtx.tx);
3962 ins_wtx.CopyFrom(to_copy_wtx);
3965 return util::Error{
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
3967 watchonly_batch->WriteTx(
data.watchonly_wallet->mapWallet.at(hash));
3970 txids_to_delete.push_back(hash);
3977 return util::Error{
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
3982 if (txids_to_delete.size() > 0) {
3983 if (
auto res =
RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
3989 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
3990 if (
data.watchonly_wallet) wallets_vec.emplace_back(
data.watchonly_wallet, std::move(watchonly_batch));
3991 if (
data.solvable_wallet) wallets_vec.emplace_back(
data.solvable_wallet, std::move(solvables_batch));
3997 if (entry.label) batch.
WriteName(address, *entry.label);
3998 for (
const auto& [
id, request] : entry.receive_requests) {
4005 std::vector<CTxDestination> dests_to_delete;
4006 for (
const auto& [dest, record] : m_address_book) {
4010 bool copied =
false;
4011 for (
auto& [
wallet, batch] : wallets_vec) {
4013 if (require_transfer && !
wallet->IsMine(dest))
continue;
4016 wallet->m_address_book[dest] = record;
4017 func_store_addr(*batch, dest, record);
4021 if (require_transfer) {
4022 dests_to_delete.push_back(dest);
4030 if (require_transfer && !copied) {
4033 if (not_migrated_dests.count(dest) > 0) {
4034 dests_to_delete.push_back(dest);
4038 return util::Error{
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4043 for (
auto& [
wallet, batch] : wallets_vec) {
4050 if (dests_to_delete.size() > 0) {
4051 for (
const auto& dest : dests_to_delete) {
4053 return util::Error{
_(
"Error: Unable to remove watchonly address book data")};
4071 std::optional<MigrationData>
data =
wallet.GetDescriptorsForLegacy(error);
4072 if (
data == std::nullopt)
return false;
4075 if (
data->watch_descs.size() > 0 ||
data->solvable_descs.size() > 0) {
4082 empty_context.
args = context.args;
4092 if (
data->watch_descs.size() > 0) {
4093 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4096 std::vector<bilingual_str> warnings;
4097 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4098 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4100 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4105 if (!
data->watchonly_wallet) {
4106 error =
_(
"Error: Failed to create new watchonly wallet");
4109 res.watchonly_wallet =
data->watchonly_wallet;
4110 LOCK(
data->watchonly_wallet->cs_wallet);
4113 for (
const auto& [desc_str, creation_time] :
data->watch_descs) {
4116 std::string parse_err;
4117 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4118 assert(descs.size() == 1);
4119 assert(!descs.at(0)->IsRange());
4123 if (
auto spkm_res =
data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false); !spkm_res) {
4131 if (
data->solvable_descs.size() > 0) {
4132 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4135 std::vector<bilingual_str> warnings;
4136 std::string wallet_name =
wallet.GetName() +
"_solvables";
4137 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4139 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4144 if (!
data->solvable_wallet) {
4145 error =
_(
"Error: Failed to create new watchonly wallet");
4148 res.solvables_wallet =
data->solvable_wallet;
4149 LOCK(
data->solvable_wallet->cs_wallet);
4152 for (
const auto& [desc_str, creation_time] :
data->solvable_descs) {
4155 std::string parse_err;
4156 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4157 assert(descs.size() == 1);
4158 assert(!descs.at(0)->IsRange());
4162 if (
auto spkm_res =
data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false); !spkm_res) {
4174 if (auto res_migration = wallet.ApplyMigrationData(batch, *data); !res_migration) {
4175 error = util::ErrorString(res_migration);
4178 wallet.WalletLogPrintf(
"Wallet migration complete.\n");
4185 std::vector<bilingual_str> warnings;
4189 bool was_loaded =
false;
4192 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4196 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4210 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4222 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4228 std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.
create_flags, error, warnings);
4229 if (!local_wallet) {
4240 std::vector<bilingual_str> warnings;
4246 const std::string wallet_name = local_wallet->GetName();
4249 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4250 assert(to_reload.use_count() == 1);
4251 std::string
name = to_reload->GetName();
4253 to_reload =
LoadWallet(context,
name, std::nullopt, options, status, error, warnings);
4254 return to_reload !=
nullptr;
4260 reload_wallet(local_wallet);
4262 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4268 fs::path backup_path = this_wallet_dir / backup_filename;
4271 reload_wallet(local_wallet);
4273 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4277 bool success =
false;
4280 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4282 reload_wallet(local_wallet);
4284 if (passphrase.find(
'\0') == std::string::npos) {
4285 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4287 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4288 "The passphrase contains a null character (ie - a zero byte). "
4289 "If this passphrase was set with a version of this software prior to 25.0, "
4290 "please try again with only the characters up to — but not including — "
4291 "the first null character.")};
4296 LOCK(local_wallet->cs_wallet);
4298 if (!local_wallet->MigrateToSQLite(error))
return util::Error{error};
4302 success =
DoMigration(*local_wallet, context, error, res);
4314 std::set<fs::path> wallet_dirs;
4318 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4319 success = reload_wallet(local_wallet);
4320 res.
wallet = local_wallet;
4337 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4340 std::vector<std::shared_ptr<CWallet>> created_wallets;
4341 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4346 for (std::shared_ptr<CWallet>& w : created_wallets) {
4351 for (std::shared_ptr<CWallet>& w : created_wallets) {
4352 if (w->HaveChain()) {
4355 error +=
_(
"\nUnable to cleanup failed migration");
4361 assert(w.use_count() == 1);
4367 for (
const fs::path& dir : wallet_dirs) {
4368 fs::remove_all(dir);
4375 const auto& ptr_wallet =
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status, restore_error, warnings, was_loaded);
4376 if (!restore_error.
empty()) {
4377 error += restore_error +
_(
"\nUnable to restore backup of wallet.");
4382 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4383 fs::remove(temp_backup_location);
4387 bool wallet_reloaded = ptr_wallet !=
nullptr;
4388 assert(was_loaded == wallet_reloaded);
4397 for (
const auto&
script : spks) {
4398 m_cached_spks[
script].push_back(spkm);
4405 CacheNewScriptPubKeys(spks, spkm);
4408std::set<CExtPubKey> CWallet::GetActiveHDPubKeys()
const
4414 std::set<CExtPubKey> active_xpubs;
4415 for (
const auto& spkm : GetActiveScriptPubKeyMans()) {
4421 std::set<CPubKey> desc_pubkeys;
4422 std::set<CExtPubKey> desc_xpubs;
4423 w_desc.
descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4424 active_xpubs.merge(std::move(desc_xpubs));
4426 return active_xpubs;
4429std::optional<CKey> CWallet::GetKey(
const CKeyID& keyid)
const
4433 for (
const auto& spkm : GetAllScriptPubKeyMans()) {
4437 if (std::optional<CKey> key = desc_spkm->
GetKey(keyid)) {
4441 return std::nullopt;
4444void CWallet::WriteBestBlock()
const
4448 if (!m_last_block_processed.IsNull()) {
4450 chain().findBlock(m_last_block_processed,
FoundBlock().locator(loc));
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
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.
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.
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 std::vector< CTxOut > vout
const Txid & GetHash() const LIFETIMEBOUND
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.
std::unordered_set< Element, ByteVectorHash > ElementSet
Different type to mark Mutex at global scope.
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
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
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
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 bool updateRwSetting(const std::string &name, const SettingsUpdate &update_function)=0
Updates a setting in <datadir>/settings.json.
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 void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual 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
constexpr const std::byte * begin() const
std::string GetHex() const
Encryption/decryption context with key information.
bool Decrypt(std::span< const unsigned char > ciphertext, CKeyingMaterial &plaintext) const
bool SetKeyFromPassphrase(const SecureString &key_data, std::span< const unsigned char > salt, const unsigned int rounds, const unsigned int derivation_method)
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
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()
std::vector< unsigned char > vchCryptedKey
unsigned int nDeriveIterations
static constexpr unsigned int DEFAULT_DERIVE_ITERATIONS
Default/minimum number of key derivation rounds.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
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)
std::atomic< bool > fAbortRescan
bool TopUpKeyPool(unsigned int kpSize=0)
bool HaveChain() const
Interface to assert chain access.
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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
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.
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.
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)
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...
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, std::optional< int > sighash_type=std::nullopt, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
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
LegacyDataSPKM * GetLegacyDataSPKM() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
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.
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
bool HaveCryptedKeys() const
LegacyDataSPKM * GetOrCreateLegacyDataSPKM()
interfaces::Chain & chain() const
Interface for accessing chain state.
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
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)
util::Result< void > RemoveTxs(std::vector< Txid > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
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.
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void WalletLogPrintf(util::ConstevalFormatString< sizeof...(Params)> wallet_fmt, const Params &... params) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
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.
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
MasterKeyMap mapMasterKeys
boost::signals2::signal< void(const Txid &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
util::Result< void > ApplyMigrationData(WalletBatch &local_wallet_batch, MigrationData &data) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan,...
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
WalletDatabase & GetDatabase() const override
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
void WriteBestBlock() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Write the current best block to database.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
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< std::string > ListAddrBookLabels(const std::optional< AddressPurpose > purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
bool IsLocked() const override
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
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.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
util::Result< CTxDestination > GetNewChangeDestination(const OutputType 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().
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 ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
bool DelAddressBook(const CTxDestination &address)
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 Legacy(Data)SPKM 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.
std::multimap< int64_t, CWalletTx * > TxItems
void SetupOwnDescriptorScriptPubKeyMans(WalletBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new seed and default DescriptorScriptPubKeyMans for this wallet.
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.
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.
util::Result< std::reference_wrapper< DescriptorScriptPubKeyMan > > AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
A transaction with a bunch of additional info that only the owner cares about.
bool isBlockConflicted() const
const Txid & GetHash() const LIFETIMEBOUND
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
std::vector< std::pair< std::string, std::string > > vOrderForm
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
unsigned int nTimeReceived
time received by this node
void SetTx(CTransactionRef arg)
unsigned int fTimeReceivedIsTxTime
int64_t GetTxTime() const
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
unsigned int 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 DeleteRecordsWithDB(WalletBatch &batch)
Delete all the records of this LegacyScriptPubKeyMan from disk.
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
uint256 GetID() const override
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid,...
A wrapper to reserve an address from a wallet.
const CWallet *const pwallet
The wallet to reserve from.
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
CTxDestination address
The destination.
bool fInternal
Whether this is from the internal (change output) keypool.
void ReturnDestination()
Return reserved address.
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.
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
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)
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)
void RegisterTxnListener(const DbTxnListener &l)
Registers db txn callback functions.
bool ReadBestBlock(CBlockLocator &locator)
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 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.
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)
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.
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
void RecursiveUpdateTxState(const Txid &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.
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)
bool AbandonTransaction(const Txid &hashTx)
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SetWalletFlagWithDB(WalletBatch &batch, uint64_t flags)
Store wallet flags.
static bool EncryptMasterKey(const SecureString &wallet_passphrase, const CKeyingMaterial &plain_master_key, CMasterKey &master_key)
void updatedBlockTip() override
bool TransactionCanBeAbandoned(const Txid &hashTx) const
Return whether transaction can be abandoned.
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(void SetWalletFlag(uint64_t flags)
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
void blockConnected(ChainstateRole role, const interfaces::BlockInfo &block) override
void MaybeUpdateBirthTime(int64_t time)
Updates wallet birth time if 'time' is below it.
void blockDisconnected(const interfaces::BlockInfo &block) override
std::set< Txid > GetConflicts(const Txid &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
static bool DecryptMasterKey(const SecureString &wallet_passphrase, const CMasterKey &master_key, CKeyingMaterial &plain_master_key)
void SetLastBlockProcessedInMem(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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:
std::set< Txid > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void ResubmitWalletTransactions(bool relay, bool force)
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
bool MarkReplaced(const Txid &originalHash, const Txid &newHash)
Mark a transaction as replaced by another transaction.
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.
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.
const CWalletTx * GetWalletTx(const Txid &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
bool SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
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)
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Set last block processed height, and write to database.
bool LoadToWallet(const Txid &hash, const UpdateWalletTxFn &fill_wtx) 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 UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
void AddToSpends(const COutPoint &outpoint, const Txid &txid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SetSpentKeyState(WalletBatch &batch, const Txid &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const Txid &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
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 LogDebug(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.
is a home for simple string functions returning descriptive messages that are used in RPC and GUI int...
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
static int sign(const secp256k1_context *ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64)
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
bilingual_str AmountHighWarn(const std::string &optname)
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)
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
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)
static std::set< std::string > g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex)
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
Overview of wallet database classes:
@ UNEXPECTED_LEGACY_ENTRY
@ EXTERNAL_SIGNER_SUPPORT_REQUIRED
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
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
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 load_after_restore)
util::Result< MigrationResult > MigrateLegacyToDescriptor(std::shared_ptr< CWallet > local_wallet, const SecureString &passphrase, WalletContext &context, bool was_loaded)
Requirement: The wallet provided to this function must be isolated, with no attachment to the node's ...
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...
std::underlying_type_t< isminetype > isminefilter
used for bitflags of isminetype
static const bool DEFAULT_WALLETCROSSCHAIN
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
bool HasLegacyRecords(CWallet &wallet)
Returns true if there are any DBKeys::LEGACY_TYPES record in the wallet db.
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 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)
bool IsBDBFile(const fs::path &path)
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
fs::path BDBDataFile(const fs::path &wallet_path)
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
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)
static void FlushAndDeleteWallet(CWallet *wallet)
@ 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,...
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
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)
static util::Result< fs::path > GetWalletPath(const std::string &name)
@ 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)
is a home for public enum and struct type definitions that are used internally by node code,...
std::optional< OutputType > ParseOutputType(const std::string &type)
const std::string & FormatOutputType(OutputType type)
static constexpr auto OUTPUT_TYPES
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData *txdata)
Checks whether a PSBTInput is already signed by doing script verification using final fields.
void RemoveUnnecessaryTransactions(PartiallySignedTransaction &psbtx)
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(std::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
@ PRIVATE_KEY_NOT_AVAILABLE
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(std::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
enum wallet::CWallet::ScanResult::@19 status
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.
SecureString create_passphrase
std::optional< DatabaseFormat > require_format
struct containing information needed for migrating legacy wallets to descriptor wallets
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(...)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
is a home for public enum and struct type definitions that are used by internally by wallet code,...
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.
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.