8 #if defined(HAVE_CONFIG_H) 12 #include <blockfilter.h> 76 #include <condition_variable> 95 if (value.isStr() && value.get_str() == wallet_name)
return true;
104 if (!setting_value.
isArray())
return true;
107 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
109 if (new_value.
size() == setting_value.
size())
return true;
114 const std::string& wallet_name,
115 std::optional<bool> load_on_startup,
116 std::vector<bilingual_str>& warnings)
118 if (!load_on_startup)
return;
120 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
122 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
144 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
145 if (i != context.wallets.end())
return false;
146 context.wallets.push_back(
wallet);
147 wallet->ConnectScriptPubKeyManNotifiers();
148 wallet->NotifyCanGetAddressesChanged();
160 wallet->m_chain_notifications_handler.reset();
162 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
163 if (i == context.wallets.end())
return false;
164 context.wallets.erase(i);
174 std::vector<bilingual_str> warnings;
181 return context.wallets;
187 count = context.wallets.size();
188 return count == 1 ? context.wallets[0] :
nullptr;
194 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
203 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
210 for (
auto& load_wallet : context.wallet_load_fns) {
225 wallet->WalletLogPrintf(
"Releasing wallet\n");
231 if (g_unloading_wallet_set.erase(
name) == 0) {
245 auto it = g_unloading_wallet_set.insert(
name);
257 while (g_unloading_wallet_set.count(
name) == 1) {
264 std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context,
const std::string&
name, std::optional<bool> load_on_start,
const DatabaseOptions& options,
DatabaseStatus& status,
bilingual_str&
error, std::vector<bilingual_str>& warnings)
273 context.chain->initMessage(
_(
"Loading wallet…").translated);
283 warnings.push_back(
_(
"Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet."));
288 wallet->postInitProcess();
294 }
catch (
const std::runtime_error& e) {
301 class FastWalletRescanFilter
310 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
311 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
312 assert(desc_spkm !=
nullptr);
313 AddScriptPubKeys(desc_spkm);
315 if (desc_spkm->IsHDEnabled()) {
321 void UpdateIfNeeded()
325 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
326 assert(desc_spkm !=
nullptr);
327 int32_t current_range_end{desc_spkm->GetEndRange()};
328 if (current_range_end > last_range_end) {
329 AddScriptPubKeys(desc_spkm, last_range_end);
335 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const 351 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
353 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
354 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
363 if (!result.second) {
368 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status,
error, warnings);
384 if (!passphrase.empty()) {
390 error =
Untranslated(
"Private keys must be disabled when using an external signer");
397 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
404 error =
Untranslated(
"Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
428 if (!
wallet->EncryptWallet(passphrase)) {
435 if (!
wallet->Unlock(passphrase)) {
445 wallet->SetupDescriptorScriptPubKeyMans();
447 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
448 if (!spk_man->SetupGeneration()) {
464 wallet->postInitProcess();
471 warnings.push_back(
_(
"Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future."));
485 auto wallet_file = wallet_path /
"wallet.dat";
486 std::shared_ptr<CWallet>
wallet;
501 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
504 }
catch (
const std::exception& e) {
510 fs::remove_all(wallet_path);
524 const auto it = mapWallet.find(hash);
525 if (it == mapWallet.end())
527 return &(it->second);
541 spk_man->UpgradeKeyMetadata();
565 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
567 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
569 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
571 if (
Unlock(_vMasterKey)) {
595 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
597 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
602 auto start{SteadyClock::now()};
603 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
604 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
606 start = SteadyClock::now();
607 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
608 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
610 if (pMasterKey.second.nDeriveIterations < 25000)
611 pMasterKey.second.nDeriveIterations = 25000;
613 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
615 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
617 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
644 if (nWalletVersion >= nVersion)
647 nWalletVersion = nVersion;
651 if (nWalletVersion > 40000)
660 std::set<uint256> result;
663 const auto it = mapWallet.find(txid);
664 if (it == mapWallet.end())
668 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
670 for (
const CTxIn& txin : wtx.
tx->vin)
672 if (mapTxSpends.count(txin.
prevout) <= 1)
674 range = mapTxSpends.equal_range(txin.
prevout);
675 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
676 result.insert(_it->second);
684 const Txid& txid = tx->GetHash();
685 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
709 int nMinOrderPos = std::numeric_limits<int>::max();
711 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
712 const CWalletTx* wtx = &mapWallet.at(it->second);
724 for (TxSpends::iterator it = range.first; it != range.second; ++it)
726 const uint256& hash = it->second;
728 if (copyFrom == copyTo)
continue;
729 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
748 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
749 range = mapTxSpends.equal_range(outpoint);
751 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
752 const uint256& wtxid = it->second;
753 const auto mit = mapWallet.find(wtxid);
754 if (mit != mapWallet.end()) {
756 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
765 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
774 std::pair<TxSpends::iterator, TxSpends::iterator> range;
775 range = mapTxSpends.equal_range(outpoint);
785 for (
const CTxIn& txin : wtx.
tx->vin)
806 auto start{SteadyClock::now()};
808 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
810 start = SteadyClock::now();
829 delete encrypted_batch;
830 encrypted_batch =
nullptr;
836 auto spk_man = spk_man_pair.second.get();
837 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
839 delete encrypted_batch;
840 encrypted_batch =
nullptr;
851 delete encrypted_batch;
852 encrypted_batch =
nullptr;
858 delete encrypted_batch;
859 encrypted_batch =
nullptr;
862 Unlock(strWalletPassphrase);
869 if (spk_man->IsHDEnabled()) {
870 if (!spk_man->SetupGeneration(
true)) {
901 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
904 for (
auto& entry : mapWallet)
911 std::vector<int64_t> nOrderPosOffsets;
912 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
919 nOrderPos = nOrderPosNext++;
920 nOrderPosOffsets.push_back(nOrderPos);
927 int64_t nOrderPosOff = 0;
928 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
930 if (nOrderPos >= nOffsetStart)
933 nOrderPos += nOrderPosOff;
934 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
952 int64_t nRet = nOrderPosNext++;
965 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
966 item.second.MarkDirty();
974 auto mi = mapWallet.find(originalHash);
977 assert(mi != mapWallet.end());
982 assert(wtx.mapValue.count(
"replaced_by_txid") == 0);
984 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
993 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
1013 tx_destinations.insert(dst);
1033 assert(spk_man !=
nullptr);
1062 std::set<CTxDestination> tx_destinations;
1064 for (
const CTxIn& txin : tx->vin) {
1073 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1075 bool fInsertedNew =
ret.second;
1076 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1090 if (state.index() != wtx.
m_state.index()) {
1102 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1110 std::vector<CWalletTx*> txs{&wtx};
1114 while (!txs.empty()) {
1117 desc_tx->
m_state = inactive_state;
1122 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1124 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1125 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1126 const auto wit = mapWallet.find(it->second);
1127 if (wit != mapWallet.end()) {
1128 txs.push_back(&wit->second);
1139 if (fInsertedNew || fUpdated)
1153 if (!strCmd.empty())
1158 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1172 std::thread
t(runCommand, strCmd);
1182 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1184 if (!fill_wtx(wtx, ins.second)) {
1196 for (
const CTxIn& txin : wtx.
tx->vin) {
1198 if (it != mapWallet.end()) {
1218 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1220 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1221 while (range.first != range.second) {
1222 if (range.first->second != tx.
GetHash()) {
1223 WalletLogPrintf(
"Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.
GetHash().
ToString(), conf->confirmed_block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1224 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1231 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1232 if (fExisted && !fUpdate)
return false;
1244 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1246 if (!dest.internal.has_value()) {
1251 if (!dest.internal.has_value())
continue;
1265 TxState tx_state = std::visit([](
auto&& s) ->
TxState {
return s; }, state);
1270 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1287 for (
const CTxIn& txin : tx->vin) {
1289 if (it != mapWallet.end()) {
1290 it->second.MarkDirty();
1300 auto it = mapWallet.find(hashTx);
1301 assert(it != mapWallet.end());
1309 assert(!wtx.isConfirmed());
1310 assert(!wtx.InMempool());
1312 if (!wtx.isConflicted() && !wtx.isAbandoned()) {
1338 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1341 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1342 if (conflictconfirms >= 0)
1364 std::set<uint256> todo;
1365 std::set<uint256> done;
1367 todo.insert(tx_hash);
1369 while (!todo.empty()) {
1373 auto it = mapWallet.find(now);
1374 assert(it != mapWallet.end());
1377 TxUpdate update_state = try_updating_state(wtx);
1378 if (update_state != TxUpdate::UNCHANGED) {
1382 for (
unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1383 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(
Txid::FromUint256(now), i));
1384 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1385 if (!done.count(iter->second)) {
1386 todo.insert(iter->second);
1391 if (update_state == TxUpdate::NOTIFY_CHANGED) {
1397 MarkInputsDirty(wtx.tx);
1417 auto it = mapWallet.find(tx->GetHash());
1418 if (it != mapWallet.end()) {
1425 auto it = mapWallet.find(tx->GetHash());
1426 if (it != mapWallet.end()) {
1468 m_last_block_processed_height = block.
height;
1469 m_last_block_processed = block.
hash;
1476 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1491 m_last_block_processed_height = block.
height - 1;
1494 int disconnect_height = block.
height;
1499 for (
const CTxIn& tx_in : ptx->vin) {
1501 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1503 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1506 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1507 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1511 auto try_updating_state = [&](
CWalletTx& tx) {
1531 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1547 const auto mi = mapWallet.find(txin.
prevout.
hash);
1548 if (mi != mapWallet.end())
1579 for (
const auto& spkm : it->second) {
1580 res = std::max(res, spkm->IsMine(script));
1608 if (outpoint.
n >= wtx->tx->vout.size()) {
1611 return IsMine(wtx->tx->vout[outpoint.
n]);
1626 throw std::runtime_error(std::string(__func__) +
": value out of range");
1634 bool result =
false;
1636 if (!spk_man->IsHDEnabled())
return false;
1648 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1655 void CWallet::SetWalletFlag(uint64_t
flags)
1660 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1674 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1709 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1721 LOCK(spk_man->cs_KeyStore);
1722 return spk_man->ImportScripts(scripts, timestamp);
1731 LOCK(spk_man->cs_KeyStore);
1732 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1735 bool CWallet::ImportPubKeys(
const std::vector<CKeyID>& ordered_pubkeys,
const std::map<CKeyID, CPubKey>& pubkey_map,
const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins,
const bool add_keypool,
const bool internal,
const int64_t timestamp)
1741 LOCK(spk_man->cs_KeyStore);
1742 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1745 bool CWallet::ImportScriptPubKeys(
const std::string& label,
const std::set<CScript>& script_pub_keys,
const bool have_solving_data,
const bool apply_label,
const int64_t timestamp)
1751 LOCK(spk_man->cs_KeyStore);
1752 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1757 for (
const CScript& script : script_pub_keys) {
1771 if (time < birthtime) {
1789 int start_height = 0;
1830 constexpr
auto INTERVAL_TIME{60s};
1831 auto current_time{reserver.
now()};
1832 auto start_time{reserver.
now()};
1836 uint256 block_hash = start_block;
1839 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1843 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1852 double progress_current = progress_begin;
1853 int block_height = start_height;
1855 if (progress_end - progress_begin > 0.0) {
1856 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1860 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1864 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1865 if (next_interval) {
1866 current_time = reserver.
now();
1867 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1870 bool fetch_block{
true};
1871 if (fast_rescan_filter) {
1872 fast_rescan_filter->UpdateIfNeeded();
1873 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1874 if (matches_block.has_value()) {
1875 if (*matches_block) {
1876 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1880 fetch_block =
false;
1883 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1889 bool block_still_active =
false;
1890 bool next_block =
false;
1901 if (!block_still_active) {
1908 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1915 if (save_progress && next_interval) {
1930 if (max_height && block_height >= *max_height) {
1941 block_hash = next_block_hash;
1946 const uint256 prev_tip_hash = tip_hash;
1948 if (!max_height && prev_tip_hash != tip_hash) {
1960 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1962 }
else if (block_height &&
chain().shutdownRequested()) {
1963 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1966 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
2007 result.erase(myHash);
2019 if (!
chain().isReadyToBroadcast())
return false;
2060 int submitted_tx_count = 0;
2067 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2068 for (
auto& [txid, wtx] : mapWallet) {
2070 if (!wtx.isUnconfirmed())
continue;
2075 to_submit.insert(&wtx);
2078 for (
auto wtx : to_submit) {
2079 std::string unused_err_string;
2084 if (submitted_tx_count > 0) {
2085 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2093 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2094 if (!pwallet->ShouldResend())
continue;
2095 pwallet->ResubmitWalletTransactions(
true,
false);
2096 pwallet->SetNextResend();
2111 std::map<COutPoint, Coin> coins;
2112 for (
auto& input : tx.
vin) {
2113 const auto mi = mapWallet.find(input.prevout.hash);
2114 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2119 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2121 std::map<int, bilingual_str> input_errors;
2131 if (spk_man->SignTransaction(tx, coins,
sighash, input_errors)) {
2147 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2148 const CTxIn& txin = psbtx.
tx->vin[i];
2158 const auto it = mapWallet.find(txhash);
2159 if (it != mapWallet.end()) {
2172 int n_signed_this_spkm = 0;
2173 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize);
2179 (*n_signed) += n_signed_this_spkm;
2187 for (
const auto& input : psbtx.
inputs) {
2199 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2201 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2211 return *change_type;
2220 bool any_wpkh{
false};
2222 bool any_pkh{
false};
2224 for (
const auto& recipient : vecSend) {
2225 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2227 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2229 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2231 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2237 if (has_bech32m_spkman && any_tr) {
2242 if (has_bech32_spkman && any_wpkh) {
2247 if (has_p2sh_segwit_spkman && any_sh) {
2253 if (has_legacy_spkman && any_pkh) {
2258 if (has_bech32m_spkman) {
2261 if (has_bech32_spkman) {
2278 wtx.
mapValue = std::move(mapValue);
2287 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2291 for (
const CTxIn& txin : tx->vin) {
2302 std::string err_string;
2304 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2321 spk_man_pair.second->RewriteDB();
2331 return nLoadWalletRet;
2338 if (!batch.
TxnBegin())
return util::Error{
_(
"Error starting db txn for wallet transactions removal")};
2341 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2342 std::vector<TxIterator> erased_txs;
2344 for (
const uint256& hash : txs_to_remove) {
2345 auto it_wtx = mapWallet.find(hash);
2346 if (it_wtx == mapWallet.end()) {
2347 str_err =
strprintf(
_(
"Transaction %s does not belong to this wallet"), hash.GetHex());
2351 str_err =
strprintf(
_(
"Failure removing transaction: %s"), hash.GetHex());
2354 erased_txs.emplace_back(it_wtx);
2358 if (!str_err.
empty()) {
2364 if (!batch.
TxnCommit())
return util::Error{
_(
"Error committing db txn for wallet transactions removal")};
2367 for (
const auto& it : erased_txs) {
2368 const uint256 hash{it->first};
2369 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2370 for (
const auto& txin : it->second.tx->vin)
2371 mapTxSpends.erase(txin.prevout);
2372 mapWallet.erase(it);
2383 bool fUpdated =
false;
2385 std::optional<AddressPurpose> purpose;
2388 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2389 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2391 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2402 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2405 if (!batch.
WriteName(encoded_dest, strName)) {
2461 m_address_book.erase(address);
2474 if (legacy_spk_man) {
2475 return legacy_spk_man->KeypoolCountExternalKeys();
2478 unsigned int count = 0;
2480 count += spk_man.second->GetKeyPoolSize();
2490 unsigned int count = 0;
2492 count += spk_man->GetKeyPoolSize();
2502 res &= spk_man->TopUp(kpSize);
2515 auto op_dest = spk_man->GetNewDestination(type);
2538 return std::nullopt;
2541 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2543 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2549 for (
auto& entry : mapWallet) {
2552 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2565 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2566 const auto& entry = item.second;
2567 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2574 std::vector<CTxDestination> result;
2582 result.emplace_back(dest);
2590 std::set<std::string> label_set;
2592 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2593 if (_is_change)
return;
2594 if (!purpose || purpose == _purpose) {
2595 label_set.insert(_label);
2612 if (!op_address)
return op_address;
2643 if (signer_spk_man ==
nullptr) {
2647 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2655 setLockedCoins.insert(output);
2665 bool was_locked = setLockedCoins.erase(output);
2666 if (batch && was_locked) {
2675 bool success =
true;
2677 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2680 setLockedCoins.clear();
2687 return setLockedCoins.count(output) > 0;
2693 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2694 it != setLockedCoins.end(); it++) {
2696 vOutpts.push_back(outpt);
2704 mapKeyBirth.clear();
2707 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2714 assert(spk_man !=
nullptr);
2718 for (
const auto& entry : spk_man->mapKeyMetadata) {
2719 if (entry.second.nCreateTime) {
2720 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2726 if (mapKeyBirth.count(keyid) == 0)
2727 mapKeyFirstBlock[keyid] = &max_confirm;
2731 if (mapKeyFirstBlock.empty())
2735 for (
const auto& entry : mapWallet) {
2740 for (
const CTxOut &txout : wtx.
tx->vout) {
2744 auto rit = mapKeyFirstBlock.find(keyid);
2745 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2755 for (
const auto& entry : mapKeyFirstBlock) {
2787 std::optional<uint256> block_hash;
2789 block_hash = conf->confirmed_block_hash;
2791 block_hash = conf->conflicting_block_hash;
2797 int64_t block_max_time;
2798 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2799 if (rescanning_old_block) {
2800 nTimeSmart = block_max_time;
2803 int64_t latestEntry = 0;
2806 int64_t latestTolerated = latestNow + 300;
2808 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2818 if (nSmartTime <= latestTolerated) {
2819 latestEntry = nSmartTime;
2820 if (nSmartTime > latestNow) {
2821 latestNow = nSmartTime;
2827 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2838 if (std::get_if<CNoDestination>(&dest))
2842 if (
auto* data{
common::FindKey(m_address_book, dest)}) data->previously_spent =
false;
2852 m_address_book[dest].previously_spent =
true;
2857 m_address_book[dest].receive_requests[id] = request;
2862 if (
auto* data{
common::FindKey(m_address_book, dest)})
return data->previously_spent;
2868 std::vector<std::string>
values;
2869 for (
const auto& [dest, entry] : m_address_book) {
2870 for (
const auto& [
id, request] : entry.receive_requests) {
2871 values.emplace_back(request);
2880 m_address_book[dest].receive_requests[id] = value;
2887 m_address_book[dest].receive_requests.erase(
id);
2900 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2901 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2902 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2905 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 2906 "database/log.?????????? files can be stored, a location where such a directory could be created, " 2907 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2912 return MakeDatabase(wallet_path, options, status, error_string);
2919 const std::string& walletFile = database->Filename();
2921 const auto start{SteadyClock::now()};
2926 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
2929 bool rescan_required =
false;
2930 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2933 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2938 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 2939 " or address metadata may be missing or incorrect."),
2947 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2955 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect." 2956 " Rescanning wallet."), walletFile));
2957 rescan_required =
true;
2959 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n" 2960 "The wallet might had been created on a newer version.\n" 2961 "Please try running the latest software version.\n"), walletFile);
2964 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n" 2965 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
2974 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2982 walletInstance->InitWalletFlags(wallet_creation_flags);
2986 walletInstance->SetupLegacyScriptPubKeyMan();
2990 LOCK(walletInstance->cs_wallet);
2992 walletInstance->SetupDescriptorScriptPubKeyMans();
2996 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2997 if (!spk_man->SetupGeneration()) {
2998 error =
_(
"Unable to generate initial keys");
3010 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3013 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3014 if (spk_man->HavePrivateKeys()) {
3015 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3021 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
3027 walletInstance->m_default_address_type = parsed.value();
3030 if (!
args.
GetArg(
"-changetype",
"").empty()) {
3036 walletInstance->m_default_change_type = parsed.value();
3046 _(
"This is the minimum transaction fee you pay on every transaction."));
3049 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
3053 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
3054 if (max_aps_fee ==
"-1") {
3055 walletInstance->m_max_aps_fee = -1;
3056 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
3059 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3061 walletInstance->m_max_aps_fee = max_fee.value();
3070 if (!fallback_fee) {
3075 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3077 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3081 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3090 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3092 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3102 _(
"This is the transaction fee you will pay if you send a transaction."));
3105 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3108 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3120 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3124 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3129 walletInstance->m_default_max_tx_fee = max_fee.value();
3133 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3134 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3143 _(
"The wallet will avoid paying less than the minimum relay fee."));
3150 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3153 walletInstance->TopUpKeyPool();
3156 std::optional<int64_t> time_first_key;
3157 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3158 int64_t time = spk_man->GetTimeFirstKey();
3159 if (!time_first_key || time < *time_first_key) time_first_key = time;
3161 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3164 walletInstance->m_chain_notifications_handler.reset();
3169 LOCK(walletInstance->cs_wallet);
3171 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3172 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3173 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3176 return walletInstance;
3181 LOCK(walletInstance->cs_wallet);
3183 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3184 walletInstance->m_chain = &
chain;
3190 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 &&
chain.
getHeight()) {
3194 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3210 walletInstance->m_attaching_chain =
true;
3211 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3214 int rescan_height = 0;
3215 if (!rescan_required)
3219 if (batch.ReadBestBlock(locator)) {
3221 rescan_height = *fork_height;
3229 walletInstance->m_last_block_processed_height = *tip_height;
3231 walletInstance->m_last_block_processed.
SetNull();
3232 walletInstance->m_last_block_processed_height = -1;
3235 if (tip_height && *tip_height != rescan_height)
3239 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3240 if (time_first_key) {
3247 rescan_height = *tip_height;
3255 int block_height = *tip_height;
3256 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3260 if (rescan_height != block_height) {
3271 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3273 "Error loading wallet. Wallet requires blocks to be downloaded, " 3274 "and software does not currently support loading wallets while " 3275 "blocks are being downloaded out of order when using assumeutxo " 3276 "snapshots. Wallet should be able to load successfully after " 3277 "node sync reaches height %s"), block_height);
3283 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3288 error =
_(
"Failed to rescan the wallet during initialization");
3292 walletInstance->m_attaching_chain =
false;
3294 walletInstance->GetDatabase().IncrementUpdateCounter();
3296 walletInstance->m_attaching_chain =
false;
3303 const auto& address_book_it = m_address_book.find(dest);
3304 if (address_book_it == m_address_book.end())
return nullptr;
3305 if ((!allow_change) && address_book_it->second.IsChange()) {
3308 return &address_book_it->second;
3320 if (version < prev_version) {
3321 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3329 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);
3337 if (!spk_man->Upgrade(prev_version, version,
error)) {
3378 assert(conf->confirmed_block_height >= 0);
3381 assert(conf->conflicting_block_height >= 0);
3396 assert(chain_depth >= 0);
3419 return vMasterKey.empty();
3429 if (!vMasterKey.empty()) {
3430 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3444 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3448 vMasterKey = vMasterKeyIn;
3456 std::set<ScriptPubKeyMan*> spk_mans;
3457 for (
bool internal : {
false,
true}) {
3461 spk_mans.insert(spk_man);
3470 std::set<ScriptPubKeyMan*> spk_mans;
3472 spk_mans.insert(spk_man_pair.second.get());
3480 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3481 if (it == spk_managers.end()) {
3489 std::set<ScriptPubKeyMan*> spk_mans;
3494 spk_mans.insert(it->second.begin(), it->second.end());
3497 Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](
ScriptPubKeyMan* spkm) {
return spkm->CanProvide(script, sigdata); }));
3525 Assume(it->second.at(0)->CanProvide(script, sigdata));
3526 return it->second.at(0)->GetSolvingProvider(script);
3537 std::vector<WalletDescriptor> descs;
3539 if (
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3540 LOCK(desc_spk_man->cs_desc_man);
3541 descs.push_back(desc_spk_man->GetWalletDescriptor());
3586 uint256 id = spk_manager->GetID();
3593 return cb(vMasterKey);
3619 return *spk_manager;
3628 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors setup");
3630 for (
bool internal : {
false,
true}) {
3635 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3637 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3638 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3641 spk_manager->SetupDescriptorGeneration(batch, master_key,
t,
internal);
3642 uint256 id = spk_manager->GetID();
3649 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors setup");
3674 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3677 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3679 for (
bool internal : {
false,
true}) {
3680 const UniValue& descriptor_vals = signer_res.
find_value(
internal ?
"internal" :
"receive");
3681 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3683 const std::string& desc_str = desc_val.
getValStr();
3685 std::string desc_error;
3686 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, desc_error,
false);
3687 if (desc ==
nullptr) {
3688 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3690 if (!desc->GetOutputType()) {
3695 spk_manager->SetupDescriptor(batch, std::move(desc));
3696 uint256 id = spk_manager->GetID();
3703 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3716 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3731 spk_mans[type] = spk_man;
3733 const auto it = spk_mans_other.find(type);
3734 if (it != spk_mans_other.end() && it->second == spk_man) {
3735 spk_mans_other.erase(type);
3744 if (spk_man !=
nullptr && spk_man->GetID() == id) {
3748 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3752 spk_mans.erase(type);
3764 return spk_man !=
nullptr;
3784 return std::nullopt;
3789 return std::nullopt;
3793 if (!desc_spk_man) {
3794 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3797 LOCK(desc_spk_man->cs_desc_man);
3798 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3799 assert(type.has_value());
3809 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3816 spk_man->UpdateWalletDescriptor(desc);
3819 spk_man = new_spk_man.get();
3822 uint256 id = new_spk_man->GetID();
3827 for (
const auto& entry : signing_provider.
keys) {
3828 const CKey& key = entry.second;
3829 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3833 if (!spk_man->TopUp()) {
3841 auto script_pub_keys = spk_man->GetScriptPubKeys();
3842 if (script_pub_keys.empty()) {
3843 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3848 for (
const auto& script : script_pub_keys) {
3858 spk_man->WriteDescriptor();
3867 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3870 error =
_(
"Error: This wallet already uses SQLite");
3875 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3876 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3877 std::vector<std::pair<SerializeData, SerializeData>> records;
3879 error =
_(
"Error: Unable to begin reading all records in the database");
3886 status = cursor->Next(ss_key, ss_value);
3892 records.emplace_back(key, value);
3897 error =
_(
"Error: Unable to read all records in the database");
3904 fs::remove(db_path);
3915 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status,
error);
3922 bool began = batch->TxnBegin();
3924 for (
const auto& [key, value] : records) {
3925 if (!batch->Write(
Span{key},
Span{value})) {
3932 bool committed = batch->TxnCommit();
3942 if (!
Assume(legacy_spkm)) {
3945 return std::nullopt;
3949 if (res == std::nullopt) {
3950 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
3951 return std::nullopt;
3961 if (!
Assume(legacy_spkm)) {
3968 std::set<CTxDestination> not_migrated_dests;
3978 error =
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
3981 uint256 id = desc_spkm->GetID();
4010 error =
_(
"Error: Unable to read wallet's best block locator record");
4016 std::vector<uint256> txids_to_delete;
4017 std::unique_ptr<WalletBatch> watchonly_batch;
4019 watchonly_batch = std::make_unique<WalletBatch>(data.
watchonly_wallet->GetDatabase());
4025 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4026 error =
_(
"Error: Unable to write watchonly wallet best block locator record");
4033 error =
_(
"Error: Unable to write solvable wallet best block locator record");
4045 const uint256& hash = wtx->GetHash();
4048 if (!new_tx) return false;
4049 ins_wtx.SetTx(to_copy_wtx.tx);
4050 ins_wtx.CopyFrom(to_copy_wtx);
4053 error =
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex());
4059 txids_to_delete.push_back(hash);
4066 error =
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
4070 watchonly_batch.reset();
4072 if (txids_to_delete.size() > 0) {
4073 if (
auto res =
RemoveTxs(txids_to_delete); !res) {
4080 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4082 if (!ext_wallet)
continue;
4084 std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
4085 if (!batch->TxnBegin()) {
4086 error =
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
4089 wallets_vec.emplace_back(ext_wallet, std::move(batch));
4096 if (entry.label) batch.
WriteName(address, *entry.label);
4097 for (
const auto& [
id, request] : entry.receive_requests) {
4104 std::vector<CTxDestination> dests_to_delete;
4105 for (
const auto& [dest, record] : m_address_book) {
4109 bool copied =
false;
4110 for (
auto& [
wallet, batch] : wallets_vec) {
4112 if (require_transfer && !
wallet->IsMine(dest))
continue;
4115 wallet->m_address_book[dest] = record;
4116 func_store_addr(*batch, dest, record);
4120 if (require_transfer) {
4121 dests_to_delete.push_back(dest);
4129 if (require_transfer && !copied) {
4132 if (not_migrated_dests.count(dest) > 0) {
4133 dests_to_delete.push_back(dest);
4137 error =
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets");
4143 for (
auto& [
wallet, batch] : wallets_vec) {
4153 if (dests_to_delete.size() > 0) {
4154 for (
const auto& dest : dests_to_delete) {
4156 error =
_(
"Error: Unable to remove watchonly address book data");
4182 std::optional<MigrationData> data =
wallet.GetDescriptorsForLegacy(
error);
4183 if (data == std::nullopt)
return false;
4186 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4193 empty_context.
args = context.args;
4203 if (data->watch_descs.size() > 0) {
4204 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4207 std::vector<bilingual_str> warnings;
4208 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4216 if (!data->watchonly_wallet) {
4217 error =
_(
"Error: Failed to create new watchonly wallet");
4220 res.watchonly_wallet = data->watchonly_wallet;
4221 LOCK(data->watchonly_wallet->cs_wallet);
4224 for (
const auto& [desc_str, creation_time] : data->watch_descs) {
4227 std::string parse_err;
4228 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4230 assert(!desc->IsRange());
4234 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4240 if (data->solvable_descs.size() > 0) {
4241 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4244 std::vector<bilingual_str> warnings;
4245 std::string wallet_name =
wallet.GetName() +
"_solvables";
4253 if (!data->solvable_wallet) {
4254 error =
_(
"Error: Failed to create new watchonly wallet");
4257 res.solvables_wallet = data->solvable_wallet;
4258 LOCK(data->solvable_wallet->cs_wallet);
4261 for (
const auto& [desc_str, creation_time] : data->solvable_descs) {
4264 std::string parse_err;
4265 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4267 assert(!desc->IsRange());
4271 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4290 std::vector<bilingual_str> warnings;
4293 bool was_loaded =
false;
4296 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4316 if (!local_wallet) {
4321 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4322 assert(to_reload.use_count() == 1);
4323 std::string
name = to_reload->GetName();
4326 return to_reload !=
nullptr;
4332 reload_wallet(local_wallet);
4334 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4340 fs::path backup_path = this_wallet_dir / backup_filename;
4343 reload_wallet(local_wallet);
4345 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4349 bool success =
false;
4352 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4354 reload_wallet(local_wallet);
4356 if (passphrase.find(
'\0') == std::string::npos) {
4357 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4359 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. " 4360 "The passphrase contains a null character (ie - a zero byte). " 4361 "If this passphrase was set with a version of this software prior to 25.0, " 4362 "please try again with only the characters up to — but not including — " 4363 "the first null character.")};
4368 LOCK(local_wallet->cs_wallet);
4386 std::set<fs::path> wallet_dirs;
4390 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4391 success = reload_wallet(local_wallet);
4392 res.
wallet = local_wallet;
4409 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4412 std::vector<std::shared_ptr<CWallet>> created_wallets;
4413 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4418 for (std::shared_ptr<CWallet>& w : created_wallets) {
4423 for (std::shared_ptr<CWallet>& w : created_wallets) {
4424 if (w->HaveChain()) {
4427 error +=
_(
"\nUnable to cleanup failed migration");
4433 assert(w.use_count() == 1);
4439 for (
const fs::path& dir : wallet_dirs) {
4440 fs::remove_all(dir);
4445 std::vector<bilingual_str> warnings;
4446 if (!
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status,
error, warnings)) {
4447 error +=
_(
"\nUnable to restore backup of wallet.");
4452 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4453 fs::remove(temp_backup_location);
4462 for (
const auto& script : spks) {
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
std::shared_ptr< const CTransaction > CTransactionRef
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
void ReturnDestination()
Return reserved address.
void SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
NodeClock::time_point m_next_resend
The next scheduled rebroadcast of wallet transactions.
static const std::string sighash
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Helper for findBlock to selectively return pieces of block data.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
std::optional< DatabaseFormat > require_format
static path PathFromString(const std::string &string)
Convert byte string to path object.
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
void MaybeUpdateBirthTime(int64_t time)
Updates wallet birth time if 'time' is below it.
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
void push_back(UniValue val)
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
std::atomic< bool > fAbortRescan
State of transaction added to mempool.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
void chainStateFlushed(ChainstateRole role, const CBlockLocator &loc) override
virtual bool updateRwSetting(const std::string &name, const common::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
interfaces::Chain & chain() const
Interface for accessing chain state.
std::chrono::time_point< NodeClock > time_point
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Enables interaction with an external signing device or service, such as a hardware wallet...
mapValue_t mapValue
Key/value map with information about the transaction.
void MarkDirty()
make sure balances are recalculated
bool EraseAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EraseAddressData(const CTxDestination &dest)
const std::vector< UniValue > & getValues() const
bool CanGetAddresses(bool internal=false) const
int64_t nIndex
The index of the address's key in the keypool.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
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...
bool HasEncryptionKeys() const override
#define LogPrint(category,...)
isminetype IsMine(const CScript &script) const override
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
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...
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::optional< int > last_scanned_height
bool DoMigration(CWallet &wallet, WalletContext &context, bilingual_str &error, MigrationResult &res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
std::optional< AddressPurpose > purpose
Address purpose which was originally recorded for payment protocol support but now serves as a cached...
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsAddressPreviouslySpent(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs) ...
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
DBErrors
Error statuses for the wallet database.
bool ApplyMigrationData(MigrationData &data, bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan, and where needed, moves tx and address book entries to watchonly_wallet or solvable_wallet.
virtual CBlockLocator getActiveChainLocator(const uint256 &block_hash)=0
Return a locator that refers to a block in the active chain.
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
RecursiveMutex cs_KeyStore
std::map< std::string, std::string > mapValue_t
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
void LoadAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &request) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Appends payment request to destination.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual bool hasBlockFilterIndex(BlockFilterType filter_type)=0
Returns whether a block filter index is available.
GCSFilter::ElementSet m_filter_set
std::string m_notify_tx_changed_script
Notify external script when a wallet transaction comes in or is updated (handled by -walletnotify) ...
bool MigrateToSQLite(bilingual_str &error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Move all records from the BDB database to a new SQLite database for storage.
std::map< CKeyID, CKey > keys
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.
bool ImportScriptPubKeys(const std::string &label, const std::set< CScript > &script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const override
Pass the encryption key to cb().
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal...
virtual void Flush()=0
Make sure all changes are flushed to database file.
std::vector< std::pair< std::string, std::string > > vOrderForm
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
void transactionAddedToMempool(const CTransactionRef &tx) override
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)
struct containing information needed for migrating legacy wallets to descriptor wallets ...
std::atomic< int64_t > m_birth_time
bool MoneyRange(const CAmount &nValue)
#define CHECK_NONFATAL(condition)
Identity function.
void updateState(interfaces::Chain &chain)
Update transaction state when attaching to a chain, filling in heights of conflicted and confirmed bl...
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
bool WriteAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &receive_request)
util::Result< void > RemoveTxs(std::vector< uint256 > &txs_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases the provided transactions from the wallet.
bool IsLegacy() const
Determine if we are a legacy wallet.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
Removed for conflict with in-block transaction.
MasterKeyMap mapMasterKeys
WalletDatabase & GetDatabase() const override
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule) ...
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
std::string PurposeToString(AddressPurpose p)
bool TxnAbort()
Abort current transaction.
bool fInternal
Whether this is from the internal (change output) keypool.
std::optional< int64_t > GetOldestKeyPoolTime() const
const CWallet *const pwallet
The wallet to reserve from.
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
std::string TxStateString(const T &state)
Return TxState or SyncTxState as a string for logging or debugging.
bool DelAddressBook(const CTxDestination &address)
CTxDestination address
The destination.
RecursiveMutex cs_wallet
Main wallet lock.
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
void CacheNewScriptPubKeys(const std::set< CScript > &spks, ScriptPubKeyMan *spkm)
Add scriptPubKeys for this ScriptPubKeyMan into the scriptPubKey cache.
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
State of transaction not confirmed or conflicting with a known block and not in the mempool...
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
virtual void Close()=0
Flush to the database file and close the database.
const UniValue & get_array() const
std::variant< TxStateConfirmed, TxStateInMempool, TxStateInactive > SyncTxState
Subset of states transaction sync logic is implemented to handle.
RAII object to check and reserve a wallet rescan.
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
std::multimap< int64_t, CWalletTx * > TxItems
bool WriteLockedUTXO(const COutPoint &output)
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
static GlobalMutex g_loading_wallet_mutex
A version of CTransaction with the PSBT format.
bool isConflicted() const
bool WriteMinVersion(int nVersion)
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool reserve(bool with_passphrase=false)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
std::shared_ptr< CWallet > solvable_wallet
Access to the wallet database.
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
A key from a CWallet's keypool.
RecursiveMutex m_relock_mutex
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
State of transaction confirmed in a block.
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
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.
bool WriteOrderPosNext(int64_t nOrderPosNext)
int conflicting_block_height
fs::path GetWalletDir()
Get the path of the wallet directory.
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.
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
const std::string & getValStr() const
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
bool EncryptWallet(const SecureString &strWalletPassphrase)
static NodeClock::time_point GetDefaultNextResend()
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses, and other watch only things, and is therefore "blank.".
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
static constexpr auto OUTPUT_TYPES
void updatedBlockTip() override
const std::vector< CTxIn > vin
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
int64_t GetTxTime() const
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
constexpr unsigned char * begin()
bool WriteBestBlock(const CBlockLocator &locator)
static const bool DEFAULT_WALLET_RBF
-walletrbf default
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
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.
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
CKey GenerateRandomKey(bool compressed) noexcept
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
int64_t CAmount
Amount in satoshis (Can be negative)
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...
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
const UniValue & find_value(std::string_view key) const
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...
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
A transaction with a bunch of additional info that only the owner cares about.
interfaces::Chain * m_chain
Interface for accessing chain state.
std::function< TxUpdate(CWalletTx &wtx)> TryUpdatingStateFn
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
void LoadAddressPreviouslySpent(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks destination as previously spent.
bool EraseName(const std::string &strAddress)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet...
bool SetAddressPreviouslySpent(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Block data sent with blockConnected, blockDisconnected notifications.
bool IsLocked() const override
Indicates that the wallet needs an external signer.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
DBErrors LoadWallet(CWallet *pwallet)
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
std::set< CKeyID > GetKeys() const override
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
std::shared_ptr< CWallet > wallet
bool TxnCommit()
Commit current transaction.
static std::string PathToString(const path &path)
Convert path object to a byte string.
SecureString create_passphrase
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
CPubKey vchPubKey
The public key.
bool Unlock(const CKeyingMaterial &vMasterKeyIn)
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
int64_t m_keypool_size
Number of pre-generated keys/scripts by each spkm (part of the look-ahead process, used to detect payments)
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.
const uint256 * prev_hash
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
bool WriteAddressPreviouslySpent(const CTxDestination &dest, bool previously_spent)
An input of a transaction.
static constexpr uint64_t KNOWN_WALLET_FLAGS
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
std::string ShellEscape(const std::string &arg)
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
Double ended buffer combining vector and stream-like interfaces.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.
void Flush()
Flush wallet (bitdb flush)
bool WriteTx(const CWalletTx &wtx)
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
bilingual_str _(const char *psz)
Translation function.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
virtual void ReloadDbEnv()=0
std::optional< OutputType > ParseOutputType(const std::string &type)
void blockDisconnected(const interfaces::BlockInfo &block) override
bilingual_str AmountHighWarn(const std::string &optname)
void blockConnected(ChainstateRole role, const interfaces::BlockInfo &block) override
std::shared_ptr< Descriptor > descriptor
An encapsulated public key.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
const std::vector< CTxOut > vout
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
WalletFeature
(client) version numbers for particular wallet features
Indicate that this wallet supports DescriptorScriptPubKeyMan.
bool AbandonTransaction(const uint256 &hashTx)
unsigned int ComputeTimeSmart(const CWalletTx &wtx, bool rescanning_old_block) const
Compute smart timestamp for a transaction being added to the wallet.
std::string ToString() const
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
void AddActiveScriptPubKeyManWithDb(WalletBatch &batch, uint256 id, OutputType type, bool internal)
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 BackupWallet(const std::string &strDest) const
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip...
std::unique_ptr< Handler > MakeCleanupHandler(std::function< void()> cleanup)
Return handler wrapping a cleanup function.
std::set< uint256 > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason) override
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WriteWalletFlags(const uint64_t flags)
#define WAIT_LOCK(cs, name)
An output of a transaction.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
unsigned int nDeriveIterations
std::string ToString() const
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::string m_name
Wallet name: relative directory name or "" for default wallet.
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
An outpoint - a combination of a transaction hash and an index n into its vout.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
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.
int confirmed_block_height
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid, such as a sh(sh(pkh())) script, or not watched.
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
std::vector< PSBTInput > inputs
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::shared_ptr< CWallet > solvables_wallet
bool ErasePurpose(const std::string &strAddress)
void TopUpCallback(const std::set< CScript > &spks, ScriptPubKeyMan *spkm) override
Callback function for after TopUp completes containing any scripts that were added by a SPKMan...
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
uint256 GetID() const override
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
void UpgradeDescriptorCache()
std::unordered_set< Element, ByteVectorHash > ElementSet
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called...
Descriptor with some wallet metadata.
void Close()
Close wallet database.
virtual void KeepDestination(int64_t index, const OutputType &type)
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
static const bool DEFAULT_WALLETBROADCAST
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
static void ReleaseWallet(CWallet *wallet)
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
std::unordered_map< CScript, std::vector< ScriptPubKeyMan * >, SaltedSipHasher > m_cached_spks
Cache of descriptor ScriptPubKeys used for IsMine. Maps ScriptPubKey to set of spkms.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
const std::string & FormatOutputType(OutputType type)
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
std::map< uint256, int32_t > m_last_range_ends
Map for keeping track of each range descriptor's last seen end range.
std::atomic< int64_t > m_best_block_time
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const Txid & GetHash() const LIFETIMEBOUND
static time_point now() noexcept
Return current system time or mocked time, if set.
unsigned int fTimeReceivedIsTxTime
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
void ResubmitWalletTransactions(bool relay, bool force)
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
static ExternalSigner GetExternalSigner()
void SetSeed(Span< const std::byte > seed)
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
bool TopUpKeyPool(unsigned int kpSize=0)
bool CanGrindR() const
Whether the (external) signer performs R-value signature grinding.
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &strPurpose)
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
State of rejected transaction that conflicts with a confirmed block.
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope...
bool error(const char *fmt, const Args &... args)
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
Serialized script, used inside transaction inputs and outputs.
static transaction_identifier FromUint256(const uint256 &id)
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node...
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 AddScriptPubKeyMan(const uint256 &id, std::unique_ptr< ScriptPubKeyMan > spkm_man)
std::shared_ptr< CWallet > watchonly_wallet
virtual util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool EraseAddressReceiveRequest(const CTxDestination &dest, const std::string &id)
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
std::optional< std::string > m_op_label
static void NotifyTransactionChanged(WalletModel *walletmodel, const uint256 &hash, ChangeType status)
virtual void initMessage(const std::string &message)=0
Send init message.
A reference to a CKey: the Hash160 of its serialized public key.
std::string GetHex() const
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet...
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
bool TxnBegin()
Begin a new transaction.
bool EraseTx(uint256 hash)
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
A wrapper to reserve an address from a wallet.
DBErrors ReorderTransactions()
std::vector< unsigned char > vchSalt
bool HaveChain() const
Interface to assert chain access.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SetLabel(std::string name)
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
#define AssertLockNotHeld(cs)
const unsigned int WALLET_CRYPTO_KEY_SIZE
std::optional< MigrationData > GetDescriptorsForLegacy(bilingual_str &error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all of the descriptors from a legacy wallet.
bilingual_str ErrorString(const Result< T > &result)
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...
Encryption/decryption context with key information.
interfaces::Chain * chain
std::vector< WalletDescriptor > GetWalletDescriptors(const CScript &script) const
Get the wallet descriptors for a script.
bool WriteName(const std::string &strAddress, const std::string &strName)
std::string EncodeDestination(const CTxDestination &dest)
A mutable version of CTransaction.
std::shared_ptr< CWallet > watchonly_wallet
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
std::unique_ptr< WalletDatabase > m_database
Internal database handle.
enum wallet::CWallet::ScanResult::@19 status
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
static GlobalMutex g_wallet_release_mutex
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet) ...
static auto quoted(const std::string &s)
#define STR_INTERNAL_BUG(msg)
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 ...
FoundBlock & height(int &height)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
unsigned int nTimeReceived
time received by this node
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...
std::vector< unsigned char > vchCryptedKey
An encapsulated private key.
A Span is an object that can refer to a contiguous sequence of objects.
The basic transaction that is broadcasted on the network and contained in blocks. ...
Different type to mark Mutex at global scope.
static const bool DEFAULT_WALLETCROSSCHAIN
std::shared_ptr< CWallet > wallet
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
int64_t nOrderPos
position in ordered transaction list
OutputType m_default_address_type
void RemoveUnnecessaryTransactions(PartiallySignedTransaction &psbtx, const int &sighash_type)
Reduces the size of the PSBT by dropping unnecessary non_witness_utxos (i.e.
bool EraseLockedUTXO(const COutPoint &output)
std::optional< CMutableTransaction > tx
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::optional< AddressPurpose > &purpose)
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo >> &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 bool exists(const path &p)
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, AddressPurpose purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
static path u8path(const std::string &utf8_str)
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)
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
unsigned int nMasterKeyMaxID
int64_t GetTime()
DEPRECATED, see GetTime.
bool DelAddressBookWithDB(WalletBatch &batch, const CTxDestination &address)
unsigned int chain_time_max
virtual common::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
const unsigned int WALLET_CRYPTO_SALT_SIZE
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
static path absolute(const path &p)
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &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...
std::atomic< double > m_scanning_progress
static std::set< std::string > g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex)
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
void SetTx(CTransactionRef arg)
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool HasWalletDescriptor(const WalletDescriptor &desc) const
std::variant< TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
WalletFeature GetClosestWalletFeature(int version)
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
#define PACKAGE_BUGREPORT
static std::condition_variable g_wallet_release_cv
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
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.
virtual bool havePruned()=0
Check if any block has been pruned.
util::Result< CTxDestination > GetNewChangeDestination(const OutputType type)
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
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.
Clock::time_point now() const
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
#define Assert(val)
Identity function.
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
bool IsSpentKey(const CScript &scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< std::unique_ptr< DescriptorScriptPubKeyMan > > desc_spkms
const Txid & GetHash() const LIFETIMEBOUND
static bool copy_file(const path &from, const path &to, copy_options options)
void GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
static std::shared_ptr< CWallet > Create(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool IsValid() const
Check whether this private key is valid.
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...
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::atomic< bool > m_attaching_chain
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
int GetTxDepthInMainChain(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.