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();
169 wallet->m_chain_notifications_handler.reset();
172 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
173 if (i == context.wallets.end())
return false;
174 context.wallets.erase(i);
187 std::vector<bilingual_str> warnings;
194 return context.wallets;
200 count = context.wallets.size();
201 return count == 1 ? context.wallets[0] :
nullptr;
207 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
216 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
223 for (
auto& load_wallet : context.wallet_load_fns) {
238 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
320 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
321 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
322 assert(desc_spkm !=
nullptr);
323 AddScriptPubKeys(desc_spkm);
325 if (desc_spkm->IsHDEnabled()) {
331 void UpdateIfNeeded()
335 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
336 assert(desc_spkm !=
nullptr);
337 int32_t current_range_end{desc_spkm->GetEndRange()};
338 if (current_range_end > last_range_end) {
339 AddScriptPubKeys(desc_spkm, last_range_end);
345 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const
361 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
363 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
364 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
373 if (!result.second) {
378 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status, error, warnings);
399 if (!passphrase.empty()) {
405 error =
Untranslated(
"Private keys must be disabled when using an external signer");
412 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
419 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.");
434 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), wallet_creation_flags, error, warnings);
443 if (!
wallet->EncryptWallet(passphrase)) {
444 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
450 if (!
wallet->Unlock(passphrase)) {
451 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
460 wallet->SetupDescriptorScriptPubKeyMans();
462 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
463 if (!spk_man->SetupGeneration()) {
464 error =
Untranslated(
"Unable to generate initial keys");
479 wallet->postInitProcess();
486 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."));
502 auto wallet_file = wallet_path /
"wallet.dat";
503 std::shared_ptr<CWallet>
wallet;
518 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
520 if (load_after_restore) {
521 wallet =
LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
523 }
catch (
const std::exception& e) {
530 if (load_after_restore && !
wallet) {
531 fs::remove_all(wallet_path);
545 const auto it = mapWallet.find(hash);
546 if (it == mapWallet.end())
548 return &(it->second);
562 spk_man->UpgradeKeyMetadata();
586 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
588 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
590 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
592 if (
Unlock(_vMasterKey)) {
616 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
618 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
623 auto start{SteadyClock::now()};
624 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
625 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
627 start = SteadyClock::now();
628 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
629 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
631 if (pMasterKey.second.nDeriveIterations < 25000)
632 pMasterKey.second.nDeriveIterations = 25000;
634 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
636 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
638 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
665 if (nWalletVersion >= nVersion)
668 nWalletVersion = nVersion;
672 if (nWalletVersion > 40000)
681 std::set<uint256> result;
684 const auto it = mapWallet.find(txid);
685 if (it == mapWallet.end())
689 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
691 for (
const CTxIn& txin : wtx.
tx->vin)
693 if (mapTxSpends.count(txin.
prevout) <= 1)
695 range = mapTxSpends.equal_range(txin.
prevout);
696 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
697 result.insert(_it->second);
705 const Txid& txid = tx->GetHash();
706 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
730 int nMinOrderPos = std::numeric_limits<int>::max();
732 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
733 const CWalletTx* wtx = &mapWallet.at(it->second);
745 for (TxSpends::iterator it = range.first; it != range.second; ++it)
747 const uint256& hash = it->second;
749 if (copyFrom == copyTo)
continue;
750 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
769 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
770 range = mapTxSpends.equal_range(outpoint);
772 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
773 const uint256& wtxid = it->second;
774 const auto mit = mapWallet.find(wtxid);
775 if (mit != mapWallet.end()) {
776 const auto& wtx = mit->second;
777 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
786 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
795 std::pair<TxSpends::iterator, TxSpends::iterator> range;
796 range = mapTxSpends.equal_range(outpoint);
806 for (
const CTxIn& txin : wtx.
tx->vin)
827 auto start{SteadyClock::now()};
829 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
831 start = SteadyClock::now();
850 delete encrypted_batch;
851 encrypted_batch =
nullptr;
857 auto spk_man = spk_man_pair.second.get();
858 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
860 delete encrypted_batch;
861 encrypted_batch =
nullptr;
872 delete encrypted_batch;
873 encrypted_batch =
nullptr;
879 delete encrypted_batch;
880 encrypted_batch =
nullptr;
883 Unlock(strWalletPassphrase);
890 if (spk_man->IsHDEnabled()) {
891 if (!spk_man->SetupGeneration(
true)) {
922 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
925 for (
auto& entry : mapWallet)
932 std::vector<int64_t> nOrderPosOffsets;
933 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
940 nOrderPos = nOrderPosNext++;
941 nOrderPosOffsets.push_back(nOrderPos);
948 int64_t nOrderPosOff = 0;
949 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
951 if (nOrderPos >= nOffsetStart)
954 nOrderPos += nOrderPosOff;
955 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
973 int64_t nRet = nOrderPosNext++;
986 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
987 item.second.MarkDirty();
995 auto mi = mapWallet.find(originalHash);
998 assert(mi != mapWallet.end());
1012 bool success =
true;
1034 tx_destinations.insert(dst);
1082 std::set<CTxDestination> tx_destinations;
1084 for (
const CTxIn& txin : tx->vin) {
1093 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1095 bool fInsertedNew =
ret.second;
1096 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1110 if (state.index() != wtx.
m_state.index()) {
1122 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1130 std::vector<CWalletTx*> txs{&wtx};
1134 while (!txs.empty()) {
1137 desc_tx->
m_state = inactive_state;
1142 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1144 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1145 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1146 const auto wit = mapWallet.find(it->second);
1147 if (wit != mapWallet.end()) {
1148 txs.push_back(&wit->second);
1159 if (fInsertedNew || fUpdated)
1173 if (!strCmd.empty())
1178 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1192 std::thread
t(runCommand, strCmd);
1202 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1204 if (!fill_wtx(wtx, ins.second)) {
1216 for (
const CTxIn& txin : wtx.
tx->vin) {
1218 if (it != mapWallet.end()) {
1238 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1240 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1241 while (range.first != range.second) {
1242 if (range.first->second != tx.
GetHash()) {
1243 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);
1244 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1251 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1252 if (fExisted && !fUpdate)
return false;
1264 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1266 if (!dest.internal.has_value()) {
1271 if (!dest.internal.has_value())
continue;
1285 TxState tx_state = std::visit([](
auto&&
s) ->
TxState {
return s; }, state);
1290 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1307 for (
const CTxIn& txin : tx->vin) {
1309 if (it != mapWallet.end()) {
1310 it->second.MarkDirty();
1318 auto it = mapWallet.find(hashTx);
1319 assert(it != mapWallet.end());
1332 assert(!wtx.isConfirmed());
1333 assert(!wtx.InMempool());
1335 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1361 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1364 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1365 if (conflictconfirms >= 0)
1390 std::set<uint256> todo;
1391 std::set<uint256> done;
1393 todo.insert(tx_hash);
1395 while (!todo.empty()) {
1399 auto it = mapWallet.find(now);
1400 assert(it != mapWallet.end());
1403 TxUpdate update_state = try_updating_state(wtx);
1406 if (batch) batch->
WriteTx(wtx);
1408 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); ++i) {
1409 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(
Txid::FromUint256(now), i));
1410 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1411 if (!done.count(iter->second)) {
1412 todo.insert(iter->second);
1443 auto it = mapWallet.find(tx->GetHash());
1444 if (it != mapWallet.end()) {
1448 const Txid& txid = tx->GetHash();
1450 for (
const CTxIn& tx_in : tx->vin) {
1452 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1453 const uint256& spent_id = range.first->second;
1455 if (spent_id == txid)
continue;
1465 auto it = mapWallet.find(tx->GetHash());
1466 if (it != mapWallet.end()) {
1499 const Txid& txid = tx->GetHash();
1501 for (
const CTxIn& tx_in : tx->vin) {
1505 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1506 const uint256& spent_id = range.first->second;
1523 m_last_block_processed_height = block.
height;
1524 m_last_block_processed = block.
hash;
1531 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1546 m_last_block_processed_height = block.
height - 1;
1549 int disconnect_height = block.
height;
1554 for (
const CTxIn& tx_in : ptx->vin) {
1556 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1558 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1561 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1562 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1566 auto try_updating_state = [&](
CWalletTx& tx) {
1586void CWallet::BlockUntilSyncedToCurrentChain()
const {
1602 const auto mi = mapWallet.find(txin.
prevout.
hash);
1603 if (mi != mapWallet.end())
1634 for (
const auto& spkm : it->second) {
1635 res = std::max(res, spkm->IsMine(
script));
1643 return spkm->IsMine(
script);
1665 if (outpoint.
n >= wtx->tx->vout.size()) {
1668 return IsMine(wtx->tx->vout[outpoint.
n]);
1683 throw std::runtime_error(std::string(__func__) +
": value out of range");
1691 bool result =
false;
1693 if (!spk_man->IsHDEnabled())
return false;
1705 if (spk_man && spk_man->CanGetAddresses(internal)) {
1723 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1737 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1772 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1784 LOCK(spk_man->cs_KeyStore);
1785 return spk_man->ImportScripts(scripts, timestamp);
1794 LOCK(spk_man->cs_KeyStore);
1795 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1798bool CWallet::ImportPubKeys(
const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys,
const std::map<CKeyID, CPubKey>& pubkey_map,
const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins,
const bool add_keypool,
const int64_t timestamp)
1804 LOCK(spk_man->cs_KeyStore);
1805 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, timestamp);
1808bool 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)
1814 LOCK(spk_man->cs_KeyStore);
1815 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1834 if (time < birthtime) {
1852 int start_height = 0;
1893 constexpr auto INTERVAL_TIME{60
s};
1894 auto current_time{reserver.
now()};
1895 auto start_time{reserver.
now()};
1899 uint256 block_hash = start_block;
1902 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1906 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1915 double progress_current = progress_begin;
1916 int block_height = start_height;
1918 if (progress_end - progress_begin > 0.0) {
1919 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1923 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1927 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1928 if (next_interval) {
1929 current_time = reserver.
now();
1930 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1933 bool fetch_block{
true};
1934 if (fast_rescan_filter) {
1935 fast_rescan_filter->UpdateIfNeeded();
1936 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1937 if (matches_block.has_value()) {
1938 if (*matches_block) {
1943 fetch_block =
false;
1946 LogDebug(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.
ToString());
1952 bool block_still_active =
false;
1953 bool next_block =
false;
1964 if (!block_still_active) {
1971 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1978 if (save_progress && next_interval) {
1993 if (max_height && block_height >= *max_height) {
2012 block_hash = next_block_hash;
2017 const uint256 prev_tip_hash = tip_hash;
2019 if (!max_height && prev_tip_hash != tip_hash) {
2031 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
2033 }
else if (block_height &&
chain().shutdownRequested()) {
2034 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2037 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
2078 result.erase(myHash);
2090 if (!
chain().isReadyToBroadcast())
return false;
2131 int submitted_tx_count = 0;
2138 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2139 for (
auto& [txid, wtx] : mapWallet) {
2141 if (!wtx.isUnconfirmed())
continue;
2146 to_submit.insert(&wtx);
2149 for (
auto wtx : to_submit) {
2150 std::string unused_err_string;
2155 if (submitted_tx_count > 0) {
2156 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2164 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2165 if (!pwallet->ShouldResend())
continue;
2166 pwallet->ResubmitWalletTransactions(
true,
false);
2167 pwallet->SetNextResend();
2182 std::map<COutPoint, Coin> coins;
2183 for (
auto& input : tx.
vin) {
2184 const auto mi = mapWallet.find(input.prevout.hash);
2185 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2190 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2192 std::map<int, bilingual_str> input_errors;
2202 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2218 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2219 const CTxIn& txin = psbtx.
tx->vin[i];
2229 const auto it = mapWallet.find(txhash);
2230 if (it != mapWallet.end()) {
2243 int n_signed_this_spkm = 0;
2244 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type,
sign, bip32derivs, &n_signed_this_spkm, finalize)};
2250 (*n_signed) += n_signed_this_spkm;
2258 for (
size_t i = 0; i < psbtx.
inputs.size(); ++i) {
2270 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2272 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2282 return *change_type;
2291 bool any_wpkh{
false};
2293 bool any_pkh{
false};
2295 for (
const auto& recipient : vecSend) {
2296 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2298 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2300 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2302 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2308 if (has_bech32m_spkman && any_tr) {
2313 if (has_bech32_spkman && any_wpkh) {
2318 if (has_p2sh_segwit_spkman && any_sh) {
2324 if (has_legacy_spkman && any_pkh) {
2329 if (has_bech32m_spkman) {
2332 if (has_bech32_spkman) {
2349 wtx.
mapValue = std::move(mapValue);
2358 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2362 for (
const CTxIn& txin : tx->vin) {
2373 std::string err_string;
2375 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2392 spk_man_pair.second->RewriteDB();
2402 return nLoadWalletRet;
2412 return result.has_value();
2415 if (!was_txn_committed)
return util::Error{
_(
"Error starting/committing db txn for wallet transactions removal process")};
2425 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2426 std::vector<TxIterator> erased_txs;
2428 for (
const uint256& hash : txs_to_remove) {
2429 auto it_wtx = mapWallet.find(hash);
2430 if (it_wtx == mapWallet.end()) {
2436 erased_txs.emplace_back(it_wtx);
2442 for (
const auto& it : erased_txs) {
2443 const uint256 hash{it->first};
2444 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2445 for (
const auto& txin : it->second.tx->vin)
2446 mapTxSpends.erase(txin.prevout);
2447 mapWallet.erase(it);
2459 bool fUpdated =
false;
2461 std::optional<AddressPurpose> purpose;
2464 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2465 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2467 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2478 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2481 if (!batch.
WriteName(encoded_dest, strName)) {
2515 WalletLogPrintf(
"%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2537 m_address_book.erase(address);
2550 if (legacy_spk_man) {
2551 return legacy_spk_man->KeypoolCountExternalKeys();
2554 unsigned int count = 0;
2556 count += spk_man.second->GetKeyPoolSize();
2566 unsigned int count = 0;
2568 count += spk_man->GetKeyPoolSize();
2578 res &= spk_man->TopUp(kpSize);
2591 auto op_dest = spk_man->GetNewDestination(type);
2614 return std::nullopt;
2617 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2619 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2625 for (
auto& entry : mapWallet) {
2628 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2641 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2642 const auto& entry = item.second;
2643 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2650 std::vector<CTxDestination> result;
2658 result.emplace_back(dest);
2666 std::set<std::string> label_set;
2668 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2669 if (_is_change)
return;
2670 if (!purpose || purpose == _purpose) {
2671 label_set.insert(_label);
2688 if (!op_address)
return op_address;
2719 if (signer_spk_man ==
nullptr) {
2723 return signer_spk_man->DisplayAddress(dest,
signer);
2725 return util::Error{
_(
"There is no ScriptPubKeyManager for this address")};
2731 setLockedCoins.insert(output);
2741 bool was_locked = setLockedCoins.erase(output);
2742 if (batch && was_locked) {
2751 bool success =
true;
2753 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2756 setLockedCoins.clear();
2763 return setLockedCoins.count(output) > 0;
2769 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2770 it != setLockedCoins.end(); it++) {
2772 vOutpts.push_back(outpt);
2780 mapKeyBirth.clear();
2783 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2790 assert(spk_man !=
nullptr);
2794 for (
const auto& entry : spk_man->mapKeyMetadata) {
2795 if (entry.second.nCreateTime) {
2796 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2802 if (mapKeyBirth.count(keyid) == 0)
2803 mapKeyFirstBlock[keyid] = &max_confirm;
2807 if (mapKeyFirstBlock.empty())
2811 for (
const auto& entry : mapWallet) {
2816 for (
const CTxOut &txout : wtx.
tx->vout) {
2820 auto rit = mapKeyFirstBlock.find(keyid);
2821 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2831 for (
const auto& entry : mapKeyFirstBlock) {
2863 std::optional<uint256> block_hash;
2865 block_hash = conf->confirmed_block_hash;
2867 block_hash = conf->conflicting_block_hash;
2873 int64_t block_max_time;
2874 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2875 if (rescanning_old_block) {
2876 nTimeSmart = block_max_time;
2879 int64_t latestEntry = 0;
2882 int64_t latestTolerated = latestNow + 300;
2884 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2894 if (nSmartTime <= latestTolerated) {
2895 latestEntry = nSmartTime;
2896 if (nSmartTime > latestNow) {
2897 latestNow = nSmartTime;
2903 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2914 if (std::get_if<CNoDestination>(&dest))
2928 m_address_book[dest].previously_spent =
true;
2933 m_address_book[dest].receive_requests[id] = request;
2944 std::vector<std::string>
values;
2945 for (
const auto& [dest, entry] : m_address_book) {
2946 for (
const auto& [
id, request] : entry.receive_requests) {
2947 values.emplace_back(request);
2956 m_address_book[dest].receive_requests[id] = value;
2963 m_address_book[dest].receive_requests.erase(
id);
2976 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2977 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2978 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2981 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2982 "database/log.?????????? files can be stored, a location where such a directory could be created, "
2983 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2997 return MakeDatabase(*wallet_path, options, status, error_string);
3004 const std::string& walletFile = database->Filename();
3006 const auto start{SteadyClock::now()};
3011 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
3014 bool rescan_required =
false;
3015 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
3018 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
3023 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
3024 " or address metadata may be missing or incorrect."),
3028 error =
strprintf(
_(
"Error loading %s: Wallet requires newer version of %s"), walletFile, CLIENT_NAME);
3032 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
3037 error =
strprintf(
_(
"Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
3040 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect."
3041 " Rescanning wallet."), walletFile));
3042 rescan_required =
true;
3044 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n"
3045 "The wallet might had been created on a newer version.\n"
3046 "Please try running the latest software version.\n"), walletFile);
3049 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
3050 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3053 error =
strprintf(
_(
"Error loading %s"), walletFile);
3059 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3067 walletInstance->InitWalletFlags(wallet_creation_flags);
3071 walletInstance->SetupLegacyScriptPubKeyMan();
3075 LOCK(walletInstance->cs_wallet);
3077 walletInstance->SetupDescriptorScriptPubKeyMans();
3081 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3082 if (!spk_man->SetupGeneration()) {
3083 error =
_(
"Unable to generate initial keys");
3095 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3098 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3099 if (spk_man->HavePrivateKeys()) {
3100 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3106 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
3112 walletInstance->m_default_address_type = parsed.value();
3115 if (!
args.
GetArg(
"-changetype",
"").empty()) {
3121 walletInstance->m_default_change_type = parsed.value();
3131 _(
"This is the minimum transaction fee you pay on every transaction."));
3134 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
3138 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
3139 if (max_aps_fee ==
"-1") {
3140 walletInstance->m_max_aps_fee = -1;
3141 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
3144 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3146 walletInstance->m_max_aps_fee = max_fee.value();
3155 if (!fallback_fee) {
3156 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-fallbackfee",
args.
GetArg(
"-fallbackfee",
""));
3160 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3162 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3166 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3171 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-discardfee",
args.
GetArg(
"-discardfee",
""));
3175 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3177 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3187 _(
"This is the transaction fee you will pay if you send a transaction."));
3190 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3193 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3205 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3209 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3214 walletInstance->m_default_max_tx_fee = max_fee.value();
3218 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3219 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3228 _(
"The wallet will avoid paying less than the minimum relay fee."));
3235 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3238 walletInstance->TopUpKeyPool();
3241 std::optional<int64_t> time_first_key;
3242 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3243 int64_t time = spk_man->GetTimeFirstKey();
3244 if (!time_first_key || time < *time_first_key) time_first_key = time;
3246 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3249 walletInstance->m_chain_notifications_handler.reset();
3254 LOCK(walletInstance->cs_wallet);
3256 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3257 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3258 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3261 return walletInstance;
3266 LOCK(walletInstance->cs_wallet);
3268 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3269 walletInstance->m_chain = &
chain;
3279 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3295 walletInstance->m_attaching_chain =
true;
3296 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3299 int rescan_height = 0;
3300 if (!rescan_required)
3306 rescan_height = *fork_height;
3314 walletInstance->m_last_block_processed_height = *tip_height;
3316 walletInstance->m_last_block_processed.
SetNull();
3317 walletInstance->m_last_block_processed_height = -1;
3320 if (tip_height && *tip_height != rescan_height)
3324 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3325 if (time_first_key) {
3332 rescan_height = *tip_height;
3340 int block_height = *tip_height;
3341 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3345 if (rescan_height != block_height) {
3356 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3358 "Error loading wallet. Wallet requires blocks to be downloaded, "
3359 "and software does not currently support loading wallets while "
3360 "blocks are being downloaded out of order when using assumeutxo "
3361 "snapshots. Wallet should be able to load successfully after "
3362 "node sync reaches height %s"), block_height);
3368 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3373 error =
_(
"Failed to rescan the wallet during initialization");
3377 walletInstance->m_attaching_chain =
false;
3379 walletInstance->GetDatabase().IncrementUpdateCounter();
3381 walletInstance->m_attaching_chain =
false;
3388 const auto& address_book_it = m_address_book.find(dest);
3389 if (address_book_it == m_address_book.end())
return nullptr;
3390 if ((!allow_change) && address_book_it->second.IsChange()) {
3393 return &address_book_it->second;
3405 if (version < prev_version) {
3406 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3414 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);
3422 if (!spk_man->Upgrade(prev_version, version, error)) {
3471 assert(conf->confirmed_block_height >= 0);
3474 assert(conf->conflicting_block_height >= 0);
3489 assert(chain_depth >= 0);
3512 return vMasterKey.empty();
3522 if (!vMasterKey.empty()) {
3523 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(
decltype(vMasterKey)::value_type));
3537 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3541 vMasterKey = vMasterKeyIn;
3549 std::set<ScriptPubKeyMan*> spk_mans;
3550 for (
bool internal : {
false,
true}) {
3554 spk_mans.insert(spk_man);
3564 if (ext_spkm == &spkm)
return true;
3567 if (int_spkm == &spkm)
return true;
3574 std::set<ScriptPubKeyMan*> spk_mans;
3576 spk_mans.insert(spk_man_pair.second.get());
3584 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3585 if (it == spk_managers.end()) {
3593 std::set<ScriptPubKeyMan*> spk_mans;
3598 spk_mans.insert(it->second.begin(), it->second.end());
3601 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&
script, &sigdata](
ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
3631 return it->second.at(0)->GetSolvingProvider(
script);
3643 std::vector<WalletDescriptor> descs;
3646 LOCK(desc_spk_man->cs_desc_man);
3647 descs.push_back(desc_spk_man->GetWalletDescriptor());
3703 std::unique_ptr<ScriptPubKeyMan> spk_manager =
m_database->Format() ==
"bdb_ro" ?
3704 std::make_unique<LegacyDataSPKM>(*
this) :
3711 uint256 id = spk_manager->GetID();
3718 return cb(vMasterKey);
3729 if (spkm->HaveCryptedKeys())
return true;
3752 return *spk_manager;
3761 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3763 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3764 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3767 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
3769 uint256 id = spk_manager->GetID();
3778 for (
bool internal : {
false,
true}) {
3809 }))
throw std::runtime_error(
"Error: cannot process db transaction for descriptors setup");
3817 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3820 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3822 for (
bool internal : {
false,
true}) {
3823 const UniValue& descriptor_vals = signer_res.
find_value(internal ?
"internal" :
"receive");
3824 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3826 const std::string& desc_str = desc_val.getValStr();
3828 std::string desc_error;
3829 auto descs =
Parse(desc_str, keys, desc_error,
false);
3830 if (descs.empty()) {
3831 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3833 auto& desc = descs.at(0);
3834 if (!desc->GetOutputType()) {
3839 spk_manager->SetupDescriptor(batch, std::move(desc));
3840 uint256 id = spk_manager->GetID();
3847 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3860 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3875 spk_mans[type] = spk_man;
3877 const auto it = spk_mans_other.find(type);
3878 if (it != spk_mans_other.end() && it->second == spk_man) {
3879 spk_mans_other.erase(type);
3888 if (spk_man !=
nullptr && spk_man->GetID() ==
id) {
3892 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3896 spk_mans.erase(type);
3924 return std::nullopt;
3929 return std::nullopt;
3933 if (!desc_spk_man) {
3934 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3937 LOCK(desc_spk_man->cs_desc_man);
3938 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3939 assert(type.has_value());
3949 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3956 spk_man->UpdateWalletDescriptor(desc);
3959 spk_man = new_spk_man.get();
3962 uint256 id = new_spk_man->GetID();
3967 for (
const auto& entry : signing_provider.
keys) {
3968 const CKey& key = entry.second;
3969 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3973 if (!spk_man->TopUp()) {
3981 auto script_pub_keys = spk_man->GetScriptPubKeys();
3982 if (script_pub_keys.empty()) {
3983 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3988 for (
const auto&
script : script_pub_keys) {
3998 spk_man->WriteDescriptor();
4007 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
4010 error =
_(
"Error: This wallet already uses SQLite");
4015 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
4016 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
4017 std::vector<std::pair<SerializeData, SerializeData>> records;
4019 error =
_(
"Error: Unable to begin reading all records in the database");
4026 status = cursor->Next(ss_key, ss_value);
4032 records.emplace_back(key, value);
4037 error =
_(
"Error: Unable to read all records in the database");
4044 fs::remove(db_path);
4055 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status, error);
4062 bool began = batch->TxnBegin();
4064 for (
const auto& [key, value] : records) {
4065 if (!batch->Write(
Span{key},
Span{value})) {
4072 bool committed = batch->TxnCommit();
4082 if (!
Assume(legacy_spkm)) {
4085 return std::nullopt;
4089 if (res == std::nullopt) {
4090 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4091 return std::nullopt;
4101 if (!
Assume(legacy_spkm)) {
4107 std::set<CTxDestination> not_migrated_dests;
4116 if (!
data.watch_descs.empty())
Assume(!
data.watchonly_wallet->m_cached_spks.empty());
4117 if (!
data.solvable_descs.empty())
Assume(!
data.solvable_wallet->m_cached_spks.empty());
4119 for (
auto& desc_spkm :
data.desc_spkms) {
4121 return util::Error{
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
4123 uint256 id = desc_spkm->GetID();
4129 return util::Error{
_(
"Error: cannot remove legacy wallet records")};
4141 if (
data.master_key.key.IsValid()) {
4151 if (!local_wallet_batch.
ReadBestBlock(best_block_locator)) {
4152 return util::Error{
_(
"Error: Unable to read wallet's best block locator record")};
4157 std::vector<uint256> txids_to_delete;
4158 std::unique_ptr<WalletBatch> watchonly_batch;
4159 if (
data.watchonly_wallet) {
4160 watchonly_batch = std::make_unique<WalletBatch>(
data.watchonly_wallet->GetDatabase());
4161 if (!watchonly_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.watchonly_wallet->GetName())};
4163 LOCK(
data.watchonly_wallet->cs_wallet);
4164 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
4165 watchonly_batch->WriteOrderPosNext(
data.watchonly_wallet->nOrderPosNext);
4167 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4168 return util::Error{
_(
"Error: Unable to write watchonly wallet best block locator record")};
4171 std::unique_ptr<WalletBatch> solvables_batch;
4172 if (
data.solvable_wallet) {
4173 solvables_batch = std::make_unique<WalletBatch>(
data.solvable_wallet->GetDatabase());
4174 if (!solvables_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.solvable_wallet->GetName())};
4176 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
4177 return util::Error{
_(
"Error: Unable to write solvable wallet best block locator record")};
4184 if (
data.watchonly_wallet) {
4185 LOCK(
data.watchonly_wallet->cs_wallet);
4186 if (
data.watchonly_wallet->IsMine(*wtx->tx) ||
data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4188 const uint256& hash = wtx->GetHash();
4191 if (!new_tx) return false;
4192 ins_wtx.SetTx(to_copy_wtx.tx);
4193 ins_wtx.CopyFrom(to_copy_wtx);
4196 return util::Error{
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
4198 watchonly_batch->WriteTx(
data.watchonly_wallet->mapWallet.at(hash));
4201 txids_to_delete.push_back(hash);
4208 return util::Error{
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
4213 if (txids_to_delete.size() > 0) {
4214 if (
auto res =
RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
4220 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4221 if (
data.watchonly_wallet) wallets_vec.emplace_back(
data.watchonly_wallet, std::move(watchonly_batch));
4222 if (
data.solvable_wallet) wallets_vec.emplace_back(
data.solvable_wallet, std::move(solvables_batch));
4228 if (entry.label) batch.
WriteName(address, *entry.label);
4229 for (
const auto& [
id, request] : entry.receive_requests) {
4236 std::vector<CTxDestination> dests_to_delete;
4237 for (
const auto& [dest, record] : m_address_book) {
4241 bool copied =
false;
4242 for (
auto& [
wallet, batch] : wallets_vec) {
4244 if (require_transfer && !
wallet->IsMine(dest))
continue;
4247 wallet->m_address_book[dest] = record;
4248 func_store_addr(*batch, dest, record);
4252 if (require_transfer) {
4253 dests_to_delete.push_back(dest);
4261 if (require_transfer && !copied) {
4264 if (not_migrated_dests.count(dest) > 0) {
4265 dests_to_delete.push_back(dest);
4269 return util::Error{
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4274 for (
auto& [
wallet, batch] : wallets_vec) {
4281 if (dests_to_delete.size() > 0) {
4282 for (
const auto& dest : dests_to_delete) {
4284 return util::Error{
_(
"Error: Unable to remove watchonly address book data")};
4302 std::optional<MigrationData>
data =
wallet.GetDescriptorsForLegacy(error);
4303 if (
data == std::nullopt)
return false;
4306 if (
data->watch_descs.size() > 0 ||
data->solvable_descs.size() > 0) {
4313 empty_context.
args = context.args;
4323 if (
data->watch_descs.size() > 0) {
4324 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4327 std::vector<bilingual_str> warnings;
4328 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4329 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4331 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4336 if (!
data->watchonly_wallet) {
4337 error =
_(
"Error: Failed to create new watchonly wallet");
4340 res.watchonly_wallet =
data->watchonly_wallet;
4341 LOCK(
data->watchonly_wallet->cs_wallet);
4344 for (
const auto& [desc_str, creation_time] :
data->watch_descs) {
4347 std::string parse_err;
4348 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4349 assert(descs.size() == 1);
4350 assert(!descs.at(0)->IsRange());
4354 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4360 if (
data->solvable_descs.size() > 0) {
4361 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4364 std::vector<bilingual_str> warnings;
4365 std::string wallet_name =
wallet.GetName() +
"_solvables";
4366 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4368 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4373 if (!
data->solvable_wallet) {
4374 error =
_(
"Error: Failed to create new watchonly wallet");
4377 res.solvables_wallet =
data->solvable_wallet;
4378 LOCK(
data->solvable_wallet->cs_wallet);
4381 for (
const auto& [desc_str, creation_time] :
data->solvable_descs) {
4384 std::string parse_err;
4385 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4386 assert(descs.size() == 1);
4387 assert(!descs.at(0)->IsRange());
4391 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4401 if (auto res_migration = wallet.ApplyMigrationData(batch, *data); !res_migration) {
4402 error = util::ErrorString(res_migration);
4405 wallet.WalletLogPrintf(
"Wallet migration complete.\n");
4412 std::vector<bilingual_str> warnings;
4416 bool was_loaded =
false;
4419 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4428 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4442 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4454 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4460 std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.
create_flags, error, warnings);
4461 if (!local_wallet) {
4472 std::vector<bilingual_str> warnings;
4478 const std::string wallet_name = local_wallet->GetName();
4481 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4482 assert(to_reload.use_count() == 1);
4483 std::string
name = to_reload->GetName();
4485 to_reload =
LoadWallet(context,
name, std::nullopt, options, status, error, warnings);
4486 return to_reload !=
nullptr;
4492 reload_wallet(local_wallet);
4494 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4500 fs::path backup_path = this_wallet_dir / backup_filename;
4503 reload_wallet(local_wallet);
4505 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4509 bool success =
false;
4512 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4514 reload_wallet(local_wallet);
4516 if (passphrase.find(
'\0') == std::string::npos) {
4517 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4519 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4520 "The passphrase contains a null character (ie - a zero byte). "
4521 "If this passphrase was set with a version of this software prior to 25.0, "
4522 "please try again with only the characters up to — but not including — "
4523 "the first null character.")};
4528 LOCK(local_wallet->cs_wallet);
4530 if (!local_wallet->MigrateToSQLite(error))
return util::Error{error};
4535 success =
DoMigration(*local_wallet, context, error, res);
4546 std::set<fs::path> wallet_dirs;
4550 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4551 success = reload_wallet(local_wallet);
4552 res.
wallet = local_wallet;
4569 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4572 std::vector<std::shared_ptr<CWallet>> created_wallets;
4573 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4578 for (std::shared_ptr<CWallet>& w : created_wallets) {
4583 for (std::shared_ptr<CWallet>& w : created_wallets) {
4584 if (w->HaveChain()) {
4587 error +=
_(
"\nUnable to cleanup failed migration");
4593 assert(w.use_count() == 1);
4599 for (
const fs::path& dir : wallet_dirs) {
4600 fs::remove_all(dir);
4607 const auto& ptr_wallet =
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status, restore_error, warnings, was_loaded);
4608 if (!restore_error.
empty()) {
4609 error += restore_error +
_(
"\nUnable to restore backup of wallet.");
4614 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4615 fs::remove(temp_backup_location);
4619 bool wallet_reloaded = ptr_wallet !=
nullptr;
4620 assert(was_loaded == wallet_reloaded);
4629 for (
const auto&
script : spks) {
4630 m_cached_spks[
script].push_back(spkm);
4637 CacheNewScriptPubKeys(spks, spkm);
4640std::set<CExtPubKey> CWallet::GetActiveHDPubKeys()
const
4646 std::set<CExtPubKey> active_xpubs;
4647 for (
const auto& spkm : GetActiveScriptPubKeyMans()) {
4653 std::set<CPubKey> desc_pubkeys;
4654 std::set<CExtPubKey> desc_xpubs;
4655 w_desc.
descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4656 active_xpubs.merge(std::move(desc_xpubs));
4658 return active_xpubs;
4661std::optional<CKey> CWallet::GetKey(
const CKeyID& keyid)
const
4665 for (
const auto& spkm : GetAllScriptPubKeyMans()) {
4669 if (std::optional<CKey> key = desc_spkm->
GetKey(keyid)) {
4673 return std::nullopt;
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, 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.
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.
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.
RecursiveMutex cs_KeyStore
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.
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 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
static transaction_identifier FromUint256(const uint256 &id)
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
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
bool HaveChain() const
Interface to assert chain access.
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool IsActiveScriptPubKeyMan(const ScriptPubKeyMan &spkm) const
OutputType m_default_address_type
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
std::function< void(const CTxDestination &dest, const std::string &label, bool is_change, const std::optional< AddressPurpose > purpose)> ListAddrBookFunc
Walk-through the address book entries.
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
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
LegacyDataSPKM * GetLegacyDataSPKM() const
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
bool IsLegacy() const
Determine if we are a legacy wallet.
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
bool 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)
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)
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.
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
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)
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 IsLocked() const override
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Pass the encryption key to cb().
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process,...
RecursiveMutex cs_wallet
Main wallet lock.
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
std::atomic< int64_t > m_best_block_time
std::unordered_map< CScript, std::vector< ScriptPubKeyMan * >, SaltedSipHasher > m_cached_spks
Cache of descriptor ScriptPubKeys used for IsMine. Maps ScriptPubKey to set of spkms.
void SetupLegacyScriptPubKeyMan()
Make a 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.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
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.
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
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
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
unsigned int nTimeReceived
time received by this node
void SetTx(CTransactionRef arg)
unsigned int fTimeReceivedIsTxTime
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)
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,...
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
bool CanProvide(const CScript &script, SignatureData &sigdata) override
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that,...
std::set< CKeyID > GetKeys() const override
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)
virtual bool CanProvide(const CScript &script, SignatureData &sigdata)
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that,...
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 EraseTx(uint256 hash)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteMinVersion(int nVersion)
bool TxnBegin()
Begin a new transaction.
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool WriteWalletFlags(const uint64_t flags)
bool EraseAddressData(const CTxDestination &dest)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool WriteTx(const CWalletTx &wtx)
bool ErasePurpose(const std::string &strAddress)
bool EraseLockedUTXO(const COutPoint &output)
bool WriteLockedUTXO(const COutPoint &output)
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
virtual void ReloadDbEnv()=0
virtual void Close()=0
Flush to the database file and close the database.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
virtual void Flush()=0
Make sure all changes are flushed to database file.
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
Clock::time_point now() const
bool reserve(bool with_passphrase=false)
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
std::string ShellEscape(const std::string &arg)
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
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)
std::optional< common::PSBTError > 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 UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope.
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
void ReturnDestination()
Return reserved address.
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
util::Result< void > RemoveTxs(std::vector< uint256 > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::optional< int64_t > GetOldestKeyPoolTime() const
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
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)
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)
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.
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
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)
void SetWalletFlagWithDB(WalletBatch &batch, uint64_t flags)
Store wallet flags.
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 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 Flush()
Flush wallet (bitdb flush)
void blockDisconnected(const interfaces::BlockInfo &block) override
bool ImportPubKeys(const std::vector< std::pair< CKeyID, bool > > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > &key_origins, const bool add_keypool, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void ResubmitWalletTransactions(bool relay, bool force)
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void RecursiveUpdateTxState(const uint256 &tx_hash, const TryUpdatingStateFn &try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction (and its in-wallet descendants) as a particular tx state.
bool CanGetAddresses(bool internal=false) const
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate, const bool save_progress)
Scan the block chain (starting in start_block) for transactions from or to us.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
static NodeClock::time_point GetDefaultNextResend()
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool AbandonTransaction(const uint256 &hashTx)
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
bool EncryptWallet(const SecureString &strWalletPassphrase)
CWalletTx * AddToWallet(CTransactionRef tx, const TxState &state, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block=false)
Add the transaction to the wallet, wrapping it up inside a CWalletTx.
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
DBErrors ReorderTransactions()
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, const SyncTxState &state, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx) override
void Close()
Close wallet database.
bool SubmitTxMemoryPoolAndRelay(CWalletTx &wtx, std::string &err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
CKey GenerateRandomKey(bool compressed) noexcept
std::string EncodeDestination(const CTxDestination &dest)
#define 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)
static path absolute(const path &p)
static path u8path(const std::string &utf8_str)
static auto quoted(const std::string &s)
static bool exists(const path &p)
static bool copy_file(const path &from, const path &to, copy_options options)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
std::unique_ptr< Handler > MakeCleanupHandler(std::function< void()> cleanup)
Return handler wrapping a cleanup function.
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
bilingual_str ErrorString(const Result< T > &result)
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
Error statuses for the wallet database.
@ UNEXPECTED_LEGACY_ENTRY
@ EXTERNAL_SIGNER_SUPPORT_REQUIRED
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
static GlobalMutex g_wallet_release_mutex
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
const unsigned int WALLET_CRYPTO_KEY_SIZE
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...
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)
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
fs::path GetWalletDir()
Get the path of the wallet directory.
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
static 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, const int &sighash_type)
Reduces the size of the PSBT by dropping unnecessary non_witness_utxos (i.e.
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
void GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
@ 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(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(...)
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
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
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.