41 #include <boost/algorithm/string/replace.hpp>
47 "You need to rescan the blockchain in order to correctly mark used "
48 "destinations in the past. Until this is done, some destinations may "
49 "be considered unused, even if the opposite is the case."
64 if (value.isStr() && value.get_str() == wallet_name)
return true;
73 if (!setting_value.
isArray())
return true;
76 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
78 if (new_value.
size() == setting_value.
size())
return true;
83 const std::string& wallet_name,
85 std::vector<bilingual_str>& warnings)
87 if (load_on_startup ==
nullopt)
return;
89 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
91 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
95 bool AddWallet(
const std::shared_ptr<CWallet>& wallet)
99 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
100 if (i != vpwallets.end())
return false;
101 vpwallets.push_back(wallet);
102 wallet->ConnectScriptPubKeyManNotifiers();
103 wallet->NotifyCanGetAddressesChanged();
112 std::string
name = wallet->GetName();
115 wallet->m_chain_notifications_handler.reset();
117 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
118 if (i == vpwallets.end())
return false;
129 std::vector<bilingual_str> warnings;
142 for (
const std::shared_ptr<CWallet>& wallet : vpwallets) {
143 if (wallet->GetName() ==
name)
return wallet;
151 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
171 if (g_unloading_wallet_set.erase(
name) == 0) {
182 const std::string
name = wallet->GetName();
185 auto it = g_unloading_wallet_set.insert(
name);
191 wallet->NotifyUnload();
197 while (g_unloading_wallet_set.count(
name) == 1) {
220 wallet->postInitProcess();
226 }
catch (
const std::runtime_error& e) {
237 if (!result.second) {
242 auto wallet = LoadWalletInternal(chain,
name, load_on_start, options, status,
error, warnings);
258 if (!passphrase.empty()) {
272 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.");
278 std::shared_ptr<CWallet> wallet =
CWallet::Create(chain,
name, std::move(database), wallet_creation_flags,
error, warnings);
287 if (!wallet->EncryptWallet(passphrase)) {
294 if (!wallet->Unlock(passphrase)) {
302 LOCK(wallet->cs_wallet);
304 wallet->SetupDescriptorScriptPubKeyMans();
306 for (
auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
307 if (!spk_man->SetupGeneration()) {
321 wallet->postInitProcess();
343 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(hash);
344 if (
it == mapWallet.end())
346 return &(
it->second);
360 spk_man->UpgradeKeyMetadata();
371 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
373 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
375 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
377 if (
Unlock(_vMasterKey, accept_no_keys)) {
399 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
401 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
406 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
407 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(
GetTimeMillis() - nStartTime))));
410 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
411 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
413 if (pMasterKey.second.nDeriveIterations < 25000)
414 pMasterKey.second.nDeriveIterations = 25000;
416 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
418 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
420 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
442 if (nWalletVersion >= nVersion)
444 nWalletVersion = nVersion;
448 if (nWalletVersion > 40000)
457 std::set<uint256> result;
460 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(txid);
461 if (
it == mapWallet.end())
465 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
467 for (
const CTxIn& txin : wtx.
tx->vin)
469 if (mapTxSpends.count(txin.
prevout) <= 1)
471 range = mapTxSpends.equal_range(txin.
prevout);
472 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
473 result.insert(_it->second);
481 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
482 return (iter != mapTxSpends.end() && iter->first.hash == txid);
501 int nMinOrderPos = std::numeric_limits<int>::max();
503 for (TxSpends::iterator
it = range.first;
it != range.second; ++
it) {
516 for (TxSpends::iterator
it = range.first;
it != range.second; ++
it)
520 if (copyFrom == copyTo)
continue;
521 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
541 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
542 range = mapTxSpends.equal_range(outpoint);
544 for (TxSpends::const_iterator
it = range.first;
it != range.second; ++
it)
547 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
548 if (mit != mapWallet.end()) {
549 int depth = mit->second.GetDepthInMainChain();
550 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
559 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
561 setLockedCoins.erase(outpoint);
563 std::pair<TxSpends::iterator, TxSpends::iterator> range;
564 range = mapTxSpends.equal_range(outpoint);
571 auto it = mapWallet.find(wtxid);
572 assert(
it != mapWallet.end());
577 for (
const CTxIn& txin : thisTx.
tx->vin)
620 delete encrypted_batch;
621 encrypted_batch =
nullptr;
627 auto spk_man = spk_man_pair.second.get();
628 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
630 delete encrypted_batch;
631 encrypted_batch =
nullptr;
642 delete encrypted_batch;
643 encrypted_batch =
nullptr;
649 delete encrypted_batch;
650 encrypted_batch =
nullptr;
653 Unlock(strWalletPassphrase);
660 if (spk_man->IsHDEnabled()) {
661 if (!spk_man->SetupGeneration(
true)) {
692 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
695 for (
auto& entry : mapWallet)
702 std::vector<int64_t> nOrderPosOffsets;
703 for (TxItems::iterator
it = txByTime.begin();
it != txByTime.end(); ++
it)
710 nOrderPos = nOrderPosNext++;
711 nOrderPosOffsets.push_back(nOrderPos);
718 int64_t nOrderPosOff = 0;
719 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
721 if (nOrderPos >= nOffsetStart)
724 nOrderPos += nOrderPosOff;
725 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
743 int64_t nRet = nOrderPosNext++;
756 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
757 item.second.MarkDirty();
765 auto mi = mapWallet.find(originalHash);
768 assert(mi != mapWallet.end());
773 assert(wtx.
mapValue.count(
"replaced_by_txid") == 0);
801 tx_destinations.insert(dst);
803 }
else if (!used &&
GetDestData(dst,
"used",
nullptr)) {
815 assert(srctx->
tx->vout.size() > n);
825 assert(spk_man !=
nullptr);
826 for (
const auto& keyid :
GetAffectedKeys(srctx->
tx->vout[n].scriptPubKey, *spk_man)) {
855 std::set<CTxDestination> tx_destinations;
857 for (
const CTxIn& txin : tx->vin) {
866 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this, tx));
868 bool fInsertedNew = ret.second;
869 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
897 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
904 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
907 if (fInsertedNew || fUpdated)
919 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
923 boost::replace_all(strCmd,
"%s", hash.
GetHex());
932 std::thread t(runCommand, strCmd);
942 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this,
nullptr));
944 if (!fill_wtx(wtx, ins.second)) {
971 for (
const CTxIn& txin : wtx.
tx->vin) {
973 if (
it != mapWallet.end()) {
991 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
992 while (range.first != range.second) {
993 if (range.first->second != tx.
GetHash()) {
994 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);
1002 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1003 if (fExisted && !fUpdate)
return false;
1015 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1036 for (
const CTxIn& txin : tx->vin) {
1038 if (
it != mapWallet.end()) {
1039 it->second.MarkDirty();
1050 std::set<uint256> todo;
1051 std::set<uint256> done;
1054 auto it = mapWallet.find(hashTx);
1055 assert(
it != mapWallet.end());
1061 todo.insert(hashTx);
1063 while (!todo.empty()) {
1067 auto it = mapWallet.find(
now);
1068 assert(
it != mapWallet.end());
1072 assert(currentconfirm <= 0);
1082 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(
now, 0));
1083 while (iter != mapTxSpends.end() && iter->first.hash ==
now) {
1084 if (!done.count(iter->second)) {
1085 todo.insert(iter->second);
1102 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1107 if (conflictconfirms >= 0)
1113 std::set<uint256> todo;
1114 std::set<uint256> done;
1116 todo.insert(hashTx);
1118 while (!todo.empty()) {
1122 auto it = mapWallet.find(
now);
1123 assert(
it != mapWallet.end());
1126 if (conflictconfirms < currentconfirm) {
1136 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(
now, 0));
1137 while (iter != mapTxSpends.end() && iter->first.hash ==
now) {
1138 if (!done.count(iter->second)) {
1139 todo.insert(iter->second);
1165 auto it = mapWallet.find(tx->GetHash());
1166 if (
it != mapWallet.end()) {
1167 it->second.fInMempool =
true;
1173 auto it = mapWallet.find(tx->GetHash());
1174 if (
it != mapWallet.end()) {
1175 it->second.fInMempool =
false;
1214 m_last_block_processed_height = height;
1215 m_last_block_processed = block_hash;
1216 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1217 SyncTransaction(block.
vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1230 m_last_block_processed_height = height - 1;
1243 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1257 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1258 if (mi != mapWallet.end())
1273 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1274 if (mi != mapWallet.end())
1302 result = std::max(result, spk_man_pair.second->IsMine(script));
1310 throw std::runtime_error(std::string(__func__) +
": value out of range");
1346 throw std::runtime_error(std::string(__func__) +
": value out of range");
1371 throw std::runtime_error(std::string(__func__) +
": value out of range");
1383 if (mi == mapWallet.end())
1404 throw std::runtime_error(std::string(__func__) +
": value out of range");
1417 throw std::runtime_error(std::string(__func__) +
": value out of range");
1427 result &= spk_man->IsHDEnabled();
1438 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1450 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1464 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1495 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1533 for (
const auto& txout : txouts)
1550 LOCK(spk_man->cs_KeyStore);
1551 return spk_man->ImportScripts(scripts, timestamp);
1560 LOCK(spk_man->cs_KeyStore);
1561 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1564 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)
1570 LOCK(spk_man->cs_KeyStore);
1571 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1574 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)
1580 LOCK(spk_man->cs_KeyStore);
1581 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1586 for (
const CScript& script : script_pub_keys) {
1599 std::vector<CTxOut> txouts;
1600 for (
const CTxIn& input : tx.
vin) {
1601 const auto mi = wallet->mapWallet.find(input.
prevout.
hash);
1603 if (mi == wallet->mapWallet.end()) {
1606 assert(input.
prevout.
n < mi->second.tx->vout.size());
1607 txouts.emplace_back(mi->second.tx->vout[input.
prevout.
n]);
1616 if (!wallet->
DummySignTx(txNew, txouts, use_max_sig)) {
1636 listReceived.clear();
1644 nFee = nDebit - nValueOut;
1649 for (
unsigned int i = 0; i <
tx->vout.size(); ++i)
1662 else if (!(fIsMine & filter))
1679 listSent.push_back(output);
1682 if (fIsMine & filter)
1683 listReceived.push_back(output);
1701 int start_height = 0;
1746 uint256 block_hash = start_block;
1758 double progress_current = progress_begin;
1759 int block_height = start_height;
1761 if (progress_end - progress_begin > 0.0) {
1762 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1766 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1771 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1790 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1791 SyncTransaction(block.
vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1802 if (max_height && block_height >= *max_height) {
1806 if (!next_block || reorg) {
1813 block_hash = next_block_hash;
1818 const uint256 prev_tip_hash = tip_hash;
1820 if (!max_height && prev_tip_hash != tip_hash) {
1828 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1830 }
else if (block_height &&
chain().shutdownRequested()) {
1831 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1844 std::map<int64_t, CWalletTx*> mapSorted;
1847 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1848 const uint256& wtxid = item.first;
1850 assert(wtx.
GetHash() == wtxid);
1855 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1860 for (
const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1862 std::string unused_err_string;
1897 std::set<uint256> result;
1902 result.erase(myHash);
1910 if (recalculate || !amount.m_cached[filter]) {
1914 return amount.m_value[filter];
1919 if (
tx->vin.empty())
1977 for (
unsigned int i = 0; i <
tx->vout.size(); i++)
1983 throw std::runtime_error(std::string(__func__) +
" : value out of range");
2020 std::set<uint256> trusted_parents;
2029 if (!
chain().checkFinalTx(*wtx.
tx))
return false;
2031 if (nDepth >= 1)
return true;
2032 if (nDepth < 0)
return false;
2040 for (
const CTxIn& txin : wtx.
tx->vin)
2044 if (parent ==
nullptr)
return false;
2049 if (trusted_parents.count(parent->
GetHash()))
continue;
2051 if (!
IsTrusted(*parent, trusted_parents))
return false;
2052 trusted_parents.insert(parent->
GetHash());
2061 for (
auto& txin : tx1.vin) txin.scriptSig =
CScript();
2062 for (
auto& txin : tx2.vin) txin.scriptSig =
CScript();
2079 if (!
chain().isReadyToBroadcast())
return;
2089 int submitted_tx_count = 0;
2095 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
2101 std::string unused_err_string;
2106 if (submitted_tx_count > 0) {
2107 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2115 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
2116 pwallet->ResendWalletTransactions();
2133 std::set<uint256> trusted_parents;
2134 for (
const auto& entry : mapWallet)
2137 const bool is_trusted{
IsTrusted(wtx, trusted_parents)};
2141 if (is_trusted && tx_depth >= min_depth) {
2145 if (!is_trusted && tx_depth == 0 && wtx.
InMempool()) {
2161 std::vector<COutput>
vCoins;
2164 if (out.fSpendable) {
2165 balance += out.tx->tx->vout[out.i].nValue;
2183 std::set<uint256> trusted_parents;
2184 for (
const auto& entry : mapWallet)
2186 const uint256& wtxid = entry.first;
2205 bool safeTx =
IsTrusted(wtx, trusted_parents);
2222 if (nDepth == 0 && wtx.
mapValue.count(
"replaces_txid")) {
2234 if (nDepth == 0 && wtx.
mapValue.count(
"replaced_by_txid")) {
2238 if (fOnlySafe && !safeTx) {
2242 if (nDepth < min_depth || nDepth > max_depth) {
2246 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2252 if (wtx.
tx->vout[i].nValue < nMinimumAmount || wtx.
tx->vout[i].nValue > nMaximumAmount)
2270 if (!allow_used_addresses &&
IsSpentKey(wtxid, i)) {
2276 bool solvable = provider ?
IsSolvable(*provider, wtx.
tx->vout[i].scriptPubKey) :
false;
2283 nTotal += wtx.
tx->vout[i].nValue;
2285 if (nTotal >= nMinimumSumAmount) {
2291 if (nMaximumCount > 0 &&
vCoins.size() >= nMaximumCount) {
2302 std::map<CTxDestination, std::vector<COutput>> result;
2303 std::vector<COutput> availableCoins;
2307 for (
const COutput& coin : availableCoins) {
2311 result[address].emplace_back(std::move(coin));
2315 std::vector<COutPoint> lockedCoins;
2320 for (
const COutPoint& output : lockedCoins) {
2321 auto it = mapWallet.find(output.hash);
2322 if (
it != mapWallet.end()) {
2323 int depth =
it->second.GetDepthInMainChain();
2324 if (depth >= 0 && output.n <
it->second.tx->vout.size() &&
2325 IsMine(
it->second.tx->vout[output.n]) == is_mine_filter
2329 result[address].emplace_back(
2330 &
it->second, output.n, depth,
true ,
true ,
false );
2346 auto it = mapWallet.find(prevout.
hash);
2347 if (
it == mapWallet.end() ||
it->second.tx->vout.size() <= prevout.
n ||
2348 !
IsMine(
it->second.tx->vout[prevout.
n])) {
2351 ptx =
it->second.tx.get();
2354 return ptx->
vout[n];
2360 setCoinsRet.clear();
2363 std::vector<OutputGroup> utxo_pool;
2376 if (!group.EligibleForSpending(eligibility_filter))
continue;
2380 group.SetFees(
CFeeRate(0) , long_term_feerate);
2391 return SelectCoinsBnB(utxo_pool, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
2395 if (!group.EligibleForSpending(eligibility_filter))
continue;
2396 utxo_pool.push_back(group);
2399 return KnapsackSolver(nTargetValue, utxo_pool, setCoinsRet, nValueRet);
2405 std::vector<COutput>
vCoins(vAvailableCoins);
2406 CAmount value_to_select = nTargetValue;
2416 if (!out.fSpendable)
2418 nValueRet += out.tx->tx->vout[out.i].nValue;
2419 setCoinsRet.insert(out.GetInputCoin());
2421 return (nValueRet >= nTargetValue);
2425 std::set<CInputCoin> setPresetCoins;
2426 CAmount nValueFromPresetInputs = 0;
2428 std::vector<COutPoint> vPresetInputs;
2430 for (
const COutPoint& outpoint : vPresetInputs)
2432 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(outpoint.hash);
2433 if (
it != mapWallet.end())
2437 if (wtx.
tx->vout.size() <= outpoint.n) {
2452 setPresetCoins.insert(coin);
2461 if (setPresetCoins.count(
it->GetInputCoin()))
2467 unsigned int limit_ancestor_count = 0;
2468 unsigned int limit_descendant_count = 0;
2470 size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2471 size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2484 bool res = value_to_select <= 0 ||
2488 (
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)), groups, setCoinsRet, nValueRet,
coin_selection_params, bnb_used)) ||
2497 nValueRet += nValueFromPresetInputs;
2507 std::map<COutPoint, Coin> coins;
2508 for (
auto& input : tx.
vin) {
2509 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
2510 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2516 std::map<int, std::string> input_errors;
2526 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2542 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
2543 const CTxIn& txin = psbtx.
tx->vin[i];
2553 const auto it = mapWallet.find(txhash);
2554 if (
it != mapWallet.end()) {
2565 int n_signed_this_spkm = 0;
2566 TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
2572 (*n_signed) += n_signed_this_spkm;
2578 for (
const auto& input : psbtx.
inputs) {
2590 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2591 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2599 std::vector<CRecipient> vecSend;
2602 for (
size_t idx = 0; idx < tx.
vout.size(); idx++) {
2605 vecSend.push_back(recipient);
2620 if (!
CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut,
error, coinControl, fee_calc_out,
false)) {
2624 if (nChangePosInOut != -1) {
2625 tx.
vout.insert(tx.
vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
2630 for (
unsigned int idx = 0; idx < tx.
vout.size(); idx++) {
2631 tx.
vout[idx].nValue = tx_new->vout[idx].nValue;
2635 for (
const CTxIn& txin : tx_new->vin) {
2637 tx.
vin.push_back(txin);
2654 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
2657 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
2691 locktime = block_height;
2698 locktime = std::max(0, (
int)locktime -
GetRandInt(100));
2713 return *change_type;
2724 for (
const auto& recipient : vecSend) {
2726 int witnessversion = 0;
2727 std::vector<unsigned char> witnessprogram;
2728 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
2738 const std::vector<CRecipient>& vecSend,
2741 int& nChangePosInOut,
2750 int nChangePosRequest = nChangePosInOut;
2751 unsigned int nSubtractFeeFromAmount = 0;
2752 for (
const auto& recipient : vecSend)
2754 if (nValue < 0 || recipient.nAmount < 0)
2756 error =
_(
"Transaction amounts must not be negative");
2759 nValue += recipient.nAmount;
2761 if (recipient.fSubtractFeeFromAmount)
2762 nSubtractFeeFromAmount++;
2764 if (vecSend.empty())
2766 error =
_(
"Transaction must have at least one recipient");
2775 std::set<CInputCoin> setCoins;
2779 std::vector<COutput> vAvailableCoins;
2789 if (!boost::get<CNoDestination>(&coin_control.
destChange)) {
2803 error =
_(
"Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.");
2811 CTxOut change_prototype_txout(0, scriptChange);
2826 bool pick_new_inputs =
true;
2836 nChangePosInOut = nChangePosRequest;
2841 CAmount nValueToSelect = nValue;
2842 if (nSubtractFeeFromAmount == 0)
2843 nValueToSelect += nFeeRet;
2849 for (
const auto& recipient : vecSend)
2851 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
2853 if (recipient.fSubtractFeeFromAmount)
2855 assert(nSubtractFeeFromAmount != 0);
2856 txout.
nValue -= nFeeRet / nSubtractFeeFromAmount;
2861 txout.
nValue -= nFeeRet % nSubtractFeeFromAmount;
2871 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
2874 error =
_(
"The transaction amount is too small to pay the fee");
2876 error =
_(
"The transaction amount is too small to send after the fee has been deducted");
2879 error =
_(
"Transaction amount too small");
2882 txNew.
vout.push_back(txout);
2886 bool bnb_used =
false;
2887 if (pick_new_inputs) {
2893 if (change_spend_size == -1) {
2907 error =
_(
"Insufficient funds");
2915 const CAmount nChange = nValueIn - nValueToSelect;
2919 CTxOut newTxOut(nChange, scriptChange);
2924 if (
IsDust(newTxOut, discard_rate) || bnb_used)
2926 nChangePosInOut = -1;
2931 if (nChangePosInOut == -1)
2936 else if ((
unsigned int)nChangePosInOut > txNew.
vout.size())
2938 error =
_(
"Change index out of range");
2942 std::vector<CTxOut>::iterator position = txNew.
vout.begin()+nChangePosInOut;
2943 txNew.
vout.insert(position, newTxOut);
2946 nChangePosInOut = -1;
2951 for (
const auto& coin : setCoins) {
2957 error =
_(
"Signing transaction failed");
2961 nFeeNeeded =
GetMinimumFee(*
this, nBytes, coin_control, &feeCalc);
2964 error =
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
2968 if (nFeeRet >= nFeeNeeded) {
2979 if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
2981 CAmount fee_needed_with_change =
GetMinimumFee(*
this, tx_size_with_change, coin_control,
nullptr);
2983 if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
2984 pick_new_inputs =
false;
2985 nFeeRet = fee_needed_with_change;
2991 if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
2992 CAmount extraFeePaid = nFeeRet - nFeeNeeded;
2993 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
2994 change_position->nValue += extraFeePaid;
2995 nFeeRet -= extraFeePaid;
2999 else if (!pick_new_inputs) {
3004 error =
_(
"Transaction fee and change calculation failed");
3009 if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3010 CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3011 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
3014 change_position->nValue -= additionalFeeNeeded;
3015 nFeeRet += additionalFeeNeeded;
3022 if (nSubtractFeeFromAmount > 0) {
3023 pick_new_inputs =
false;
3027 nFeeRet = nFeeNeeded;
3033 if (scriptChange.
empty() && nChangePosInOut != -1) {
3040 std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
3052 for (
const auto& coin : selected_coins) {
3057 error =
_(
"Signing transaction failed");
3067 error =
_(
"Transaction too large");
3079 if (!
chain().checkChainLimits(tx)) {
3080 error =
_(
"Transaction has too long of a mempool chain");
3088 fee_calc_out = feeCalc;
3090 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",
3102 const std::vector<CRecipient>& vecSend,
3105 int& nChangePosInOut,
3111 int nChangePosIn = nChangePosInOut;
3119 int nChangePosInOut2 = nChangePosIn;
3124 WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n", nFeeRet, nFeeRet2, use_aps ?
"grouped" :
"non-grouped");
3128 nChangePosInOut = nChangePosInOut2;
3145 wtx.
mapValue = std::move(mapValue);
3153 for (
const CTxIn& txin : tx->vin) {
3161 CWalletTx& wtx = mapWallet.at(tx->GetHash());
3168 std::string err_string;
3170 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
3179 fFirstRunRet =
false;
3186 spk_man_pair.second->RewriteDB();
3199 return nLoadWalletRet;
3208 for (
const uint256& hash : vHashOut) {
3209 const auto&
it = mapWallet.find(hash);
3211 for (
const auto& txin :
it->second.tx->vin)
3212 mapTxSpends.erase(txin.prevout);
3213 mapWallet.erase(
it);
3222 spk_man_pair.second->RewriteDB();
3228 return nZapSelectTxRet;
3237 bool fUpdated =
false;
3241 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
3242 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
3243 m_address_book[address].SetLabel(strName);
3244 if (!strPurpose.empty())
3245 m_address_book[address].purpose = strPurpose;
3276 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
3280 m_address_book.erase(address);
3294 unsigned int count = 0;
3296 count += spk_man->KeypoolCountExternalKeys();
3306 unsigned int count = 0;
3308 count += spk_man->GetKeyPoolSize();
3318 res &= spk_man->TopUp(kpSize);
3327 bool result =
false;
3331 result = spk_man->GetNewDestination(type, dest,
error);
3349 error =
_(
"Error: Keypool ran out, please call keypoolrefill first").
translated;
3360 int64_t oldestKey = std::numeric_limits<int64_t>::max();
3362 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
3368 for (
auto& entry : mapWallet) {
3371 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
3383 std::map<CTxDestination, CAmount> balances;
3387 std::set<uint256> trusted_parents;
3388 for (
const auto& walletEntry : mapWallet)
3390 const CWalletTx& wtx = walletEntry.second;
3402 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++)
3411 balances[addr] += n;
3422 std::set< std::set<CTxDestination> > groupings;
3423 std::set<CTxDestination> grouping;
3425 for (
const auto& walletEntry : mapWallet)
3427 const CWalletTx& wtx = walletEntry.second;
3429 if (wtx.
tx->vin.size() > 0)
3431 bool any_mine =
false;
3433 for (
const CTxIn& txin : wtx.
tx->vin)
3440 grouping.insert(address);
3447 for (
const CTxOut& txout : wtx.
tx->vout)
3453 grouping.insert(txoutAddr);
3456 if (grouping.size() > 0)
3458 groupings.insert(grouping);
3464 for (
const auto& txout : wtx.
tx->vout)
3470 grouping.insert(address);
3471 groupings.insert(grouping);
3476 std::set< std::set<CTxDestination>* > uniqueGroupings;
3477 std::map< CTxDestination, std::set<CTxDestination>* > setmap;
3478 for (std::set<CTxDestination> _grouping : groupings)
3481 std::set< std::set<CTxDestination>* > hits;
3482 std::map< CTxDestination, std::set<CTxDestination>* >::iterator
it;
3484 if ((
it = setmap.find(address)) != setmap.end())
3485 hits.insert((*it).second);
3488 std::set<CTxDestination>* merged =
new std::set<CTxDestination>(_grouping);
3489 for (std::set<CTxDestination>* hit : hits)
3491 merged->insert(hit->begin(), hit->end());
3492 uniqueGroupings.erase(hit);
3495 uniqueGroupings.insert(merged);
3499 setmap[element] = merged;
3502 std::set< std::set<CTxDestination> > ret;
3503 for (
const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
3505 ret.insert(*uniqueGrouping);
3506 delete uniqueGrouping;
3515 std::set<CTxDestination> result;
3516 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
3518 if (item.second.IsChange())
continue;
3520 const std::string& strName = item.second.GetLabel();
3521 if (strName == label)
3522 result.insert(address);
3570 setLockedCoins.insert(output);
3576 setLockedCoins.erase(output);
3582 setLockedCoins.clear();
3590 return (setLockedCoins.count(outpt) > 0);
3596 for (std::set<COutPoint>::iterator
it = setLockedCoins.begin();
3597 it != setLockedCoins.end();
it++) {
3599 vOutpts.push_back(outpt);
3607 mapKeyBirth.clear();
3610 assert(spk_man !=
nullptr);
3614 for (
const auto& entry : spk_man->mapKeyMetadata) {
3615 if (entry.second.nCreateTime) {
3616 mapKeyBirth[entry.first] = entry.second.nCreateTime;
3621 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
3626 if (mapKeyBirth.count(keyid) == 0)
3627 mapKeyFirstBlock[keyid] = &max_confirm;
3631 if (mapKeyFirstBlock.empty())
3635 for (
const auto& entry : mapWallet) {
3640 for (
const CTxOut &txout : wtx.
tx->vout) {
3644 auto rit = mapKeyFirstBlock.find(keyid);
3654 for (
const auto& entry : mapKeyFirstBlock) {
3689 int64_t latestEntry = 0;
3692 int64_t latestTolerated = latestNow + 300;
3694 for (
auto it = txOrdered.rbegin();
it != txOrdered.rend(); ++
it) {
3704 if (nSmartTime <= latestTolerated) {
3705 latestEntry = nSmartTime;
3706 if (nSmartTime > latestNow) {
3707 latestNow = nSmartTime;
3713 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
3723 if (boost::get<CNoDestination>(&dest))
3726 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3732 if (!m_address_book[dest].destdata.erase(key))
3739 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3744 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
3745 if(i != m_address_book.end())
3747 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
3748 if(j != i->second.destdata.end())
3760 std::vector<std::string> values;
3761 for (
const auto& address : m_address_book) {
3762 for (
const auto& data : address.second.destdata) {
3764 values.emplace_back(data.second);
3780 fs::file_type path_type = fs::symlink_status(wallet_path).type();
3781 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
3782 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
3783 (path_type == fs::regular_file && fs::path(
name).filename() ==
name))) {
3785 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
3786 "database/log.?????????? files can be stored, a location where such a directory could be created, "
3787 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
3792 return MakeDatabase(wallet_path, options, status, error_string);
3797 const std::string& walletFile =
database->Filename();
3802 bool fFirstRun =
true;
3806 DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
3809 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
3814 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data"
3815 " or address book entries might be missing or incorrect."),
3838 walletInstance->AddWalletFlags(wallet_creation_flags);
3842 walletInstance->SetupLegacyScriptPubKeyMan();
3846 LOCK(walletInstance->cs_wallet);
3848 walletInstance->SetupDescriptorScriptPubKeyMans();
3852 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3853 if (!spk_man->SetupGeneration()) {
3854 error =
_(
"Unable to generate initial keys");
3864 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3867 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3868 if (spk_man->HavePrivateKeys()) {
3869 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3888 walletInstance->m_default_change_type = out_type;
3899 _(
"This is the minimum transaction fee you pay on every transaction."));
3901 walletInstance->m_min_fee =
CFeeRate(n);
3905 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
3907 if (max_aps_fee ==
"-1") {
3915 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3917 walletInstance->m_max_aps_fee = n;
3928 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3930 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
3933 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
3943 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3945 walletInstance->m_discard_rate =
CFeeRate(nFeePerK);
3955 _(
"This is the transaction fee you will pay if you send a transaction."));
3957 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
3959 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
3972 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
3975 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3979 walletInstance->m_default_max_tx_fee = nMaxFee;
3984 _(
"The wallet will avoid paying less than the minimum relay fee."));
3991 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
GetTimeMillis() - nStart);
3994 walletInstance->TopUpKeyPool();
3996 LOCK(walletInstance->cs_wallet);
4006 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
4008 int rescan_height = 0;
4015 rescan_height = *fork_height;
4023 walletInstance->m_last_block_processed_height = *tip_height;
4025 walletInstance->m_last_block_processed.
SetNull();
4026 walletInstance->m_last_block_processed_height = -1;
4029 if (tip_height && *tip_height != rescan_height)
4038 int block_height = *tip_height;
4039 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
4043 if (rescan_height != block_height) {
4044 error =
_(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
4050 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
4056 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
4057 int64_t time = spk_man->GetTimeFirstKey();
4058 if (!time_first_key || time < *time_first_key) time_first_key = time;
4060 if (time_first_key) {
4062 rescan_height = *first_block;
4069 error =
_(
"Failed to rescan the wallet during initialization");
4074 walletInstance->database->IncrementUpdateCounter();
4079 for (
auto& load_wallet : g_load_wallet_fns) {
4087 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
4088 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
4089 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
4092 return walletInstance;
4097 const auto& address_book_it = m_address_book.find(dest);
4098 if (address_book_it == m_address_book.end())
return nullptr;
4099 if ((!allow_change) && address_book_it->second.IsChange()) {
4102 return &address_book_it->second;
4114 if (version < prev_version)
4116 error =
_(
"Cannot downgrade wallet");
4124 error =
_(
"Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.");
4132 if (!spk_man->Upgrade(prev_version, version,
error)) {
4185 assert(chain_depth >= 0);
4195 std::vector<OutputGroup>
CWallet::GroupOutputs(
const std::vector<COutput>& outputs,
bool single_coin,
const size_t max_ancestors)
const {
4196 std::vector<OutputGroup> groups;
4197 std::map<CTxDestination, OutputGroup> gmap;
4198 std::set<CTxDestination> full_groups;
4200 for (
const auto& output : outputs) {
4201 if (output.fSpendable) {
4203 CInputCoin input_coin = output.GetInputCoin();
4205 size_t ancestors, descendants;
4207 if (!single_coin &&
ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
4208 auto it = gmap.find(dst);
4209 if (
it != gmap.end()) {
4216 groups.push_back(
it->second);
4218 full_groups.insert(dst);
4220 it->second.Insert(input_coin, output.nDepth, output.tx->IsFromMe(
ISMINE_ALL), ancestors, descendants);
4222 gmap[dst].Insert(input_coin, output.nDepth, output.tx->IsFromMe(
ISMINE_ALL), ancestors, descendants);
4225 groups.emplace_back(input_coin, output.nDepth, output.tx->IsFromMe(
ISMINE_ALL), ancestors, descendants);
4230 for (
auto&
it : gmap) {
4231 auto& group =
it.second;
4232 if (full_groups.count(
it.first) > 0) {
4234 group.m_ancestors = max_ancestors - 1;
4236 groups.push_back(group);
4253 return vMasterKey.empty();
4275 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
4279 vMasterKey = vMasterKeyIn;
4287 std::set<ScriptPubKeyMan*> spk_mans;
4288 for (
bool internal : {
false,
true}) {
4292 spk_mans.insert(spk_man);
4301 std::set<ScriptPubKeyMan*> spk_mans;
4303 spk_mans.insert(spk_man_pair.second.get());
4311 std::map<OutputType, ScriptPubKeyMan*>::const_iterator
it = spk_managers.find(type);
4312 if (
it == spk_managers.end()) {
4313 WalletLogPrintf(
"%s scriptPubKey Manager for output type %d does not exist\n",
internal ?
"Internal" :
"External",
static_cast<int>(type));
4321 std::set<ScriptPubKeyMan*> spk_mans;
4323 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4324 spk_mans.insert(spk_man_pair.second.get());
4334 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4335 return spk_man_pair.second.get();
4358 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4359 return spk_man_pair.second->GetSolvingProvider(script);
4435 for (
bool internal : {
false,
true}) {
4440 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
4442 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
4443 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
4446 spk_manager->SetupDescriptorGeneration(master_key, t);
4447 uint256 id = spk_manager->GetID();
4458 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
4465 WalletLogPrintf(
"Setting spkMan to active: id = %s, type = %d, internal = %d\n",
id.
ToString(),
static_cast<int>(type),
static_cast<int>(
internal));
4468 spk_man->SetInternal(
internal);
4469 spk_mans[type] = spk_man;
4480 return spk_man !=
nullptr;
4499 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
4512 LOCK(old_spk_man->cs_desc_man);
4513 new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache);
4517 auto old_spk_man_id = old_spk_man->GetID();
4518 for (
bool internal : {
false,
true}) {
4521 if (active_spk_man && active_spk_man->GetID() == old_spk_man_id) {
4535 for (
const auto& entry : signing_provider.
keys) {
4536 const CKey& key = entry.second;
4537 new_spk_man->AddDescriptorKey(key, key.
GetPubKey());
4541 if (!new_spk_man->TopUp()) {
4549 auto script_pub_keys = new_spk_man->GetScriptPubKeys();
4550 if (script_pub_keys.empty()) {
4551 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
4562 auto ret = new_spk_man.get();
4566 ret->WriteDescriptor();
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
static const CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
#define PACKAGE_BUGREPORT
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::vector< CTransactionRef > vtx
Optional< OutputType > m_change_type
Override the default change type if set, ignored if destChange is set.
Optional< unsigned int > m_confirm_target
Override the default confirmation target if set.
Optional< bool > m_signal_bip125_rbf
Override the wallet's m_signal_rbf if set.
bool IsSelected(const COutPoint &output) const
int m_max_depth
Maximum chain depth value for coin availability.
void Select(const COutPoint &output)
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
int m_min_depth
Minimum chain depth value for coin availability.
bool m_add_inputs
If false, only selected inputs are used.
CTxDestination destChange
Custom change destination, if not set an address is generated.
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
Optional< CFeeRate > m_feerate
Override the wallet's m_pay_tx_fee if set.
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
bool fAllowOtherInputs
If false, allows unselected inputs, but requires all selected inputs be used.
void ListSelected(std::vector< COutPoint > &vOutpoints) const
Encryption/decryption context with key information.
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Fee rate in satoshis per kilobyte: CAmount / kB.
CAmount GetFee(size_t nBytes) const
Return the fee in satoshis for the given size in bytes.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
An encapsulated private key.
unsigned int size() const
Simple read-only vector-like interface.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
const unsigned char * begin() const
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
A reference to a CKey: the Hash160 of its serialized public key.
A key from a CWallet's keypool.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
CPubKey vchPubKey
The public key.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
std::vector< unsigned char > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
std::vector< unsigned char > vchCryptedKey
unsigned int nDeriveIterations
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
Serialized script, used inside transaction inputs and outputs.
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const uint256 & GetHash() const
const std::vector< CTxIn > vin
An input of a transaction.
static const uint32_t SEQUENCE_FINAL
An output of a transaction.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
std::atomic< int64_t > m_best_block_time
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script, SignatureData &sigdata) const
Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e....
bool HaveChain() const
Interface to assert chain access.
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
bool AddDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, and saves it to disk When adding new fields,...
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
MasterKeyMap mapMasterKeys
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Look up a destination data tuple in the store, return true if found false otherwise.
std::vector< OutputGroup > GroupOutputs(const std::vector< COutput > &outputs, bool single_coin, const size_t max_ancestors) const
bool IsLegacy() const
Determine if we are a legacy wallet.
interfaces::Chain & chain() const
Interface for accessing chain state.
std::atomic< bool > fAbortRescan
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
static std::shared_ptr< CWallet > Create(interfaces::Chain &chain, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
OutputType m_default_address_type
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
boost::signals2::signal< void(CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
std::atomic< uint64_t > m_wallet_flags
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Optional< OutputType > m_default_change_type
Default output type for change outputs.
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
bool BackupWallet(const std::string &strDest) const
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
std::unique_ptr< WalletDatabase > database
Internal database handle.
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
std::multimap< int64_t, CWalletTx * > TxItems
std::vector< std::string > GetDestValues(const std::string &prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all destination values matching a prefix.
bool IsLocked() const override
bool m_allow_fallback_fee
will be false if -fallbackfee=0
std::atomic< double > m_scanning_progress
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EraseDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases a destination data tuple in the store and on disk.
bool HasEncryptionKeys() const override
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool m_spend_zero_conf_change
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
bool fBroadcastTransactions
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
CAmount m_max_aps_fee
note: this is absolute fee, not fee rate
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
unsigned int nMasterKeyMaxID
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CKeyingMaterial & GetEncryptionKey() const override
A transaction with a bunch of additional info that only the owner cares about.
mapValue_t mapValue
Key/value map with information about the transaction.
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
bool isUnconfirmed() const
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
bool IsFromMe(const isminefilter &filter) const
void SetTx(CTransactionRef arg)
int GetBlocksToMaturity() const
bool IsInMainChain() const
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool isConflicted() const
const CWallet *const pwallet
std::vector< std::pair< std::string, std::string > > vOrderForm
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
bool IsImmatureCoinBase() const
const uint256 & GetHash() const
unsigned int fTimeReceivedIsTxTime
CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]
void MarkDirty()
make sure balances are recalculated
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
unsigned int nTimeReceived
time received by this node
int64_t nOrderPos
position in ordered transaction list
int GetSpendSize(unsigned int out, bool use_max_sig=false) const
bool HasWalletDescriptor(const WalletDescriptor &desc) const
RecursiveMutex cs_KeyStore
std::set< CKeyID > GetKeys() const override
A wrapper to reserve an address from a wallet.
bool fInternal
Whether this is from the internal (change output) keypool.
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called.
int64_t nIndex
The index of the address's key in the keypool.
CTxDestination address
The destination.
const CWallet *const pwallet
The wallet to reserve from.
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool)
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
const std::vector< UniValue > & getValues() const
bool push_back(const UniValue &val)
Access to the wallet database.
bool TxnCommit()
Commit current transaction.
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteName(const std::string &strAddress, const std::string &strName)
bool WriteMinVersion(int nVersion)
bool ErasePurpose(const std::string &strAddress)
bool WriteWalletFlags(const uint64_t flags)
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
bool ReadBestBlock(CBlockLocator &locator)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool WriteTx(const CWalletTx &wtx)
bool TxnBegin()
Begin a new transaction.
bool TxnAbort()
Abort current transaction.
bool WriteBestBlock(const CBlockLocator &locator)
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
bool EraseName(const std::string &strAddress)
DBErrors LoadWallet(CWallet *pwallet)
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
std::string ToString() const
std::string GetHex() const
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
virtual bool isInitialBlockDownload()=0
Check if in IBD.
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual bool havePruned()=0
Check if any block has been pruned.
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value)=0
Write a setting to <datadir>/settings.json.
virtual int64_t getAdjustedTime()=0
Get adjusted time.
virtual bool findNextBlock(const uint256 &block_hash, int block_height, const FoundBlock &next={}, bool *reorg=nullptr)=0
Find next block if block is part of current chain.
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.
virtual void getTransactionAncestry(const uint256 &txid, size_t &ancestors, size_t &descendants)=0
Calculate mempool ancestor and descendant counts for the given transaction.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual Optional< int > getBlockHeight(const uint256 &hash)=0
Get block height above genesis block.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual 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...
virtual void initMessage(const std::string &message)=0
Send init message.
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...
virtual void getPackageLimits(unsigned int &limit_ancestor_count, unsigned int &limit_descendant_count)=0
Get the node's package limits.
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual void requestMempoolTransactions(Notifications ¬ifications)=0
Synchronously send transactionAddedToMempool notifications about all current mempool transactions to ...
virtual bool checkFinalTx(const CTransaction &tx)=0
Check if transaction will be final given chain height current time.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
virtual Optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual Optional< int > findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256 *hash)=0
Return height of the first block in the chain with timestamp equal or greater than the given time and...
Helper for findBlock to selectively return pieces of block data.
const int DEFAULT_MAX_DEPTH
const int DEFAULT_MIN_DEPTH
bool KnapsackSolver(const CAmount &nTargetValue, std::vector< OutputGroup > &groups, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet)
bool SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const CAmount &target_value, const CAmount &cost_of_change, std::set< CInputCoin > &out_set, CAmount &value_ret, CAmount not_input_fees)
static const CAmount MIN_FINAL_CHANGE
final minimum change amount after paying for fees
static std::vector< COutput > vCoins
CoinSelectionParams coin_selection_params(false, 0, 0, CFeeRate(0), 0)
static int64_t GetTransactionWeight(const CTransaction &tx)
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
const unsigned int WALLET_CRYPTO_SALT_SIZE
const unsigned int WALLET_CRYPTO_KEY_SIZE
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
bilingual_str TransactionErrorString(const TransactionError err)
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
@ SAT_VB
Use sat/vB fee rate unit.
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SelectCoins(const std::vector< COutput > &vAvailableCoins, const CAmount &nTargetValue, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet, const CCoinControl &coin_control, CoinSelectionParams &coin_selection_params, bool &bnb_used) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Select a set of coins such that nValueRet >= nTargetValue and at least all coins from coinControl are...
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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 ...
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::map< CTxDestination, CAmount > GetAddressBalances() const
static bool IsCurrentForAntiFeeSniping(interfaces::Chain &chain, const uint256 &block_hash)
std::map< CTxDestination, std::vector< COutput > > ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return list of available coins and locked coins grouped by non-change output address.
void KeepDestination()
Keep the address. Do not return it's key to the keypool when this object goes out of scope.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static uint32_t GetLocktimeForNewTransaction(interfaces::Chain &chain, const uint256 &block_hash, int block_height)
Return a height-based locktime for new transactions (uses the height of the current chain tip unless ...
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CTxOut & FindNonChangeParentOutput(const CTransaction &tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Find non-change parent output.
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
bool CreateTransactionInternal(const std::vector< CRecipient > &vecSend, CTransactionRef &tx, CAmount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, FeeCalculation &fee_calc_out, bool sign)
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
bool SelectCoinsMinConf(const CAmount &nTargetValue, const CoinEligibilityFilter &eligibility_filter, std::vector< OutputGroup > groups, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet, const CoinSelectionParams &coin_selection_params, bool &bnb_used) const
Shuffle and select coins until nTargetValue is reached while avoiding small change; This method is st...
DBErrors LoadWallet(bool &fFirstRunRet)
Balance GetBalance(int min_depth=0, bool avoid_reuse=true) const
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ReturnDestination()
Return reserved address.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, int sighash_type=1, bool sign=true, bool bip32derivs=true, size_t *n_signed=nullptr) const
Fills out a PSBT with information from the wallet.
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
bool TopUpKeyPool(unsigned int kpSize=0)
void AvailableCoins(std::vector< COutput > &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl=nullptr, const CAmount &nMinimumAmount=1, const CAmount &nMaximumAmount=MAX_MONEY, const CAmount &nMinimumSumAmount=MAX_MONEY, const uint64_t nMaximumCount=0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
populate vCoins with vector of available COutputs.
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &tx, CAmount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, FeeCalculation &fee_calc_out, bool sign=true)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
bool GetReservedDestination(CTxDestination &pubkey, bool internal)
Reserve an address.
int64_t GetOldestKeyPoolTime() const
bool DelAddressBook(const CTxDestination &address)
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, std::string &error)
bool FundTransaction(CMutableTransaction &tx, CAmount &nFeeRet, int &nChangePosInOut, bilingual_str &error, bool lockUnspents, const std::set< int > &setSubtractFeeFromOutputs, CCoinControl)
Insert additional inputs into the transaction by calling CreateTransaction();.
CAmount GetAvailableBalance(const CCoinControl *coinControl=nullptr) const
OutputType TransactionChangeType(const Optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend)
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
std::set< std::set< CTxDestination > > GetAddressGroupings() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const
int CalculateMaximumSignedInputSize(const CTxOut &txout, const CWallet *wallet, bool use_max_sig)
bool AddWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t returns false if unknown, non-tolerable flags are present
bool IsTrusted(const CWalletTx &wtx, std::set< uint256 > &trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockConnected(const CBlock &block, int height) override
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
void Flush()
Flush wallet (bitdb flush)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
CAmount GetCredit(const isminefilter &filter) const
bool HasWalletSpend(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet.
CAmount GetImmatureCredit(bool fUseCache=true) const
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, Optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate)
Scan the block chain (starting in start_block) for transactions from or to us.
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction (e.g., BIP 125).
CAmount GetChange(const CTxOut &txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo >> &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
void BlockUntilSyncedToCurrentChain() const EXCLUSIVE_LOCKS_REQUIRED(! void SetWalletFlag(uint64_t flags)
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
bool IsAllFromMe(const CTransaction &tx, const isminefilter &filter) const
Returns whether all of the inputs match the filter.
bool IsEquivalentTo(const CWalletTx &tx) const
CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter &filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
CAmount GetChange() const
CAmount GetCachableAmount(AmountType type, const isminefilter &filter, bool recalculate=false) const
bool IsSpent(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
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 CanGetAddresses(bool internal=false) const
bool SubmitMemoryPoolAndRelay(std::string &err_string, bool relay)
bool IsChange(const CTxOut &txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool AbandonTransaction(const uint256 &hashTx)
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
CAmount GetCredit(const CTxOut &txout, const isminefilter &filter) const
void GetAmounts(std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, const isminefilter &filter) const
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EncryptWallet(const SecureString &strWalletPassphrase)
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t GetTxTime() const
void updatedBlockTip() override
std::set< uint256 > GetConflicts() const NO_THREAD_SAFETY_ANALYSIS
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
std::string ToString() const
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
DBErrors ReorderTransactions()
bool IsSpentKey(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockDisconnected(const CBlock &block, int height) override
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
void Close()
Close wallet database.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
void ResendWalletTransactions()
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
void chainStateFlushed(const CBlockLocator &loc) override
isminetype
IsMine() return codes.
std::string EncodeDestination(const CTxDestination &dest)
@ PRIVATE_KEY_NOT_AVAILABLE
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
bool ParseMoney(const std::string &money_string, CAmount &nRet)
Parse an amount denoted in full coins.
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
Return implementation of Wallet interface.
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
const std::chrono::seconds now
std::deque< CInv >::iterator it
Optional< T > MakeOptional(bool condition, T &&value)
Substitute for C++17 std::make_optional.
static auto & nullopt
Substitute for C++17 std::nullopt.
boost::optional< T > Optional
Substitute for C++17 std::optional.
const std::string & FormatOutputType(OutputType type)
bool ParseOutputType(const std::string &type, OutputType &output_type)
const std::array< OutputType, 3 > OUTPUT_TYPES
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
static const unsigned int MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
static CTransactionRef MakeTransactionRef()
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
void GetStrongRandBytes(unsigned char *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
int GetRandInt(int nMax) noexcept
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
static const unsigned int LOCKTIME_THRESHOLD
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
size_t GetSerializeSize(const T &t, int nVersion=0)
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
void UpdateInput(CTxIn &input, const SignatureData &data)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
void SetSeed(const unsigned char *seed, unsigned int nSeedLen)
A mutable version of CTransaction.
std::vector< CTxOut > vout
CAmount m_mine_trusted
Trusted, at depth=GetBalance.min_depth or more.
CAmount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
CAmount m_mine_immature
Immature coinbases in the main chain.
CAmount m_watchonly_trusted
CAmount m_watchonly_untrusted_pending
CAmount m_watchonly_immature
Optional< int > last_scanned_height
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
enum CWallet::ScanResult::@15 status
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
void Set(isminefilter filter, CAmount value)
CAmount m_value[ISMINE_ENUM_ELEMENTS]
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
size_t change_output_size
Optional< DatabaseFormat > require_format
SecureString create_passphrase
std::map< CKeyID, CKey > keys
OutputGroup GetPositiveOnlyGroup()
A version of CTransaction with the PSBT format.
Optional< CMutableTransaction > tx
std::vector< PSBTInput > inputs
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::string ShellEscape(const std::string &arg)
bool error(const char *fmt, const Args &... args)
int64_t GetTimeMillis()
Returns the system time (not mockable)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
bilingual_str _(const char *psz)
Translation function.
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.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
std::string StringForFeeReason(FeeReason reason)
static const uint32_t MAX_BIP125_RBF_SEQUENCE
AssertLockHeld(mempool.cs)
static const int PROTOCOL_VERSION
network protocol versioning
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
CFeeRate GetDiscardRate(const CWallet &wallet)
Return the maximum feerate for discarding change.
CAmount GetMinimumFee(const CWallet &wallet, unsigned int nTxBytes, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee considering user set parameters and the required fee.
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
static void ReleaseWallet(CWallet *wallet)
static Mutex g_wallet_release_mutex
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, Optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
static std::vector< std::shared_ptr< CWallet > > vpwallets GUARDED_BY(cs_wallets)
std::shared_ptr< CWallet > GetWallet(const std::string &name)
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
static std::condition_variable g_wallet_release_cv
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
std::shared_ptr< CWallet > CreateWallet(interfaces::Chain &chain, const std::string &name, Optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
static RecursiveMutex cs_wallets
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
static const size_t OUTPUT_GROUP_MAX_ENTRIES
std::vector< std::shared_ptr< CWallet > > GetWallets()
static Mutex g_loading_wallet_mutex
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, Optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
std::shared_ptr< CWallet > LoadWallet(interfaces::Chain &chain, const std::string &name, Optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
static constexpr uint64_t KNOWN_WALLET_FLAGS
static const bool DEFAULT_WALLETBROADCAST
std::map< std::string, std::string > mapValue_t
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
static const bool DEFAULT_WALLET_RBF
-walletrbf default
DBErrors
Error statuses for the wallet database.
fs::path GetWalletDir()
Get the path of the wallet directory.
WalletFeature GetClosestWalletFeature(int version)
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_KEY_ORIGIN_METADATA
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
WalletFeature
(client) version numbers for particular wallet features
@ FEATURE_PRE_SPLIT_KEYPOOL