8 #if defined(HAVE_CONFIG_H)
12 #include <blockfilter.h>
75 #include <condition_variable>
94 if (value.isStr() && value.get_str() == wallet_name)
return true;
103 if (!setting_value.
isArray())
return true;
106 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
108 if (new_value.
size() == setting_value.
size())
return true;
113 const std::string& wallet_name,
114 std::optional<bool> load_on_startup,
115 std::vector<bilingual_str>& warnings)
117 if (!load_on_startup)
return;
119 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
121 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
143 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(
context.wallets.begin(),
context.wallets.end(),
wallet);
144 if (i !=
context.wallets.end())
return false;
146 wallet->ConnectScriptPubKeyManNotifiers();
147 wallet->NotifyCanGetAddressesChanged();
159 wallet->m_chain_notifications_handler.reset();
161 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(
context.wallets.begin(),
context.wallets.end(),
wallet);
162 if (i ==
context.wallets.end())
return false;
173 std::vector<bilingual_str> warnings;
193 for (
const std::shared_ptr<CWallet>&
wallet :
context.wallets) {
202 auto it =
context.wallet_load_fns.emplace(
context.wallet_load_fns.end(), std::move(load_wallet));
209 for (
auto& load_wallet :
context.wallet_load_fns) {
224 wallet->WalletLogPrintf(
"Releasing wallet\n");
230 if (g_unloading_wallet_set.erase(
name) == 0) {
244 auto it = g_unloading_wallet_set.insert(
name);
256 while (g_unloading_wallet_set.count(
name) == 1) {
263 std::shared_ptr<CWallet> LoadWalletInternal(WalletContext&
context,
const std::string&
name, std::optional<bool> load_on_start,
const DatabaseOptions& options,
DatabaseStatus& status,
bilingual_str&
error, std::vector<bilingual_str>& warnings)
282 warnings.push_back(
_(
"Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet."));
287 wallet->postInitProcess();
293 }
catch (
const std::runtime_error& e) {
300 class FastWalletRescanFilter
309 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
310 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
311 assert(desc_spkm !=
nullptr);
312 AddScriptPubKeys(desc_spkm);
314 if (desc_spkm->IsHDEnabled()) {
320 void UpdateIfNeeded()
324 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
325 assert(desc_spkm !=
nullptr);
326 int32_t current_range_end{desc_spkm->GetEndRange()};
327 if (current_range_end > last_range_end) {
328 AddScriptPubKeys(desc_spkm, last_range_end);
334 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const
350 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
352 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
353 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
362 if (!result.second) {
383 if (!passphrase.empty()) {
389 error =
Untranslated(
"Private keys must be disabled when using an external signer");
396 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
403 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.");
427 if (!
wallet->EncryptWallet(passphrase)) {
434 if (!
wallet->Unlock(passphrase)) {
444 wallet->SetupDescriptorScriptPubKeyMans();
446 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
447 if (!spk_man->SetupGeneration()) {
463 wallet->postInitProcess();
470 warnings.push_back(
_(
"Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future."));
484 auto wallet_file = wallet_path /
"wallet.dat";
485 std::shared_ptr<CWallet>
wallet;
500 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
503 }
catch (
const std::exception& e) {
509 fs::remove_all(wallet_path);
523 const auto it = mapWallet.find(hash);
524 if (it == mapWallet.end())
526 return &(it->second);
540 spk_man->UpgradeKeyMetadata();
564 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
566 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
568 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
570 if (
Unlock(_vMasterKey, accept_no_keys)) {
594 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
596 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
601 auto start{SteadyClock::now()};
602 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
603 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
605 start = SteadyClock::now();
606 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
607 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
609 if (pMasterKey.second.nDeriveIterations < 25000)
610 pMasterKey.second.nDeriveIterations = 25000;
612 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
614 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
616 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
643 if (nWalletVersion >= nVersion)
646 nWalletVersion = nVersion;
650 if (nWalletVersion > 40000)
659 std::set<uint256> result;
662 const auto it = mapWallet.find(txid);
663 if (it == mapWallet.end())
667 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
669 for (
const CTxIn& txin : wtx.
tx->vin)
671 if (mapTxSpends.count(txin.
prevout) <= 1)
673 range = mapTxSpends.equal_range(txin.
prevout);
674 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
675 result.insert(_it->second);
683 const uint256& txid = tx->GetHash();
684 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
708 int nMinOrderPos = std::numeric_limits<int>::max();
710 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
711 const CWalletTx* wtx = &mapWallet.at(it->second);
723 for (TxSpends::iterator it = range.first; it != range.second; ++it)
725 const uint256& hash = it->second;
727 if (copyFrom == copyTo)
continue;
728 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
747 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
748 range = mapTxSpends.equal_range(outpoint);
750 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
751 const uint256& wtxid = it->second;
752 const auto mit = mapWallet.find(wtxid);
753 if (mit != mapWallet.end()) {
755 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
764 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
773 std::pair<TxSpends::iterator, TxSpends::iterator> range;
774 range = mapTxSpends.equal_range(outpoint);
784 for (
const CTxIn& txin : wtx.
tx->vin)
805 auto start{SteadyClock::now()};
807 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
809 start = SteadyClock::now();
828 delete encrypted_batch;
829 encrypted_batch =
nullptr;
835 auto spk_man = spk_man_pair.second.get();
836 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
838 delete encrypted_batch;
839 encrypted_batch =
nullptr;
850 delete encrypted_batch;
851 encrypted_batch =
nullptr;
857 delete encrypted_batch;
858 encrypted_batch =
nullptr;
861 Unlock(strWalletPassphrase);
868 if (spk_man->IsHDEnabled()) {
869 if (!spk_man->SetupGeneration(
true)) {
900 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
903 for (
auto& entry : mapWallet)
910 std::vector<int64_t> nOrderPosOffsets;
911 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
918 nOrderPos = nOrderPosNext++;
919 nOrderPosOffsets.push_back(nOrderPos);
926 int64_t nOrderPosOff = 0;
927 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
929 if (nOrderPos >= nOffsetStart)
932 nOrderPos += nOrderPosOff;
933 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
951 int64_t nRet = nOrderPosNext++;
964 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
965 item.second.MarkDirty();
973 auto mi = mapWallet.find(originalHash);
976 assert(mi != mapWallet.end());
1012 tx_destinations.insert(dst);
1032 assert(spk_man !=
nullptr);
1061 std::set<CTxDestination> tx_destinations;
1063 for (
const CTxIn& txin : tx->vin) {
1072 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1074 bool fInsertedNew =
ret.second;
1075 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1086 if (state.index() != wtx.
m_state.index()) {
1098 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1106 std::vector<CWalletTx*> txs{&wtx};
1110 while (!txs.empty()) {
1113 desc_tx->
m_state = inactive_state;
1118 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1120 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1121 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1122 const auto wit = mapWallet.find(it->second);
1123 if (wit != mapWallet.end()) {
1124 txs.push_back(&wit->second);
1132 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
1135 if (fInsertedNew || fUpdated)
1149 if (!strCmd.empty())
1154 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1168 std::thread
t(runCommand, strCmd);
1178 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1180 if (!fill_wtx(wtx, ins.second)) {
1187 auto lookup_block = [&](
const uint256& hash,
int& height,
TxState& state) {
1199 lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, wtx.
m_state);
1201 lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, wtx.
m_state);
1208 for (
const CTxIn& txin : wtx.
tx->vin) {
1210 if (it != mapWallet.end()) {
1226 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1228 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1229 while (range.first != range.second) {
1230 if (range.first->second != tx.
GetHash()) {
1231 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);
1232 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1239 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1240 if (fExisted && !fUpdate)
return false;
1252 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1254 if (!dest.internal.has_value()) {
1259 if (!dest.internal.has_value())
continue;
1273 TxState tx_state = std::visit([](
auto&& s) ->
TxState {
return s; }, state);
1278 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1295 for (
const CTxIn& txin : tx->vin) {
1297 if (it != mapWallet.end()) {
1298 it->second.MarkDirty();
1308 auto it = mapWallet.find(hashTx);
1309 assert(it != mapWallet.end());
1317 assert(!wtx.isConfirmed());
1318 assert(!wtx.InMempool());
1320 if (!wtx.isConflicted() && !wtx.isAbandoned()) {
1342 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1347 if (conflictconfirms >= 0)
1369 std::set<uint256> todo;
1370 std::set<uint256> done;
1372 todo.insert(tx_hash);
1374 while (!todo.empty()) {
1378 auto it = mapWallet.find(now);
1379 assert(it != mapWallet.end());
1382 TxUpdate update_state = try_updating_state(wtx);
1383 if (update_state != TxUpdate::UNCHANGED) {
1387 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); ++i) {
1388 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(now, i));
1389 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1390 if (!done.count(iter->second)) {
1391 todo.insert(iter->second);
1396 if (update_state == TxUpdate::NOTIFY_CHANGED) {
1402 MarkInputsDirty(wtx.
tx);
1422 auto it = mapWallet.find(tx->GetHash());
1423 if (it != mapWallet.end()) {
1430 auto it = mapWallet.find(tx->GetHash());
1431 if (it != mapWallet.end()) {
1470 m_last_block_processed_height = block.
height;
1471 m_last_block_processed = block.
hash;
1478 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1493 m_last_block_processed_height = block.
height - 1;
1496 int disconnect_height = block.
height;
1501 for (
const CTxIn& tx_in : ptx->vin) {
1503 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1505 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1508 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1509 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1513 auto try_updating_state = [&](
CWalletTx& tx) {
1533 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1549 const auto mi = mapWallet.find(txin.
prevout.
hash);
1550 if (mi != mapWallet.end())
1578 result = std::max(result, spk_man_pair.second->IsMine(script));
1599 if (outpoint.
n >= wtx->tx->vout.size()) {
1602 return IsMine(wtx->tx->vout[outpoint.
n]);
1617 throw std::runtime_error(std::string(__func__) +
": value out of range");
1625 bool result =
false;
1627 if (!spk_man->IsHDEnabled())
return false;
1639 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1646 void CWallet::SetWalletFlag(uint64_t
flags)
1651 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1665 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1700 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1712 LOCK(spk_man->cs_KeyStore);
1713 return spk_man->ImportScripts(scripts, timestamp);
1722 LOCK(spk_man->cs_KeyStore);
1723 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1726 bool CWallet::ImportPubKeys(
const std::vector<CKeyID>& ordered_pubkeys,
const std::map<CKeyID, CPubKey>& pubkey_map,
const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins,
const bool add_keypool,
const bool internal,
const int64_t timestamp)
1732 LOCK(spk_man->cs_KeyStore);
1733 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1736 bool CWallet::ImportScriptPubKeys(
const std::string& label,
const std::set<CScript>& script_pub_keys,
const bool have_solving_data,
const bool apply_label,
const int64_t timestamp)
1742 LOCK(spk_man->cs_KeyStore);
1743 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1748 for (
const CScript& script : script_pub_keys) {
1762 if (new_birth_time < birthtime) {
1780 int start_height = 0;
1821 constexpr
auto INTERVAL_TIME{60s};
1822 auto current_time{reserver.
now()};
1823 auto start_time{reserver.
now()};
1827 uint256 block_hash = start_block;
1830 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1834 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1843 double progress_current = progress_begin;
1844 int block_height = start_height;
1846 if (progress_end - progress_begin > 0.0) {
1847 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1851 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1855 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1856 if (next_interval) {
1857 current_time = reserver.
now();
1858 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1861 bool fetch_block{
true};
1862 if (fast_rescan_filter) {
1863 fast_rescan_filter->UpdateIfNeeded();
1864 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1865 if (matches_block.has_value()) {
1866 if (*matches_block) {
1871 fetch_block =
false;
1874 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.
ToString());
1880 bool block_still_active =
false;
1881 bool next_block =
false;
1892 if (!block_still_active) {
1899 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1906 if (save_progress && next_interval) {
1921 if (max_height && block_height >= *max_height) {
1932 block_hash = next_block_hash;
1937 const uint256 prev_tip_hash = tip_hash;
1939 if (!max_height && prev_tip_hash != tip_hash) {
1951 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1953 }
else if (block_height &&
chain().shutdownRequested()) {
1954 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1957 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
1998 result.erase(myHash);
2010 if (!
chain().isReadyToBroadcast())
return false;
2051 int submitted_tx_count = 0;
2058 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2059 for (
auto& [txid, wtx] : mapWallet) {
2061 if (!wtx.isUnconfirmed())
continue;
2066 to_submit.insert(&wtx);
2069 for (
auto wtx : to_submit) {
2070 std::string unused_err_string;
2075 if (submitted_tx_count > 0) {
2076 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2085 if (!pwallet->ShouldResend())
continue;
2086 pwallet->ResubmitWalletTransactions(
true,
false);
2087 pwallet->SetNextResend();
2102 std::map<COutPoint, Coin> coins;
2103 for (
auto& input : tx.
vin) {
2104 const auto mi = mapWallet.find(input.prevout.hash);
2105 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2110 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2112 std::map<int, bilingual_str> input_errors;
2122 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2138 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2139 const CTxIn& txin = psbtx.
tx->vin[i];
2149 const auto it = mapWallet.find(txhash);
2150 if (it != mapWallet.end()) {
2163 int n_signed_this_spkm = 0;
2164 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize);
2170 (*n_signed) += n_signed_this_spkm;
2178 for (
const auto& input : psbtx.
inputs) {
2190 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2192 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2202 return *change_type;
2211 bool any_wpkh{
false};
2213 bool any_pkh{
false};
2215 for (
const auto& recipient : vecSend) {
2216 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2218 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2220 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2222 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2228 if (has_bech32m_spkman && any_tr) {
2233 if (has_bech32_spkman && any_wpkh) {
2238 if (has_p2sh_segwit_spkman && any_sh) {
2244 if (has_legacy_spkman && any_pkh) {
2249 if (has_bech32m_spkman) {
2252 if (has_bech32_spkman) {
2269 wtx.
mapValue = std::move(mapValue);
2278 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2282 for (
const CTxIn& txin : tx->vin) {
2293 std::string err_string;
2295 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2310 spk_man_pair.second->RewriteDB();
2320 return nLoadWalletRet;
2327 for (
const uint256& hash : vHashOut) {
2328 const auto& it = mapWallet.find(hash);
2329 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2330 for (
const auto& txin : it->second.tx->vin)
2331 mapTxSpends.erase(txin.prevout);
2332 mapWallet.erase(it);
2341 spk_man_pair.second->RewriteDB();
2347 return nZapSelectTxRet;
2356 bool fUpdated =
false;
2358 std::optional<AddressPurpose> purpose;
2361 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2362 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2363 m_address_book[address].SetLabel(strName);
2366 purpose = m_address_book[address].purpose = new_purpose;
2368 purpose = m_address_book[address].purpose;
2400 m_address_book.erase(address);
2414 if (legacy_spk_man) {
2415 return legacy_spk_man->KeypoolCountExternalKeys();
2418 unsigned int count = 0;
2420 count += spk_man.second->GetKeyPoolSize();
2430 unsigned int count = 0;
2432 count += spk_man->GetKeyPoolSize();
2442 res &= spk_man->TopUp(kpSize);
2455 auto op_dest = spk_man->GetNewDestination(type);
2478 return std::nullopt;
2481 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2483 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2489 for (
auto& entry : mapWallet) {
2492 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2505 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2506 const auto& entry = item.second;
2507 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2514 std::vector<CTxDestination> result;
2522 result.emplace_back(dest);
2530 std::set<std::string> label_set;
2532 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2533 if (_is_change)
return;
2534 if (!purpose || purpose == _purpose) {
2535 label_set.insert(_label);
2551 if (!op_address)
return op_address;
2581 if (signer_spk_man ==
nullptr) {
2585 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2593 setLockedCoins.insert(output);
2603 bool was_locked = setLockedCoins.erase(output);
2604 if (batch && was_locked) {
2613 bool success =
true;
2615 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2618 setLockedCoins.clear();
2625 return setLockedCoins.count(output) > 0;
2631 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2632 it != setLockedCoins.end(); it++) {
2634 vOutpts.push_back(outpt);
2642 mapKeyBirth.clear();
2645 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2652 assert(spk_man !=
nullptr);
2656 for (
const auto& entry : spk_man->mapKeyMetadata) {
2657 if (entry.second.nCreateTime) {
2658 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2664 if (mapKeyBirth.count(keyid) == 0)
2665 mapKeyFirstBlock[keyid] = &max_confirm;
2669 if (mapKeyFirstBlock.empty())
2673 for (
const auto& entry : mapWallet) {
2678 for (
const CTxOut &txout : wtx.
tx->vout) {
2682 auto rit = mapKeyFirstBlock.find(keyid);
2683 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2693 for (
const auto& entry : mapKeyFirstBlock) {
2725 std::optional<uint256> block_hash;
2727 block_hash = conf->confirmed_block_hash;
2729 block_hash = conf->conflicting_block_hash;
2735 int64_t block_max_time;
2736 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2737 if (rescanning_old_block) {
2738 nTimeSmart = block_max_time;
2741 int64_t latestEntry = 0;
2744 int64_t latestTolerated = latestNow + 300;
2746 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2756 if (nSmartTime <= latestTolerated) {
2757 latestEntry = nSmartTime;
2758 if (nSmartTime > latestNow) {
2759 latestNow = nSmartTime;
2765 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2776 if (std::get_if<CNoDestination>(&dest))
2780 if (
auto* data{
common::FindKey(m_address_book, dest)}) data->previously_spent =
false;
2790 m_address_book[dest].previously_spent =
true;
2795 m_address_book[dest].receive_requests[id] = request;
2800 if (
auto* data{
common::FindKey(m_address_book, dest)})
return data->previously_spent;
2806 std::vector<std::string>
values;
2807 for (
const auto& [dest, entry] : m_address_book) {
2808 for (
const auto& [
id, request] : entry.receive_requests) {
2809 values.emplace_back(request);
2818 m_address_book[dest].receive_requests[id] = value;
2825 m_address_book[dest].receive_requests.erase(
id);
2838 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2839 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2840 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2843 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2844 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2845 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2850 return MakeDatabase(wallet_path, options, status, error_string);
2857 const std::string& walletFile = database->Filename();
2859 const auto start{SteadyClock::now()};
2864 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
2867 bool rescan_required =
false;
2868 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2871 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2876 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
2877 " or address metadata may be missing or incorrect."),
2885 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2893 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect."
2894 " Rescanning wallet."), walletFile));
2895 rescan_required =
true;
2897 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n"
2898 "The wallet might had been created on a newer version.\n"
2899 "Please try running the latest software version.\n"), walletFile);
2902 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
2903 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
2912 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2920 walletInstance->InitWalletFlags(wallet_creation_flags);
2924 walletInstance->SetupLegacyScriptPubKeyMan();
2928 LOCK(walletInstance->cs_wallet);
2930 walletInstance->SetupDescriptorScriptPubKeyMans();
2934 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2935 if (!spk_man->SetupGeneration()) {
2936 error =
_(
"Unable to generate initial keys");
2948 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
2951 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2952 if (spk_man->HavePrivateKeys()) {
2953 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2959 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
2965 walletInstance->m_default_address_type = parsed.value();
2968 if (!
args.
GetArg(
"-changetype",
"").empty()) {
2974 walletInstance->m_default_change_type = parsed.value();
2984 _(
"This is the minimum transaction fee you pay on every transaction."));
2987 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
2991 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
2992 if (max_aps_fee ==
"-1") {
2993 walletInstance->m_max_aps_fee = -1;
2994 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
2997 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2999 walletInstance->m_max_aps_fee = max_fee.value();
3008 if (!fallback_fee) {
3013 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3015 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3019 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3028 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3030 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3040 _(
"This is the transaction fee you will pay if you send a transaction."));
3043 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3046 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3058 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3062 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3067 walletInstance->m_default_max_tx_fee = max_fee.value();
3071 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3072 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3081 _(
"The wallet will avoid paying less than the minimum relay fee."));
3088 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3091 walletInstance->TopUpKeyPool();
3094 std::optional<int64_t> time_first_key;
3095 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3096 int64_t time = spk_man->GetTimeFirstKey();
3097 if (!time_first_key || time < *time_first_key) time_first_key = time;
3099 if (time_first_key) walletInstance->m_birth_time = *time_first_key;
3106 LOCK(walletInstance->cs_wallet);
3108 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3109 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3110 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3113 return walletInstance;
3118 LOCK(walletInstance->cs_wallet);
3120 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3121 walletInstance->m_chain = &
chain;
3131 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3147 walletInstance->m_attaching_chain =
true;
3148 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3151 int rescan_height = 0;
3152 if (!rescan_required)
3158 rescan_height = *fork_height;
3166 walletInstance->m_last_block_processed_height = *tip_height;
3168 walletInstance->m_last_block_processed.
SetNull();
3169 walletInstance->m_last_block_processed_height = -1;
3172 if (tip_height && *tip_height != rescan_height)
3176 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3177 if (time_first_key) {
3184 rescan_height = *tip_height;
3192 int block_height = *tip_height;
3193 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3197 if (rescan_height != block_height) {
3208 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3210 "Error loading wallet. Wallet requires blocks to be downloaded, "
3211 "and software does not currently support loading wallets while "
3212 "blocks are being downloaded out of order when using assumeutxo "
3213 "snapshots. Wallet should be able to load successfully after "
3214 "node sync reaches height %s"), block_height);
3220 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3225 error =
_(
"Failed to rescan the wallet during initialization");
3229 walletInstance->m_attaching_chain =
false;
3231 walletInstance->GetDatabase().IncrementUpdateCounter();
3233 walletInstance->m_attaching_chain =
false;
3240 const auto& address_book_it = m_address_book.find(dest);
3241 if (address_book_it == m_address_book.end())
return nullptr;
3242 if ((!allow_change) && address_book_it->second.IsChange()) {
3245 return &address_book_it->second;
3257 if (version < prev_version) {
3258 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3266 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);
3274 if (!spk_man->Upgrade(prev_version, version,
error)) {
3331 assert(chain_depth >= 0);
3354 return vMasterKey.empty();
3364 if (!vMasterKey.empty()) {
3365 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3379 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
3383 vMasterKey = vMasterKeyIn;
3391 std::set<ScriptPubKeyMan*> spk_mans;
3392 for (
bool internal : {
false,
true}) {
3396 spk_mans.insert(spk_man);
3405 std::set<ScriptPubKeyMan*> spk_mans;
3407 spk_mans.insert(spk_man_pair.second.get());
3415 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3416 if (it == spk_managers.end()) {
3424 std::set<ScriptPubKeyMan*> spk_mans;
3427 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3428 spk_mans.insert(spk_man_pair.second.get());
3451 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3452 return spk_man_pair.second->GetSolvingProvider(script);
3460 std::vector<WalletDescriptor> descs;
3463 LOCK(desc_spk_man->cs_desc_man);
3464 descs.push_back(desc_spk_man->GetWalletDescriptor());
3507 uint256 id = spk_manager->GetID();
3526 spk_man->NotifyFirstKeyTimeChanged.connect(std::bind(&
CWallet::FirstKeyTimeChanged,
this, std::placeholders::_1, std::placeholders::_2));
3545 for (
bool internal : {
false,
true}) {
3550 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3552 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3553 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3556 spk_manager->SetupDescriptorGeneration(master_key,
t,
internal);
3557 uint256 id = spk_manager->GetID();
3587 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3588 for (
bool internal : {
false,
true}) {
3589 const UniValue& descriptor_vals = signer_res.
find_value(
internal ?
"internal" :
"receive");
3590 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3592 const std::string& desc_str = desc_val.getValStr();
3594 std::string desc_error;
3595 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, desc_error,
false);
3596 if (desc ==
nullptr) {
3597 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3599 if (!desc->GetOutputType()) {
3604 spk_manager->SetupDescriptor(std::move(desc));
3605 uint256 id = spk_manager->GetID();
3617 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3632 spk_mans[type] = spk_man;
3634 const auto it = spk_mans_other.find(type);
3635 if (it != spk_mans_other.end() && it->second == spk_man) {
3636 spk_mans_other.erase(type);
3645 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3649 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3653 spk_mans.erase(type);
3665 return spk_man !=
nullptr;
3685 return std::nullopt;
3690 return std::nullopt;
3694 if (!desc_spk_man) {
3695 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3698 LOCK(desc_spk_man->cs_desc_man);
3699 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3700 assert(type.has_value());
3710 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3717 spk_man->UpdateWalletDescriptor(desc);
3720 spk_man = new_spk_man.get();
3723 uint256 id = new_spk_man->GetID();
3728 for (
const auto& entry : signing_provider.
keys) {
3729 const CKey& key = entry.second;
3730 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3734 if (!spk_man->TopUp()) {
3742 auto script_pub_keys = spk_man->GetScriptPubKeys();
3743 if (script_pub_keys.empty()) {
3744 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3749 for (
const auto& script : script_pub_keys) {
3759 spk_man->WriteDescriptor();
3768 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3771 error =
_(
"Error: This wallet already uses SQLite");
3776 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3777 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3778 std::vector<std::pair<SerializeData, SerializeData>> records;
3780 error =
_(
"Error: Unable to begin reading all records in the database");
3787 status = cursor->Next(ss_key, ss_value);
3793 records.emplace_back(key, value);
3798 error =
_(
"Error: Unable to read all records in the database");
3805 fs::remove(db_path);
3816 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status,
error);
3823 bool began = batch->TxnBegin();
3825 for (
const auto& [key, value] : records) {
3826 if (!batch->Write(
Span{key},
Span{value})) {
3833 bool committed = batch->TxnCommit();
3846 if (res == std::nullopt) {
3847 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
3848 return std::nullopt;
3859 error =
_(
"Error: This wallet is already a descriptor wallet");
3864 std::set<CTxDestination> not_migrated_dests;
3872 error =
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
3875 uint256 id = desc_spkm->GetID();
3903 std::vector<uint256> txids_to_delete;
3913 error =
_(
"Error: Could not add watchonly tx to watchonly wallet");
3917 txids_to_delete.push_back(wtx->GetHash());
3922 error =
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
3927 if (txids_to_delete.size() > 0) {
3928 std::vector<uint256> deleted_txids;
3930 error =
_(
"Error: Could not delete watchonly transactions");
3933 if (deleted_txids != txids_to_delete) {
3934 error =
_(
"Error: Not all watchonly txs could be deleted");
3938 for (
const uint256& txid : deleted_txids) {
3944 std::vector<CTxDestination> dests_to_delete;
3945 for (
const auto& addr_pair : m_address_book) {
3948 if (!
IsMine(addr_pair.first)) {
3954 std::string label = addr_pair.second.GetLabel();
3955 data.
watchonly_wallet->m_address_book[addr_pair.first].purpose = addr_pair.second.purpose;
3956 if (!addr_pair.second.IsChange()) {
3959 dests_to_delete.push_back(addr_pair.first);
3967 std::string label = addr_pair.second.GetLabel();
3968 data.
solvable_wallet->m_address_book[addr_pair.first].purpose = addr_pair.second.purpose;
3969 if (!addr_pair.second.IsChange()) {
3970 data.
solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
3972 dests_to_delete.push_back(addr_pair.first);
3978 if (not_migrated_dests.count(addr_pair.first) > 0) {
3979 dests_to_delete.push_back(addr_pair.first);
3984 error =
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets");
3992 std::string label = addr_pair.second.GetLabel();
3993 data.
watchonly_wallet->m_address_book[addr_pair.first].purpose = addr_pair.second.purpose;
3994 if (!addr_pair.second.IsChange()) {
4001 std::string label = addr_pair.second.GetLabel();
4002 data.
solvable_wallet->m_address_book[addr_pair.first].purpose = addr_pair.second.purpose;
4003 if (!addr_pair.second.IsChange()) {
4004 data.
solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
4014 for (
const auto& [destination, addr_book_data] :
wallet.m_address_book) {
4016 std::optional<std::string> label = addr_book_data.IsChange() ? std::nullopt : std::make_optional(addr_book_data.GetLabel());
4018 if (addr_book_data.purpose) batch.WritePurpose(address,
PurposeToString(*addr_book_data.purpose));
4019 if (label) batch.WriteName(address, *label);
4026 if (dests_to_delete.size() > 0) {
4027 for (
const auto& dest : dests_to_delete) {
4029 error =
_(
"Error: Unable to remove watchonly address book data");
4054 std::optional<MigrationData> data =
wallet.GetDescriptorsForLegacy(
error);
4055 if (data == std::nullopt)
return false;
4058 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4071 if (data->watch_descs.size() > 0) {
4072 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4075 std::vector<bilingual_str> warnings;
4076 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4079 error =
_(
"Error: Failed to create new watchonly wallet");
4082 res.watchonly_wallet = data->watchonly_wallet;
4083 LOCK(data->watchonly_wallet->cs_wallet);
4086 for (
const auto& [desc_str, creation_time] : data->watch_descs) {
4089 std::string parse_err;
4090 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4092 assert(!desc->IsRange());
4096 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4102 if (data->solvable_descs.size() > 0) {
4103 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4106 std::vector<bilingual_str> warnings;
4107 std::string wallet_name =
wallet.GetName() +
"_solvables";
4110 error =
_(
"Error: Failed to create new watchonly wallet");
4113 res.solvables_wallet = data->solvable_wallet;
4114 LOCK(data->solvable_wallet->cs_wallet);
4117 for (
const auto& [desc_str, creation_time] : data->solvable_descs) {
4120 std::string parse_err;
4121 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4123 assert(!desc->IsRange());
4127 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4146 std::vector<bilingual_str> warnings;
4151 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4170 if (!local_wallet) {
4175 if (!local_wallet->GetLegacyScriptPubKeyMan()) {
4176 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4182 fs::path backup_path = this_wallet_dir / backup_filename;
4184 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4188 bool success =
false;
4190 LOCK(local_wallet->cs_wallet);
4193 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4194 if (passphrase.find(
'\0') == std::string::npos) {
4195 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4197 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4198 "The passphrase contains a null character (ie - a zero byte). "
4199 "If this passphrase was set with a version of this software prior to 25.0, "
4200 "please try again with only the characters up to — but not including — "
4201 "the first null character.")};
4214 assert(local_wallet.use_count() == 1);
4215 local_wallet.reset();
4222 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4225 std::vector<fs::path> wallet_dirs;
4226 wallet_dirs.push_back(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4229 assert(local_wallet.use_count() == 1);
4230 local_wallet.reset();
4233 std::vector<std::shared_ptr<CWallet>> created_wallets;
4238 for (std::shared_ptr<CWallet>& w : created_wallets) {
4239 wallet_dirs.push_back(
fs::PathFromString(w->GetDatabase().Filename()).parent_path());
4243 for (std::shared_ptr<CWallet>& w : created_wallets) {
4245 error +=
_(
"\nUnable to cleanup failed migration");
4252 for (
fs::path& dir : wallet_dirs) {
4253 fs::remove_all(dir);
4258 std::vector<bilingual_str> warnings;
4260 error +=
_(
"\nUnable to restore backup of wallet.");
4265 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4266 fs::remove(temp_backup_location);
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
#define PACKAGE_BUGREPORT
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define CHECK_NONFATAL(condition)
Identity function.
#define Assert(val)
Identity function.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::vector< CTransactionRef > vtx
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
An encapsulated private key.
bool IsValid() const
Check whether this private key is valid.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
A reference to a CKey: the Hash160 of its serialized public key.
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 uint256 & GetHash() const
const std::vector< CTxIn > vin
An input of a transaction.
An output of a transaction.
Double ended buffer combining vector and stream-like interfaces.
Enables interaction with an external signing device or service, such as a hardware wallet.
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
RecursiveMutex cs_KeyStore
std::unordered_set< Element, ByteVectorHash > ElementSet
Different type to mark Mutex at global scope.
A Span is an object that can refer to a contiguous sequence of objects.
void push_back(UniValue val)
const UniValue & find_value(std::string_view key) const
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
std::string ToString() const
constexpr unsigned char * begin()
std::string GetHex() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
virtual CBlockLocator getActiveChainLocator(const uint256 &block_hash)=0
Return a locator that refers to a block in the active chain.
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height,...
virtual bool havePruned()=0
Check if any block has been pruned.
virtual common::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual bool updateRwSetting(const std::string &name, const common::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
Helper for findBlock to selectively return pieces of block data.
FoundBlock & height(int &height)
Encryption/decryption context with key information.
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
A key from a CWallet's keypool.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
CPubKey vchPubKey
The public key.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
std::vector< unsigned char > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
std::vector< unsigned char > vchCryptedKey
unsigned int nDeriveIterations
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
std::atomic< bool > fAbortRescan
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
bool HaveChain() const
Interface to assert chain access.
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
OutputType m_default_address_type
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
std::function< void(const CTxDestination &dest, const std::string &label, bool is_change, const std::optional< AddressPurpose > purpose)> ListAddrBookFunc
Walk-through the address book entries.
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CKeyingMaterial & GetEncryptionKey() const override
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
int GetTxDepthInMainChain(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
unsigned int nMasterKeyMaxID
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
std::atomic< double > m_scanning_progress
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
WalletDatabase & GetDatabase() const override
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
bool IsLegacy() const
Determine if we are a legacy wallet.
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
bool MigrateToSQLite(bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Move all records from the BDB database to a new SQLite database for storage.
bool BackupWallet(const std::string &strDest) const
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
std::string m_name
Wallet name: relative directory name or "" for default wallet.
bool SetAddressPreviouslySpent(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
RecursiveMutex m_relock_mutex
std::string m_notify_tx_changed_script
Notify external script when a wallet transaction comes in or is updated (handled by -walletnotify)
std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
std::atomic< bool > m_attaching_chain
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool HasEncryptionKeys() const override
static std::shared_ptr< CWallet > Create(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
bool CanGrindR() const
Whether the (external) signer performs R-value signature grinding.
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
MasterKeyMap mapMasterKeys
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
void LoadAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &request) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Appends payment request to destination.
void AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
interfaces::Chain * m_chain
Interface for accessing chain state.
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool IsLocked() const override
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process,...
RecursiveMutex cs_wallet
Main wallet lock.
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
std::atomic< int64_t > m_best_block_time
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, const bool rescan_required, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, AddressPurpose purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
std::multimap< int64_t, CWalletTx * > TxItems
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ApplyMigrationData(MigrationData &data, bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan,...
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
std::function< TxUpdate(CWalletTx &wtx)> TryUpdatingStateFn
std::atomic< int64_t > m_birth_time
void LoadAddressPreviouslySpent(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks destination as previously spent.
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
interfaces::Chain & chain() const
Interface for accessing chain state.
A transaction with a bunch of additional info that only the owner cares about.
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
std::vector< std::pair< std::string, std::string > > vOrderForm
mapValue_t mapValue
Key/value map with information about the transaction.
int64_t nOrderPos
position in ordered transaction list
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
unsigned int nTimeReceived
time received by this node
bool isConflicted() const
void SetTx(CTransactionRef arg)
unsigned int fTimeReceivedIsTxTime
const uint256 & GetHash() const
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
void MarkDirty()
make sure balances are recalculated
void UpgradeDescriptorCache()
bool HasWalletDescriptor(const WalletDescriptor &desc) const
static ExternalSigner GetExternalSigner()
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
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,...
std::set< CKeyID > GetKeys() const override
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
A wrapper to reserve an address from a wallet.
const CWallet *const pwallet
The wallet to reserve from.
CTxDestination address
The destination.
bool fInternal
Whether this is from the internal (change output) keypool.
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called.
int64_t nIndex
The index of the address's key in the keypool.
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
virtual util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool)
Access to the wallet database.
bool TxnAbort()
Abort current transaction.
bool EraseName(const std::string &strAddress)
DBErrors LoadWallet(CWallet *pwallet)
bool WriteBestBlock(const CBlockLocator &locator)
bool ReadBestBlock(CBlockLocator &locator)
bool 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)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
virtual void ReloadDbEnv()=0
virtual void Close()=0
Flush to the database file and close the database.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
virtual void Flush()=0
Make sure all changes are flushed to database file.
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
Clock::time_point now() const
bool reserve(bool with_passphrase=false)
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
std::string ShellEscape(const std::string &arg)
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
void MarkDestinationsDirty(const std::set< CTxDestination > &destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks all outputs in each one of the destinations dirty, so their cache is reset and does not return ...
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
bool TopUpKeyPool(unsigned int kpSize=0)
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
void ReturnDestination()
Return reserved address.
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::optional< int64_t > GetOldestKeyPoolTime() const
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< std::string > ListAddrBookLabels(const std::optional< AddressPurpose > purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DelAddressBook(const CTxDestination &address)
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
bool HasWalletSpend(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet.
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportScriptPubKeys(const std::string &label, const std::set< CScript > &script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block.
void updatedBlockTip() override
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void Flush()
Flush wallet (bitdb flush)
void blockDisconnected(const interfaces::BlockInfo &block) override
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
void blockConnected(const interfaces::BlockInfo &block) override
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
void FirstKeyTimeChanged(const ScriptPubKeyMan *spkm, int64_t new_birth_time)
Updates wallet birth time if 'new_birth_time' is below it.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void ResubmitWalletTransactions(bool relay, bool force)
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void RecursiveUpdateTxState(const uint256 &tx_hash, const TryUpdatingStateFn &try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction (and its in-wallet descendants) as a particular tx state.
bool CanGetAddresses(bool internal=false) const
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate, const bool save_progress)
Scan the block chain (starting in start_block) for transactions from or to us.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo >> &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
static NodeClock::time_point GetDefaultNextResend()
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool AbandonTransaction(const uint256 &hashTx)
void chainStateFlushed(const CBlockLocator &loc) override
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
bool EncryptWallet(const SecureString &strWalletPassphrase)
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
DBErrors ReorderTransactions()
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, const SyncTxState &state, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx) override
void Close()
Close wallet database.
bool SubmitTxMemoryPoolAndRelay(CWalletTx &wtx, std::string &err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
std::string EncodeDestination(const CTxDestination &dest)
#define LogPrint(category,...)
bool error(const char *fmt, const Args &... args)
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
@ PRIVATE_KEY_NOT_AVAILABLE
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
static path absolute(const path &p)
static path u8path(const std::string &utf8_str)
static auto quoted(const std::string &s)
static bool exists(const path &p)
static bool copy_file(const path &from, const path &to, copy_options options)
static std::string PathToString(const path &path)
Convert path object to a byte string.