10 #include <blockfilter.h> 75 #include <condition_variable> 97 if (!setting_value.isArray()) setting_value.setArray();
98 for (
const auto& value : setting_value.getValues()) {
101 setting_value.push_back(wallet_name);
112 for (
const auto& value : setting_value.getValues()) {
113 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
116 setting_value = std::move(new_value);
123 const std::string& wallet_name,
124 std::optional<bool> load_on_startup,
125 std::vector<bilingual_str>& warnings)
127 if (!load_on_startup)
return;
129 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
131 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
153 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
154 if (i != context.wallets.end())
return false;
155 context.wallets.push_back(
wallet);
156 wallet->ConnectScriptPubKeyManNotifiers();
157 wallet->NotifyCanGetAddressesChanged();
169 wallet->m_chain_notifications_handler.reset();
172 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
173 if (i == context.wallets.end())
return false;
174 context.wallets.erase(i);
187 std::vector<bilingual_str> warnings;
194 return context.wallets;
200 count = context.wallets.size();
201 return count == 1 ? context.wallets[0] :
nullptr;
207 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
216 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
223 for (
auto& load_wallet : context.wallet_load_fns) {
238 wallet->WalletLogPrintf(
"Releasing wallet %s..\n",
name);
244 if (g_unloading_wallet_set.erase(
name) == 0) {
258 g_unloading_wallet_set.insert(
name);
267 while (g_unloading_wallet_set.count(
name) == 1) {
274 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)
283 context.chain->initMessage(
_(
"Loading wallet…").translated);
284 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), options.create_flags, error, warnings);
293 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."));
298 wallet->postInitProcess();
304 }
catch (
const std::runtime_error& e) {
311 class FastWalletRescanFilter
320 for (
auto spkm :
m_wallet.GetAllScriptPubKeyMans()) {
321 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(spkm)};
322 assert(desc_spkm !=
nullptr);
323 AddScriptPubKeys(desc_spkm);
325 if (desc_spkm->IsHDEnabled()) {
331 void UpdateIfNeeded()
335 auto desc_spkm{
dynamic_cast<DescriptorScriptPubKeyMan*
>(
m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
336 assert(desc_spkm !=
nullptr);
337 int32_t current_range_end{desc_spkm->GetEndRange()};
338 if (current_range_end > last_range_end) {
339 AddScriptPubKeys(desc_spkm, last_range_end);
345 std::optional<bool> MatchesBlock(
const uint256& block_hash)
const 361 void AddScriptPubKeys(
const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
363 for (
const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
364 m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
373 if (!result.second) {
378 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status, error, warnings);
399 if (!passphrase.empty()) {
405 error =
Untranslated(
"Private keys must be disabled when using an external signer");
412 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
419 error =
Untranslated(
"Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
434 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), wallet_creation_flags, error, warnings);
443 if (!
wallet->EncryptWallet(passphrase)) {
444 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
450 if (!
wallet->Unlock(passphrase)) {
451 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
460 wallet->SetupDescriptorScriptPubKeyMans();
462 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
463 if (!spk_man->SetupGeneration()) {
464 error =
Untranslated(
"Unable to generate initial keys");
479 wallet->postInitProcess();
486 warnings.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."));
500 auto wallet_file = wallet_path /
"wallet.dat";
501 std::shared_ptr<CWallet>
wallet;
516 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
518 wallet =
LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
519 }
catch (
const std::exception& e) {
525 fs::remove_all(wallet_path);
539 const auto it = mapWallet.find(hash);
540 if (it == mapWallet.end())
542 return &(it->second);
556 spk_man->UpgradeKeyMetadata();
580 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
582 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
584 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
586 if (
Unlock(_vMasterKey)) {
610 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
612 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
617 auto start{SteadyClock::now()};
618 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
619 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
621 start = SteadyClock::now();
622 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
623 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
625 if (pMasterKey.second.nDeriveIterations < 25000)
626 pMasterKey.second.nDeriveIterations = 25000;
628 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
630 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
632 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
659 if (nWalletVersion >= nVersion)
662 nWalletVersion = nVersion;
666 if (nWalletVersion > 40000)
675 std::set<uint256> result;
678 const auto it = mapWallet.find(txid);
679 if (it == mapWallet.end())
683 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
685 for (
const CTxIn& txin : wtx.
tx->vin)
687 if (mapTxSpends.count(txin.
prevout) <= 1)
689 range = mapTxSpends.equal_range(txin.
prevout);
690 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
691 result.insert(_it->second);
699 const Txid& txid = tx->GetHash();
700 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
724 int nMinOrderPos = std::numeric_limits<int>::max();
726 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
727 const CWalletTx* wtx = &mapWallet.at(it->second);
739 for (TxSpends::iterator it = range.first; it != range.second; ++it)
741 const uint256& hash = it->second;
743 if (copyFrom == copyTo)
continue;
744 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
763 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
764 range = mapTxSpends.equal_range(outpoint);
766 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
767 const uint256& wtxid = it->second;
768 const auto mit = mapWallet.find(wtxid);
769 if (mit != mapWallet.end()) {
770 const auto& wtx = mit->second;
771 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
780 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
789 std::pair<TxSpends::iterator, TxSpends::iterator> range;
790 range = mapTxSpends.equal_range(outpoint);
800 for (
const CTxIn& txin : wtx.
tx->vin)
821 auto start{SteadyClock::now()};
823 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
825 start = SteadyClock::now();
844 delete encrypted_batch;
845 encrypted_batch =
nullptr;
851 auto spk_man = spk_man_pair.second.get();
852 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
854 delete encrypted_batch;
855 encrypted_batch =
nullptr;
866 delete encrypted_batch;
867 encrypted_batch =
nullptr;
873 delete encrypted_batch;
874 encrypted_batch =
nullptr;
877 Unlock(strWalletPassphrase);
884 if (spk_man->IsHDEnabled()) {
885 if (!spk_man->SetupGeneration(
true)) {
916 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
919 for (
auto& entry : mapWallet)
926 std::vector<int64_t> nOrderPosOffsets;
927 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
934 nOrderPos = nOrderPosNext++;
935 nOrderPosOffsets.push_back(nOrderPos);
942 int64_t nOrderPosOff = 0;
943 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
945 if (nOrderPos >= nOffsetStart)
948 nOrderPos += nOrderPosOff;
949 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
967 int64_t nRet = nOrderPosNext++;
980 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
981 item.second.MarkDirty();
989 auto mi = mapWallet.find(originalHash);
992 assert(mi != mapWallet.end());
997 assert(wtx.mapValue.count(
"replaced_by_txid") == 0);
999 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
1006 bool success =
true;
1008 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
1028 tx_destinations.insert(dst);
1076 std::set<CTxDestination> tx_destinations;
1078 for (
const CTxIn& txin : tx->vin) {
1087 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1089 bool fInsertedNew =
ret.second;
1090 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1104 if (state.index() != wtx.
m_state.index()) {
1116 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1124 std::vector<CWalletTx*> txs{&wtx};
1128 while (!txs.empty()) {
1131 desc_tx->
m_state = inactive_state;
1136 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1138 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1139 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1140 const auto wit = mapWallet.find(it->second);
1141 if (wit != mapWallet.end()) {
1142 txs.push_back(&wit->second);
1153 if (fInsertedNew || fUpdated)
1167 if (!strCmd.empty())
1172 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1186 std::thread
t(runCommand, strCmd);
1196 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1198 if (!fill_wtx(wtx, ins.second)) {
1210 for (
const CTxIn& txin : wtx.
tx->vin) {
1212 if (it != mapWallet.end()) {
1232 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1234 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1235 while (range.first != range.second) {
1236 if (range.first->second != tx.
GetHash()) {
1237 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);
1238 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1245 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1246 if (fExisted && !fUpdate)
return false;
1258 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1260 if (!dest.internal.has_value()) {
1265 if (!dest.internal.has_value())
continue;
1279 TxState tx_state = std::visit([](
auto&& s) ->
TxState {
return s; }, state);
1284 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1301 for (
const CTxIn& txin : tx->vin) {
1303 if (it != mapWallet.end()) {
1304 it->second.MarkDirty();
1314 auto it = mapWallet.find(hashTx);
1315 assert(it != mapWallet.end());
1323 assert(!wtx.isConfirmed());
1324 assert(!wtx.InMempool());
1326 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1352 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1355 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1356 if (conflictconfirms >= 0)
1381 std::set<uint256> todo;
1382 std::set<uint256> done;
1384 todo.insert(tx_hash);
1386 while (!todo.empty()) {
1390 auto it = mapWallet.find(now);
1391 assert(it != mapWallet.end());
1394 TxUpdate update_state = try_updating_state(wtx);
1397 if (batch) batch->
WriteTx(wtx);
1399 for (
unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1400 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(
Txid::FromUint256(now), i));
1401 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1402 if (!done.count(iter->second)) {
1403 todo.insert(iter->second);
1434 auto it = mapWallet.find(tx->GetHash());
1435 if (it != mapWallet.end()) {
1439 const Txid& txid = tx->GetHash();
1441 for (
const CTxIn& tx_in : tx->vin) {
1443 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1444 const uint256& spent_id = range.first->second;
1446 if (spent_id == txid)
continue;
1456 auto it = mapWallet.find(tx->GetHash());
1457 if (it != mapWallet.end()) {
1490 const Txid& txid = tx->GetHash();
1492 for (
const CTxIn& tx_in : tx->vin) {
1496 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1497 const uint256& spent_id = range.first->second;
1514 m_last_block_processed_height = block.
height;
1515 m_last_block_processed = block.
hash;
1522 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1537 m_last_block_processed_height = block.
height - 1;
1540 int disconnect_height = block.
height;
1545 for (
const CTxIn& tx_in : ptx->vin) {
1547 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1549 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1552 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1553 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1557 auto try_updating_state = [&](
CWalletTx& tx) {
1577 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1593 const auto mi = mapWallet.find(txin.
prevout.
hash);
1594 if (mi != mapWallet.end())
1625 for (
const auto& spkm : it->second) {
1626 res = std::max(res, spkm->IsMine(
script));
1634 return spkm->IsMine(
script);
1656 if (outpoint.
n >= wtx->tx->vout.size()) {
1659 return IsMine(wtx->tx->vout[outpoint.
n]);
1674 throw std::runtime_error(std::string(__func__) +
": value out of range");
1682 bool result =
false;
1684 if (!spk_man->IsHDEnabled())
return false;
1696 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1703 void CWallet::SetWalletFlag(uint64_t
flags)
1708 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1722 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1757 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1769 LOCK(spk_man->cs_KeyStore);
1770 return spk_man->ImportScripts(scripts, timestamp);
1779 LOCK(spk_man->cs_KeyStore);
1780 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1783 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)
1789 LOCK(spk_man->cs_KeyStore);
1790 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1793 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)
1799 LOCK(spk_man->cs_KeyStore);
1800 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1819 if (time < birthtime) {
1837 int start_height = 0;
1878 constexpr
auto INTERVAL_TIME{60s};
1879 auto current_time{reserver.
now()};
1880 auto start_time{reserver.
now()};
1884 uint256 block_hash = start_block;
1887 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1891 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1900 double progress_current = progress_begin;
1901 int block_height = start_height;
1903 if (progress_end - progress_begin > 0.0) {
1904 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1908 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1912 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1913 if (next_interval) {
1914 current_time = reserver.
now();
1915 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1918 bool fetch_block{
true};
1919 if (fast_rescan_filter) {
1920 fast_rescan_filter->UpdateIfNeeded();
1921 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1922 if (matches_block.has_value()) {
1923 if (*matches_block) {
1924 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1928 fetch_block =
false;
1931 LogPrint(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1937 bool block_still_active =
false;
1938 bool next_block =
false;
1949 if (!block_still_active) {
1956 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1963 if (save_progress && next_interval) {
1978 if (max_height && block_height >= *max_height) {
1989 block_hash = next_block_hash;
1994 const uint256 prev_tip_hash = tip_hash;
1996 if (!max_height && prev_tip_hash != tip_hash) {
2008 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
2010 }
else if (block_height &&
chain().shutdownRequested()) {
2011 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2014 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
2055 result.erase(myHash);
2067 if (!
chain().isReadyToBroadcast())
return false;
2108 int submitted_tx_count = 0;
2115 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2116 for (
auto& [txid, wtx] : mapWallet) {
2118 if (!wtx.isUnconfirmed())
continue;
2123 to_submit.insert(&wtx);
2126 for (
auto wtx : to_submit) {
2127 std::string unused_err_string;
2132 if (submitted_tx_count > 0) {
2133 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2141 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2142 if (!pwallet->ShouldResend())
continue;
2143 pwallet->ResubmitWalletTransactions(
true,
false);
2144 pwallet->SetNextResend();
2159 std::map<COutPoint, Coin> coins;
2160 for (
auto& input : tx.
vin) {
2161 const auto mi = mapWallet.find(input.prevout.hash);
2162 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2167 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2169 std::map<int, bilingual_str> input_errors;
2179 if (spk_man->SignTransaction(tx, coins,
sighash, input_errors)) {
2195 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2196 const CTxIn& txin = psbtx.
tx->vin[i];
2206 const auto it = mapWallet.find(txhash);
2207 if (it != mapWallet.end()) {
2220 int n_signed_this_spkm = 0;
2221 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize)};
2227 (*n_signed) += n_signed_this_spkm;
2235 for (
size_t i = 0; i < psbtx.
inputs.size(); ++i) {
2247 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2249 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2259 return *change_type;
2268 bool any_wpkh{
false};
2270 bool any_pkh{
false};
2272 for (
const auto& recipient : vecSend) {
2273 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2275 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2277 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2279 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2285 if (has_bech32m_spkman && any_tr) {
2290 if (has_bech32_spkman && any_wpkh) {
2295 if (has_p2sh_segwit_spkman && any_sh) {
2301 if (has_legacy_spkman && any_pkh) {
2306 if (has_bech32m_spkman) {
2309 if (has_bech32_spkman) {
2326 wtx.
mapValue = std::move(mapValue);
2335 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2339 for (
const CTxIn& txin : tx->vin) {
2350 std::string err_string;
2352 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2369 spk_man_pair.second->RewriteDB();
2379 return nLoadWalletRet;
2386 if (!batch.
TxnBegin())
return util::Error{
_(
"Error starting db txn for wallet transactions removal")};
2389 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2390 std::vector<TxIterator> erased_txs;
2392 for (
const uint256& hash : txs_to_remove) {
2393 auto it_wtx = mapWallet.find(hash);
2394 if (it_wtx == mapWallet.end()) {
2395 str_err =
strprintf(
_(
"Transaction %s does not belong to this wallet"), hash.GetHex());
2399 str_err =
strprintf(
_(
"Failure removing transaction: %s"), hash.GetHex());
2402 erased_txs.emplace_back(it_wtx);
2406 if (!str_err.
empty()) {
2412 if (!batch.
TxnCommit())
return util::Error{
_(
"Error committing db txn for wallet transactions removal")};
2415 for (
const auto& it : erased_txs) {
2416 const uint256 hash{it->first};
2417 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2418 for (
const auto& txin : it->second.tx->vin)
2419 mapTxSpends.erase(txin.prevout);
2420 mapWallet.erase(it);
2431 bool fUpdated =
false;
2433 std::optional<AddressPurpose> purpose;
2436 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2437 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2439 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2450 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2453 if (!batch.
WriteName(encoded_dest, strName)) {
2509 m_address_book.erase(address);
2522 if (legacy_spk_man) {
2523 return legacy_spk_man->KeypoolCountExternalKeys();
2526 unsigned int count = 0;
2528 count += spk_man.second->GetKeyPoolSize();
2538 unsigned int count = 0;
2540 count += spk_man->GetKeyPoolSize();
2550 res &= spk_man->TopUp(kpSize);
2563 auto op_dest = spk_man->GetNewDestination(type);
2586 return std::nullopt;
2589 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2591 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2597 for (
auto& entry : mapWallet) {
2600 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2613 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2614 const auto& entry = item.second;
2615 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2622 std::vector<CTxDestination> result;
2630 result.emplace_back(dest);
2638 std::set<std::string> label_set;
2640 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2641 if (_is_change)
return;
2642 if (!purpose || purpose == _purpose) {
2643 label_set.insert(_label);
2660 if (!op_address)
return op_address;
2691 if (signer_spk_man ==
nullptr) {
2695 return signer_spk_man->DisplayAddress(dest, signer);
2697 return util::Error{
_(
"There is no ScriptPubKeyManager for this address")};
2703 setLockedCoins.insert(output);
2713 bool was_locked = setLockedCoins.erase(output);
2714 if (batch && was_locked) {
2723 bool success =
true;
2725 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2728 setLockedCoins.clear();
2735 return setLockedCoins.count(output) > 0;
2741 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2742 it != setLockedCoins.end(); it++) {
2744 vOutpts.push_back(outpt);
2752 mapKeyBirth.clear();
2755 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2762 assert(spk_man !=
nullptr);
2766 for (
const auto& entry : spk_man->mapKeyMetadata) {
2767 if (entry.second.nCreateTime) {
2768 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2774 if (mapKeyBirth.count(keyid) == 0)
2775 mapKeyFirstBlock[keyid] = &max_confirm;
2779 if (mapKeyFirstBlock.empty())
2783 for (
const auto& entry : mapWallet) {
2788 for (
const CTxOut &txout : wtx.
tx->vout) {
2792 auto rit = mapKeyFirstBlock.find(keyid);
2793 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2803 for (
const auto& entry : mapKeyFirstBlock) {
2835 std::optional<uint256> block_hash;
2837 block_hash = conf->confirmed_block_hash;
2839 block_hash = conf->conflicting_block_hash;
2845 int64_t block_max_time;
2846 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2847 if (rescanning_old_block) {
2848 nTimeSmart = block_max_time;
2851 int64_t latestEntry = 0;
2854 int64_t latestTolerated = latestNow + 300;
2856 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2866 if (nSmartTime <= latestTolerated) {
2867 latestEntry = nSmartTime;
2868 if (nSmartTime > latestNow) {
2869 latestNow = nSmartTime;
2875 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2886 if (std::get_if<CNoDestination>(&dest))
2890 if (
auto* data{
common::FindKey(m_address_book, dest)}) data->previously_spent =
false;
2900 m_address_book[dest].previously_spent =
true;
2905 m_address_book[dest].receive_requests[id] = request;
2910 if (
auto* data{
common::FindKey(m_address_book, dest)})
return data->previously_spent;
2916 std::vector<std::string>
values;
2917 for (
const auto& [dest, entry] : m_address_book) {
2918 for (
const auto& [
id, request] : entry.receive_requests) {
2919 values.emplace_back(request);
2928 m_address_book[dest].receive_requests[id] = value;
2935 m_address_book[dest].receive_requests.erase(
id);
2948 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2949 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2950 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2953 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 2954 "database/log.?????????? files can be stored, a location where such a directory could be created, " 2955 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2969 return MakeDatabase(*wallet_path, options, status, error_string);
2976 const std::string& walletFile = database->Filename();
2978 const auto start{SteadyClock::now()};
2983 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
2986 bool rescan_required =
false;
2987 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2990 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2995 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 2996 " or address metadata may be missing or incorrect."),
3004 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
3012 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect." 3013 " Rescanning wallet."), walletFile));
3014 rescan_required =
true;
3016 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n" 3017 "The wallet might had been created on a newer version.\n" 3018 "Please try running the latest software version.\n"), walletFile);
3021 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n" 3022 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3025 error =
strprintf(
_(
"Error loading %s"), walletFile);
3031 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3039 walletInstance->InitWalletFlags(wallet_creation_flags);
3043 walletInstance->SetupLegacyScriptPubKeyMan();
3047 LOCK(walletInstance->cs_wallet);
3049 walletInstance->SetupDescriptorScriptPubKeyMans();
3053 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3054 if (!spk_man->SetupGeneration()) {
3055 error =
_(
"Unable to generate initial keys");
3067 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3070 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3071 if (spk_man->HavePrivateKeys()) {
3072 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3078 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
3084 walletInstance->m_default_address_type = parsed.value();
3087 if (!
args.
GetArg(
"-changetype",
"").empty()) {
3093 walletInstance->m_default_change_type = parsed.value();
3103 _(
"This is the minimum transaction fee you pay on every transaction."));
3106 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
3110 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
3111 if (max_aps_fee ==
"-1") {
3112 walletInstance->m_max_aps_fee = -1;
3113 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
3116 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3118 walletInstance->m_max_aps_fee = max_fee.value();
3127 if (!fallback_fee) {
3128 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-fallbackfee",
args.
GetArg(
"-fallbackfee",
""));
3132 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3134 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3138 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3143 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-discardfee",
args.
GetArg(
"-discardfee",
""));
3147 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3149 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3159 _(
"This is the transaction fee you will pay if you send a transaction."));
3162 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3165 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3177 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3181 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3186 walletInstance->m_default_max_tx_fee = max_fee.value();
3190 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3191 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3200 _(
"The wallet will avoid paying less than the minimum relay fee."));
3207 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3210 walletInstance->TopUpKeyPool();
3213 std::optional<int64_t> time_first_key;
3214 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3215 int64_t time = spk_man->GetTimeFirstKey();
3216 if (!time_first_key || time < *time_first_key) time_first_key = time;
3218 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3221 walletInstance->m_chain_notifications_handler.reset();
3226 LOCK(walletInstance->cs_wallet);
3228 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3229 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3230 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3233 return walletInstance;
3238 LOCK(walletInstance->cs_wallet);
3240 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3241 walletInstance->m_chain = &
chain;
3247 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 &&
chain.
getHeight()) {
3251 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3267 walletInstance->m_attaching_chain =
true;
3268 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3271 int rescan_height = 0;
3272 if (!rescan_required)
3276 if (batch.ReadBestBlock(locator)) {
3278 rescan_height = *fork_height;
3286 walletInstance->m_last_block_processed_height = *tip_height;
3288 walletInstance->m_last_block_processed.
SetNull();
3289 walletInstance->m_last_block_processed_height = -1;
3292 if (tip_height && *tip_height != rescan_height)
3296 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3297 if (time_first_key) {
3304 rescan_height = *tip_height;
3312 int block_height = *tip_height;
3313 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3317 if (rescan_height != block_height) {
3328 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3330 "Error loading wallet. Wallet requires blocks to be downloaded, " 3331 "and software does not currently support loading wallets while " 3332 "blocks are being downloaded out of order when using assumeutxo " 3333 "snapshots. Wallet should be able to load successfully after " 3334 "node sync reaches height %s"), block_height);
3340 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3345 error =
_(
"Failed to rescan the wallet during initialization");
3349 walletInstance->m_attaching_chain =
false;
3351 walletInstance->GetDatabase().IncrementUpdateCounter();
3353 walletInstance->m_attaching_chain =
false;
3360 const auto& address_book_it = m_address_book.find(dest);
3361 if (address_book_it == m_address_book.end())
return nullptr;
3362 if ((!allow_change) && address_book_it->second.IsChange()) {
3365 return &address_book_it->second;
3377 if (version < prev_version) {
3378 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3386 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);
3394 if (!spk_man->Upgrade(prev_version, version, error)) {
3435 assert(conf->confirmed_block_height >= 0);
3438 assert(conf->conflicting_block_height >= 0);
3453 assert(chain_depth >= 0);
3476 return vMasterKey.empty();
3486 if (!vMasterKey.empty()) {
3487 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3501 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3505 vMasterKey = vMasterKeyIn;
3513 std::set<ScriptPubKeyMan*> spk_mans;
3514 for (
bool internal : {
false,
true}) {
3518 spk_mans.insert(spk_man);
3528 if (ext_spkm == &spkm)
return true;
3531 if (int_spkm == &spkm)
return true;
3538 std::set<ScriptPubKeyMan*> spk_mans;
3540 spk_mans.insert(spk_man_pair.second.get());
3548 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3549 if (it == spk_managers.end()) {
3557 std::set<ScriptPubKeyMan*> spk_mans;
3562 spk_mans.insert(it->second.begin(), it->second.end());
3595 return it->second.at(0)->GetSolvingProvider(
script);
3607 std::vector<WalletDescriptor> descs;
3609 if (
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3610 LOCK(desc_spk_man->cs_desc_man);
3611 descs.push_back(desc_spk_man->GetWalletDescriptor());
3667 std::unique_ptr<ScriptPubKeyMan> spk_manager =
m_database->Format() ==
"bdb_ro" ?
3668 std::make_unique<LegacyDataSPKM>(*this) :
3675 uint256 id = spk_manager->GetID();
3682 return cb(vMasterKey);
3708 return *spk_manager;
3717 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3719 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3720 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3723 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type,
internal);
3725 uint256 id = spk_manager->GetID();
3737 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors setup");
3739 for (
bool internal : {
false,
true}) {
3746 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors setup");
3771 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3774 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3776 for (
bool internal : {
false,
true}) {
3777 const UniValue& descriptor_vals = signer_res.
find_value(
internal ?
"internal" :
"receive");
3778 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3780 const std::string& desc_str = desc_val.
getValStr();
3782 std::string desc_error;
3783 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, desc_error,
false);
3784 if (desc ==
nullptr) {
3785 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3787 if (!desc->GetOutputType()) {
3792 spk_manager->SetupDescriptor(batch, std::move(desc));
3793 uint256 id = spk_manager->GetID();
3800 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3813 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3828 spk_mans[type] = spk_man;
3830 const auto it = spk_mans_other.find(type);
3831 if (it != spk_mans_other.end() && it->second == spk_man) {
3832 spk_mans_other.erase(type);
3841 if (spk_man !=
nullptr && spk_man->GetID() == id) {
3845 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3849 spk_mans.erase(type);
3877 return std::nullopt;
3882 return std::nullopt;
3886 if (!desc_spk_man) {
3887 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3890 LOCK(desc_spk_man->cs_desc_man);
3891 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3892 assert(type.has_value());
3902 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3909 spk_man->UpdateWalletDescriptor(desc);
3912 spk_man = new_spk_man.get();
3915 uint256 id = new_spk_man->GetID();
3920 for (
const auto& entry : signing_provider.
keys) {
3921 const CKey& key = entry.second;
3922 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3926 if (!spk_man->TopUp()) {
3934 auto script_pub_keys = spk_man->GetScriptPubKeys();
3935 if (script_pub_keys.empty()) {
3936 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3941 for (
const auto&
script : script_pub_keys) {
3951 spk_man->WriteDescriptor();
3960 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3963 error =
_(
"Error: This wallet already uses SQLite");
3968 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3969 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
3970 std::vector<std::pair<SerializeData, SerializeData>> records;
3972 error =
_(
"Error: Unable to begin reading all records in the database");
3979 status = cursor->Next(ss_key, ss_value);
3985 records.emplace_back(key, value);
3990 error =
_(
"Error: Unable to read all records in the database");
3997 fs::remove(db_path);
4008 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status, error);
4015 bool began = batch->TxnBegin();
4017 for (
const auto& [key, value] : records) {
4018 if (!batch->Write(
Span{key},
Span{value})) {
4025 bool committed = batch->TxnCommit();
4035 if (!
Assume(legacy_spkm)) {
4038 return std::nullopt;
4042 if (res == std::nullopt) {
4043 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4044 return std::nullopt;
4054 if (!
Assume(legacy_spkm)) {
4061 std::set<CTxDestination> not_migrated_dests;
4071 error =
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
4074 uint256 id = desc_spkm->GetID();
4103 error =
_(
"Error: Unable to read wallet's best block locator record");
4109 std::vector<uint256> txids_to_delete;
4110 std::unique_ptr<WalletBatch> watchonly_batch;
4112 watchonly_batch = std::make_unique<WalletBatch>(data.
watchonly_wallet->GetDatabase());
4118 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4119 error =
_(
"Error: Unable to write watchonly wallet best block locator record");
4126 error =
_(
"Error: Unable to write solvable wallet best block locator record");
4138 const uint256& hash = wtx->GetHash();
4141 if (!new_tx) return false;
4142 ins_wtx.SetTx(to_copy_wtx.tx);
4143 ins_wtx.CopyFrom(to_copy_wtx);
4146 error =
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex());
4152 txids_to_delete.push_back(hash);
4159 error =
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
4163 watchonly_batch.reset();
4165 if (txids_to_delete.size() > 0) {
4166 if (
auto res =
RemoveTxs(txids_to_delete); !res) {
4167 error =
_(
"Error: Could not delete watchonly transactions. ") +
util::ErrorString(res);
4173 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4175 if (!ext_wallet)
continue;
4177 std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
4178 if (!batch->TxnBegin()) {
4179 error =
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
4182 wallets_vec.emplace_back(ext_wallet, std::move(batch));
4189 if (entry.label) batch.
WriteName(address, *entry.label);
4190 for (
const auto& [
id, request] : entry.receive_requests) {
4197 std::vector<CTxDestination> dests_to_delete;
4198 for (
const auto& [dest, record] : m_address_book) {
4202 bool copied =
false;
4203 for (
auto& [
wallet, batch] : wallets_vec) {
4205 if (require_transfer && !
wallet->IsMine(dest))
continue;
4208 wallet->m_address_book[dest] = record;
4209 func_store_addr(*batch, dest, record);
4213 if (require_transfer) {
4214 dests_to_delete.push_back(dest);
4222 if (require_transfer && !copied) {
4225 if (not_migrated_dests.count(dest) > 0) {
4226 dests_to_delete.push_back(dest);
4230 error =
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets");
4236 for (
auto& [
wallet, batch] : wallets_vec) {
4238 error =
strprintf(
_(
"Error: address book copy failed for wallet %s"),
wallet->GetName());
4246 if (dests_to_delete.size() > 0) {
4247 for (
const auto& dest : dests_to_delete) {
4249 error =
_(
"Error: Unable to remove watchonly address book data");
4275 std::optional<MigrationData> data =
wallet.GetDescriptorsForLegacy(error);
4276 if (data == std::nullopt)
return false;
4279 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
4286 empty_context.
args = context.args;
4296 if (data->watch_descs.size() > 0) {
4297 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4300 std::vector<bilingual_str> warnings;
4301 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4302 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4304 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4309 if (!data->watchonly_wallet) {
4310 error =
_(
"Error: Failed to create new watchonly wallet");
4313 res.watchonly_wallet = data->watchonly_wallet;
4314 LOCK(data->watchonly_wallet->cs_wallet);
4317 for (
const auto& [desc_str, creation_time] : data->watch_descs) {
4320 std::string parse_err;
4321 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4323 assert(!desc->IsRange());
4327 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4333 if (data->solvable_descs.size() > 0) {
4334 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4337 std::vector<bilingual_str> warnings;
4338 std::string wallet_name =
wallet.GetName() +
"_solvables";
4339 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4341 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4346 if (!data->solvable_wallet) {
4347 error =
_(
"Error: Failed to create new watchonly wallet");
4350 res.solvables_wallet = data->solvable_wallet;
4351 LOCK(data->solvable_wallet->cs_wallet);
4354 for (
const auto& [desc_str, creation_time] : data->solvable_descs) {
4357 std::string parse_err;
4358 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4360 assert(!desc->IsRange());
4364 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4373 if (!
wallet.ApplyMigrationData(*data, error)) {
4383 std::vector<bilingual_str> warnings;
4386 bool was_loaded =
false;
4389 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4393 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4404 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4416 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4422 std::shared_ptr<CWallet> local_wallet =
CWallet::Create(empty_context, wallet_name, std::move(database), options.
create_flags, error, warnings);
4423 if (!local_wallet) {
4428 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4431 assert(to_reload.use_count() == 1);
4432 std::string
name = to_reload->GetName();
4434 to_reload =
LoadWallet(context,
name, std::nullopt, options, status, error, warnings);
4435 return to_reload !=
nullptr;
4441 reload_wallet(local_wallet);
4443 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4449 fs::path backup_path = this_wallet_dir / backup_filename;
4452 reload_wallet(local_wallet);
4454 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4458 bool success =
false;
4461 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4463 reload_wallet(local_wallet);
4465 if (passphrase.find(
'\0') == std::string::npos) {
4466 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4468 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. " 4469 "The passphrase contains a null character (ie - a zero byte). " 4470 "If this passphrase was set with a version of this software prior to 25.0, " 4471 "please try again with only the characters up to — but not including — " 4472 "the first null character.")};
4477 LOCK(local_wallet->cs_wallet);
4479 if (!local_wallet->MigrateToSQLite(error))
return util::Error{error};
4484 success =
DoMigration(*local_wallet, context, error, res);
4495 std::set<fs::path> wallet_dirs;
4499 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4500 success = reload_wallet(local_wallet);
4501 res.
wallet = local_wallet;
4518 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4521 std::vector<std::shared_ptr<CWallet>> created_wallets;
4522 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4527 for (std::shared_ptr<CWallet>& w : created_wallets) {
4532 for (std::shared_ptr<CWallet>& w : created_wallets) {
4533 if (w->HaveChain()) {
4536 error +=
_(
"\nUnable to cleanup failed migration");
4542 assert(w.use_count() == 1);
4548 for (
const fs::path& dir : wallet_dirs) {
4549 fs::remove_all(dir);
4554 std::vector<bilingual_str> warnings;
4555 if (!
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status, error, warnings)) {
4556 error +=
_(
"\nUnable to restore backup of wallet.");
4561 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4562 fs::remove(temp_backup_location);
4571 for (
const auto&
script : spks) {
4588 std::set<CExtPubKey> active_xpubs;
4595 std::set<CPubKey> desc_pubkeys;
4596 std::set<CExtPubKey> desc_xpubs;
4597 w_desc.
descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4598 active_xpubs.merge(std::move(desc_xpubs));
4600 return active_xpubs;
4611 if (std::optional<CKey> key = desc_spkm->
GetKey(keyid)) {
4615 return std::nullopt;
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 ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
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)
std::optional< CKey > GetKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet...
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
bool 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
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)
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,...)
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)
DescriptorScriptPubKeyMan & SetupDescriptorScriptPubKeyMan(WalletBatch &batch, const CExtKey &master_key, const OutputType &output_type, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMan and add it to the wallet.
std::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)
bilingual_str AmountHighWarn(const std::string &optname)
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.
is a home for simple string functions returning descriptive messages that are used in RPC and GUI int...
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.
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
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.
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)
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
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)
static GlobalMutex g_loading_wallet_mutex
A version of CTransaction with the PSBT format.
std::set< CExtPubKey > GetActiveHDPubKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve the xpubs in use by the active descriptors.
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)
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.
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.
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
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.
bool CanProvide(const CScript &script, SignatureData &sigdata) override
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that...
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...
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
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)
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 Legacy(Data)SPKM 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.
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
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 IsBDBFile(const fs::path &path)
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)
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData *txdata)
Checks whether a PSBTInput is already signed by doing script verification using final fields...
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
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)
virtual bool updateRwSetting(const std::string &name, const SettingsUpdate &update_function)=0
Updates a setting in <datadir>/settings.json.
void blockDisconnected(const interfaces::BlockInfo &block) override
std::optional< CKey > GetKey(const CKeyID &keyid) const
Find the private key for the given key id from the wallet's descriptors, if available Returns nullopt...
void blockConnected(ChainstateRole role, const interfaces::BlockInfo &block) override
State of rejected transaction that conflicts with a confirmed block.
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.
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
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
LegacyDataSPKM * GetOrCreateLegacyDataSPKM()
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.
std::set< Txid > mempool_conflicts
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)
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
bool WriteWalletFlags(const uint64_t flags)
#define WAIT_LOCK(cs, name)
An output of a transaction.
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 void FlushAndDeleteWallet(CWallet *wallet)
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
is a home for public enum and struct type definitions that are used by internally by wallet code...
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
bool isBlockConflicted() const
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.
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 ...
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.
const std::string & FormatOutputType(OutputType type)
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
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
uint256 GetID() const override
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const Txid & GetHash() const LIFETIMEBOUND
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
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)
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 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::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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)
fs::path BDBDataFile(const fs::path &wallet_path)
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
RecursiveMutex cs_desc_man
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
int conflicting_block_height
std::optional< std::string > m_op_label
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.
enum wallet::CWallet::ScanResult::@18 status
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)
static util::Result< fs::path > GetWalletPath(const std::string &name)
#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.
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)
is a home for public enum and struct type definitions that are used by internally by node code...
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
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.
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)
bilingual_str _(ConstevalStringLiteral str)
Translation function.
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
LegacyDataSPKM * GetLegacyDataSPKM() const
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
WalletFeature GetClosestWalletFeature(int version)
#define PACKAGE_BUGREPORT
static std::condition_variable g_wallet_release_cv
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
bool IsActiveScriptPubKeyMan(const ScriptPubKeyMan &spkm) const
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.