54 "You need to rescan the blockchain in order to correctly mark used " 55 "destinations in the past. Until this is done, some destinations may " 56 "be considered unused, even if the opposite is the case." 65 if (value.isStr() && value.get_str() == wallet_name)
return true;
74 if (!setting_value.
isArray())
return true;
77 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
79 if (new_value.
size() == setting_value.
size())
return true;
84 const std::string& wallet_name,
85 std::optional<bool> load_on_startup,
86 std::vector<bilingual_str>& warnings)
88 if (!load_on_startup)
return;
90 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
92 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
114 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(
context.wallets.begin(),
context.wallets.end(),
wallet);
115 if (i !=
context.wallets.end())
return false;
117 wallet->ConnectScriptPubKeyManNotifiers();
118 wallet->NotifyCanGetAddressesChanged();
130 wallet->m_chain_notifications_handler.reset();
132 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(
context.wallets.begin(),
context.wallets.end(),
wallet);
133 if (i ==
context.wallets.end())
return false;
144 std::vector<bilingual_str> warnings;
164 for (
const std::shared_ptr<CWallet>&
wallet :
context.wallets) {
173 auto it =
context.wallet_load_fns.emplace(
context.wallet_load_fns.end(), std::move(load_wallet));
180 for (
auto& load_wallet :
context.wallet_load_fns) {
195 wallet->WalletLogPrintf(
"Releasing wallet\n");
201 if (g_unloading_wallet_set.erase(
name) == 0) {
215 auto it = g_unloading_wallet_set.insert(
name);
227 while (g_unloading_wallet_set.count(
name) == 1) {
234 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)
253 wallet->postInitProcess();
259 }
catch (
const std::runtime_error& e) {
270 if (!result.second) {
291 if (!passphrase.empty()) {
297 error =
Untranslated(
"Private keys must be disabled when using an external signer");
304 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
311 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.");
335 if (!
wallet->EncryptWallet(passphrase)) {
342 if (!
wallet->Unlock(passphrase)) {
352 wallet->SetupDescriptorScriptPubKeyMans();
354 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
355 if (!spk_man->SetupGeneration()) {
371 wallet->postInitProcess();
378 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."));
392 auto wallet_file = wallet_path /
"wallet.dat";
393 std::shared_ptr<CWallet>
wallet;
408 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
411 }
catch (
const std::exception& e) {
417 fs::remove(wallet_file);
418 fs::remove(wallet_path);
432 const auto it = mapWallet.find(hash);
433 if (it == mapWallet.end())
435 return &(it->second);
449 spk_man->UpgradeKeyMetadata();
473 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
475 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
477 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
479 if (
Unlock(_vMasterKey, accept_no_keys)) {
503 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
505 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
510 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
511 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(
GetTimeMillis() - nStartTime))));
514 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
515 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
517 if (pMasterKey.second.nDeriveIterations < 25000)
518 pMasterKey.second.nDeriveIterations = 25000;
520 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
522 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
524 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
551 if (nWalletVersion >= nVersion)
554 nWalletVersion = nVersion;
558 if (nWalletVersion > 40000)
567 std::set<uint256> result;
570 const auto it = mapWallet.find(txid);
571 if (it == mapWallet.end())
575 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
577 for (
const CTxIn& txin : wtx.
tx->vin)
579 if (mapTxSpends.count(txin.
prevout) <= 1)
581 range = mapTxSpends.equal_range(txin.
prevout);
582 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
583 result.insert(_it->second);
591 const uint256& txid = tx->GetHash();
592 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
616 int nMinOrderPos = std::numeric_limits<int>::max();
618 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
619 const CWalletTx* wtx = &mapWallet.at(it->second);
631 for (TxSpends::iterator it = range.first; it != range.second; ++it)
633 const uint256& hash = it->second;
635 if (copyFrom == copyTo)
continue;
636 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
655 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
656 range = mapTxSpends.equal_range(outpoint);
658 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
659 const uint256& wtxid = it->second;
660 const auto mit = mapWallet.find(wtxid);
661 if (mit != mapWallet.end()) {
663 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
672 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
681 std::pair<TxSpends::iterator, TxSpends::iterator> range;
682 range = mapTxSpends.equal_range(outpoint);
692 for (
const CTxIn& txin : wtx.
tx->vin)
735 delete encrypted_batch;
736 encrypted_batch =
nullptr;
742 auto spk_man = spk_man_pair.second.get();
743 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
745 delete encrypted_batch;
746 encrypted_batch =
nullptr;
757 delete encrypted_batch;
758 encrypted_batch =
nullptr;
764 delete encrypted_batch;
765 encrypted_batch =
nullptr;
768 Unlock(strWalletPassphrase);
775 if (spk_man->IsHDEnabled()) {
776 if (!spk_man->SetupGeneration(
true)) {
807 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
810 for (
auto& entry : mapWallet)
817 std::vector<int64_t> nOrderPosOffsets;
818 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
825 nOrderPos = nOrderPosNext++;
826 nOrderPosOffsets.push_back(nOrderPos);
833 int64_t nOrderPosOff = 0;
834 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
836 if (nOrderPos >= nOffsetStart)
839 nOrderPos += nOrderPosOff;
840 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
858 int64_t nRet = nOrderPosNext++;
871 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
872 item.second.MarkDirty();
880 auto mi = mapWallet.find(originalHash);
883 assert(mi != mapWallet.end());
888 assert(wtx.mapValue.count(
"replaced_by_txid") == 0);
890 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
899 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
919 tx_destinations.insert(dst);
939 assert(spk_man !=
nullptr);
968 std::set<CTxDestination> tx_destinations;
970 for (
const CTxIn& txin : tx->vin) {
979 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
981 bool fInsertedNew =
ret.second;
982 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
993 if (state.index() != wtx.
m_state.index()) {
1005 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1012 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
1015 if (fInsertedNew || fUpdated)
1027 std::string strCmd =
m_args.
GetArg(
"-walletnotify",
"");
1029 if (!strCmd.empty())
1034 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1048 std::thread
t(runCommand, strCmd);
1058 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1060 if (!fill_wtx(wtx, ins.second)) {
1067 auto lookup_block = [&](
const uint256& hash,
int& height,
TxState& state) {
1079 lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, wtx.
m_state);
1081 lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, wtx.
m_state);
1088 for (
const CTxIn& txin : wtx.
tx->vin) {
1090 if (it != mapWallet.end()) {
1106 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1108 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1109 while (range.first != range.second) {
1110 if (range.first->second != tx.
GetHash()) {
1111 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);
1112 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1119 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1120 if (fExisted && !fUpdate)
return false;
1132 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1134 if (!dest.internal.has_value()) {
1139 if (!dest.internal.has_value())
continue;
1153 TxState tx_state = std::visit([](
auto&& s) ->
TxState {
return s; }, state);
1158 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1175 for (
const CTxIn& txin : tx->vin) {
1177 if (it != mapWallet.end()) {
1178 it->second.MarkDirty();
1189 std::set<uint256> todo;
1190 std::set<uint256> done;
1193 auto it = mapWallet.find(hashTx);
1194 assert(it != mapWallet.end());
1200 todo.insert(hashTx);
1202 while (!todo.empty()) {
1206 auto it = mapWallet.find(now);
1207 assert(it != mapWallet.end());
1211 assert(currentconfirm <= 0);
1213 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1215 assert(!wtx.InMempool());
1221 for (
unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1222 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(now, i));
1223 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1224 if (!done.count(iter->second)) {
1225 todo.insert(iter->second);
1242 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1247 if (conflictconfirms >= 0)
1253 std::set<uint256> todo;
1254 std::set<uint256> done;
1256 todo.insert(hashTx);
1258 while (!todo.empty()) {
1262 auto it = mapWallet.find(now);
1263 assert(it != mapWallet.end());
1266 if (conflictconfirms < currentconfirm) {
1273 for (
unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1274 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(now, i));
1275 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1276 if (!done.count(iter->second)) {
1277 todo.insert(iter->second);
1303 auto it = mapWallet.find(tx->GetHash());
1304 if (it != mapWallet.end()) {
1311 auto it = mapWallet.find(tx->GetHash());
1312 if (it != mapWallet.end()) {
1351 m_last_block_processed_height = block.
height;
1352 m_last_block_processed = block.
hash;
1353 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1368 m_last_block_processed_height = block.
height - 1;
1380 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1396 const auto mi = mapWallet.find(txin.
prevout.
hash);
1397 if (mi != mapWallet.end())
1425 result = std::max(result, spk_man_pair.second->IsMine(script));
1446 if (outpoint.
n >= wtx->tx->vout.size()) {
1449 return IsMine(wtx->tx->vout[outpoint.
n]);
1464 throw std::runtime_error(std::string(__func__) +
": value out of range");
1472 bool result =
false;
1474 if (!spk_man->IsHDEnabled())
return false;
1486 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1493 void CWallet::SetWalletFlag(uint64_t
flags)
1498 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1512 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1547 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1579 if (target_weight < txin_weight) {
1582 if (target_weight == txin_weight) {
1587 int64_t add_weight = target_weight - txin_weight;
1597 if ((add_weight >= 253 && add_weight < 263)
1598 || (add_weight > std::numeric_limits<uint16_t>::max() && add_weight <= std::numeric_limits<uint16_t>::max() + 10)
1599 || (add_weight > std::numeric_limits<uint32_t>::max() && add_weight <= std::numeric_limits<uint32_t>::max() + 10)) {
1600 int64_t first_weight = add_weight / 3;
1601 add_weight -= first_weight;
1619 for (
const auto& txout : txouts)
1630 const std::unique_ptr<SigningProvider> provider =
GetSolvingProvider(txout.scriptPubKey);
1631 if (!provider || !
DummySignInput(*provider, txin, txout, coin_control)) {
1648 LOCK(spk_man->cs_KeyStore);
1649 return spk_man->ImportScripts(scripts, timestamp);
1658 LOCK(spk_man->cs_KeyStore);
1659 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1662 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)
1668 LOCK(spk_man->cs_KeyStore);
1669 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1672 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)
1678 LOCK(spk_man->cs_KeyStore);
1679 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1684 for (
const CScript& script : script_pub_keys) {
1708 int start_height = 0;
1749 constexpr
auto INTERVAL_TIME{60s};
1750 auto current_time{reserver.
now()};
1751 auto start_time{reserver.
now()};
1755 uint256 block_hash = start_block;
1767 double progress_current = progress_begin;
1768 int block_height = start_height;
1770 if (progress_end - progress_begin > 0.0) {
1771 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1775 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1779 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1780 if (next_interval) {
1781 current_time = reserver.
now();
1782 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1791 bool block_still_active =
false;
1792 bool next_block =
false;
1798 if (!block_still_active) {
1805 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1812 if (save_progress && next_interval) {
1826 if (max_height && block_height >= *max_height) {
1837 block_hash = next_block_hash;
1842 const uint256 prev_tip_hash = tip_hash;
1844 if (!max_height && prev_tip_hash != tip_hash) {
1856 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1858 }
else if (block_height &&
chain().shutdownRequested()) {
1859 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1862 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
1903 result.erase(myHash);
1915 if (!
chain().isReadyToBroadcast())
return false;
1956 int submitted_tx_count = 0;
1963 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
1964 for (
auto& [txid, wtx] : mapWallet) {
1966 if (!wtx.isUnconfirmed())
continue;
1971 to_submit.insert(&wtx);
1974 for (
auto wtx : to_submit) {
1975 std::string unused_err_string;
1980 if (submitted_tx_count > 0) {
1981 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
1990 if (!pwallet->ShouldResend())
continue;
1991 pwallet->ResubmitWalletTransactions(
true,
false);
1992 pwallet->SetNextResend();
2007 std::map<COutPoint, Coin> coins;
2008 for (
auto& input : tx.
vin) {
2009 const auto mi = mapWallet.find(input.prevout.hash);
2010 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2015 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2017 std::map<int, bilingual_str> input_errors;
2027 if (spk_man->SignTransaction(tx, coins,
sighash, input_errors)) {
2043 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2044 const CTxIn& txin = psbtx.
tx->vin[i];
2054 const auto it = mapWallet.find(txhash);
2055 if (it != mapWallet.end()) {
2068 int n_signed_this_spkm = 0;
2069 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm, finalize);
2075 (*n_signed) += n_signed_this_spkm;
2082 std::vector<unsigned int> to_drop;
2083 for (
unsigned int i = 0; i < psbtx.
inputs.size(); ++i) {
2084 const auto& input = psbtx.
inputs.at(i);
2086 std::vector<unsigned char> wit_prog;
2087 if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
2097 if (input.non_witness_utxo) {
2098 to_drop.push_back(i);
2103 for (
unsigned int i : to_drop) {
2104 psbtx.
inputs.at(i).non_witness_utxo =
nullptr;
2110 for (
const auto& input : psbtx.
inputs) {
2122 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2124 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2134 return *change_type;
2143 bool any_wpkh{
false};
2145 bool any_pkh{
false};
2147 for (
const auto& recipient : vecSend) {
2148 std::vector<std::vector<uint8_t>> dummy;
2162 if (has_bech32m_spkman && any_tr) {
2167 if (has_bech32_spkman && any_wpkh) {
2172 if (has_p2sh_segwit_spkman && any_sh) {
2178 if (has_legacy_spkman && any_pkh) {
2183 if (has_bech32m_spkman) {
2186 if (has_bech32_spkman) {
2203 wtx.
mapValue = std::move(mapValue);
2212 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2216 for (
const CTxIn& txin : tx->vin) {
2227 std::string err_string;
2229 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2244 spk_man_pair.second->RewriteDB();
2254 return nLoadWalletRet;
2261 for (
const uint256& hash : vHashOut) {
2262 const auto& it = mapWallet.find(hash);
2263 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2264 for (
const auto& txin : it->second.tx->vin)
2265 mapTxSpends.erase(txin.prevout);
2266 mapWallet.erase(it);
2275 spk_man_pair.second->RewriteDB();
2281 return nZapSelectTxRet;
2290 bool fUpdated =
false;
2294 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2295 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2296 m_address_book[address].SetLabel(strName);
2297 if (!strPurpose.empty())
2298 m_address_book[address].purpose = strPurpose;
2329 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
2333 m_address_book.erase(address);
2348 if (legacy_spk_man) {
2349 return legacy_spk_man->KeypoolCountExternalKeys();
2352 unsigned int count = 0;
2354 count += spk_man.second->GetKeyPoolSize();
2364 unsigned int count = 0;
2366 count += spk_man->GetKeyPoolSize();
2376 res &= spk_man->TopUp(kpSize);
2390 auto op_dest = spk_man->GetNewDestination(type);
2413 return std::nullopt;
2416 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2418 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2424 for (
auto& entry : mapWallet) {
2427 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2440 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2441 const auto& entry = item.second;
2442 func(item.first, entry.GetLabel(), entry.purpose, entry.IsChange());
2449 std::vector<CTxDestination> result;
2457 result.emplace_back(dest);
2465 std::set<std::string> label_set;
2467 const std::string& _purpose,
bool _is_change) {
2468 if (_is_change)
return;
2469 if (purpose.empty() || _purpose == purpose) {
2470 label_set.insert(_label);
2489 if (!op_address)
return op_address;
2519 if (signer_spk_man ==
nullptr) {
2523 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2531 setLockedCoins.insert(output);
2541 bool was_locked = setLockedCoins.erase(output);
2542 if (batch && was_locked) {
2551 bool success =
true;
2553 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2556 setLockedCoins.clear();
2563 return setLockedCoins.count(output) > 0;
2569 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2570 it != setLockedCoins.end(); it++) {
2572 vOutpts.push_back(outpt);
2580 mapKeyBirth.clear();
2583 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2590 assert(spk_man !=
nullptr);
2594 for (
const auto& entry : spk_man->mapKeyMetadata) {
2595 if (entry.second.nCreateTime) {
2596 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2602 if (mapKeyBirth.count(keyid) == 0)
2603 mapKeyFirstBlock[keyid] = &max_confirm;
2607 if (mapKeyFirstBlock.empty())
2611 for (
const auto& entry : mapWallet) {
2616 for (
const CTxOut &txout : wtx.
tx->vout) {
2620 auto rit = mapKeyFirstBlock.find(keyid);
2621 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2631 for (
const auto& entry : mapKeyFirstBlock) {
2663 std::optional<uint256> block_hash;
2665 block_hash = conf->confirmed_block_hash;
2667 block_hash = conf->conflicting_block_hash;
2673 int64_t block_max_time;
2674 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2675 if (rescanning_old_block) {
2676 nTimeSmart = block_max_time;
2679 int64_t latestEntry = 0;
2682 int64_t latestTolerated = latestNow + 300;
2684 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2694 if (nSmartTime <= latestTolerated) {
2695 latestEntry = nSmartTime;
2696 if (nSmartTime > latestNow) {
2697 latestNow = nSmartTime;
2703 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2714 const std::string key{
"used"};
2715 if (std::get_if<CNoDestination>(&dest))
2719 if (
auto* data =
util::FindKey(m_address_book, dest)) data->destdata.erase(key);
2723 const std::string value{
"1"};
2724 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2730 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2735 const std::string key{
"used"};
2736 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
2737 if(i != m_address_book.end())
2739 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2740 if(j != i->second.destdata.end())
2750 const std::string
prefix{
"rr"};
2751 std::vector<std::string>
values;
2752 for (
const auto& address : m_address_book) {
2753 for (
const auto& data : address.second.destdata) {
2755 values.emplace_back(data.second);
2764 const std::string key{
"rr" +
id};
2766 if (value.empty()) {
2785 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2786 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2787 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2790 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 2791 "database/log.?????????? files can be stored, a location where such a directory could be created, " 2792 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2797 return MakeDatabase(wallet_path, options, status, error_string);
2804 const std::string& walletFile = database->Filename();
2806 const auto start{SteadyClock::now()};
2810 bool rescan_required =
false;
2811 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2814 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2819 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 2820 " or address book entries might be missing or incorrect."),
2828 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
2836 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect." 2837 " Rescanning wallet."), walletFile));
2838 rescan_required =
true;
2840 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n" 2841 "The wallet might had been created on a newer version.\n" 2842 "Please try running the latest software version.\n"), walletFile);
2851 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2859 walletInstance->InitWalletFlags(wallet_creation_flags);
2863 walletInstance->SetupLegacyScriptPubKeyMan();
2867 LOCK(walletInstance->cs_wallet);
2869 walletInstance->SetupDescriptorScriptPubKeyMans();
2873 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2874 if (!spk_man->SetupGeneration()) {
2875 error =
_(
"Unable to generate initial keys");
2887 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
2890 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2891 if (spk_man->HavePrivateKeys()) {
2892 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2898 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
2904 walletInstance->m_default_address_type = parsed.value();
2907 if (!
args.
GetArg(
"-changetype",
"").empty()) {
2913 walletInstance->m_default_change_type = parsed.value();
2918 if (!min_tx_fee || min_tx_fee.value() == 0) {
2923 _(
"This is the minimum transaction fee you pay on every transaction."));
2926 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
2930 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
2931 if (max_aps_fee ==
"-1") {
2932 walletInstance->m_max_aps_fee = -1;
2933 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
2936 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2938 walletInstance->m_max_aps_fee = max_fee.value();
2947 if (!fallback_fee) {
2952 _(
"This is the transaction fee you may pay when fee estimates are not available."));
2954 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
2958 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
2967 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
2969 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
2979 _(
"This is the transaction fee you will pay if you send a transaction."));
2982 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
2985 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
2997 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
3001 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3006 walletInstance->m_default_max_tx_fee = max_fee.value();
3010 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3011 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3020 _(
"The wallet will avoid paying less than the minimum relay fee."));
3027 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3030 walletInstance->TopUpKeyPool();
3037 LOCK(walletInstance->cs_wallet);
3039 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3040 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3041 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3044 return walletInstance;
3049 LOCK(walletInstance->cs_wallet);
3051 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3052 walletInstance->m_chain = &
chain;
3058 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 &&
chain.
getHeight()) {
3062 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3078 walletInstance->m_attaching_chain =
true;
3079 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3082 int rescan_height = 0;
3083 if (!rescan_required)
3087 if (batch.ReadBestBlock(locator)) {
3089 rescan_height = *fork_height;
3097 walletInstance->m_last_block_processed_height = *tip_height;
3099 walletInstance->m_last_block_processed.
SetNull();
3100 walletInstance->m_last_block_processed_height = -1;
3103 if (tip_height && *tip_height != rescan_height)
3107 std::optional<int64_t> time_first_key;
3108 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3109 int64_t time = spk_man->GetTimeFirstKey();
3110 if (!time_first_key || time < *time_first_key) time_first_key = time;
3112 if (time_first_key) {
3119 rescan_height = *tip_height;
3127 int block_height = *tip_height;
3128 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3132 if (rescan_height != block_height) {
3144 "Assumed-valid: last wallet synchronisation goes beyond " 3145 "available block data. You need to wait for the background " 3146 "validation chain to download more blocks.") :
3147 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
3153 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3158 error =
_(
"Failed to rescan the wallet during initialization");
3162 walletInstance->m_attaching_chain =
false;
3164 walletInstance->GetDatabase().IncrementUpdateCounter();
3166 walletInstance->m_attaching_chain =
false;
3173 const auto& address_book_it = m_address_book.find(dest);
3174 if (address_book_it == m_address_book.end())
return nullptr;
3175 if ((!allow_change) && address_book_it->second.IsChange()) {
3178 return &address_book_it->second;
3190 if (version < prev_version) {
3191 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3199 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);
3207 if (!spk_man->Upgrade(prev_version, version,
error)) {
3264 assert(chain_depth >= 0);
3287 return vMasterKey.empty();
3297 if (!vMasterKey.empty()) {
3298 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3312 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
3316 vMasterKey = vMasterKeyIn;
3324 std::set<ScriptPubKeyMan*> spk_mans;
3325 for (
bool internal : {
false,
true}) {
3329 spk_mans.insert(spk_man);
3338 std::set<ScriptPubKeyMan*> spk_mans;
3340 spk_mans.insert(spk_man_pair.second.get());
3348 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3349 if (it == spk_managers.end()) {
3357 std::set<ScriptPubKeyMan*> spk_mans;
3360 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3361 spk_mans.insert(spk_man_pair.second.get());
3384 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3385 return spk_man_pair.second->GetSolvingProvider(script);
3393 std::vector<WalletDescriptor> descs;
3395 if (
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3396 LOCK(desc_spk_man->cs_desc_man);
3397 descs.push_back(desc_spk_man->GetWalletDescriptor());
3468 for (
bool internal : {
false,
true}) {
3473 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3475 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3476 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3479 spk_manager->SetupDescriptorGeneration(master_key,
t,
internal);
3480 uint256 id = spk_manager->GetID();
3510 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3511 for (
bool internal : {
false,
true}) {
3512 const UniValue& descriptor_vals =
find_value(signer_res,
internal ?
"internal" :
"receive");
3513 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3515 const std::string& desc_str = desc_val.getValStr();
3517 std::string desc_error;
3518 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, desc_error,
false);
3519 if (desc ==
nullptr) {
3520 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3522 if (!desc->GetOutputType()) {
3527 spk_manager->SetupDescriptor(std::move(desc));
3528 uint256 id = spk_manager->GetID();
3540 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3555 spk_mans[type] = spk_man;
3557 const auto it = spk_mans_other.find(type);
3558 if (it != spk_mans_other.end() && it->second == spk_man) {
3559 spk_mans_other.erase(type);
3568 if (spk_man !=
nullptr && spk_man->GetID() == id) {
3572 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3576 spk_mans.erase(type);
3588 return spk_man !=
nullptr;
3608 return std::nullopt;
3613 return std::nullopt;
3617 if (!desc_spk_man) {
3618 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3621 LOCK(desc_spk_man->cs_desc_man);
3622 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3623 assert(type.has_value());
3633 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3640 spk_man->UpdateWalletDescriptor(desc);
3643 spk_man = new_spk_man.get();
3650 for (
const auto& entry : signing_provider.
keys) {
3651 const CKey& key = entry.second;
3652 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3656 if (!spk_man->TopUp()) {
3664 auto script_pub_keys = spk_man->GetScriptPubKeys();
3665 if (script_pub_keys.empty()) {
3666 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3671 for (
const auto& script : script_pub_keys) {
3681 spk_man->WriteDescriptor();
3690 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
3693 error =
_(
"Error: This wallet already uses SQLite");
3698 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
3699 std::vector<std::pair<SerializeData, SerializeData>> records;
3700 if (!batch->StartCursor()) {
3701 error =
_(
"Error: Unable to begin reading all records in the database");
3704 bool complete =
false;
3708 bool ret = batch->ReadAtCursor(ss_key, ss_value, complete);
3714 records.emplace_back(key, value);
3716 batch->CloseCursor();
3719 error =
_(
"Error: Unable to read all records in the database");
3725 fs::path db_dir = db_path.parent_path();
3727 fs::remove(db_path);
3734 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(db_dir, opts, db_status,
error);
3741 bool began = batch->TxnBegin();
3743 for (
const auto& [key, value] : records) {
3746 if (!batch->Write(ss_key, ss_value)) {
3753 bool committed = batch->TxnCommit();
3764 error =
_(
"Error: This wallet is already a descriptor wallet");
3765 return std::nullopt;
3769 if (res == std::nullopt) {
3770 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
3771 return std::nullopt;
3782 error =
_(
"Error: This wallet is already a descriptor wallet");
3788 error =
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
3818 std::vector<uint256> txids_to_delete;
3828 error =
_(
"Error: Could not add watchonly tx to watchonly wallet");
3832 txids_to_delete.push_back(wtx->GetHash());
3837 error =
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
3842 if (txids_to_delete.size() > 0) {
3843 std::vector<uint256> deleted_txids;
3845 error =
_(
"Error: Could not delete watchonly transactions");
3848 if (deleted_txids != txids_to_delete) {
3849 error =
_(
"Error: Not all watchonly txs could be deleted");
3853 for (
const uint256& txid : deleted_txids) {
3859 std::vector<CTxDestination> dests_to_delete;
3860 for (
const auto& addr_pair : m_address_book) {
3862 if (addr_pair.second.purpose ==
"receive") {
3863 if (!
IsMine(addr_pair.first)) {
3869 std::string label = addr_pair.second.GetLabel();
3870 std::string purpose = addr_pair.second.purpose;
3871 if (!purpose.empty()) {
3874 if (!addr_pair.second.IsChange()) {
3877 dests_to_delete.push_back(addr_pair.first);
3885 std::string label = addr_pair.second.GetLabel();
3886 std::string purpose = addr_pair.second.purpose;
3887 if (!purpose.empty()) {
3888 data.
solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;
3890 if (!addr_pair.second.IsChange()) {
3891 data.
solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
3893 dests_to_delete.push_back(addr_pair.first);
3898 error =
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets");
3906 std::string label = addr_pair.second.GetLabel();
3907 std::string purpose = addr_pair.second.purpose;
3908 if (!purpose.empty()) {
3911 if (!addr_pair.second.IsChange()) {
3919 std::string label = addr_pair.second.GetLabel();
3920 std::string purpose = addr_pair.second.purpose;
3921 if (!purpose.empty()) {
3922 data.
solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;
3924 if (!addr_pair.second.IsChange()) {
3925 data.
solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
3936 for (
const auto& [destination, addr_book_data] :
wallet.m_address_book) {
3938 auto purpose{addr_book_data.purpose};
3939 auto label{addr_book_data.GetLabel()};
3941 if (purpose !=
"unknown") batch.WritePurpose(address, purpose);
3942 if (!label.empty()) batch.WriteName(address, label);
3949 if (dests_to_delete.size() > 0) {
3950 for (
const auto& dest : dests_to_delete) {
3952 error =
_(
"Error: Unable to remove watchonly address book data");
3972 std::optional<MigrationData> data =
wallet.GetDescriptorsForLegacy(
error);
3973 if (data == std::nullopt)
return false;
3976 if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
3989 if (data->watch_descs.size() > 0) {
3990 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
3993 std::vector<bilingual_str> warnings;
3994 std::string wallet_name =
wallet.GetName() +
"_watchonly";
3997 error =
_(
"Error: Failed to create new watchonly wallet");
4000 res.watchonly_wallet = data->watchonly_wallet;
4001 LOCK(data->watchonly_wallet->cs_wallet);
4004 for (
const auto& [desc_str, creation_time] : data->watch_descs) {
4007 std::string parse_err;
4008 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4010 assert(!desc->IsRange());
4014 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4020 if (data->solvable_descs.size() > 0) {
4021 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4024 std::vector<bilingual_str> warnings;
4025 std::string wallet_name =
wallet.GetName() +
"_solvables";
4028 error =
_(
"Error: Failed to create new watchonly wallet");
4031 res.solvables_wallet = data->solvable_wallet;
4032 LOCK(data->solvable_wallet->cs_wallet);
4035 for (
const auto& [desc_str, creation_time] : data->solvable_descs) {
4038 std::string parse_err;
4039 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, parse_err,
true);
4041 assert(!desc->IsRange());
4045 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4064 std::vector<bilingual_str> warnings;
4069 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4088 if (!local_wallet) {
4093 if (!local_wallet->GetLegacyScriptPubKeyMan()) {
4094 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4100 fs::path backup_path = this_wallet_dir / backup_filename;
4102 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4106 bool success =
false;
4108 LOCK(local_wallet->cs_wallet);
4111 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4112 if (passphrase.find(
'\0') == std::string::npos) {
4113 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4115 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. " 4116 "The passphrase contains a null character (ie - a zero byte). " 4117 "If this passphrase was set with a version of this software prior to 25.0, " 4118 "please try again with only the characters up to — but not including — " 4119 "the first null character.")};
4132 assert(local_wallet.use_count() == 1);
4133 local_wallet.reset();
4140 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4143 std::vector<fs::path> wallet_dirs;
4144 wallet_dirs.push_back(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4147 assert(local_wallet.use_count() == 1);
4148 local_wallet.reset();
4151 std::vector<std::shared_ptr<CWallet>> created_wallets;
4156 for (std::shared_ptr<CWallet>& w : created_wallets) {
4157 wallet_dirs.push_back(
fs::PathFromString(w->GetDatabase().Filename()).parent_path());
4161 for (std::shared_ptr<CWallet>& w : created_wallets) {
4163 error +=
_(
"\nUnable to cleanup failed migration");
4170 for (
fs::path& dir : wallet_dirs) {
4171 fs::remove_all(dir);
4176 std::vector<bilingual_str> warnings;
4178 error +=
_(
"\nUnable to restore backup of wallet.");
4183 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4184 fs::remove(temp_backup_location);
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
std::shared_ptr< const CTransaction > CTransactionRef
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
void ReturnDestination()
Return reserved address.
void SyncTransaction(const CTransactionRef &tx, const SyncTxState &state, bool update_tx=true, bool rescanning_old_block=false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Helper for findBlock to selectively return pieces of block data.
enum wallet::CWallet::ScanResult::@17 status
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.
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void push_back(UniValue val)
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
std::atomic< bool > fAbortRescan
State of transaction added to mempool.
std::vector< CTxDestination > ListAddrBookAddresses(const std::optional< AddrBookFilter > &filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Filter and retrieve destinations stored in the addressbook.
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
interfaces::Chain & chain() const
Interface for accessing chain state.
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
const std::vector< UniValue > & getValues() const
bool CanGetAddresses(bool internal=false) const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
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 SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height...
bool HasEncryptionKeys() const override
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 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)
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const ArgsManager & m_args
Provider of aplication-wide arguments.
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs) ...
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
int64_t GetTimeMillis()
Returns the system time (not mockable)
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
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.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, const CCoinControl *coin_control=nullptr) const
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)
static int g_sqlite_count GUARDED_BY(g_sqlite_mutex)=0
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
CScriptWitness scriptWitness
Only serialized through CTransaction.
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)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
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.
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 ...
bool MoneyRange(const CAmount &nValue)
#define CHECK_NONFATAL(condition)
Identity function.
std::string ShellEscape(const std::string &arg)
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
void blockConnected(const interfaces::BlockInfo &block) override
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
bool IsLegacy() const
Determine if we are a legacy wallet.
unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 ...
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 unsigned const char sighash[]
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
bool TxnAbort()
Abort current transaction.
bool fInternal
Whether this is from the internal (change output) keypool.
std::vector< std::vector< unsigned char > > stack
std::optional< int64_t > GetOldestKeyPoolTime() const
const CWallet *const pwallet
The wallet to reserve from.
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
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.
bool DelAddressBook(const CTxDestination &address)
CTxDestination address
The destination.
RecursiveMutex cs_wallet
Main wallet lock.
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
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.
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal...
std::multimap< int64_t, CWalletTx * > TxItems
bool WriteLockedUTXO(const COutPoint &output)
bool DeleteRecords()
Delete all the records ofthis LegacyScriptPubKeyMan from disk.
FlatSigningProvider m_external_provider
SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs...
static GlobalMutex g_loading_wallet_mutex
A version of CTransaction with the PSBT format.
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
Double ended buffer combining vector and stream-like interfaces.
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 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.
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.
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
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)
bool IsAddressUsed(const CTxDestination &dest) 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.
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
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 int64_t GetDefaultNextResend()
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses, and other watch only things, and is therefore "blank.".
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
static constexpr auto OUTPUT_TYPES
void updatedBlockTip() override
const std::vector< CTxIn > vin
std::optional< bool > IsInternalScriptPubKeyMan(ScriptPubKeyMan *spk_man) const
Returns whether the provided ScriptPubKeyMan is internal.
const UniValue & find_value(const UniValue &obj, const std::string &name)
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)
bool WriteBestBlock(const CBlockLocator &locator)
static const bool DEFAULT_WALLET_RBF
-walletrbf default
void MaybeResendWalletTxs(WalletContext &context)
Called periodically by the schedule thread.
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
int64_t CAmount
Amount in satoshis (Can be negative)
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
bool HasWalletSpend(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet...
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
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.
bool FillInputToWeight(CTxIn &txin, int64_t target_weight)
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
int64_t GetInputWeight(const COutPoint &outpoint) const
bool EraseName(const std::string &strAddress)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet...
Block data sent with blockConnected, blockDisconnected notifications.
bool IsLocked() const override
Indicates that the wallet needs an external signer.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
DBErrors LoadWallet(CWallet *pwallet)
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
virtual bool hasAssumedValidChain()=0
Return true if an assumed-valid chain is in use.
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
bool ShouldResend() const
Return true if all conditions for periodically resending transactions are met.
std::set< CKeyID > GetKeys() const override
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
bool TxnCommit()
Commit current transaction.
static std::string PathToString(const path &path)
Convert path object to a byte string.
SecureString create_passphrase
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
CPubKey vchPubKey
The public key.
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
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
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
An input of a transaction.
static int64_t GetTransactionInputWeight(const CTxIn &txin)
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.
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
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
const uint256 & GetHash() const
bilingual_str _(const char *psz)
Translation function.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
void chainStateFlushed(const CBlockLocator &loc) override
Removed for conflict with in-block transaction.
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
virtual void ReloadDbEnv()=0
std::optional< OutputType > ParseOutputType(const std::string &type)
void blockDisconnected(const interfaces::BlockInfo &block) override
bilingual_str AmountHighWarn(const std::string &optname)
std::shared_ptr< Descriptor > descriptor
An encapsulated public key.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
int64_t m_next_resend
The next scheduled rebroadcast of wallet transactions.
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
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.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
bool BackupWallet(const std::string &strDest) const
static int TxStateSerializedIndex(const TxState &state)
Get TxState serialized block index. Inverse of TxStateInterpretSerialized.
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip...
std::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...
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsExternalSelected(const COutPoint &output) const
bool WriteWalletFlags(const uint64_t flags)
#define WAIT_LOCK(cs, name)
An output of a transaction.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
unsigned int nDeriveIterations
std::string ToString() const
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
bool UnlockCoin(const COutPoint &output, WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_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.
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
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
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
std::vector< PSBTInput > inputs
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void ForEachAddrBookEntry(const ListAddrBookFunc &func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::shared_ptr< CWallet > solvables_wallet
bool ErasePurpose(const std::string &strAddress)
static uint256 TxStateSerializedBlockHash(const TxState &state)
Get TxState serialized block hash. Inverse of TxStateInterpretSerialized.
uint256 GetID() const override
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
void UpgradeDescriptorCache()
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.
bool SetAddressUsed(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void Close()
Close wallet database.
CWallet(interfaces::Chain *chain, const std::string &name, const ArgsManager &args, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
virtual void KeepDestination(int64_t index, const OutputType &type)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
static const bool DEFAULT_WALLETBROADCAST
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
static void ReleaseWallet(CWallet *wallet)
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
const std::string & FormatOutputType(OutputType type)
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
std::atomic< int64_t > m_best_block_time
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::function< void(const CTxDestination &dest, const std::string &label, const std::string &purpose, bool is_change)> ListAddrBookFunc
Walk-through the address book entries.
unsigned int fTimeReceivedIsTxTime
#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()
const_iterator end() const
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
void SetSeed(Span< const std::byte > seed)
const_iterator begin() const
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
An interface to be implemented by keystores that support signing.
bool TopUpKeyPool(unsigned int kpSize=0)
bool IsLockedCoin(const COutPoint &output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
State of rejected transaction that conflicts with a confirmed block.
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
void KeepDestination()
Keep the address. Do not return it's 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.
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 ...
std::shared_ptr< CWallet > watchonly_wallet
virtual util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script) const
Get all the ScriptPubKeyMans for a script.
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value, bool write=true)=0
Write a setting to <datadir>/settings.json.
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
std::optional< std::string > m_op_label
const uint256 & GetHash() const
virtual void initMessage(const std::string &message)=0
Send init message.
A reference to a CKey: the Hash160 of its serialized public key.
void UpdateInput(CTxIn &input, const SignatureData &data)
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
std::string GetHex() const
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
std::set< std::string > ListAddrBookLabels(const std::string &purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Retrieve all the known labels in the address book.
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.
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.
DBErrors
Error statuses for the wallet database.
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)
#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.
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
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.
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)
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.
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
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
OutputType m_default_address_type
bool EraseLockedUTXO(const COutPoint &output)
std::optional< CMutableTransaction > tx
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
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)
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
static path u8path(const std::string &utf8_str)
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
util::Result< CTxDestination > GetNewDestination(const OutputType type, const std::string label)
unsigned int nMasterKeyMaxID
int64_t GetTime()
DEPRECATED, see GetTime.
bool DummySignInput(const SigningProvider &provider, CTxIn &tx_in, const CTxOut &txout, const CCoinControl *coin_control)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
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 const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
static path absolute(const path &p)
const CKeyingMaterial & GetEncryptionKey() const override
std::shared_ptr< CWallet > GetDefaultWallet(WalletContext &context, size_t &count)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block...
bool error(const char *fmt, const Args &... args)
std::atomic< double > m_scanning_progress
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
void SetTx(CTransactionRef arg)
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool HasWalletDescriptor(const WalletDescriptor &desc) const
std::variant< TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
WalletFeature GetClosestWalletFeature(int version)
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr, bool finalize=true) const
Fills out a PSBT with information from the wallet.
#define PACKAGE_BUGREPORT
static std::condition_variable g_wallet_release_cv
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
bool HasInputWeight(const COutPoint &outpoint) 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.
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
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.
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
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.