8 #include <bitcoin-build-config.h> 10 #include <blockfilter.h> 75 #include <condition_variable> 97 if (!setting_value.isArray()) setting_value.setArray();
98 for (
const auto& value : setting_value.getValues()) {
101 setting_value.push_back(wallet_name);
112 for (
const auto& value : setting_value.getValues()) {
113 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
116 setting_value = std::move(new_value);
123 const std::string& wallet_name,
124 std::optional<bool> load_on_startup,
125 std::vector<bilingual_str>& warnings)
127 if (!load_on_startup)
return;
129 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
131 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
153 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
154 if (i != context.wallets.end())
return false;
155 context.wallets.push_back(
wallet);
156 wallet->ConnectScriptPubKeyManNotifiers();
157 wallet->NotifyCanGetAddressesChanged();
169 wallet->m_chain_notifications_handler.reset();
172 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(),
wallet);
173 if (i == context.wallets.end())
return false;
174 context.wallets.erase(i);
187 std::vector<bilingual_str> warnings;
194 return context.wallets;
200 count = context.wallets.size();
201 return count == 1 ? context.wallets[0] :
nullptr;
207 for (
const std::shared_ptr<CWallet>&
wallet : context.wallets) {
216 auto it = context.wallet_load_fns.emplace(context.wallet_load_fns.end(), std::move(load_wallet));
223 for (
auto& load_wallet : context.wallet_load_fns) {
238 wallet->WalletLogPrintf(
"Releasing wallet %s..\n",
name);
244 if (g_unloading_wallet_set.erase(
name) == 0) {
258 g_unloading_wallet_set.insert(
name);
267 while (g_unloading_wallet_set.count(
name) == 1) {
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…"));
284 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), options.create_flags, error, warnings);
293 warnings.emplace_back(
_(
"Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet."));
298 wallet->postInitProcess();
304 }
catch (
const std::runtime_error& e) {
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());
378 auto wallet = LoadWalletInternal(context,
name, load_on_start, options, status, error, warnings);
399 if (!passphrase.empty()) {
405 error =
Untranslated(
"Private keys must be disabled when using an external signer");
412 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
419 error =
Untranslated(
"Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
434 std::shared_ptr<CWallet>
wallet =
CWallet::Create(context,
name, std::move(database), wallet_creation_flags, error, warnings);
443 if (!
wallet->EncryptWallet(passphrase)) {
444 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
450 if (!
wallet->Unlock(passphrase)) {
451 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
460 wallet->SetupDescriptorScriptPubKeyMans();
462 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
463 if (!spk_man->SetupGeneration()) {
464 error =
Untranslated(
"Unable to generate initial keys");
479 wallet->postInitProcess();
486 warnings.emplace_back(
_(
"Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future."));
502 auto wallet_file = wallet_path /
"wallet.dat";
503 std::shared_ptr<CWallet>
wallet;
518 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
520 if (load_after_restore) {
521 wallet =
LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
523 }
catch (
const std::exception& e) {
530 if (load_after_restore && !
wallet) {
531 fs::remove_all(wallet_path);
545 const auto it = mapWallet.find(hash);
546 if (it == mapWallet.end())
548 return &(it->second);
562 spk_man->UpgradeKeyMetadata();
586 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
588 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
590 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
592 if (
Unlock(_vMasterKey)) {
616 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
618 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
623 auto start{SteadyClock::now()};
624 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
625 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
627 start = SteadyClock::now();
628 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
629 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
631 if (pMasterKey.second.nDeriveIterations < 25000)
632 pMasterKey.second.nDeriveIterations = 25000;
634 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
636 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
638 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
665 if (nWalletVersion >= nVersion)
668 nWalletVersion = nVersion;
672 if (nWalletVersion > 40000)
684 const auto it = mapWallet.find(txid);
685 if (it == mapWallet.end())
689 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
691 for (
const CTxIn& txin : wtx.
tx->vin)
693 if (mapTxSpends.count(txin.
prevout) <= 1)
695 range = mapTxSpends.equal_range(txin.
prevout);
696 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
697 result.insert(_it->second);
705 const Txid& txid = tx->GetHash();
706 for (
unsigned int i = 0; i < tx->vout.size(); ++i) {
730 int nMinOrderPos = std::numeric_limits<int>::max();
732 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
733 const CWalletTx* wtx = &mapWallet.at(it->second);
745 for (TxSpends::iterator it = range.first; it != range.second; ++it)
747 const uint256& hash = it->second;
749 if (copyFrom == copyTo)
continue;
750 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
769 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
770 range = mapTxSpends.equal_range(outpoint);
772 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
773 const uint256& wtxid = it->second;
774 const auto mit = mapWallet.find(wtxid);
775 if (mit != mapWallet.end()) {
776 const auto& wtx = mit->second;
777 if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
786 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
795 std::pair<TxSpends::iterator, TxSpends::iterator> range;
796 range = mapTxSpends.equal_range(outpoint);
806 for (
const CTxIn& txin : wtx.
tx->vin)
827 auto start{SteadyClock::now()};
829 kMasterKey.
nDeriveIterations =
static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
831 start = SteadyClock::now();
850 delete encrypted_batch;
851 encrypted_batch =
nullptr;
857 auto spk_man = spk_man_pair.second.get();
858 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
860 delete encrypted_batch;
861 encrypted_batch =
nullptr;
872 delete encrypted_batch;
873 encrypted_batch =
nullptr;
879 delete encrypted_batch;
880 encrypted_batch =
nullptr;
883 Unlock(strWalletPassphrase);
890 if (spk_man->IsHDEnabled()) {
891 if (!spk_man->SetupGeneration(
true)) {
922 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
925 for (
auto& entry : mapWallet)
932 std::vector<int64_t> nOrderPosOffsets;
933 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
940 nOrderPos = nOrderPosNext++;
941 nOrderPosOffsets.push_back(nOrderPos);
948 int64_t nOrderPosOff = 0;
949 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
951 if (nOrderPos >= nOffsetStart)
954 nOrderPos += nOrderPosOff;
955 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
973 int64_t nRet = nOrderPosNext++;
986 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
987 item.second.MarkDirty();
995 auto mi = mapWallet.find(originalHash);
998 assert(mi != mapWallet.end());
1003 assert(wtx.mapValue.count(
"replaced_by_txid") == 0);
1005 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
1012 bool success =
true;
1014 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
1034 tx_destinations.insert(dst);
1082 std::set<CTxDestination> tx_destinations;
1084 for (
const CTxIn& txin : tx->vin) {
1093 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(tx, state));
1095 bool fInsertedNew =
ret.second;
1096 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1110 if (state.index() != wtx.
m_state.index()) {
1122 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
1130 std::vector<CWalletTx*> txs{&wtx};
1134 while (!txs.empty()) {
1137 desc_tx->
m_state = inactive_state;
1142 for (
unsigned int i = 0; i < desc_tx->
tx->vout.size(); ++i) {
1144 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
1145 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
1146 const auto wit = mapWallet.find(it->second);
1147 if (wit != mapWallet.end()) {
1148 txs.push_back(&wit->second);
1159 if (fInsertedNew || fUpdated)
1173 if (!strCmd.empty())
1178 ReplaceAll(strCmd,
"%b", conf->confirmed_block_hash.GetHex());
1192 std::thread
t(runCommand, strCmd);
1202 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
nullptr,
TxStateInactive{}));
1204 if (!fill_wtx(wtx, ins.second)) {
1216 for (
const CTxIn& txin : wtx.
tx->vin) {
1218 if (it != mapWallet.end()) {
1238 if (
auto* conf = std::get_if<TxStateConfirmed>(&state)) {
1240 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1241 while (range.first != range.second) {
1242 if (range.first->second != tx.
GetHash()) {
1243 WalletLogPrintf(
"Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.
GetHash().
ToString(), conf->confirmed_block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1244 MarkConflicted(conf->confirmed_block_hash, conf->confirmed_block_height, range.first->second);
1251 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1252 if (fExisted && !fUpdate)
return false;
1264 for (
auto &dest : spk_man->MarkUnusedAddresses(txout.
scriptPubKey)) {
1266 if (!dest.internal.has_value()) {
1271 if (!dest.internal.has_value())
continue;
1285 TxState tx_state = std::visit([](
auto&&
s) ->
TxState {
return s; }, state);
1290 throw std::runtime_error(
"DB error adding transaction to wallet, write failed");
1307 for (
const CTxIn& txin : tx->vin) {
1309 if (it != mapWallet.end()) {
1310 it->second.MarkDirty();
1318 auto it = mapWallet.find(hashTx);
1319 assert(it != mapWallet.end());
1332 assert(!wtx.isConfirmed());
1333 assert(!wtx.InMempool());
1335 if (!wtx.isBlockConflicted() && !wtx.isAbandoned()) {
1361 if (m_last_block_processed_height < 0 || conflicting_height < 0) {
1364 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1365 if (conflictconfirms >= 0)
1390 std::set<uint256> todo;
1391 std::set<uint256> done;
1393 todo.insert(tx_hash);
1395 while (!todo.empty()) {
1399 auto it = mapWallet.find(now);
1400 assert(it != mapWallet.end());
1403 TxUpdate update_state = try_updating_state(wtx);
1406 if (batch) batch->
WriteTx(wtx);
1408 for (
unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
1409 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(
COutPoint(
Txid::FromUint256(now), i));
1410 for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
1411 if (!done.count(iter->second)) {
1412 todo.insert(iter->second);
1443 auto it = mapWallet.find(tx->GetHash());
1444 if (it != mapWallet.end()) {
1448 const Txid& txid = tx->GetHash();
1450 for (
const CTxIn& tx_in : tx->vin) {
1452 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1453 const uint256& spent_id = range.first->second;
1455 if (spent_id == txid)
continue;
1465 auto it = mapWallet.find(tx->GetHash());
1466 if (it != mapWallet.end()) {
1499 const Txid& txid = tx->GetHash();
1501 for (
const CTxIn& tx_in : tx->vin) {
1505 for (
auto range = mapTxSpends.equal_range(tx_in.
prevout); range.first != range.second; range.first++) {
1506 const uint256& spent_id = range.first->second;
1523 m_last_block_processed_height = block.
height;
1524 m_last_block_processed = block.
hash;
1531 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1546 m_last_block_processed_height = block.
height - 1;
1549 int disconnect_height = block.
height;
1551 for (
size_t index = 0; index < block.
data->
vtx.size(); index++) {
1557 for (
const CTxIn& tx_in : ptx->vin) {
1559 if (mapTxSpends.count(tx_in.
prevout) < 1)
continue;
1561 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.
prevout);
1564 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
1565 CWalletTx& wtx = mapWallet.find(_it->second)->second;
1569 auto try_updating_state = [&](
CWalletTx& tx) {
1589 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1605 const auto mi = mapWallet.find(txin.
prevout.
hash);
1606 if (mi != mapWallet.end())
1637 for (
const auto& spkm : it->second) {
1638 res = std::max(res, spkm->IsMine(
script));
1646 return spkm->IsMine(
script);
1668 if (outpoint.
n >= wtx->tx->vout.size()) {
1671 return IsMine(wtx->tx->vout[outpoint.
n]);
1686 throw std::runtime_error(std::string(__func__) +
": value out of range");
1696 if (!spk_man->IsHDEnabled())
return false;
1708 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1715 void CWallet::SetWalletFlag(uint64_t
flags)
1726 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1740 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1775 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1787 LOCK(spk_man->cs_KeyStore);
1788 return spk_man->ImportScripts(scripts, timestamp);
1797 LOCK(spk_man->cs_KeyStore);
1798 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1801 bool CWallet::ImportPubKeys(
const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys,
const std::map<CKeyID, CPubKey>& pubkey_map,
const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins,
const bool add_keypool,
const int64_t timestamp)
1807 LOCK(spk_man->cs_KeyStore);
1808 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, timestamp);
1811 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)
1817 LOCK(spk_man->cs_KeyStore);
1818 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1837 if (time < birthtime) {
1855 int start_height = 0;
1896 constexpr
auto INTERVAL_TIME{60
s};
1897 auto current_time{reserver.
now()};
1898 auto start_time{reserver.
now()};
1902 uint256 block_hash = start_block;
1905 std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
1909 fast_rescan_filter ?
"fast variant using block filters" :
"slow variant inspecting all blocks");
1918 double progress_current = progress_begin;
1919 int block_height = start_height;
1921 if (progress_end - progress_begin > 0.0) {
1922 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1926 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1930 bool next_interval = reserver.
now() >= current_time + INTERVAL_TIME;
1931 if (next_interval) {
1932 current_time = reserver.
now();
1933 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1936 bool fetch_block{
true};
1937 if (fast_rescan_filter) {
1938 fast_rescan_filter->UpdateIfNeeded();
1939 auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)};
1940 if (matches_block.has_value()) {
1941 if (*matches_block) {
1942 LogDebug(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString());
1944 result.last_scanned_block = block_hash;
1945 result.last_scanned_height = block_height;
1946 fetch_block =
false;
1949 LogDebug(
BCLog::SCAN,
"Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString());
1955 bool block_still_active =
false;
1956 bool next_block =
false;
1967 if (!block_still_active) {
1970 result.last_failed_block = block_hash;
1974 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1978 result.last_scanned_block = block_hash;
1979 result.last_scanned_height = block_height;
1981 if (save_progress && next_interval) {
1992 result.last_failed_block = block_hash;
1996 if (max_height && block_height >= *max_height) {
2015 block_hash = next_block_hash;
2020 const uint256 prev_tip_hash = tip_hash;
2022 if (!max_height && prev_tip_hash != tip_hash) {
2034 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
2036 }
else if (block_height &&
chain().shutdownRequested()) {
2037 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
2040 WalletLogPrintf(
"Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.
now() - start_time));
2093 if (!
chain().isReadyToBroadcast())
return false;
2134 int submitted_tx_count = 0;
2141 std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
2142 for (
auto& [txid, wtx] : mapWallet) {
2144 if (!wtx.isUnconfirmed())
continue;
2149 to_submit.insert(&wtx);
2152 for (
auto wtx : to_submit) {
2153 std::string unused_err_string;
2158 if (submitted_tx_count > 0) {
2159 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2167 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
2168 if (!pwallet->ShouldResend())
continue;
2169 pwallet->ResubmitWalletTransactions(
true,
false);
2170 pwallet->SetNextResend();
2185 std::map<COutPoint, Coin> coins;
2186 for (
auto& input : tx.
vin) {
2187 const auto mi = mapWallet.find(input.prevout.hash);
2188 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2193 coins[input.prevout] =
Coin(wtx.
tx->vout[input.prevout.n], prev_height, wtx.
IsCoinBase());
2195 std::map<int, bilingual_str> input_errors;
2205 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2221 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2222 const CTxIn& txin = psbtx.
tx->vin[i];
2232 const auto it = mapWallet.find(txhash);
2233 if (it != mapWallet.end()) {
2246 int n_signed_this_spkm = 0;
2247 const auto error{spk_man->FillPSBT(psbtx, txdata, sighash_type,
sign, bip32derivs, &n_signed_this_spkm, finalize)};
2253 (*n_signed) += n_signed_this_spkm;
2261 for (
size_t i = 0; i < psbtx.
inputs.size(); ++i) {
2273 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2275 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2285 return *change_type;
2294 bool any_wpkh{
false};
2296 bool any_pkh{
false};
2298 for (
const auto& recipient : vecSend) {
2299 if (std::get_if<WitnessV1Taproot>(&recipient.dest)) {
2301 }
else if (std::get_if<WitnessV0KeyHash>(&recipient.dest)) {
2303 }
else if (std::get_if<ScriptHash>(&recipient.dest)) {
2305 }
else if (std::get_if<PKHash>(&recipient.dest)) {
2311 if (has_bech32m_spkman && any_tr) {
2316 if (has_bech32_spkman && any_wpkh) {
2321 if (has_p2sh_segwit_spkman && any_sh) {
2327 if (has_legacy_spkman && any_pkh) {
2332 if (has_bech32m_spkman) {
2335 if (has_bech32_spkman) {
2352 wtx.
mapValue = std::move(mapValue);
2361 throw std::runtime_error(std::string(__func__) +
": Wallet db error, transaction commit failed");
2365 for (
const CTxIn& txin : tx->vin) {
2376 std::string err_string;
2378 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
2395 spk_man_pair.second->RewriteDB();
2405 return nLoadWalletRet;
2415 return result.has_value();
2418 if (!was_txn_committed)
return util::Error{
_(
"Error starting/committing db txn for wallet transactions removal process")};
2428 using TxIterator = std::unordered_map<uint256, CWalletTx, SaltedTxidHasher>::const_iterator;
2429 std::vector<TxIterator> erased_txs;
2431 for (
const uint256& hash : txs_to_remove) {
2432 auto it_wtx = mapWallet.find(hash);
2433 if (it_wtx == mapWallet.end()) {
2439 erased_txs.emplace_back(it_wtx);
2445 for (
const auto& it : erased_txs) {
2446 const uint256 hash{it->first};
2447 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2448 for (
const auto& txin : it->second.tx->vin)
2449 mapTxSpends.erase(txin.prevout);
2450 mapWallet.erase(it);
2462 bool fUpdated =
false;
2464 std::optional<AddressPurpose> purpose;
2467 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2468 fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
2470 CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
2481 WalletLogPrintf(
"Error: fail to write address book 'purpose' entry\n");
2484 if (!batch.
WriteName(encoded_dest, strName)) {
2518 WalletLogPrintf(
"%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, CLIENT_BUGREPORT);
2540 m_address_book.erase(address);
2553 if (legacy_spk_man) {
2554 return legacy_spk_man->KeypoolCountExternalKeys();
2557 unsigned int count = 0;
2559 count += spk_man.second->GetKeyPoolSize();
2569 unsigned int count = 0;
2571 count += spk_man->GetKeyPoolSize();
2581 res &= spk_man->TopUp(kpSize);
2594 auto op_dest = spk_man->GetNewDestination(type);
2617 return std::nullopt;
2620 std::optional<int64_t> oldest_key{std::numeric_limits<int64_t>::max()};
2622 oldest_key = std::min(oldest_key, spk_man_pair.second->GetOldestKeyPoolTime());
2628 for (
auto& entry : mapWallet) {
2631 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2644 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
2645 const auto& entry = item.second;
2646 func(item.first, entry.GetLabel(), entry.IsChange(), entry.purpose);
2653 std::vector<CTxDestination>
result;
2661 result.emplace_back(dest);
2669 std::set<std::string> label_set;
2671 bool _is_change,
const std::optional<AddressPurpose>& _purpose) {
2672 if (_is_change)
return;
2673 if (!purpose || purpose == _purpose) {
2674 label_set.insert(_label);
2691 if (!op_address)
return op_address;
2722 if (signer_spk_man ==
nullptr) {
2726 return signer_spk_man->DisplayAddress(dest,
signer);
2728 return util::Error{
_(
"There is no ScriptPubKeyManager for this address")};
2734 setLockedCoins.insert(output);
2744 bool was_locked = setLockedCoins.erase(output);
2745 if (batch && was_locked) {
2754 bool success =
true;
2756 for (
auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
2759 setLockedCoins.clear();
2766 return setLockedCoins.count(output) > 0;
2772 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2773 it != setLockedCoins.end(); it++) {
2775 vOutpts.push_back(outpt);
2783 mapKeyBirth.clear();
2786 std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
2793 assert(spk_man !=
nullptr);
2797 for (
const auto& entry : spk_man->mapKeyMetadata) {
2798 if (entry.second.nCreateTime) {
2799 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2805 if (mapKeyBirth.count(keyid) == 0)
2806 mapKeyFirstBlock[keyid] = &max_confirm;
2810 if (mapKeyFirstBlock.empty())
2814 for (
const auto& entry : mapWallet) {
2819 for (
const CTxOut &txout : wtx.
tx->vout) {
2823 auto rit = mapKeyFirstBlock.find(keyid);
2824 if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
2834 for (
const auto& entry : mapKeyFirstBlock) {
2866 std::optional<uint256> block_hash;
2868 block_hash = conf->confirmed_block_hash;
2870 block_hash = conf->conflicting_block_hash;
2876 int64_t block_max_time;
2877 if (
chain().findBlock(*block_hash,
FoundBlock().time(blocktime).maxTime(block_max_time))) {
2878 if (rescanning_old_block) {
2879 nTimeSmart = block_max_time;
2882 int64_t latestEntry = 0;
2885 int64_t latestTolerated = latestNow + 300;
2887 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2897 if (nSmartTime <= latestTolerated) {
2898 latestEntry = nSmartTime;
2899 if (nSmartTime > latestNow) {
2900 latestNow = nSmartTime;
2906 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2917 if (std::get_if<CNoDestination>(&dest))
2931 m_address_book[dest].previously_spent =
true;
2936 m_address_book[dest].receive_requests[id] = request;
2947 std::vector<std::string>
values;
2948 for (
const auto& [dest, entry] : m_address_book) {
2949 for (
const auto& [
id, request] : entry.receive_requests) {
2950 values.emplace_back(request);
2959 m_address_book[dest].receive_requests[id] = value;
2966 m_address_book[dest].receive_requests.erase(
id);
2979 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2980 if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
2981 (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
2984 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 2985 "database/log.?????????? files can be stored, a location where such a directory could be created, " 2986 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
3000 return MakeDatabase(*wallet_path, options, status, error_string);
3007 const std::string& walletFile = database->Filename();
3009 const auto start{SteadyClock::now()};
3014 walletInstance->m_notify_tx_changed_script =
args.
GetArg(
"-walletnotify",
"");
3017 bool rescan_required =
false;
3018 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
3021 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
3026 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 3027 " or address metadata may be missing or incorrect."),
3031 error =
strprintf(
_(
"Error loading %s: Wallet requires newer version of %s"), walletFile, CLIENT_NAME);
3035 error =
strprintf(
_(
"Error loading %s: External signer wallet being loaded without external signer support compiled"), walletFile);
3040 error =
strprintf(
_(
"Wallet needed to be rewritten: restart %s to complete"), CLIENT_NAME);
3043 warnings.push_back(
strprintf(
_(
"Error reading %s! Transaction data may be missing or incorrect." 3044 " Rescanning wallet."), walletFile));
3045 rescan_required =
true;
3047 error =
strprintf(
_(
"Unrecognized descriptor found. Loading wallet %s\n\n" 3048 "The wallet might had been created on a newer version.\n" 3049 "Please try running the latest software version.\n"), walletFile);
3052 error =
strprintf(
_(
"Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n" 3053 "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
3056 error =
strprintf(
_(
"Error loading %s"), walletFile);
3062 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
3070 walletInstance->InitWalletFlags(wallet_creation_flags);
3074 walletInstance->SetupLegacyScriptPubKeyMan();
3078 LOCK(walletInstance->cs_wallet);
3080 walletInstance->SetupDescriptorScriptPubKeyMans();
3084 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3085 if (!spk_man->SetupGeneration()) {
3086 error =
_(
"Unable to generate initial keys");
3098 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3101 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3102 if (spk_man->HavePrivateKeys()) {
3103 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3109 if (!
args.
GetArg(
"-addresstype",
"").empty()) {
3115 walletInstance->m_default_address_type = parsed.value();
3118 if (!
args.
GetArg(
"-changetype",
"").empty()) {
3124 walletInstance->m_default_change_type = parsed.value();
3134 _(
"This is the minimum transaction fee you pay on every transaction."));
3137 walletInstance->m_min_fee =
CFeeRate{min_tx_fee.value()};
3141 const std::string max_aps_fee{
args.
GetArg(
"-maxapsfee",
"")};
3142 if (max_aps_fee ==
"-1") {
3143 walletInstance->m_max_aps_fee = -1;
3144 }
else if (std::optional<CAmount> max_fee =
ParseMoney(max_aps_fee)) {
3147 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3149 walletInstance->m_max_aps_fee = max_fee.value();
3158 if (!fallback_fee) {
3159 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-fallbackfee",
args.
GetArg(
"-fallbackfee",
""));
3163 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3165 walletInstance->m_fallback_fee =
CFeeRate{fallback_fee.value()};
3169 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.
GetFeePerK() != 0;
3174 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s'"),
"-discardfee",
args.
GetArg(
"-discardfee",
""));
3178 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3180 walletInstance->m_discard_rate =
CFeeRate{discard_fee.value()};
3190 _(
"This is the transaction fee you will pay if you send a transaction."));
3193 walletInstance->m_pay_tx_fee =
CFeeRate{pay_tx_fee.value(), 1000};
3196 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least %s)"),
3208 warnings.push_back(
strprintf(
_(
"%s is set very high! Fees this large could be paid on a single transaction."),
"-maxtxfee"));
3212 error =
strprintf(
_(
"Invalid amount for %s=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3217 walletInstance->m_default_max_tx_fee = max_fee.value();
3221 if (std::optional<CAmount> consolidate_feerate =
ParseMoney(
args.
GetArg(
"-consolidatefeerate",
""))) {
3222 walletInstance->m_consolidate_feerate =
CFeeRate(*consolidate_feerate);
3231 _(
"The wallet will avoid paying less than the minimum relay fee."));
3238 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
3241 walletInstance->TopUpKeyPool();
3244 std::optional<int64_t> time_first_key;
3245 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
3246 int64_t time = spk_man->GetTimeFirstKey();
3247 if (!time_first_key || time < *time_first_key) time_first_key = time;
3249 if (time_first_key) walletInstance->MaybeUpdateBirthTime(*time_first_key);
3252 walletInstance->m_chain_notifications_handler.reset();
3257 LOCK(walletInstance->cs_wallet);
3259 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
3260 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
3261 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
3264 return walletInstance;
3269 LOCK(walletInstance->cs_wallet);
3271 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
3272 walletInstance->m_chain = &
chain;
3278 if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 &&
chain.
getHeight()) {
3282 error =
Untranslated(
"Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
3298 walletInstance->m_attaching_chain =
true;
3299 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
3302 int rescan_height = 0;
3303 if (!rescan_required)
3307 if (batch.ReadBestBlock(locator)) {
3309 rescan_height = *fork_height;
3317 walletInstance->m_last_block_processed_height = *tip_height;
3319 walletInstance->m_last_block_processed.
SetNull();
3320 walletInstance->m_last_block_processed_height = -1;
3323 if (tip_height && *tip_height != rescan_height)
3327 std::optional<int64_t> time_first_key = walletInstance->m_birth_time.load();
3328 if (time_first_key) {
3335 rescan_height = *tip_height;
3343 int block_height = *tip_height;
3344 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
3348 if (rescan_height != block_height) {
3359 _(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)") :
3361 "Error loading wallet. Wallet requires blocks to be downloaded, " 3362 "and software does not currently support loading wallets while " 3363 "blocks are being downloaded out of order when using assumeutxo " 3364 "snapshots. Wallet should be able to load successfully after " 3365 "node sync reaches height %s"), block_height);
3371 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
3376 error =
_(
"Failed to rescan the wallet during initialization");
3380 walletInstance->m_attaching_chain =
false;
3382 walletInstance->GetDatabase().IncrementUpdateCounter();
3384 walletInstance->m_attaching_chain =
false;
3391 const auto& address_book_it = m_address_book.find(dest);
3392 if (address_book_it == m_address_book.end())
return nullptr;
3393 if ((!allow_change) && address_book_it->second.IsChange()) {
3396 return &address_book_it->second;
3408 if (version < prev_version) {
3409 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
3417 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);
3425 if (!spk_man->Upgrade(prev_version, version, error)) {
3474 assert(conf->confirmed_block_height >= 0);
3477 assert(conf->conflicting_block_height >= 0);
3492 assert(chain_depth >= 0);
3515 return vMasterKey.empty();
3525 if (!vMasterKey.empty()) {
3526 memory_cleanse(vMasterKey.data(), vMasterKey.size() *
sizeof(decltype(vMasterKey)::value_type));
3540 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) {
3544 vMasterKey = vMasterKeyIn;
3552 std::set<ScriptPubKeyMan*> spk_mans;
3553 for (
bool internal : {
false,
true}) {
3557 spk_mans.insert(spk_man);
3567 if (ext_spkm == &spkm)
return true;
3570 if (int_spkm == &spkm)
return true;
3577 std::set<ScriptPubKeyMan*> spk_mans;
3579 spk_mans.insert(spk_man_pair.second.get());
3587 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
3588 if (it == spk_managers.end()) {
3596 std::set<ScriptPubKeyMan*> spk_mans;
3601 spk_mans.insert(it->second.begin(), it->second.end());
3634 return it->second.at(0)->GetSolvingProvider(
script);
3646 std::vector<WalletDescriptor> descs;
3648 if (
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
3649 LOCK(desc_spk_man->cs_desc_man);
3650 descs.push_back(desc_spk_man->GetWalletDescriptor());
3706 std::unique_ptr<ScriptPubKeyMan> spk_manager =
m_database->Format() ==
"bdb_ro" ?
3707 std::make_unique<LegacyDataSPKM>(*this) :
3714 uint256 id = spk_manager->GetID();
3721 return cb(vMasterKey);
3732 if (spkm->HaveCryptedKeys())
return true;
3755 return *spk_manager;
3764 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3766 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
3767 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3770 spk_manager->SetupDescriptorGeneration(batch, master_key, output_type,
internal);
3772 uint256 id = spk_manager->GetID();
3781 for (
bool internal : {
false,
true}) {
3812 }))
throw std::runtime_error(
"Error: cannot process db transaction for descriptors setup");
3820 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3823 if (!batch.
TxnBegin())
throw std::runtime_error(
"Error: cannot create db transaction for descriptors import");
3825 for (
bool internal : {
false,
true}) {
3826 const UniValue& descriptor_vals = signer_res.
find_value(
internal ?
"internal" :
"receive");
3827 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3829 const std::string& desc_str = desc_val.
getValStr();
3831 std::string desc_error;
3832 auto descs =
Parse(desc_str, keys, desc_error,
false);
3833 if (descs.empty()) {
3834 throw std::runtime_error(std::string(__func__) +
": Invalid descriptor \"" + desc_str +
"\" (" + desc_error +
")");
3836 auto& desc = descs.at(0);
3837 if (!desc->GetOutputType()) {
3842 spk_manager->SetupDescriptor(batch, std::move(desc));
3843 uint256 id = spk_manager->GetID();
3850 if (!batch.
TxnCommit())
throw std::runtime_error(
"Error: cannot commit db transaction for descriptors import");
3863 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3878 spk_mans[type] = spk_man;
3880 const auto it = spk_mans_other.find(type);
3881 if (it != spk_mans_other.end() && it->second == spk_man) {
3882 spk_mans_other.erase(type);
3891 if (spk_man !=
nullptr && spk_man->GetID() == id) {
3895 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3899 spk_mans.erase(type);
3927 return std::nullopt;
3932 return std::nullopt;
3936 if (!desc_spk_man) {
3937 throw std::runtime_error(std::string(__func__) +
": unexpected ScriptPubKeyMan type.");
3940 LOCK(desc_spk_man->cs_desc_man);
3941 const auto& type = desc_spk_man->GetWalletDescriptor().descriptor->GetOutputType();
3942 assert(type.has_value());
3952 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3959 spk_man->UpdateWalletDescriptor(desc);
3962 spk_man = new_spk_man.get();
3965 uint256 id = new_spk_man->GetID();
3970 for (
const auto& entry : signing_provider.
keys) {
3971 const CKey& key = entry.second;
3972 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3976 if (!spk_man->TopUp()) {
3984 auto script_pub_keys = spk_man->GetScriptPubKeys();
3985 if (script_pub_keys.empty()) {
3986 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3991 for (
const auto&
script : script_pub_keys) {
4001 spk_man->WriteDescriptor();
4010 WalletLogPrintf(
"Migrating wallet storage database from BerkeleyDB to SQLite.\n");
4013 error =
_(
"Error: This wallet already uses SQLite");
4018 std::unique_ptr<DatabaseBatch> batch =
m_database->MakeBatch();
4019 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
4020 std::vector<std::pair<SerializeData, SerializeData>> records;
4022 error =
_(
"Error: Unable to begin reading all records in the database");
4029 status = cursor->Next(ss_key, ss_value);
4035 records.emplace_back(key, value);
4040 error =
_(
"Error: Unable to read all records in the database");
4047 fs::remove(db_path);
4058 std::unique_ptr<WalletDatabase> new_db =
MakeDatabase(wallet_path, opts, db_status, error);
4065 bool began = batch->TxnBegin();
4067 for (
const auto& [key, value] : records) {
4068 if (!batch->Write(
Span{key},
Span{value})) {
4075 bool committed = batch->TxnCommit();
4085 if (!
Assume(legacy_spkm)) {
4088 return std::nullopt;
4092 if (res == std::nullopt) {
4093 error =
_(
"Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet's passphrase if it is encrypted.");
4094 return std::nullopt;
4104 if (!
Assume(legacy_spkm)) {
4110 std::set<CTxDestination> not_migrated_dests;
4119 if (!
data.watch_descs.empty())
Assume(!
data.watchonly_wallet->m_cached_spks.empty());
4120 if (!
data.solvable_descs.empty())
Assume(!
data.solvable_wallet->m_cached_spks.empty());
4122 for (
auto& desc_spkm :
data.desc_spkms) {
4124 return util::Error{
_(
"Error: Duplicate descriptors created during migration. Your wallet may be corrupted.")};
4126 uint256 id = desc_spkm->GetID();
4132 return util::Error{
_(
"Error: cannot remove legacy wallet records")};
4144 if (
data.master_key.key.IsValid()) {
4154 if (!local_wallet_batch.
ReadBestBlock(best_block_locator)) {
4155 return util::Error{
_(
"Error: Unable to read wallet's best block locator record")};
4160 std::vector<uint256> txids_to_delete;
4161 std::unique_ptr<WalletBatch> watchonly_batch;
4162 if (
data.watchonly_wallet) {
4163 watchonly_batch = std::make_unique<WalletBatch>(
data.watchonly_wallet->GetDatabase());
4164 if (!watchonly_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.watchonly_wallet->GetName())};
4166 LOCK(
data.watchonly_wallet->cs_wallet);
4167 data.watchonly_wallet->nOrderPosNext = nOrderPosNext;
4168 watchonly_batch->WriteOrderPosNext(
data.watchonly_wallet->nOrderPosNext);
4170 if (!watchonly_batch->WriteBestBlock(best_block_locator)) {
4171 return util::Error{
_(
"Error: Unable to write watchonly wallet best block locator record")};
4174 std::unique_ptr<WalletBatch> solvables_batch;
4175 if (
data.solvable_wallet) {
4176 solvables_batch = std::make_unique<WalletBatch>(
data.solvable_wallet->GetDatabase());
4177 if (!solvables_batch->TxnBegin())
return util::Error{
strprintf(
_(
"Error: database transaction cannot be executed for wallet %s"),
data.solvable_wallet->GetName())};
4179 if (!solvables_batch->WriteBestBlock(best_block_locator)) {
4180 return util::Error{
_(
"Error: Unable to write solvable wallet best block locator record")};
4187 if (
data.watchonly_wallet) {
4188 LOCK(
data.watchonly_wallet->cs_wallet);
4189 if (
data.watchonly_wallet->IsMine(*wtx->tx) ||
data.watchonly_wallet->IsFromMe(*wtx->tx)) {
4191 const uint256& hash = wtx->GetHash();
4194 if (!new_tx) return false;
4195 ins_wtx.SetTx(to_copy_wtx.tx);
4196 ins_wtx.CopyFrom(to_copy_wtx);
4199 return util::Error{
strprintf(
_(
"Error: Could not add watchonly tx %s to watchonly wallet"), wtx->GetHash().GetHex())};
4201 watchonly_batch->WriteTx(
data.watchonly_wallet->mapWallet.at(hash));
4204 txids_to_delete.push_back(hash);
4211 return util::Error{
strprintf(
_(
"Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex())};
4216 if (txids_to_delete.size() > 0) {
4217 if (
auto res =
RemoveTxs(local_wallet_batch, txids_to_delete); !res) {
4223 std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4224 if (
data.watchonly_wallet) wallets_vec.emplace_back(
data.watchonly_wallet, std::move(watchonly_batch));
4225 if (
data.solvable_wallet) wallets_vec.emplace_back(
data.solvable_wallet, std::move(solvables_batch));
4231 if (entry.label) batch.
WriteName(address, *entry.label);
4232 for (
const auto& [
id, request] : entry.receive_requests) {
4239 std::vector<CTxDestination> dests_to_delete;
4240 for (
const auto& [dest, record] : m_address_book) {
4244 bool copied =
false;
4245 for (
auto& [
wallet, batch] : wallets_vec) {
4247 if (require_transfer && !
wallet->IsMine(dest))
continue;
4250 wallet->m_address_book[dest] = record;
4251 func_store_addr(*batch, dest, record);
4255 if (require_transfer) {
4256 dests_to_delete.push_back(dest);
4264 if (require_transfer && !copied) {
4267 if (not_migrated_dests.count(dest) > 0) {
4268 dests_to_delete.push_back(dest);
4272 return util::Error{
_(
"Error: Address book data in wallet cannot be identified to belong to migrated wallets")};
4277 for (
auto& [
wallet, batch] : wallets_vec) {
4284 if (dests_to_delete.size() > 0) {
4285 for (
const auto& dest : dests_to_delete) {
4287 return util::Error{
_(
"Error: Unable to remove watchonly address book data")};
4305 std::optional<MigrationData>
data =
wallet.GetDescriptorsForLegacy(error);
4306 if (
data == std::nullopt)
return false;
4309 if (
data->watch_descs.size() > 0 ||
data->solvable_descs.size() > 0) {
4316 empty_context.
args = context.args;
4326 if (
data->watch_descs.size() > 0) {
4327 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the watched scripts\n");
4330 std::vector<bilingual_str> warnings;
4331 std::string wallet_name =
wallet.GetName() +
"_watchonly";
4332 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4334 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4339 if (!
data->watchonly_wallet) {
4340 error =
_(
"Error: Failed to create new watchonly wallet");
4343 res.watchonly_wallet =
data->watchonly_wallet;
4344 LOCK(
data->watchonly_wallet->cs_wallet);
4347 for (
const auto& [desc_str, creation_time] :
data->watch_descs) {
4350 std::string parse_err;
4351 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4352 assert(descs.size() == 1);
4353 assert(!descs.at(0)->IsRange());
4357 data->watchonly_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4363 if (
data->solvable_descs.size() > 0) {
4364 wallet.WalletLogPrintf(
"Making a new watchonly wallet containing the unwatched solvable scripts\n");
4367 std::vector<bilingual_str> warnings;
4368 std::string wallet_name =
wallet.GetName() +
"_solvables";
4369 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4371 error =
strprintf(
_(
"Wallet file creation failed: %s"), error);
4376 if (!
data->solvable_wallet) {
4377 error =
_(
"Error: Failed to create new watchonly wallet");
4380 res.solvables_wallet =
data->solvable_wallet;
4381 LOCK(
data->solvable_wallet->cs_wallet);
4384 for (
const auto& [desc_str, creation_time] :
data->solvable_descs) {
4387 std::string parse_err;
4388 std::vector<std::unique_ptr<Descriptor>> descs =
Parse(desc_str, keys, parse_err,
true);
4389 assert(descs.size() == 1);
4390 assert(!descs.at(0)->IsRange());
4394 data->solvable_wallet->AddWalletDescriptor(w_desc, keys,
"",
false);
4404 if (
auto res_migration =
wallet.ApplyMigrationData(batch, *
data); !res_migration) {
4408 wallet.WalletLogPrintf(
"Wallet migration complete.\n");
4415 std::vector<bilingual_str> warnings;
4419 bool was_loaded =
false;
4422 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4431 return util::Error{
_(
"Unable to unload the wallet before migrating")};
4445 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4457 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(wallet_name, options, status, error);
4463 std::shared_ptr<CWallet> local_wallet =
CWallet::Create(empty_context, wallet_name, std::move(database), options.
create_flags, error, warnings);
4464 if (!local_wallet) {
4475 std::vector<bilingual_str> warnings;
4481 const std::string wallet_name = local_wallet->GetName();
4484 const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4485 assert(to_reload.use_count() == 1);
4486 std::string
name = to_reload->GetName();
4488 to_reload =
LoadWallet(context,
name, std::nullopt, options, status, error, warnings);
4489 return to_reload !=
nullptr;
4495 reload_wallet(local_wallet);
4497 return util::Error{
_(
"Error: This wallet is already a descriptor wallet")};
4503 fs::path backup_path = this_wallet_dir / backup_filename;
4506 reload_wallet(local_wallet);
4508 return util::Error{
_(
"Error: Unable to make a backup of your wallet")};
4512 bool success =
false;
4515 if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4517 reload_wallet(local_wallet);
4519 if (passphrase.find(
'\0') == std::string::npos) {
4520 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4522 return util::Error{
Untranslated(
"Error: Wallet decryption failed, the wallet passphrase entered was incorrect. " 4523 "The passphrase contains a null character (ie - a zero byte). " 4524 "If this passphrase was set with a version of this software prior to 25.0, " 4525 "please try again with only the characters up to — but not including — " 4526 "the first null character.")};
4531 LOCK(local_wallet->cs_wallet);
4533 if (!local_wallet->MigrateToSQLite(error))
return util::Error{error};
4538 success =
DoMigration(*local_wallet, context, error, res);
4549 std::set<fs::path> wallet_dirs;
4553 wallet_dirs.insert(
fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
4554 success = reload_wallet(local_wallet);
4555 res.
wallet = local_wallet;
4572 fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
4575 std::vector<std::shared_ptr<CWallet>> created_wallets;
4576 if (local_wallet) created_wallets.push_back(std::move(local_wallet));
4581 for (std::shared_ptr<CWallet>& w : created_wallets) {
4586 for (std::shared_ptr<CWallet>& w : created_wallets) {
4587 if (w->HaveChain()) {
4590 error +=
_(
"\nUnable to cleanup failed migration");
4596 assert(w.use_count() == 1);
4602 for (
const fs::path& dir : wallet_dirs) {
4603 fs::remove_all(dir);
4610 const auto& ptr_wallet =
RestoreWallet(context, temp_backup_location, wallet_name, std::nullopt, status, restore_error, warnings, was_loaded);
4611 if (!restore_error.
empty()) {
4612 error += restore_error +
_(
"\nUnable to restore backup of wallet.");
4617 fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
4618 fs::remove(temp_backup_location);
4622 bool wallet_reloaded = ptr_wallet !=
nullptr;
4623 assert(was_loaded == wallet_reloaded);
4632 for (
const auto&
script : spks) {
4649 std::set<CExtPubKey> active_xpubs;
4656 std::set<CPubKey> desc_pubkeys;
4657 std::set<CExtPubKey> desc_xpubs;
4658 w_desc.
descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
4659 active_xpubs.merge(std::move(desc_xpubs));
4661 return active_xpubs;
4672 if (std::optional<CKey> key = desc_spkm->
GetKey(keyid)) {
4676 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
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.
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...
bool CanProvide(const CScript &script, SignatureData &sigdata) override
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that...
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.
FoundBlock & locator(CBlockLocator &locator)
Return locator if block is in the active chain.
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
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)
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.
virtual CBlockLocator getActiveChainLocator(const uint256 &block_hash)=0
Return a locator that refers to a block in the active chain.
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 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
bool DeleteRecordsWithDB(WalletBatch &batch)
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.
util::Result< void > ApplyMigrationData(WalletBatch &local_wallet_batch, MigrationData &data) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan, and where needed, moves tx and address book entries to watchonly_wallet or solvable_wallet.
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.
void SetupOwnDescriptorScriptPubKeyMans(WalletBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new seed and default DescriptorScriptPubKeyMans for this 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.
void SetWalletFlagWithDB(WalletBatch &batch, uint64_t flags)
Store wallet flags.
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.
bool ImportPubKeys(const std::vector< std::pair< CKeyID, bool >> &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo >> &key_origins, const bool add_keypool, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
bool SetKeyFromPassphrase(const SecureString &key_data, std::span< const unsigned char > salt, const unsigned int rounds, const unsigned int derivation_method)
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)
bool ReadBestBlock(CBlockLocator &locator)
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.
consteval auto _(util::TranslatedLiteral str)
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.
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...
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.
void WalletLogPrintf(util::ConstevalFormatString< sizeof...(Params)> wallet_fmt, const Params &... params) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
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
void RegisterTxnListener(const DbTxnListener &l)
Registers db txn callback functions.
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
bool Decrypt(std::span< const unsigned char > ciphertext, CKeyingMaterial &plaintext) const
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.
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.
static int sign(const secp256k1_context *ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64)
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
static time_point now() noexcept
Return current system time or mocked time, if set.
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()
#define LogDebug(category,...)
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.
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings, bool load_after_restore)
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.
bool HaveCryptedKeys() const
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.
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
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)
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 internally by node code...
static path u8path(const std::string &utf8_str)
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)
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)
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)
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)
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.