44 #include <boost/algorithm/string/replace.hpp>
50 "You need to rescan the blockchain in order to correctly mark used "
51 "destinations in the past. Until this is done, some destinations may "
52 "be considered unused, even if the opposite is the case."
67 if (value.isStr() && value.get_str() == wallet_name)
return true;
76 if (!setting_value.
isArray())
return true;
79 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
81 if (new_value.
size() == setting_value.
size())
return true;
86 const std::string& wallet_name,
87 std::optional<bool> load_on_startup,
88 std::vector<bilingual_str>& warnings)
90 if (!load_on_startup)
return;
92 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
94 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
102 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(),
wallet);
103 if (i != vpwallets.end())
return false;
104 vpwallets.push_back(
wallet);
105 wallet->ConnectScriptPubKeyManNotifiers();
106 wallet->NotifyCanGetAddressesChanged();
110 bool RemoveWallet(
const std::shared_ptr<CWallet>&
wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
118 wallet->m_chain_notifications_handler.reset();
120 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(),
wallet);
121 if (i == vpwallets.end())
return false;
132 std::vector<bilingual_str> warnings;
145 for (
const std::shared_ptr<CWallet>&
wallet : vpwallets) {
154 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
168 wallet->WalletLogPrintf(
"Releasing wallet\n");
174 if (g_unloading_wallet_set.erase(
name) == 0) {
188 auto it = g_unloading_wallet_set.insert(
name);
200 while (g_unloading_wallet_set.count(
name) == 1) {
223 wallet->postInitProcess();
229 }
catch (
const std::runtime_error& e) {
240 if (!result.second) {
245 auto wallet = LoadWalletInternal(chain,
name, load_on_start, options, status,
error, warnings);
261 if (!passphrase.empty()) {
267 error =
Untranslated(
"Private keys must be disabled when using an external signer");
274 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
289 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.");
304 if (!
wallet->EncryptWallet(passphrase)) {
311 if (!
wallet->Unlock(passphrase)) {
321 wallet->SetupDescriptorScriptPubKeyMans();
323 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
324 if (!spk_man->SetupGeneration()) {
338 wallet->postInitProcess();
360 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(hash);
361 if (
it == mapWallet.end())
363 return &(
it->second);
377 spk_man->UpgradeKeyMetadata();
388 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
390 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
392 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
394 if (
Unlock(_vMasterKey, accept_no_keys)) {
416 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
418 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
423 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
424 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(
GetTimeMillis() - nStartTime))));
427 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
428 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
430 if (pMasterKey.second.nDeriveIterations < 25000)
431 pMasterKey.second.nDeriveIterations = 25000;
433 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
435 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
437 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
459 if (nWalletVersion >= nVersion)
461 nWalletVersion = nVersion;
465 if (nWalletVersion > 40000)
474 std::set<uint256> result;
477 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(txid);
478 if (
it == mapWallet.end())
482 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
484 for (
const CTxIn& txin : wtx.
tx->vin)
486 if (mapTxSpends.count(txin.
prevout) <= 1)
488 range = mapTxSpends.equal_range(txin.
prevout);
489 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
490 result.insert(_it->second);
498 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
499 return (iter != mapTxSpends.end() && iter->first.hash == txid);
518 int nMinOrderPos = std::numeric_limits<int>::max();
520 for (TxSpends::iterator
it = range.first;
it != range.second; ++
it) {
533 for (TxSpends::iterator
it = range.first;
it != range.second; ++
it)
537 if (copyFrom == copyTo)
continue;
538 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
558 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
559 range = mapTxSpends.equal_range(outpoint);
561 for (TxSpends::const_iterator
it = range.first;
it != range.second; ++
it)
564 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
565 if (mit != mapWallet.end()) {
566 int depth = mit->second.GetDepthInMainChain();
567 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
576 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
578 setLockedCoins.erase(outpoint);
580 std::pair<TxSpends::iterator, TxSpends::iterator> range;
581 range = mapTxSpends.equal_range(outpoint);
588 auto it = mapWallet.find(wtxid);
594 for (
const CTxIn& txin : thisTx.
tx->vin)
637 delete encrypted_batch;
638 encrypted_batch =
nullptr;
644 auto spk_man = spk_man_pair.second.get();
645 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
647 delete encrypted_batch;
648 encrypted_batch =
nullptr;
659 delete encrypted_batch;
660 encrypted_batch =
nullptr;
666 delete encrypted_batch;
667 encrypted_batch =
nullptr;
670 Unlock(strWalletPassphrase);
677 if (spk_man->IsHDEnabled()) {
678 if (!spk_man->SetupGeneration(
true)) {
709 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
712 for (
auto& entry : mapWallet)
719 std::vector<int64_t> nOrderPosOffsets;
720 for (TxItems::iterator
it = txByTime.begin();
it != txByTime.end(); ++
it)
727 nOrderPos = nOrderPosNext++;
728 nOrderPosOffsets.push_back(nOrderPos);
735 int64_t nOrderPosOff = 0;
736 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
738 if (nOrderPos >= nOffsetStart)
741 nOrderPos += nOrderPosOff;
742 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
760 int64_t nRet = nOrderPosNext++;
773 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
774 item.second.MarkDirty();
782 auto mi = mapWallet.find(originalHash);
785 assert(mi != mapWallet.end());
824 tx_destinations.insert(dst);
826 }
else if (!used &&
GetDestData(dst,
"used",
nullptr)) {
848 assert(spk_man !=
nullptr);
849 for (
const auto& keyid :
GetAffectedKeys(srctx->
tx->vout[n].scriptPubKey, *spk_man)) {
878 std::set<CTxDestination> tx_destinations;
880 for (
const CTxIn& txin : tx->vin) {
889 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this, tx));
891 bool fInsertedNew = ret.second;
892 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
920 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
927 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
930 if (fInsertedNew || fUpdated)
942 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
946 boost::replace_all(strCmd,
"%s", hash.
GetHex());
947 if (confirm.
status == CWalletTx::Status::CONFIRMED)
952 boost::replace_all(strCmd,
"%b",
"unconfirmed");
953 boost::replace_all(strCmd,
"%h",
"-1");
963 std::thread t(runCommand, strCmd);
973 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this,
nullptr));
975 if (!fill_wtx(wtx, ins.second)) {
1003 for (
const CTxIn& txin : wtx.
tx->vin) {
1005 if (
it != mapWallet.end()) {
1023 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1024 while (range.first != range.second) {
1025 if (range.first->second != tx.
GetHash()) {
1026 WalletLogPrintf(
"Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.
GetHash().
ToString(), confirm.
hashBlock.
ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1034 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1035 if (fExisted && !fUpdate)
return false;
1047 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1068 for (
const CTxIn& txin : tx->vin) {
1070 if (
it != mapWallet.end()) {
1071 it->second.MarkDirty();
1082 std::set<uint256> todo;
1083 std::set<uint256> done;
1086 auto it = mapWallet.find(hashTx);
1093 todo.insert(hashTx);
1095 while (!todo.empty()) {
1099 auto it = mapWallet.find(now);
1104 assert(currentconfirm <= 0);
1114 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1115 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1116 if (!done.count(iter->second)) {
1117 todo.insert(iter->second);
1134 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1139 if (conflictconfirms >= 0)
1145 std::set<uint256> todo;
1146 std::set<uint256> done;
1148 todo.insert(hashTx);
1150 while (!todo.empty()) {
1154 auto it = mapWallet.find(now);
1158 if (conflictconfirms < currentconfirm) {
1168 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1169 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1170 if (!done.count(iter->second)) {
1171 todo.insert(iter->second);
1197 auto it = mapWallet.find(tx->GetHash());
1198 if (
it != mapWallet.end()) {
1199 it->second.fInMempool =
true;
1205 auto it = mapWallet.find(tx->GetHash());
1206 if (
it != mapWallet.end()) {
1207 it->second.fInMempool =
false;
1245 m_last_block_processed_height = height;
1246 m_last_block_processed = block_hash;
1247 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1248 SyncTransaction(block.
vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1261 m_last_block_processed_height = height - 1;
1274 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1288 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1289 if (mi != mapWallet.end())
1304 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1305 if (mi != mapWallet.end())
1333 result = std::max(result, spk_man_pair.second->IsMine(script));
1341 throw std::runtime_error(std::string(__func__) +
": value out of range");
1377 throw std::runtime_error(std::string(__func__) +
": value out of range");
1402 throw std::runtime_error(std::string(__func__) +
": value out of range");
1414 if (mi == mapWallet.end())
1435 throw std::runtime_error(std::string(__func__) +
": value out of range");
1448 throw std::runtime_error(std::string(__func__) +
": value out of range");
1458 result &= spk_man->IsHDEnabled();
1469 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1476 void CWallet::SetWalletFlag(uint64_t
flags)
1481 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1495 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1526 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1564 for (
const auto& txout : txouts)
1581 LOCK(spk_man->cs_KeyStore);
1582 return spk_man->ImportScripts(scripts, timestamp);
1591 LOCK(spk_man->cs_KeyStore);
1592 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1595 bool CWallet::ImportPubKeys(
const std::vector<CKeyID>& ordered_pubkeys,
const std::map<CKeyID, CPubKey>& pubkey_map,
const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins,
const bool add_keypool,
const bool internal,
const int64_t timestamp)
1601 LOCK(spk_man->cs_KeyStore);
1602 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1605 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)
1611 LOCK(spk_man->cs_KeyStore);
1612 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1617 for (
const CScript& script : script_pub_keys) {
1631 std::vector<CTxOut> txouts;
1632 for (
const CTxIn& input : tx.
vin) {
1635 if (mi ==
wallet->mapWallet.end()) {
1636 return std::make_pair(-1, -1);
1639 txouts.emplace_back(mi->second.tx->vout[input.
prevout.
n]);
1648 if (!
wallet->DummySignTx(txNew, txouts, use_max_sig)) {
1649 return std::make_pair(-1, -1);
1654 return std::make_pair(vsize, weight);
1661 if (!
wallet->DummySignInput(txn.
vin[0], txout, use_max_sig)) {
1671 listReceived.clear();
1679 nFee = nDebit - nValueOut;
1684 for (
unsigned int i = 0; i <
tx->vout.size(); ++i)
1697 else if (!(fIsMine & filter))
1714 listSent.push_back(output);
1717 if (fIsMine & filter)
1718 listReceived.push_back(output);
1736 int start_height = 0;
1781 uint256 block_hash = start_block;
1793 double progress_current = progress_begin;
1794 int block_height = start_height;
1796 if (progress_end - progress_begin > 0.0) {
1797 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1801 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1806 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1815 bool block_still_active =
false;
1816 bool next_block =
false;
1822 if (!block_still_active) {
1829 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1830 SyncTransaction(block.
vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1840 if (max_height && block_height >= *max_height) {
1851 block_hash = next_block_hash;
1856 const uint256 prev_tip_hash = tip_hash;
1858 if (!max_height && prev_tip_hash != tip_hash) {
1866 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1868 }
else if (block_height &&
chain().shutdownRequested()) {
1869 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1882 std::map<int64_t, CWalletTx*> mapSorted;
1885 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1886 const uint256& wtxid = item.first;
1893 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1898 for (
const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1900 std::string unused_err_string;
1935 std::set<uint256> result;
1940 result.erase(myHash);
1948 if (recalculate || !amount.m_cached[filter]) {
1952 return amount.m_value[filter];
1957 if (
tx->vin.empty())
2015 for (
unsigned int i = 0; i <
tx->vout.size(); i++)
2021 throw std::runtime_error(std::string(__func__) +
" : value out of range");
2058 std::set<uint256> trusted_parents;
2067 if (!
chain().checkFinalTx(*wtx.
tx))
return false;
2069 if (nDepth >= 1)
return true;
2070 if (nDepth < 0)
return false;
2078 for (
const CTxIn& txin : wtx.
tx->vin)
2082 if (parent ==
nullptr)
return false;
2087 if (trusted_parents.count(parent->
GetHash()))
continue;
2089 if (!
IsTrusted(*parent, trusted_parents))
return false;
2090 trusted_parents.insert(parent->
GetHash());
2099 for (
auto& txin : tx1.vin) txin.scriptSig =
CScript();
2100 for (
auto& txin : tx2.vin) txin.scriptSig =
CScript();
2117 if (!
chain().isReadyToBroadcast())
return;
2127 int submitted_tx_count = 0;
2133 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
2139 std::string unused_err_string;
2144 if (submitted_tx_count > 0) {
2145 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2153 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
2154 pwallet->ResendWalletTransactions();
2171 std::set<uint256> trusted_parents;
2172 for (
const auto& entry : mapWallet)
2175 const bool is_trusted{
IsTrusted(wtx, trusted_parents)};
2179 if (is_trusted && tx_depth >= min_depth) {
2183 if (!is_trusted && tx_depth == 0 && wtx.
InMempool()) {
2199 std::vector<COutput>
vCoins;
2202 if (out.fSpendable) {
2203 balance += out.tx->tx->vout[out.i].nValue;
2221 std::set<uint256> trusted_parents;
2222 for (
const auto& entry : mapWallet)
2224 const uint256& wtxid = entry.first;
2243 bool safeTx =
IsTrusted(wtx, trusted_parents);
2260 if (nDepth == 0 && wtx.
mapValue.count(
"replaces_txid")) {
2272 if (nDepth == 0 && wtx.
mapValue.count(
"replaced_by_txid")) {
2276 if (fOnlySafe && !safeTx) {
2280 if (nDepth < min_depth || nDepth > max_depth) {
2284 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2290 if (wtx.
tx->vout[i].nValue < nMinimumAmount || wtx.
tx->vout[i].nValue > nMaximumAmount)
2308 if (!allow_used_addresses &&
IsSpentKey(wtxid, i)) {
2314 bool solvable = provider ?
IsSolvable(*provider, wtx.
tx->vout[i].scriptPubKey) :
false;
2321 nTotal += wtx.
tx->vout[i].nValue;
2323 if (nTotal >= nMinimumSumAmount) {
2329 if (nMaximumCount > 0 &&
vCoins.size() >= nMaximumCount) {
2340 std::map<CTxDestination, std::vector<COutput>> result;
2341 std::vector<COutput> availableCoins;
2345 for (
const COutput& coin : availableCoins) {
2349 result[address].emplace_back(std::move(coin));
2353 std::vector<COutPoint> lockedCoins;
2358 for (
const COutPoint& output : lockedCoins) {
2359 auto it = mapWallet.find(output.hash);
2360 if (
it != mapWallet.end()) {
2361 int depth =
it->second.GetDepthInMainChain();
2362 if (depth >= 0 && output.n <
it->second.tx->vout.size() &&
2363 IsMine(
it->second.tx->vout[output.n]) == is_mine_filter
2367 result[address].emplace_back(
2368 &
it->second, output.n, depth,
true ,
true ,
false );
2384 auto it = mapWallet.find(prevout.
hash);
2385 if (
it == mapWallet.end() ||
it->second.tx->vout.size() <= prevout.
n ||
2386 !
IsMine(
it->second.tx->vout[prevout.
n])) {
2389 ptx =
it->second.tx.get();
2392 return ptx->
vout[n];
2398 setCoinsRet.clear();
2417 return SelectCoinsBnB(groups, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
2422 return KnapsackSolver(nTargetValue, groups, setCoinsRet, nValueRet);
2428 std::vector<COutput>
vCoins(vAvailableCoins);
2429 CAmount value_to_select = nTargetValue;
2439 if (!out.fSpendable)
2441 nValueRet += out.tx->tx->vout[out.i].nValue;
2442 setCoinsRet.insert(out.GetInputCoin());
2444 return (nValueRet >= nTargetValue);
2448 std::set<CInputCoin> setPresetCoins;
2449 CAmount nValueFromPresetInputs = 0;
2451 std::vector<COutPoint> vPresetInputs;
2453 for (
const COutPoint& outpoint : vPresetInputs)
2455 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(outpoint.hash);
2456 if (
it != mapWallet.end())
2460 if (wtx.
tx->vout.size() <= outpoint.n) {
2475 setPresetCoins.insert(coin);
2484 if (setPresetCoins.count(
it->GetInputCoin()))
2490 unsigned int limit_ancestor_count = 0;
2491 unsigned int limit_descendant_count = 0;
2493 size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2494 size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2505 bool res = value_to_select <= 0 ||
2509 (
m_spend_zero_conf_change &&
SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, std::min((
size_t)4, max_ancestors/3), std::min((
size_t)4, max_descendants/3)),
vCoins, setCoinsRet, nValueRet,
coin_selection_params, bnb_used)) ||
2511 (
m_spend_zero_conf_change &&
SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1,
true ),
vCoins, setCoinsRet, nValueRet,
coin_selection_params, bnb_used)) ||
2512 (
m_spend_zero_conf_change && !fRejectLongChains &&
SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(),
true ),
vCoins, setCoinsRet, nValueRet,
coin_selection_params, bnb_used));
2518 nValueRet += nValueFromPresetInputs;
2528 std::map<COutPoint, Coin> coins;
2529 for (
auto& input : tx.
vin) {
2530 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
2531 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2537 std::map<int, std::string> input_errors;
2547 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2563 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2564 const CTxIn& txin = psbtx.
tx->vin[i];
2574 const auto it = mapWallet.find(txhash);
2575 if (
it != mapWallet.end()) {
2586 int n_signed_this_spkm = 0;
2587 TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
2593 (*n_signed) += n_signed_this_spkm;
2599 for (
const auto& input : psbtx.
inputs) {
2611 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2612 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2620 std::vector<CRecipient> vecSend;
2623 for (
size_t idx = 0; idx < tx.
vout.size(); idx++) {
2626 vecSend.push_back(recipient);
2641 if (!
CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut,
error, coinControl, fee_calc_out,
false)) {
2645 if (nChangePosInOut != -1) {
2646 tx.
vout.insert(tx.
vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
2651 for (
unsigned int idx = 0; idx < tx.
vout.size(); idx++) {
2652 tx.
vout[idx].nValue = tx_new->vout[idx].nValue;
2656 for (
const CTxIn& txin : tx_new->vin) {
2658 tx.
vin.push_back(txin);
2675 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
2678 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
2712 locktime = block_height;
2719 locktime = std::max(0, (
int)locktime -
GetRandInt(100));
2734 return *change_type;
2745 for (
const auto& recipient : vecSend) {
2747 int witnessversion = 0;
2748 std::vector<unsigned char> witnessprogram;
2749 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
2759 const std::vector<CRecipient>& vecSend,
2762 int& nChangePosInOut,
2771 int nChangePosRequest = nChangePosInOut;
2772 unsigned int nSubtractFeeFromAmount = 0;
2773 for (
const auto& recipient : vecSend)
2775 if (nValue < 0 || recipient.nAmount < 0)
2777 error =
_(
"Transaction amounts must not be negative");
2780 nValue += recipient.nAmount;
2782 if (recipient.fSubtractFeeFromAmount)
2783 nSubtractFeeFromAmount++;
2785 if (vecSend.empty())
2787 error =
_(
"Transaction must have at least one recipient");
2794 std::pair<int64_t, int64_t> tx_sizes;
2797 std::set<CInputCoin> setCoins;
2801 std::vector<COutput> vAvailableCoins;
2812 if (!std::get_if<CNoDestination>(&coin_control.
destChange)) {
2826 error =
_(
"Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.");
2834 CTxOut change_prototype_txout(0, scriptChange);
2850 error =
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
2860 bool pick_new_inputs =
true;
2870 nChangePosInOut = nChangePosRequest;
2875 CAmount nValueToSelect = nValue;
2876 if (nSubtractFeeFromAmount == 0)
2877 nValueToSelect += nFeeRet;
2883 for (
const auto& recipient : vecSend)
2885 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
2887 if (recipient.fSubtractFeeFromAmount)
2889 assert(nSubtractFeeFromAmount != 0);
2890 txout.
nValue -= nFeeRet / nSubtractFeeFromAmount;
2895 txout.
nValue -= nFeeRet % nSubtractFeeFromAmount;
2905 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
2908 error =
_(
"The transaction amount is too small to pay the fee");
2910 error =
_(
"The transaction amount is too small to send after the fee has been deducted");
2913 error =
_(
"Transaction amount too small");
2916 txNew.
vout.push_back(txout);
2920 bool bnb_used =
false;
2921 if (pick_new_inputs) {
2927 if (change_spend_size == -1) {
2940 error =
_(
"Insufficient funds");
2948 const CAmount nChange = nValueIn - nValueToSelect;
2952 CTxOut newTxOut(nChange, scriptChange);
2959 nChangePosInOut = -1;
2964 if (nChangePosInOut == -1)
2969 else if ((
unsigned int)nChangePosInOut > txNew.
vout.size())
2971 error =
_(
"Change index out of range");
2975 std::vector<CTxOut>::iterator position = txNew.
vout.begin()+nChangePosInOut;
2976 txNew.
vout.insert(position, newTxOut);
2979 nChangePosInOut = -1;
2984 for (
const auto& coin : setCoins) {
2989 nBytes = tx_sizes.first;
2991 error =
_(
"Signing transaction failed");
2996 if (nFeeRet >= nFeeNeeded) {
3007 if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
3011 if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
3012 pick_new_inputs =
false;
3013 nFeeRet = fee_needed_with_change;
3019 if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3020 CAmount extraFeePaid = nFeeRet - nFeeNeeded;
3021 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
3022 change_position->nValue += extraFeePaid;
3023 nFeeRet -= extraFeePaid;
3027 else if (!pick_new_inputs) {
3032 error =
_(
"Transaction fee and change calculation failed");
3037 if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3038 CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3039 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
3042 change_position->nValue -= additionalFeeNeeded;
3043 nFeeRet += additionalFeeNeeded;
3050 if (nSubtractFeeFromAmount > 0) {
3051 pick_new_inputs =
false;
3055 nFeeRet = nFeeNeeded;
3061 if (scriptChange.
empty() && nChangePosInOut != -1) {
3068 std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
3080 for (
const auto& coin : selected_coins) {
3085 error =
_(
"Signing transaction failed");
3096 error =
_(
"Transaction too large");
3108 if (!
chain().checkChainLimits(tx)) {
3109 error =
_(
"Transaction has too long of a mempool chain");
3117 fee_calc_out = feeCalc;
3119 WalletLogPrintf(
"Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
3131 const std::vector<CRecipient>& vecSend,
3134 int& nChangePosInOut,
3140 int nChangePosIn = nChangePosInOut;
3149 int nChangePosInOut2 = nChangePosIn;
3154 WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n", nFeeRet, nFeeRet2, use_aps ?
"grouped" :
"non-grouped");
3158 nChangePosInOut = nChangePosInOut2;
3175 wtx.
mapValue = std::move(mapValue);
3183 for (
const CTxIn& txin : tx->vin) {
3191 CWalletTx& wtx = mapWallet.at(tx->GetHash());
3198 std::string err_string;
3200 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
3209 fFirstRunRet =
false;
3216 spk_man_pair.second->RewriteDB();
3229 return nLoadWalletRet;
3238 for (
const uint256& hash : vHashOut) {
3239 const auto&
it = mapWallet.find(hash);
3241 for (
const auto& txin :
it->second.tx->vin)
3242 mapTxSpends.erase(txin.prevout);
3243 mapWallet.erase(
it);
3252 spk_man_pair.second->RewriteDB();
3258 return nZapSelectTxRet;
3267 bool fUpdated =
false;
3271 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
3272 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
3273 m_address_book[address].SetLabel(strName);
3274 if (!strPurpose.empty())
3275 m_address_book[address].purpose = strPurpose;
3306 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
3310 m_address_book.erase(address);
3324 unsigned int count = 0;
3326 count += spk_man->KeypoolCountExternalKeys();
3336 unsigned int count = 0;
3338 count += spk_man->GetKeyPoolSize();
3348 res &= spk_man->TopUp(kpSize);
3357 bool result =
false;
3361 result = spk_man->GetNewDestination(type, dest,
error);
3379 error =
_(
"Error: Keypool ran out, please call keypoolrefill first").
translated;
3390 int64_t oldestKey = std::numeric_limits<int64_t>::max();
3392 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
3398 for (
auto& entry : mapWallet) {
3401 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
3413 std::map<CTxDestination, CAmount> balances;
3417 std::set<uint256> trusted_parents;
3418 for (
const auto& walletEntry : mapWallet)
3420 const CWalletTx& wtx = walletEntry.second;
3432 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++)
3441 balances[addr] += n;
3452 std::set< std::set<CTxDestination> > groupings;
3453 std::set<CTxDestination> grouping;
3455 for (
const auto& walletEntry : mapWallet)
3457 const CWalletTx& wtx = walletEntry.second;
3459 if (wtx.
tx->vin.size() > 0)
3461 bool any_mine =
false;
3463 for (
const CTxIn& txin : wtx.
tx->vin)
3470 grouping.insert(address);
3477 for (
const CTxOut& txout : wtx.
tx->vout)
3483 grouping.insert(txoutAddr);
3486 if (grouping.size() > 0)
3488 groupings.insert(grouping);
3494 for (
const auto& txout : wtx.
tx->vout)
3500 grouping.insert(address);
3501 groupings.insert(grouping);
3506 std::set< std::set<CTxDestination>* > uniqueGroupings;
3507 std::map< CTxDestination, std::set<CTxDestination>* > setmap;
3508 for (std::set<CTxDestination> _grouping : groupings)
3511 std::set< std::set<CTxDestination>* > hits;
3512 std::map< CTxDestination, std::set<CTxDestination>* >::iterator
it;
3514 if ((
it = setmap.find(address)) != setmap.end())
3515 hits.insert((*it).second);
3518 std::set<CTxDestination>* merged =
new std::set<CTxDestination>(_grouping);
3519 for (std::set<CTxDestination>* hit : hits)
3521 merged->insert(hit->begin(), hit->end());
3522 uniqueGroupings.erase(hit);
3525 uniqueGroupings.insert(merged);
3529 setmap[element] = merged;
3532 std::set< std::set<CTxDestination> > ret;
3533 for (
const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
3535 ret.insert(*uniqueGrouping);
3536 delete uniqueGrouping;
3545 std::set<CTxDestination> result;
3546 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
3548 if (item.second.IsChange())
continue;
3550 const std::string& strName = item.second.GetLabel();
3551 if (strName == label)
3552 result.insert(address);
3597 #ifdef ENABLE_EXTERNAL_SIGNER
3600 const std::string command =
gArgs.
GetArg(
"-signer",
"");
3601 if (command ==
"")
throw std::runtime_error(std::string(__func__) +
": restart bitcoind with -signer=<cmd>");
3602 std::vector<ExternalSigner> signers;
3604 if (signers.empty())
throw std::runtime_error(std::string(__func__) +
": No external signers found");
3612 #ifdef ENABLE_EXTERNAL_SIGNER
3615 if (spk_man ==
nullptr) {
3619 if (signer_spk_man ==
nullptr) {
3623 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
3632 setLockedCoins.insert(output);
3638 setLockedCoins.erase(output);
3644 setLockedCoins.clear();
3652 return (setLockedCoins.count(outpt) > 0);
3658 for (std::set<COutPoint>::iterator
it = setLockedCoins.begin();
3659 it != setLockedCoins.end();
it++) {
3661 vOutpts.push_back(outpt);
3669 mapKeyBirth.clear();
3672 assert(spk_man !=
nullptr);
3676 for (
const auto& entry : spk_man->mapKeyMetadata) {
3677 if (entry.second.nCreateTime) {
3678 mapKeyBirth[entry.first] = entry.second.nCreateTime;
3683 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
3688 if (mapKeyBirth.count(keyid) == 0)
3689 mapKeyFirstBlock[keyid] = &max_confirm;
3693 if (mapKeyFirstBlock.empty())
3697 for (
const auto& entry : mapWallet) {
3702 for (
const CTxOut &txout : wtx.
tx->vout) {
3706 auto rit = mapKeyFirstBlock.find(keyid);
3716 for (
const auto& entry : mapKeyFirstBlock) {
3751 int64_t latestEntry = 0;
3754 int64_t latestTolerated = latestNow + 300;
3756 for (
auto it = txOrdered.rbegin();
it != txOrdered.rend(); ++
it) {
3766 if (nSmartTime <= latestTolerated) {
3767 latestEntry = nSmartTime;
3768 if (nSmartTime > latestNow) {
3769 latestNow = nSmartTime;
3775 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
3785 if (std::get_if<CNoDestination>(&dest))
3788 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3794 if (!m_address_book[dest].destdata.erase(key))
3801 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3806 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
3807 if(i != m_address_book.end())
3809 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
3810 if(j != i->second.destdata.end())
3822 std::vector<std::string> values;
3823 for (
const auto& address : m_address_book) {
3824 for (
const auto& data : address.second.destdata) {
3826 values.emplace_back(data.second);
3842 fs::file_type path_type = fs::symlink_status(wallet_path).type();
3843 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
3844 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
3845 (path_type == fs::regular_file && fs::path(
name).filename() ==
name))) {
3847 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
3848 "database/log.?????????? files can be stored, a location where such a directory could be created, "
3849 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
3854 return MakeDatabase(wallet_path, options, status, error_string);
3859 const std::string& walletFile = database->Filename();
3864 bool fFirstRun =
true;
3868 DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
3871 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
3876 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
3877 " or address book entries might be missing or incorrect."),
3900 walletInstance->AddWalletFlags(wallet_creation_flags);
3904 walletInstance->SetupLegacyScriptPubKeyMan();
3908 LOCK(walletInstance->cs_wallet);
3910 walletInstance->SetupDescriptorScriptPubKeyMans();
3914 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3915 if (!spk_man->SetupGeneration()) {
3916 error =
_(
"Unable to generate initial keys");
3926 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3929 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3930 if (spk_man->HavePrivateKeys()) {
3931 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3950 walletInstance->m_default_change_type = out_type;
3961 _(
"This is the minimum transaction fee you pay on every transaction."));
3963 walletInstance->m_min_fee =
CFeeRate(n);
3967 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
3969 if (max_aps_fee ==
"-1") {
3977 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3979 walletInstance->m_max_aps_fee = n;
3990 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3992 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
3995 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
4005 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
4007 walletInstance->m_discard_rate =
CFeeRate(nFeePerK);
4017 _(
"This is the transaction fee you will pay if you send a transaction."));
4019 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
4021 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
4034 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
4037 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
4041 walletInstance->m_default_max_tx_fee = nMaxFee;
4046 _(
"The wallet will avoid paying less than the minimum relay fee."));
4053 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
GetTimeMillis() - nStart);
4056 walletInstance->TopUpKeyPool();
4058 LOCK(walletInstance->cs_wallet);
4068 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
4070 int rescan_height = 0;
4077 rescan_height = *fork_height;
4085 walletInstance->m_last_block_processed_height = *tip_height;
4087 walletInstance->m_last_block_processed.
SetNull();
4088 walletInstance->m_last_block_processed_height = -1;
4091 if (tip_height && *tip_height != rescan_height)
4100 int block_height = *tip_height;
4101 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
4105 if (rescan_height != block_height) {
4106 error =
_(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
4112 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
4116 std::optional<int64_t> time_first_key;
4117 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
4118 int64_t time = spk_man->GetTimeFirstKey();
4119 if (!time_first_key || time < *time_first_key) time_first_key = time;
4121 if (time_first_key) {
4128 error =
_(
"Failed to rescan the wallet during initialization");
4133 walletInstance->GetDatabase().IncrementUpdateCounter();
4138 for (
auto& load_wallet : g_load_wallet_fns) {
4146 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
4147 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
4148 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
4151 return walletInstance;
4156 const auto& address_book_it = m_address_book.find(dest);
4157 if (address_book_it == m_address_book.end())
return nullptr;
4158 if ((!allow_change) && address_book_it->second.IsChange()) {
4161 return &address_book_it->second;
4173 if (version < prev_version) {
4174 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
4182 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);
4190 if (!spk_man->Upgrade(prev_version, version,
error)) {
4243 assert(chain_depth >= 0);
4255 std::vector<OutputGroup> groups_out;
4257 if (separate_coins) {
4259 for (
const COutput& output : outputs) {
4261 if (!output.fSpendable)
continue;
4263 size_t ancestors, descendants;
4265 CInputCoin input_coin = output.GetInputCoin();
4268 OutputGroup group{effective_feerate, long_term_feerate};
4269 group.Insert(input_coin, output.nDepth, output.tx->IsFromMe(
ISMINE_ALL), ancestors, descendants, positive_only);
4272 if (positive_only && group.effective_value <= 0)
continue;
4273 if (group.m_outputs.size() > 0 && group.EligibleForSpending(filter)) groups_out.push_back(group);
4284 std::map<CScript, std::vector<OutputGroup>> spk_to_groups_map;
4285 for (
const auto& output : outputs) {
4287 if (!output.fSpendable)
continue;
4289 size_t ancestors, descendants;
4291 CInputCoin input_coin = output.GetInputCoin();
4294 std::vector<OutputGroup>& groups = spk_to_groups_map[spk];
4296 if (groups.size() == 0) {
4298 groups.
emplace_back(effective_feerate, long_term_feerate);
4309 groups.emplace_back(effective_feerate, long_term_feerate);
4310 group = &groups.back();
4314 group->
Insert(input_coin, output.nDepth, output.tx->IsFromMe(
ISMINE_ALL), ancestors, descendants, positive_only);
4318 for (
const auto& spk_and_groups_pair: spk_to_groups_map) {
4319 const std::vector<OutputGroup>& groups_per_spk= spk_and_groups_pair.second;
4322 for (
auto group_it = groups_per_spk.rbegin(); group_it != groups_per_spk.rend(); group_it++) {
4350 return vMasterKey.empty();
4372 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
4376 vMasterKey = vMasterKeyIn;
4384 std::set<ScriptPubKeyMan*> spk_mans;
4385 for (
bool internal : {
false,
true}) {
4389 spk_mans.insert(spk_man);
4398 std::set<ScriptPubKeyMan*> spk_mans;
4400 spk_mans.insert(spk_man_pair.second.get());
4408 std::map<OutputType, ScriptPubKeyMan*>::const_iterator
it = spk_managers.find(type);
4409 if (
it == spk_managers.end()) {
4410 WalletLogPrintf(
"%s scriptPubKey Manager for output type %d does not exist\n",
internal ?
"Internal" :
"External",
static_cast<int>(type));
4418 std::set<ScriptPubKeyMan*> spk_mans;
4420 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4421 spk_mans.insert(spk_man_pair.second.get());
4431 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4432 return spk_man_pair.second.get();
4455 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4456 return spk_man_pair.second->GetSolvingProvider(script);
4515 #ifdef ENABLE_EXTERNAL_SIGNER
4519 throw std::runtime_error(std::string(__func__) +
": Configure with --enable-external-signer to use external signer wallets");
4542 for (
bool internal : {
false,
true}) {
4547 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
4549 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
4550 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
4553 spk_manager->SetupDescriptorGeneration(master_key, t);
4554 uint256 id = spk_manager->GetID();
4560 #ifdef ENABLE_EXTERNAL_SIGNER
4567 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
4568 for (
bool internal : {
false,
true}) {
4569 const UniValue& descriptor_vals =
find_value(signer_res,
internal ?
"internal" :
"receive");
4570 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
4572 std::string desc_str = desc_val.getValStr();
4574 std::string dummy_error;
4575 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, dummy_error,
false);
4576 if (!desc->GetOutputType()) {
4581 spk_manager->SetupDescriptor(std::move(desc));
4582 uint256 id = spk_manager->GetID();
4588 throw std::runtime_error(std::string(__func__) +
": Wallets with external signers require Boost::Process library.");
4597 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
4604 WalletLogPrintf(
"Setting spkMan to active: id = %s, type = %d, internal = %d\n",
id.
ToString(),
static_cast<int>(type),
static_cast<int>(
internal));
4607 spk_man->SetInternal(
internal);
4608 spk_mans[type] = spk_man;
4619 return spk_man !=
nullptr;
4638 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
4651 LOCK(old_spk_man->cs_desc_man);
4652 new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache);
4656 auto old_spk_man_id = old_spk_man->GetID();
4657 for (
bool internal : {
false,
true}) {
4660 if (active_spk_man && active_spk_man->GetID() == old_spk_man_id) {
4674 for (
const auto& entry : signing_provider.
keys) {
4675 const CKey& key = entry.second;
4676 new_spk_man->AddDescriptorKey(key, key.
GetPubKey());
4680 if (!new_spk_man->TopUp()) {
4688 auto script_pub_keys = new_spk_man->GetScriptPubKeys();
4689 if (script_pub_keys.empty()) {
4690 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
4701 auto ret = new_spk_man.get();
4705 ret->WriteDescriptor();