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." 56 static std::vector<std::shared_ptr<CWallet>> vpwallets
GUARDED_BY(cs_wallets);
57 static std::list<LoadWalletFn> g_load_wallet_fns
GUARDED_BY(cs_wallets);
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."));
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) {
151 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
158 static std::set<std::string> g_loading_wallet_set
GUARDED_BY(g_loading_wallet_mutex);
159 static std::set<std::string> g_unloading_wallet_set
GUARDED_BY(g_wallet_release_mutex);
170 LOCK(g_wallet_release_mutex);
171 if (g_unloading_wallet_set.erase(name) == 0) {
184 LOCK(g_wallet_release_mutex);
185 auto it = g_unloading_wallet_set.insert(name);
197 while (g_unloading_wallet_set.count(name) == 1) {
207 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(name, options, status, error);
220 wallet->postInitProcess();
226 }
catch (
const std::runtime_error& e) {
236 auto result =
WITH_LOCK(g_loading_wallet_mutex,
return g_loading_wallet_set.insert(name));
237 if (!result.second) {
242 auto wallet = LoadWalletInternal(chain, name, load_on_start, options, status, error, warnings);
243 WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
258 if (!passphrase.empty()) {
263 std::unique_ptr<WalletDatabase> database =
MakeWalletDatabase(name, options, status, error);
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)) {
288 error =
Untranslated(
"Error: Wallet created but failed to encrypt.");
294 if (!wallet->Unlock(passphrase)) {
295 error =
Untranslated(
"Error: Wallet was encrypted but could not be unlocked");
302 LOCK(wallet->cs_wallet);
303 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
304 wallet->SetupDescriptorScriptPubKeyMans();
306 for (
auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
307 if (!spk_man->SetupGeneration()) {
308 error =
Untranslated(
"Unable to generate initial keys");
321 wallet->postInitProcess();
343 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(hash);
344 if (it == mapWallet.end())
346 return &(it->second);
355 auto spk_man = GetLegacyScriptPubKeyMan();
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)) {
379 UpgradeKeyMetadata();
389 bool fWasLocked = IsLocked();
397 for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
399 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
401 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
403 if (Unlock(_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);
487 GetDatabase().Flush();
492 GetDatabase().Close();
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);
574 if (thisTx.IsCoinBase())
577 for (
const CTxIn& txin : thisTx.tx->vin)
578 AddToSpends(txin.
prevout, wtxid);
608 WalletLogPrintf(
"Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.
nDeriveIterations);
617 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
620 delete encrypted_batch;
621 encrypted_batch =
nullptr;
626 for (
const auto& spk_man_pair : m_spk_managers) {
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);
657 SetupDescriptorScriptPubKeyMans();
658 }
else if (
auto spk_man = GetLegacyScriptPubKeyMan()) {
660 if (spk_man->IsHDEnabled()) {
661 if (!spk_man->SetupGeneration(
true)) {
670 GetDatabase().Rewrite();
675 GetDatabase().ReloadDbEnv();
678 NotifyStatusChanged(
this);
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);
775 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
781 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
793 const CWalletTx* srctx = GetWalletTx(hash);
799 if (used && !GetDestData(dst,
"used",
nullptr)) {
800 if (AddDestData(batch, dst,
"used",
"p")) {
801 tx_destinations.insert(dst);
803 }
else if (!used && GetDestData(dst,
"used",
nullptr)) {
804 EraseDestData(batch, dst,
"used");
813 const CWalletTx* srctx = GetWalletTx(hash);
820 if (GetDestData(dest,
"used",
nullptr)) {
825 assert(spk_man !=
nullptr);
826 for (
const auto& keyid :
GetAffectedKeys(srctx->
tx->vout[n].scriptPubKey, *spk_man)) {
828 if (GetDestData(wpkh_dest,
"used",
nullptr)) {
832 if (GetDestData(sh_wpkh_dest,
"used",
nullptr)) {
836 if (GetDestData(pkh_dest,
"used",
nullptr)) {
855 std::set<CTxDestination> tx_destinations;
857 for (
const CTxIn& txin : tx->vin) {
859 SetSpentKeyState(batch, op.
hash, op.
n,
true, tx_destinations);
862 MarkDestinationsDirty(tx_destinations);
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());
930 boost::replace_all(strCmd,
"%w",
ShellEscape(GetName()));
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)) {
972 for (
const CTxIn& txin : wtx.
tx->vin) {
974 if (
it != mapWallet.end()) {
992 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
993 while (range.first != range.second) {
994 if (range.first->second != tx.
GetHash()) {
995 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);
1003 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1004 if (fExisted && !fUpdate)
return false;
1005 if (fExisted || IsMine(tx) || IsFromMe(tx))
1015 for (
const auto& spk_man_pair : m_spk_managers) {
1016 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1031 const CWalletTx* wtx = GetWalletTx(hashTx);
1037 for (
const CTxIn& txin : tx->vin) {
1039 if (
it != mapWallet.end()) {
1040 it->second.MarkDirty();
1051 std::set<uint256> todo;
1052 std::set<uint256> done;
1055 auto it = mapWallet.find(hashTx);
1058 if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1062 todo.insert(hashTx);
1064 while (!todo.empty()) {
1068 auto it = mapWallet.find(now);
1071 int currentconfirm = wtx.GetDepthInMainChain();
1073 assert(currentconfirm <= 0);
1075 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1077 assert(!wtx.InMempool());
1083 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1084 while (iter != mapTxSpends.end() && iter->first.hash ==
now) {
1085 if (!done.count(iter->second)) {
1086 todo.insert(iter->second);
1092 MarkInputsDirty(wtx.tx);
1103 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1108 if (conflictconfirms >= 0)
1114 std::set<uint256> todo;
1115 std::set<uint256> done;
1117 todo.insert(hashTx);
1119 while (!todo.empty()) {
1123 auto it = mapWallet.find(now);
1126 int currentconfirm = wtx.GetDepthInMainChain();
1127 if (conflictconfirms < currentconfirm) {
1130 wtx.m_confirm.nIndex = 0;
1131 wtx.m_confirm.hashBlock = hashBlock;
1132 wtx.m_confirm.block_height = conflicting_height;
1133 wtx.setConflicted();
1137 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1138 while (iter != mapTxSpends.end() && iter->first.hash ==
now) {
1139 if (!done.count(iter->second)) {
1140 todo.insert(iter->second);
1146 MarkInputsDirty(wtx.tx);
1153 if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
1159 MarkInputsDirty(ptx);
1164 SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, 0, {}, 0});
1166 auto it = mapWallet.find(tx->GetHash());
1167 if (it != mapWallet.end()) {
1168 it->second.fInMempool =
true;
1174 auto it = mapWallet.find(tx->GetHash());
1175 if (
it != mapWallet.end()) {
1176 it->second.fInMempool =
false;
1205 SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, 0, {}, 0});
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;
1233 SyncTransaction(ptx, {CWalletTx::Status::UNCONFIRMED, 0, {}, 0});
1239 m_best_block_time =
GetTime();
1243 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1249 uint256 last_block_hash =
WITH_LOCK(cs_wallet,
return m_last_block_processed);
1250 chain().waitForNotificationsIfTipChanged(last_block_hash);
1257 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1258 if (mi != mapWallet.end())
1262 return IsMine(prev.
tx->vout[txin.
prevout.
n]);
1273 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1274 if (mi != mapWallet.end())
1278 if (IsMine(prev.
tx->vout[txin.
prevout.
n]) & filter)
1301 for (
const auto& spk_man_pair : m_spk_managers) {
1302 result = std::max(result, spk_man_pair.second->IsMine(script));
1310 throw std::runtime_error(std::string(__func__) +
": value out of range");
1312 return ((IsMine(txout) & filter) ? txout.
nValue : 0);
1335 if (!FindAddressBookEntry(address)) {
1346 throw std::runtime_error(std::string(__func__) +
": value out of range");
1347 return (IsChange(txout) ? txout.
nValue : 0);
1369 nDebit += GetDebit(txin, filter);
1371 throw std::runtime_error(std::string(__func__) +
": value out of range");
1383 if (mi == mapWallet.end())
1391 if (!(IsMine(prev.
tx->vout[txin.
prevout.
n]) & filter))
1402 nCredit += GetCredit(txout, filter);
1404 throw std::runtime_error(std::string(__func__) +
": value out of range");
1415 nChange += GetChange(txout);
1417 throw std::runtime_error(std::string(__func__) +
": value out of range");
1426 for (
const auto& spk_man : GetActiveScriptPubKeyMans()) {
1427 result &= spk_man->IsHDEnabled();
1435 if (m_spk_managers.empty())
return false;
1437 auto spk_man = GetScriptPubKeyMan(t,
internal);
1438 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1448 m_wallet_flags |=
flags;
1449 if (!
WalletBatch(GetDatabase()).WriteWalletFlags(m_wallet_flags))
1450 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1456 UnsetWalletFlagWithDB(batch, flag);
1462 m_wallet_flags &= ~flag;
1464 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1474 return (m_wallet_flags & flag);
1484 m_wallet_flags =
flags;
1494 if (!
WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1495 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1498 return LoadWalletFlags(flags);
1503 int64_t n = nTimeSmart;
1504 return n ? n : nTimeReceived;
1515 std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
1533 for (
const auto& txout : txouts)
1535 if (!DummySignInput(txNew.
vin[nIn], txout, use_max_sig)) {
1546 auto spk_man = GetLegacyScriptPubKeyMan();
1550 LOCK(spk_man->cs_KeyStore);
1551 return spk_man->ImportScripts(scripts, timestamp);
1556 auto spk_man = GetLegacyScriptPubKeyMan();
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)
1566 auto spk_man = GetLegacyScriptPubKeyMan();
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)
1576 auto spk_man = GetLegacyScriptPubKeyMan();
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) {
1590 SetAddressBookWithDB(batch, dest, label,
"receive");
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()) {
1607 txouts.emplace_back(mi->second.tx->vout[input.
prevout.
n]);
1616 if (!wallet->
DummySignTx(txNew, txouts, use_max_sig)) {
1636 listReceived.clear();
1640 CAmount nDebit = GetDebit(filter);
1644 nFee = nDebit - nValueOut;
1647 LOCK(pwallet->cs_wallet);
1649 for (
unsigned int i = 0;
i <
tx->vout.size(); ++
i)
1659 if (pwallet->IsChange(txout))
1662 else if (!(fIsMine & filter))
1670 pwallet->WalletLogPrintf(
"CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
1679 listSent.push_back(output);
1682 if (fIsMine & filter)
1683 listReceived.push_back(output);
1701 int start_height = 0;
1703 bool start = chain().findFirstBlockWithTimeAndHeight(startTime -
TIMESTAMP_WINDOW, 0,
FoundBlock().hash(start_block).height(start_height));
1704 WalletLogPrintf(
"%s: Rescanning last %i blocks\n", __func__, start ?
WITH_LOCK(cs_wallet,
return GetLastBlockHeight()) - start_height + 1 : 0);
1708 ScanResult result = ScanForWalletTransactions(start_block, start_height, {} , reserver, update);
1709 if (result.
status == ScanResult::FAILURE) {
1746 uint256 block_hash = start_block;
1749 WalletLogPrintf(
"Rescan started from block %s...\n", start_block.
ToString());
1751 fAbortRescan =
false;
1755 if (max_height) chain().findAncestorByHeight(tip_hash, *max_height,
FoundBlock().hash(end_hash));
1756 double progress_begin = chain().guessVerificationProgress(block_hash);
1757 double progress_end = chain().guessVerificationProgress(end_hash);
1758 double progress_current = progress_begin;
1759 int block_height = start_height;
1760 while (!fAbortRescan && !chain().shutdownRequested()) {
1761 if (progress_end - progress_begin > 0.0) {
1762 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1764 m_scanning_progress = 0;
1766 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1767 ShowProgress(
strprintf(
"%s " +
_(
"Rescanning...").translated, GetDisplayName()), std::max(1, std::min(99, (
int)(m_scanning_progress * 100))));
1771 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1776 chain().findBlock(block_hash,
FoundBlock().data(block));
1780 bool block_still_active =
false;
1781 bool next_block =
false;
1783 chain().findBlock(block_hash,
FoundBlock().inActiveChain(block_still_active).nextBlock(
FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1787 if (!block_still_active) {
1791 result.
status = ScanResult::FAILURE;
1794 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1795 SyncTransaction(block.
vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1803 result.
status = ScanResult::FAILURE;
1805 if (max_height && block_height >= *max_height) {
1816 block_hash = next_block_hash;
1818 progress_current = chain().guessVerificationProgress(block_hash);
1821 const uint256 prev_tip_hash = tip_hash;
1822 tip_hash =
WITH_LOCK(cs_wallet,
return GetLastBlockHash());
1823 if (!max_height && prev_tip_hash != tip_hash) {
1825 progress_end = chain().guessVerificationProgress(tip_hash);
1830 if (block_height && fAbortRescan) {
1831 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1832 result.
status = ScanResult::USER_ABORT;
1833 }
else if (block_height && chain().shutdownRequested()) {
1834 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1835 result.
status = ScanResult::USER_ABORT;
1837 WalletLogPrintf(
"Rescan completed in %15dms\n",
GetTimeMillis() - start_time);
1845 if (!fBroadcastTransactions)
1847 std::map<int64_t, CWalletTx*> mapSorted;
1850 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1851 const uint256& wtxid = item.first;
1858 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1863 for (
const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1865 std::string unused_err_string;
1873 if (!pwallet->GetBroadcastTransactions())
return false;
1875 if (isAbandoned())
return false;
1878 if (IsCoinBase())
return false;
1880 if (GetDepthInMainChain() != 0)
return false;
1883 pwallet->WalletLogPrintf(
"Submitting wtx %s to mempool for relay\n", GetHash().
ToString());
1893 bool ret = pwallet->chain().broadcastTransaction(
tx, pwallet->m_default_max_tx_fee, relay, err_string);
1900 std::set<uint256> result;
1901 if (pwallet !=
nullptr)
1904 result = pwallet->GetConflicts(myHash);
1905 result.erase(myHash);
1912 auto& amount = m_amounts[type];
1913 if (recalculate || !amount.m_cached[filter]) {
1914 amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*
tx, filter) : pwallet->GetCredit(*
tx, filter));
1915 m_is_cache_empty =
false;
1917 return amount.m_value[filter];
1922 if (
tx->vin.empty())
1927 debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
1930 debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
1938 if (IsImmatureCoinBase())
1944 credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE);
1947 credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY);
1954 if (IsImmatureCoinBase() && IsInMainChain()) {
1963 if (pwallet ==
nullptr)
1970 if (IsImmatureCoinBase())
1973 if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
1974 return m_amounts[AVAILABLE_CREDIT].m_value[filter];
1980 for (
unsigned int i = 0;
i <
tx->vout.size();
i++)
1982 if (!pwallet->IsSpent(hashTx,
i) && (allow_used_addresses || !pwallet->IsSpentKey(hashTx,
i))) {
1984 nCredit += pwallet->
GetCredit(txout, filter);
1986 throw std::runtime_error(std::string(__func__) +
" : value out of range");
1991 m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
1992 m_is_cache_empty =
false;
2000 if (IsImmatureCoinBase() && IsInMainChain()) {
2010 return nChangeCached;
2011 nChangeCached = pwallet->GetChange(*
tx);
2012 fChangeCached =
true;
2013 return nChangeCached;
2023 std::set<uint256> trusted_parents;
2024 LOCK(pwallet->cs_wallet);
2025 return pwallet->IsTrusted(*
this, trusted_parents);
2032 if (!chain().checkFinalTx(*wtx.
tx))
return false;
2034 if (nDepth >= 1)
return true;
2035 if (nDepth < 0)
return false;
2043 for (
const CTxIn& txin : wtx.
tx->vin)
2047 if (parent ==
nullptr)
return false;
2052 if (trusted_parents.count(parent->
GetHash()))
continue;
2054 if (!IsTrusted(*parent, trusted_parents))
return false;
2055 trusted_parents.insert(parent->
GetHash());
2064 for (
auto& txin : tx1.vin) txin.scriptSig =
CScript();
2065 for (
auto& txin : tx2.vin) txin.scriptSig =
CScript();
2082 if (!chain().isReadyToBroadcast())
return;
2086 if (
GetTime() < nNextResend || !fBroadcastTransactions)
return;
2087 bool fFirst = (nNextResend == 0);
2089 nNextResend =
GetTime() + (12 * 60 * 60) +
GetRand(24 * 60 * 60);
2092 int submitted_tx_count = 0;
2098 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
2103 if (wtx.
nTimeReceived > m_best_block_time - 5 * 60)
continue;
2104 std::string unused_err_string;
2109 if (submitted_tx_count > 0) {
2110 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2118 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
2119 pwallet->ResendWalletTransactions();
2136 std::set<uint256> trusted_parents;
2137 for (
const auto& entry : mapWallet)
2140 const bool is_trusted{IsTrusted(wtx, trusted_parents)};
2144 if (is_trusted && tx_depth >= min_depth) {
2148 if (!is_trusted && tx_depth == 0 && wtx.
InMempool()) {
2164 std::vector<COutput>
vCoins;
2165 AvailableCoins(vCoins,
true, coinControl);
2166 for (
const COutput& out : vCoins) {
2167 if (out.fSpendable) {
2168 balance += out.tx->tx->vout[out.i].nValue;
2186 std::set<uint256> trusted_parents;
2187 for (
const auto& entry : mapWallet)
2189 const uint256& wtxid = entry.first;
2192 if (!chain().checkFinalTx(*wtx.
tx)) {
2208 bool safeTx = IsTrusted(wtx, trusted_parents);
2225 if (nDepth == 0 && wtx.
mapValue.count(
"replaces_txid")) {
2237 if (nDepth == 0 && wtx.
mapValue.count(
"replaced_by_txid")) {
2241 if (fOnlySafe && !safeTx) {
2245 if (nDepth < min_depth || nDepth > max_depth) {
2249 for (
unsigned int i = 0;
i < wtx.
tx->vout.size();
i++) {
2255 if (wtx.
tx->vout[
i].nValue < nMinimumAmount || wtx.
tx->vout[
i].nValue > nMaximumAmount)
2261 if (IsLockedCoin(entry.first,
i))
2264 if (IsSpent(wtxid,
i))
2273 if (!allow_used_addresses && IsSpentKey(wtxid,
i)) {
2277 std::unique_ptr<SigningProvider> provider = GetSolvingProvider(wtx.
tx->vout[
i].scriptPubKey);
2279 bool solvable = provider ?
IsSolvable(*provider, wtx.
tx->vout[
i].scriptPubKey) :
false;
2282 vCoins.push_back(
COutput(&wtx,
i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->
fAllowWatchOnly)));
2286 nTotal += wtx.
tx->vout[
i].nValue;
2288 if (nTotal >= nMinimumSumAmount) {
2294 if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
2305 std::map<CTxDestination, std::vector<COutput>> result;
2306 std::vector<COutput> availableCoins;
2308 AvailableCoins(availableCoins);
2310 for (
const COutput& coin : availableCoins) {
2313 ExtractDestination(FindNonChangeParentOutput(*coin.tx->tx, coin.i).scriptPubKey, address)) {
2314 result[address].emplace_back(std::move(coin));
2318 std::vector<COutPoint> lockedCoins;
2319 ListLockedCoins(lockedCoins);
2323 for (
const COutPoint& output : lockedCoins) {
2324 auto it = mapWallet.find(output.hash);
2325 if (
it != mapWallet.end()) {
2326 int depth =
it->second.GetDepthInMainChain();
2327 if (depth >= 0 && output.n <
it->second.tx->vout.size() &&
2328 IsMine(
it->second.tx->vout[output.n]) == is_mine_filter
2331 if (
ExtractDestination(FindNonChangeParentOutput(*
it->second.tx, output.n).scriptPubKey, address)) {
2332 result[address].emplace_back(
2333 &
it->second, output.n, depth,
true ,
true ,
false );
2347 while (IsChange(ptx->
vout[n]) && ptx->
vin.size() > 0) {
2349 auto it = mapWallet.find(prevout.
hash);
2350 if (
it == mapWallet.end() ||
it->second.tx->vout.size() <= prevout.
n ||
2351 !IsMine(
it->second.tx->vout[prevout.
n])) {
2354 ptx =
it->second.tx.get();
2357 return ptx->
vout[n];
2363 setCoinsRet.clear();
2366 std::vector<OutputGroup> utxo_pool;
2367 if (coin_selection_params.
use_bnb) {
2379 if (!group.EligibleForSpending(eligibility_filter))
continue;
2383 group.SetFees(
CFeeRate(0) , long_term_feerate);
2385 group.SetFees(coin_selection_params.
effective_fee, long_term_feerate);
2394 return SelectCoinsBnB(utxo_pool, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
2398 if (!group.EligibleForSpending(eligibility_filter))
continue;
2399 utxo_pool.push_back(group);
2402 return KnapsackSolver(nTargetValue, utxo_pool, setCoinsRet, nValueRet);
2408 std::vector<COutput>
vCoins(vAvailableCoins);
2409 CAmount value_to_select = nTargetValue;
2417 for (
const COutput& out : vCoins)
2419 if (!out.fSpendable)
2421 nValueRet += out.tx->tx->vout[out.i].nValue;
2422 setCoinsRet.insert(out.GetInputCoin());
2424 return (nValueRet >= nTargetValue);
2428 std::set<CInputCoin> setPresetCoins;
2429 CAmount nValueFromPresetInputs = 0;
2431 std::vector<COutPoint> vPresetInputs;
2433 for (
const COutPoint& outpoint : vPresetInputs)
2435 std::map<uint256, CWalletTx>::const_iterator
it = mapWallet.find(outpoint.hash);
2436 if (it != mapWallet.end())
2440 if (wtx.
tx->vout.size() <= outpoint.n) {
2446 if (coin.m_input_bytes <= 0) {
2449 coin.effective_value = coin.txout.nValue - coin_selection_params.
effective_fee.
GetFee(coin.m_input_bytes);
2450 if (coin_selection_params.
use_bnb) {
2451 value_to_select -= coin.effective_value;
2453 value_to_select -= coin.txout.nValue;
2455 setPresetCoins.insert(coin);
2462 for (std::vector<COutput>::iterator
it = vCoins.begin();
it != vCoins.end() && coin_control.
HasSelected();)
2464 if (setPresetCoins.count(
it->GetInputCoin()))
2465 it = vCoins.erase(
it);
2470 unsigned int limit_ancestor_count = 0;
2471 unsigned int limit_descendant_count = 0;
2472 chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
2473 size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2474 size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2485 std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.
m_avoid_partial_spends, max_ancestors);
2487 bool res = value_to_select <= 0 ||
2488 SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(1, 6, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2489 SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(1, 1, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2490 (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, 2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2491 (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)) ||
2492 (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2493 (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2494 (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(value_to_select,
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
2500 nValueRet += nValueFromPresetInputs;
2510 std::map<COutPoint, Coin> coins;
2511 for (
auto& input : tx.
vin) {
2512 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
2513 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2519 std::map<int, std::string> input_errors;
2529 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2545 for (
unsigned int i = 0;
i < psbtx.
tx->vin.size(); ++
i) {
2546 const CTxIn& txin = psbtx.
tx->vin[
i];
2556 const auto it = mapWallet.find(txhash);
2557 if (
it != mapWallet.end()) {
2568 int n_signed_this_spkm = 0;
2569 TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
2575 (*n_signed) += n_signed_this_spkm;
2581 for (
const auto& input : psbtx.
inputs) {
2592 for (
const auto& spk_man_pair : m_spk_managers) {
2593 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2594 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2602 std::vector<CRecipient> vecSend;
2605 for (
size_t idx = 0; idx < tx.
vout.size(); idx++) {
2608 vecSend.push_back(recipient);
2623 if (!CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut, error, coinControl, fee_calc_out,
false)) {
2627 if (nChangePosInOut != -1) {
2628 tx.
vout.insert(tx.
vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
2633 for (
unsigned int idx = 0; idx < tx.
vout.size(); idx++) {
2634 tx.
vout[idx].nValue = tx_new->vout[idx].nValue;
2638 for (
const CTxIn& txin : tx_new->vin) {
2640 tx.
vin.push_back(txin);
2657 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
2660 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
2694 locktime = block_height;
2701 locktime = std::max(0, (
int)locktime -
GetRandInt(100));
2716 return *change_type;
2727 for (
const auto& recipient : vecSend) {
2729 int witnessversion = 0;
2730 std::vector<unsigned char> witnessprogram;
2731 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
2737 return m_default_address_type;
2741 const std::vector<CRecipient>& vecSend,
2744 int& nChangePosInOut,
2753 int nChangePosRequest = nChangePosInOut;
2754 unsigned int nSubtractFeeFromAmount = 0;
2755 for (
const auto& recipient : vecSend)
2757 if (nValue < 0 || recipient.nAmount < 0)
2759 error =
_(
"Transaction amounts must not be negative");
2762 nValue += recipient.nAmount;
2764 if (recipient.fSubtractFeeFromAmount)
2765 nSubtractFeeFromAmount++;
2767 if (vecSend.empty())
2769 error =
_(
"Transaction must have at least one recipient");
2778 std::set<CInputCoin> setCoins;
2782 std::vector<COutput> vAvailableCoins;
2792 if (!std::get_if<CNoDestination>(&coin_control.
destChange)) {
2806 error =
_(
"Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.");
2814 CTxOut change_prototype_txout(0, scriptChange);
2829 bool pick_new_inputs =
true;
2834 coin_selection_params.
use_bnb =
true;
2839 nChangePosInOut = nChangePosRequest;
2844 CAmount nValueToSelect = nValue;
2845 if (nSubtractFeeFromAmount == 0)
2846 nValueToSelect += nFeeRet;
2852 for (
const auto& recipient : vecSend)
2854 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
2856 if (recipient.fSubtractFeeFromAmount)
2858 assert(nSubtractFeeFromAmount != 0);
2859 txout.
nValue -= nFeeRet / nSubtractFeeFromAmount;
2864 txout.
nValue -= nFeeRet % nSubtractFeeFromAmount;
2872 if (
IsDust(txout, chain().relayDustFee()))
2874 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
2877 error =
_(
"The transaction amount is too small to pay the fee");
2879 error =
_(
"The transaction amount is too small to send after the fee has been deducted");
2882 error =
_(
"Transaction amount too small");
2885 txNew.
vout.push_back(txout);
2889 bool bnb_used =
false;
2890 if (pick_new_inputs) {
2896 if (change_spend_size == -1) {
2902 if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used))
2906 coin_selection_params.
use_bnb =
false;
2910 error =
_(
"Insufficient funds");
2918 const CAmount nChange = nValueIn - nValueToSelect;
2922 CTxOut newTxOut(nChange, scriptChange);
2927 if (
IsDust(newTxOut, discard_rate) || bnb_used)
2929 nChangePosInOut = -1;
2934 if (nChangePosInOut == -1)
2939 else if ((
unsigned int)nChangePosInOut > txNew.
vout.size())
2941 error =
_(
"Change index out of range");
2945 std::vector<CTxOut>::iterator position = txNew.
vout.begin()+nChangePosInOut;
2946 txNew.
vout.insert(position, newTxOut);
2949 nChangePosInOut = -1;
2954 for (
const auto& coin : setCoins) {
2960 error =
_(
"Signing transaction failed");
2964 nFeeNeeded =
GetMinimumFee(*
this, nBytes, coin_control, &feeCalc);
2967 error =
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
2971 if (nFeeRet >= nFeeNeeded) {
2982 if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
2983 unsigned int tx_size_with_change = nBytes + coin_selection_params.
change_output_size + 2;
2984 CAmount fee_needed_with_change =
GetMinimumFee(*
this, tx_size_with_change, coin_control,
nullptr);
2986 if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
2987 pick_new_inputs =
false;
2988 nFeeRet = fee_needed_with_change;
2994 if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
2995 CAmount extraFeePaid = nFeeRet - nFeeNeeded;
2996 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
2997 change_position->nValue += extraFeePaid;
2998 nFeeRet -= extraFeePaid;
3002 else if (!pick_new_inputs) {
3007 error =
_(
"Transaction fee and change calculation failed");
3012 if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3013 CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3014 std::vector<CTxOut>::iterator change_position = txNew.
vout.begin()+nChangePosInOut;
3017 change_position->nValue -= additionalFeeNeeded;
3018 nFeeRet += additionalFeeNeeded;
3025 if (nSubtractFeeFromAmount > 0) {
3026 pick_new_inputs =
false;
3030 nFeeRet = nFeeNeeded;
3031 coin_selection_params.
use_bnb =
false;
3036 if (scriptChange.
empty() && nChangePosInOut != -1) {
3043 std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
3055 for (
const auto& coin : selected_coins) {
3060 error =
_(
"Signing transaction failed");
3070 error =
_(
"Transaction too large");
3075 if (nFeeRet > m_default_max_tx_fee) {
3082 if (!chain().checkChainLimits(tx)) {
3083 error =
_(
"Transaction has too long of a mempool chain");
3091 fee_calc_out = feeCalc;
3093 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",
3105 const std::vector<CRecipient>& vecSend,
3108 int& nChangePosInOut,
3114 int nChangePosIn = nChangePosInOut;
3116 bool res = CreateTransactionInternal(vecSend, tx, nFeeRet, nChangePosInOut, error, coin_control, fee_calc_out, sign);
3123 int nChangePosInOut2 = nChangePosIn;
3125 if (CreateTransactionInternal(vecSend, tx2, nFeeRet2, nChangePosInOut2, error2, tmp_cc, fee_calc_out, sign)) {
3127 const bool use_aps = nFeeRet2 <= nFeeRet + m_max_aps_fee;
3128 WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n", nFeeRet, nFeeRet2, use_aps ?
"grouped" :
"non-grouped");
3132 nChangePosInOut = nChangePosInOut2;
3142 WalletLogPrintf(
"CommitTransaction:\n%s", tx->ToString());
3146 AddToWallet(tx, {}, [&](
CWalletTx& wtx,
bool new_tx) {
3149 wtx.
mapValue = std::move(mapValue);
3157 for (
const CTxIn& txin : tx->vin) {
3165 CWalletTx& wtx = mapWallet.at(tx->GetHash());
3167 if (!fBroadcastTransactions) {
3172 std::string err_string;
3173 if (!wtx.SubmitMemoryPoolAndRelay(err_string,
true)) {
3174 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
3183 fFirstRunRet =
false;
3187 if (GetDatabase().Rewrite(
"\x04pool"))
3189 for (
const auto& spk_man_pair : m_spk_managers) {
3190 spk_man_pair.second->RewriteDB();
3198 assert(m_external_spk_managers.empty());
3199 assert(m_internal_spk_managers.empty());
3203 return nLoadWalletRet;
3212 for (
const uint256& hash : vHashOut) {
3213 const auto&
it = mapWallet.find(hash);
3214 wtxOrdered.erase(
it->second.m_it_wtxOrdered);
3215 for (
const auto& txin :
it->second.tx->vin)
3216 mapTxSpends.erase(txin.prevout);
3217 mapWallet.erase(
it);
3223 if (GetDatabase().Rewrite(
"\x04pool"))
3225 for (
const auto& spk_man_pair : m_spk_managers) {
3226 spk_man_pair.second->RewriteDB();
3232 return nZapSelectTxRet;
3241 bool fUpdated =
false;
3245 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
3246 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
3247 m_address_book[address].SetLabel(strName);
3248 if (!strPurpose.empty())
3249 m_address_book[address].purpose = strPurpose;
3262 return SetAddressBookWithDB(batch, address, strName, strPurpose);
3274 if (IsMine(address)) {
3275 WalletLogPrintf(
"%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__,
PACKAGE_BUGREPORT);
3280 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
3284 m_address_book.erase(address);
3298 unsigned int count = 0;
3299 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3300 count += spk_man->KeypoolCountExternalKeys();
3310 unsigned int count = 0;
3311 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3312 count += spk_man->GetKeyPoolSize();
3321 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3322 res &= spk_man->TopUp(kpSize);
3331 bool result =
false;
3332 auto spk_man = GetScriptPubKeyMan(type,
false );
3335 result = spk_man->GetNewDestination(type, dest, error);
3340 SetAddressBook(dest, label,
"receive");
3353 error =
_(
"Error: Keypool ran out, please call keypoolrefill first").
translated;
3364 int64_t oldestKey = std::numeric_limits<int64_t>::max();
3365 for (
const auto& spk_man_pair : m_spk_managers) {
3366 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
3372 for (
auto& entry : mapWallet) {
3375 for (
unsigned int i = 0;
i < wtx.
tx->vout.size();
i++) {
3387 std::map<CTxDestination, CAmount> balances;
3391 std::set<uint256> trusted_parents;
3392 for (
const auto& walletEntry : mapWallet)
3394 const CWalletTx& wtx = walletEntry.second;
3396 if (!IsTrusted(wtx, trusted_parents))
3406 for (
unsigned int i = 0;
i < wtx.
tx->vout.size();
i++)
3409 if (!IsMine(wtx.
tx->vout[
i]))
3414 CAmount n = IsSpent(walletEntry.first,
i) ? 0 : wtx.
tx->vout[
i].nValue;
3415 balances[addr] += n;
3426 std::set< std::set<CTxDestination> > groupings;
3427 std::set<CTxDestination> grouping;
3429 for (
const auto& walletEntry : mapWallet)
3431 const CWalletTx& wtx = walletEntry.second;
3433 if (wtx.
tx->vin.size() > 0)
3435 bool any_mine =
false;
3437 for (
const CTxIn& txin : wtx.
tx->vin)
3444 grouping.insert(address);
3451 for (
const CTxOut& txout : wtx.
tx->vout)
3452 if (IsChange(txout))
3457 grouping.insert(txoutAddr);
3460 if (grouping.size() > 0)
3462 groupings.insert(grouping);
3468 for (
const auto& txout : wtx.
tx->vout)
3474 grouping.insert(address);
3475 groupings.insert(grouping);
3480 std::set< std::set<CTxDestination>* > uniqueGroupings;
3481 std::map< CTxDestination, std::set<CTxDestination>* > setmap;
3482 for (std::set<CTxDestination> _grouping : groupings)
3485 std::set< std::set<CTxDestination>* > hits;
3486 std::map< CTxDestination, std::set<CTxDestination>* >::iterator
it;
3488 if ((it = setmap.find(address)) != setmap.end())
3489 hits.insert((*it).second);
3492 std::set<CTxDestination>* merged =
new std::set<CTxDestination>(_grouping);
3493 for (std::set<CTxDestination>* hit : hits)
3495 merged->insert(hit->begin(), hit->end());
3496 uniqueGroupings.erase(hit);
3499 uniqueGroupings.insert(merged);
3503 setmap[element] = merged;
3506 std::set< std::set<CTxDestination> > ret;
3507 for (
const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
3509 ret.insert(*uniqueGrouping);
3510 delete uniqueGrouping;
3519 std::set<CTxDestination> result;
3520 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
3522 if (item.second.IsChange())
continue;
3524 const std::string& strName = item.second.GetLabel();
3525 if (strName == label)
3526 result.insert(address);
3533 m_spk_man = pwallet->GetScriptPubKeyMan(type,
internal);
3544 if (!m_spk_man->GetReservedDestination(type,
internal, address, nIndex, keypool)) {
3556 m_spk_man->KeepDestination(nIndex, type);
3565 m_spk_man->ReturnDestination(nIndex, fInternal, address);
3574 setLockedCoins.insert(output);
3580 setLockedCoins.erase(output);
3586 setLockedCoins.clear();
3594 return (setLockedCoins.count(outpt) > 0);
3600 for (std::set<COutPoint>::iterator
it = setLockedCoins.begin();
3601 it != setLockedCoins.end();
it++) {
3603 vOutpts.push_back(outpt);
3611 mapKeyBirth.clear();
3614 assert(spk_man !=
nullptr);
3618 for (
const auto& entry : spk_man->mapKeyMetadata) {
3619 if (entry.second.nCreateTime) {
3620 mapKeyBirth[entry.first] = entry.second.nCreateTime;
3625 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
3627 max_confirm.
block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0;
3630 if (mapKeyBirth.count(keyid) == 0)
3631 mapKeyFirstBlock[keyid] = &max_confirm;
3635 if (mapKeyFirstBlock.empty())
3639 for (
const auto& entry : mapWallet) {
3644 for (
const CTxOut &txout : wtx.
tx->vout) {
3648 auto rit = mapKeyFirstBlock.find(keyid);
3658 for (
const auto& entry : mapKeyFirstBlock) {
3693 int64_t latestEntry = 0;
3696 int64_t latestTolerated = latestNow + 300;
3697 const TxItems& txOrdered = wtxOrdered;
3698 for (
auto it = txOrdered.rbegin();
it != txOrdered.rend(); ++
it) {
3708 if (nSmartTime <= latestTolerated) {
3709 latestEntry = nSmartTime;
3710 if (nSmartTime > latestNow) {
3711 latestNow = nSmartTime;
3717 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
3727 if (std::get_if<CNoDestination>(&dest))
3730 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3736 if (!m_address_book[dest].destdata.erase(key))
3743 m_address_book[dest].destdata.insert(std::make_pair(key, value));
3748 std::map<CTxDestination, CAddressBookData>::const_iterator
i = m_address_book.find(dest);
3749 if(i != m_address_book.end())
3751 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
3752 if(j != i->second.destdata.end())
3764 std::vector<std::string> values;
3765 for (
const auto& address : m_address_book) {
3766 for (
const auto& data : address.second.destdata) {
3767 if (!data.first.compare(0, prefix.size(),
prefix)) {
3768 values.emplace_back(data.second);
3784 fs::file_type path_type = fs::symlink_status(wallet_path).type();
3785 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
3786 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
3787 (path_type == fs::regular_file && fs::path(name).filename() == name))) {
3789 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 3790 "database/log.?????????? files can be stored, a location where such a directory could be created, " 3791 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
3796 return MakeDatabase(wallet_path, options, status, error_string);
3801 const std::string& walletFile = database->Filename();
3806 bool fFirstRun =
true;
3809 std::shared_ptr<CWallet> walletInstance(
new CWallet(&chain, name, std::move(database)),
ReleaseWallet);
3810 DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
3813 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
3818 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 3819 " or address book entries might be missing or incorrect."),
3832 error =
strprintf(
_(
"Error loading %s"), walletFile);
3842 walletInstance->AddWalletFlags(wallet_creation_flags);
3846 walletInstance->SetupLegacyScriptPubKeyMan();
3850 LOCK(walletInstance->cs_wallet);
3852 walletInstance->SetupDescriptorScriptPubKeyMans();
3856 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3857 if (!spk_man->SetupGeneration()) {
3858 error =
_(
"Unable to generate initial keys");
3868 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
3870 }
else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
3871 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3872 if (spk_man->HavePrivateKeys()) {
3873 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
3892 walletInstance->m_default_change_type = out_type;
3903 _(
"This is the minimum transaction fee you pay on every transaction."));
3905 walletInstance->m_min_fee =
CFeeRate(n);
3909 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
3911 if (max_aps_fee ==
"-1") {
3919 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
3921 walletInstance->m_max_aps_fee = n;
3927 error =
strprintf(
_(
"Invalid amount for -fallbackfee=<amount>: '%s'"),
gArgs.
GetArg(
"-fallbackfee",
""));
3932 _(
"This is the transaction fee you may pay when fee estimates are not available."));
3934 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
3937 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
3942 error =
strprintf(
_(
"Invalid amount for -discardfee=<amount>: '%s'"),
gArgs.
GetArg(
"-discardfee",
""));
3947 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
3949 walletInstance->m_discard_rate =
CFeeRate(nFeePerK);
3959 _(
"This is the transaction fee you will pay if you send a transaction."));
3961 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
3962 if (walletInstance->m_pay_tx_fee < chain.
relayMinFee()) {
3963 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
3976 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
3979 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
3983 walletInstance->m_default_max_tx_fee = nMaxFee;
3988 _(
"The wallet will avoid paying less than the minimum relay fee."));
3995 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
GetTimeMillis() - nStart);
3998 walletInstance->TopUpKeyPool();
4000 LOCK(walletInstance->cs_wallet);
4010 walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
4012 int rescan_height = 0;
4017 if (batch.ReadBestBlock(locator)) {
4019 rescan_height = *fork_height;
4026 walletInstance->m_last_block_processed = chain.
getBlockHash(*tip_height);
4027 walletInstance->m_last_block_processed_height = *tip_height;
4029 walletInstance->m_last_block_processed.
SetNull();
4030 walletInstance->m_last_block_processed_height = -1;
4033 if (tip_height && *tip_height != rescan_height)
4042 int block_height = *tip_height;
4043 while (block_height > 0 && chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
4047 if (rescan_height != block_height) {
4048 error =
_(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
4054 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
4059 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
4060 int64_t time = spk_man->GetTimeFirstKey();
4061 if (!time_first_key || time < *time_first_key) time_first_key = time;
4063 if (time_first_key) {
4069 if (!reserver.
reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.
getBlockHash(rescan_height), rescan_height, {} , reserver,
true ).status)) {
4070 error =
_(
"Failed to rescan the wallet during initialization");
4075 walletInstance->GetDatabase().IncrementUpdateCounter();
4080 for (
auto& load_wallet : g_load_wallet_fns) {
4088 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
4089 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
4090 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
4093 return walletInstance;
4098 const auto& address_book_it = m_address_book.find(dest);
4099 if (address_book_it == m_address_book.end())
return nullptr;
4100 if ((!allow_change) && address_book_it->second.IsChange()) {
4103 return &address_book_it->second;
4108 int prev_version = GetVersion();
4110 WalletLogPrintf(
"Performing wallet upgrade to %i\n",
FEATURE_LATEST);
4113 WalletLogPrintf(
"Allowing wallet upgrade up to %i\n", version);
4115 if (version < prev_version) {
4116 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
4124 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);
4131 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
4132 if (!spk_man->Upgrade(prev_version, version, error)) {
4145 ReacceptWalletTransactions();
4148 chain().requestMempoolTransactions(*
this);
4153 return GetDatabase().Backup(strDest);
4160 m_pre_split =
false;
4166 vchPubKey = vchPubKeyIn;
4167 fInternal = internalIn;
4168 m_pre_split =
false;
4173 assert(pwallet !=
nullptr);
4175 if (isUnconfirmed() || isAbandoned())
return 0;
4177 return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
4184 int chain_depth = GetDepthInMainChain();
4185 assert(chain_depth >= 0);
4192 return GetBlocksToMaturity() > 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;
4206 chain().getTransactionAncestry(output.tx->GetHash(), 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);
4244 return HasEncryptionKeys();
4253 return vMasterKey.empty();
4266 NotifyStatusChanged(
this);
4274 for (
const auto& spk_man_pair : m_spk_managers) {
4275 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
4279 vMasterKey = vMasterKeyIn;
4281 NotifyStatusChanged(
this);
4287 std::set<ScriptPubKeyMan*> spk_mans;
4288 for (
bool internal : {
false,
true}) {
4290 auto spk_man = GetScriptPubKeyMan(t,
internal);
4292 spk_mans.insert(spk_man);
4301 std::set<ScriptPubKeyMan*> spk_mans;
4302 for (
const auto& spk_man_pair : m_spk_managers) {
4303 spk_mans.insert(spk_man_pair.second.get());
4310 const std::map<OutputType, ScriptPubKeyMan*>& spk_managers =
internal ? m_internal_spk_managers : m_external_spk_managers;
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;
4322 for (
const auto& spk_man_pair : m_spk_managers) {
4323 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4324 spk_mans.insert(spk_man_pair.second.get());
4333 for (
const auto& spk_man_pair : m_spk_managers) {
4334 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4335 return spk_man_pair.second.get();
4343 if (m_spk_managers.count(
id) > 0) {
4344 return m_spk_managers.at(
id).get();
4352 return GetSolvingProvider(script, sigdata);
4357 for (
const auto& spk_man_pair : m_spk_managers) {
4358 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4359 return spk_man_pair.second->GetSolvingProvider(script);
4373 if (
it == m_internal_spk_managers.end())
return nullptr;
4379 SetupLegacyScriptPubKeyMan();
4380 return GetLegacyScriptPubKeyMan();
4385 if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(
WALLET_FLAG_DESCRIPTORS)) {
4391 m_internal_spk_managers[type] = spk_manager.get();
4392 m_external_spk_managers[type] = spk_manager.get();
4394 m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
4404 return !mapMasterKeys.empty();
4409 for (
const auto& spk_man : GetActiveScriptPubKeyMans()) {
4418 m_spk_managers[id] = std::move(spk_manager);
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();
4448 m_spk_managers[id] = std::move(spk_manager);
4449 AddActiveScriptPubKeyMan(
id, t,
internal);
4458 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
4460 LoadActiveScriptPubKeyMan(
id, type,
internal);
4465 WalletLogPrintf(
"Setting spkMan to active: id = %s, type = %d, internal = %d\n",
id.
ToString(), static_cast<int>(type), static_cast<int>(
internal));
4466 auto& spk_mans =
internal ? m_internal_spk_managers : m_external_spk_managers;
4467 auto spk_man = m_spk_managers.at(
id).get();
4468 spk_man->SetInternal(
internal);
4469 spk_mans[type] = spk_man;
4480 return spk_man !=
nullptr;
4485 for (
auto& spk_man_pair : m_spk_managers) {
4499 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
4507 auto old_spk_man = GetDescriptorScriptPubKeyMan(desc);
4509 WalletLogPrintf(
"Update existing descriptor: %s\n", desc.
descriptor->ToString());
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}) {
4520 auto active_spk_man = GetScriptPubKeyMan(t,
internal);
4521 if (active_spk_man && active_spk_man->GetID() == old_spk_man_id) {
4523 m_internal_spk_managers.erase(t);
4525 m_external_spk_managers.erase(t);
4531 m_spk_managers.erase(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()) {
4542 WalletLogPrintf(
"Could not top up scriptPubKeys\n");
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");
4557 SetAddressBook(dest, label,
"receive");
4562 auto ret = new_spk_man.get();
4563 m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
4566 ret->WriteDescriptor();
bool IsEquivalentTo(const CWalletTx &tx) const
std::shared_ptr< const CTransaction > CTransactionRef
bool TxnCommit()
Commit current transaction.
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
static int64_t GetTransactionWeight(const CTransaction &tx)
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, take care to consider how DelAddressBook should handle it!
bool WriteName(const std::string &strAddress, const std::string &strName)
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
Helper for findBlock to selectively return pieces of block data.
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
void Close()
Close wallet database.
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
virtual Optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
void SetSpentKeyState(WalletBatch &batch, const uint256 &hash, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void blockConnected(const CBlock &block, int height) override
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
void SignTransaction(CMutableTransaction &mtx, const SigningProvider *keystore, const std::map< COutPoint, Coin > &coins, const UniValue &hashType, UniValue &result)
Sign a transaction with the given keystore and previous transactions.
bool ErasePurpose(const std::string &strAddress)
bool IsLegacy() const
Determine if we are a legacy wallet.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
std::deque< CInv >::iterator it
CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter &filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value)=0
Write a setting to <datadir>/settings.json.
const std::chrono::seconds now
const std::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
static const uint32_t MAX_BIP125_RBF_SEQUENCE
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
std::map< std::string, std::string > mapValue_t
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock &block={})=0
Find first block in the chain with timestamp >= the given time and height >= than the given height...
std::shared_ptr< Descriptor > descriptor
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
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...
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
const unsigned int WALLET_CRYPTO_KEY_SIZE
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
constexpr CAmount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CAmount GetAvailableBalance(const CCoinControl *coinControl=nullptr) const
std::shared_ptr< CWallet > GetWallet(const std::string &name)
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.
static void ReleaseWallet(CWallet *wallet)
size_t change_output_size
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
int64_t GetTimeMillis()
Returns the system time (not mockable)
static const CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Encryption/decryption context with key information.
RecursiveMutex cs_KeyStore
bool IsFromMe(const isminefilter &filter) const
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
const CTxOut & FindNonChangeParentOutput(const CTransaction &tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Find non-change parent output.
CPubKey GetPubKey() const
Compute the public key from a private key.
CAmount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
Optional< CMutableTransaction > tx
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
std::vector< unsigned char > vchCryptedKey
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
std::map< CKeyID, CKey > keys
bool use_max_sig
Whether to use the maximum sized, 72 byte signature when calculating the size of the input spend...
bool WriteMinVersion(int nVersion)
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
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 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 uint32_t SEQUENCE_FINAL
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...
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
virtual bool isInitialBlockDownload()=0
Check if in IBD.
int64_t GetOldestKeyPoolTime() const
void ListSelected(std::vector< COutPoint > &vOutpoints) const
bool MoneyRange(const CAmount &nValue)
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
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.
bool IsChange(const CTxOut &txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static std::vector< std::shared_ptr< CWallet > > vpwallets GUARDED_BY(cs_wallets)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
int64_t nOrderPos
position in ordered transaction list
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
CFeeRate GetDiscardRate(const CWallet &wallet)
Return the maximum feerate for discarding change.
bool isConflicted() const
Balance GetBalance(int min_depth=0, bool avoid_reuse=true) const
void blockDisconnected(const CBlock &block, int height) override
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule) ...
const CKeyingMaterial & GetEncryptionKey() const override
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
bool CanGetAddresses(bool internal=false) const
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
CAmount m_mine_trusted
Trusted, at depth=GetBalance.min_depth or more.
CAmount m_watchonly_untrusted_pending
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
static auto & nullopt
Substitute for C++17 std::nullopt DEPRECATED use std::nullopt in new code.
int m_min_depth
Minimum chain depth value for coin availability.
Use sat/vB fee rate unit.
CAmount m_watchonly_immature
WalletFeature GetClosestWalletFeature(int version)
void MarkDirty()
make sure balances are recalculated
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal...
bool IsLocked() const override
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
bilingual_str TransactionErrorString(const TransactionError err)
A version of CTransaction with the PSBT format.
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
bool TxnBegin()
Begin a new transaction.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
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)
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
bool WriteTx(const CWalletTx &wtx)
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
bool ParseMoney(const std::string &money_string, CAmount &nRet)
Parse an amount denoted in full coins.
DBErrors LoadWallet(CWallet *pwallet)
void chainStateFlushed(const CBlockLocator &loc) override
const unsigned char * begin() const
bool isUnconfirmed() const
bool MarkReplaced(const uint256 &originalHash, const uint256 &newHash)
Mark a transaction as replaced by another transaction (e.g., BIP 125).
DBErrors
Error statuses for the wallet database.
bool EncryptWallet(const SecureString &strWalletPassphrase)
bool WriteWalletFlags(const uint64_t flags)
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
CAmount m_watchonly_trusted
CAmount GetImmatureCredit(bool fUseCache=true) const
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, Optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node...
static const bool DEFAULT_WALLET_RBF
-walletrbf default
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
WalletFeature
(client) version numbers for particular wallet features
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
bool BackupWallet(const std::string &strDest) const
static constexpr auto OUTPUT_TYPES
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
const std::vector< CTxIn > vin
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
size_t GetSerializeSize(const T &t, int nVersion=0)
RecursiveMutex cs_wallets
std::string ToString() const
std::map< CTxDestination, CAmount > GetAddressBalances() const
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Access to the wallet database.
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack...
mapValue_t mapValue
Key/value map with information about the transaction.
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
int64_t CAmount
Amount in satoshis (Can be negative)
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
bool WriteBestBlock(const CBlockLocator &locator)
bool TxnAbort()
Abort current transaction.
#define AssertLockHeld(cs)
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
bool HasEncryptionKeys() const override
DBErrors ReorderTransactions()
Optional< bool > m_signal_bip125_rbf
Override the wallet's m_signal_rbf if set.
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in=false)
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static void NotifyCanGetAddressesChanged(WalletModel *walletmodel)
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool DelAddressBook(const CTxDestination &address)
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
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 push_back(const UniValue &val)
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
const int DEFAULT_MAX_DEPTH
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
fs::path GetWalletDir()
Get the path of the wallet directory.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void GetAmounts(std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, const isminefilter &filter) const
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
bool AbandonTransaction(const uint256 &hashTx)
DBErrors LoadWallet(bool &fFirstRunRet)
CAmount m_mine_immature
Immature coinbases in the main chain.
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.
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...
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet...
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
An input of a transaction.
static Mutex g_loading_wallet_mutex
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();.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int CalculateMaximumSignedInputSize(const CTxOut &txout, const CWallet *wallet, bool use_max_sig)
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
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...
bool m_add_inputs
If false, only selected inputs are used.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
static void NotifyAddressBookChanged(WalletModel *walletmodel, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)
const uint256 & GetHash() const
void SetTx(CTransactionRef arg)
bilingual_str _(const char *psz)
Translation function.
Removed for conflict with in-block transaction.
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...
CTxDestination destChange
Custom change destination, if not set an address is generated.
bilingual_str AmountHighWarn(const std::string &optname)
std::set< uint256 > GetConflicts() const NO_THREAD_SAFETY_ANALYSIS
void Select(const COutPoint &output)
An encapsulated public key.
bool fAllowOtherInputs
If false, allows unselected inputs, but requires all selected inputs be used.
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
int GetBlocksToMaturity() const
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
static const bool DEFAULT_WALLETBROADCAST
const std::vector< CTxOut > vout
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses, and other watch only things, and is therefore "blank.".
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
const int DEFAULT_MIN_DEPTH
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Optional< unsigned int > m_confirm_target
Override the default confirmation target if set.
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
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 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)
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
isminetype
IsMine() return codes.
unsigned int size() const
Simple read-only vector-like interface.
bool WriteOrderPosNext(int64_t nOrderPosNext)
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
#define WAIT_LOCK(cs, name)
An output of a transaction.
std::string ToString() const
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)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Descriptor with some wallet metadata.
static const unsigned int DEFAULT_TX_CONFIRM_TARGET
-txconfirmtarget default
const uint256 & GetHash() const
OutputType TransactionChangeType(const Optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
An outpoint - a combination of a transaction hash and an index n into its vout.
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
static const CAmount MIN_FINAL_CHANGE
final minimum change amount after paying for fees
std::vector< CTxOut > vout
unsigned int fTimeReceivedIsTxTime
bool IsAllFromMe(const CTransaction &tx, const isminefilter &filter) const
Returns whether all of the inputs match the filter.
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
void SetSeed(const unsigned char *seed, unsigned int nSeedLen)
std::vector< PSBTInput > inputs
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
Return implementation of Wallet interface.
void updatedBlockTip() override
void AddToSpends(const COutPoint &outpoint, const uint256 &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) 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 ...
RAII object to check and reserve a wallet rescan.
bool HasWalletDescriptor(const WalletDescriptor &desc) const
A transaction with a bunch of additional info that only the owner cares about.
CAmount GetCachableAmount(AmountType type, const isminefilter &filter, bool recalculate=false) const
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool IsImmatureCoinBase() const
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)
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 ...
std::vector< std::shared_ptr< CWallet > > GetWallets()
std::string ShellEscape(const std::string &arg)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const std::string & FormatOutputType(OutputType type)
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
std::vector< OutputGroup > GroupOutputs(const std::vector< COutput > &outputs, bool single_coin, const size_t max_ancestors) const
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
OutputGroup GetPositiveOnlyGroup()
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
const unsigned int WALLET_CRYPTO_SALT_SIZE
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
std::vector< CTransactionRef > vtx
int m_max_depth
Maximum chain depth value for coin availability.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
CoinSelectionParams coin_selection_params(false, 0, 0, CFeeRate(0), 0)
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, Optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
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...
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
CAmount GetCredit(const isminefilter &filter) const
int64_t GetTxTime() const
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...
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
void ResendWalletTransactions()
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
Serialized script, used inside transaction inputs and outputs.
bool IsSelected(const COutPoint &output) const
bool TopUpKeyPool(unsigned int kpSize=0)
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
static const int PROTOCOL_VERSION
network protocol versioning
static const unsigned int MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
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)
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet...
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
int GetSpendSize(unsigned int out, bool use_max_sig=false) const
static bool IsCurrentForAntiFeeSniping(interfaces::Chain &chain, const uint256 &block_hash)
static void NotifyTransactionChanged(WalletModel *walletmodel, const uint256 &hash, ChangeType status)
static const size_t OUTPUT_GROUP_MAX_ENTRIES
virtual void initMessage(const std::string &message)=0
Send init message.
A reference to a CKey: the Hash160 of its serialized public key.
void UpdateInput(CTxIn &input, const SignatureData &data)
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.
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
std::string GetHex() const
bool GetReservedDestination(CTxDestination &pubkey, bool internal)
Reserve an address.
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs) ...
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Fee rate in satoshis per kilobyte: CAmount / kB.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
static Mutex g_wallet_release_mutex
#define AssertLockNotHeld(cs)
A wrapper to reserve an address from a wallet.
bool KnapsackSolver(const CAmount &nTargetValue, std::vector< OutputGroup > &groups, std::set< CInputCoin > &setCoinsRet, CAmount &nValueRet)
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
std::vector< unsigned char > vchSalt
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::string EncodeDestination(const CTxDestination &dest)
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
Optional< int > last_scanned_height
A mutable version of CTransaction.
SecureString create_passphrase
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
static std::condition_variable g_wallet_release_cv
static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
static std::vector< COutput > vCoins