35 #include <boost/algorithm/string/replace.hpp> 41 "You need to rescan the blockchain in order to correctly mark used " 42 "destinations in the past. Until this is done, some destinations may " 43 "be considered unused, even if the opposite is the case."},
47 static std::vector<std::shared_ptr<CWallet>> vpwallets
GUARDED_BY(cs_wallets);
48 static std::list<LoadWalletFn> g_load_wallet_fns
GUARDED_BY(cs_wallets);
50 bool AddWallet(
const std::shared_ptr<CWallet> &wallet) {
53 std::vector<std::shared_ptr<CWallet>>::const_iterator i =
54 std::find(vpwallets.begin(), vpwallets.end(), wallet);
55 if (i != vpwallets.end()) {
58 vpwallets.push_back(wallet);
59 wallet->ConnectScriptPubKeyManNotifiers();
66 wallet->m_chain_notifications_handler.reset();
68 std::vector<std::shared_ptr<CWallet>>::iterator i =
69 std::find(vpwallets.begin(), vpwallets.end(), wallet);
70 if (i == vpwallets.end()) {
79 return !vpwallets.empty();
89 for (
const std::shared_ptr<CWallet> &wallet : vpwallets) {
90 if (wallet->GetName() ==
name) {
97 std::unique_ptr<interfaces::Handler>
100 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(),
101 std::move(load_wallet));
104 g_load_wallet_fns.erase(it);
120 LOCK(g_wallet_release_mutex);
131 const std::string
name = wallet->GetName();
133 LOCK(g_wallet_release_mutex);
140 wallet->NotifyUnload();
158 std::vector<bilingual_str> &warnings) {
161 error =
Untranslated(
"Wallet file verification failed.") +
167 chainParams, chain, location, error, warnings);
174 wallet->postInitProcess();
176 }
catch (
const std::runtime_error &e) {
184 const std::string &
name,
186 std::vector<bilingual_str> &warnings) {
194 uint64_t wallet_creation_flags,
196 std::vector<bilingual_str> &warnings,
197 std::shared_ptr<CWallet> &result) {
203 if (!passphrase.empty()) {
218 error =
Untranslated(
"Wallet file verification failed.") +
224 if (!passphrase.empty() &&
227 "Passphrase provided but private keys are disabled. A passphrase " 228 "is only used to encrypt private keys, so cannot be used for " 229 "wallets with private keys disabled.");
235 params, chain, location, error, warnings, wallet_creation_flags);
243 if (!passphrase.empty() &&
245 if (!wallet->EncryptWallet(passphrase)) {
247 Untranslated(
"Error: Wallet created but failed to encrypt.");
252 if (!wallet->Unlock(passphrase)) {
254 "Error: Wallet was encrypted but could not be unlocked");
260 LOCK(wallet->cs_wallet);
262 wallet->SetupDescriptorScriptPubKeyMans();
264 for (
auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
265 if (!spk_man->SetupGeneration()) {
279 wallet->postInitProcess();
299 return m_chain ? m_chain->params() :
Params();
304 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
305 if (it == mapWallet.end()) {
309 return &(it->second);
317 auto spk_man = GetLegacyScriptPubKeyMan();
322 spk_man->UpgradeKeyMetadata();
327 bool accept_no_keys) {
333 for (
const MasterKeyMap::value_type &pMasterKey : mapMasterKeys) {
335 strWalletPassphrase, pMasterKey.second.vchSalt,
336 pMasterKey.second.nDeriveIterations,
337 pMasterKey.second.nDerivationMethod)) {
340 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey,
345 if (Unlock(_vMasterKey, accept_no_keys)) {
347 UpgradeKeyMetadata();
359 bool fWasLocked = IsLocked();
366 for (MasterKeyMap::value_type &pMasterKey : mapMasterKeys) {
368 strOldWalletPassphrase, pMasterKey.second.vchSalt,
369 pMasterKey.second.nDeriveIterations,
370 pMasterKey.second.nDerivationMethod)) {
374 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey)) {
378 if (Unlock(_vMasterKey)) {
381 pMasterKey.second.vchSalt,
382 pMasterKey.second.nDeriveIterations,
383 pMasterKey.second.nDerivationMethod);
384 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(
385 pMasterKey.second.nDeriveIterations *
390 pMasterKey.second.vchSalt,
391 pMasterKey.second.nDeriveIterations,
392 pMasterKey.second.nDerivationMethod);
393 pMasterKey.second.nDeriveIterations =
394 (pMasterKey.second.nDeriveIterations +
395 static_cast<unsigned int>(
396 pMasterKey.second.nDeriveIterations * 100 /
400 if (pMasterKey.second.nDeriveIterations < 25000) {
401 pMasterKey.second.nDeriveIterations = 25000;
405 "Wallet passphrase changed to an nDeriveIterations of %i\n",
406 pMasterKey.second.nDeriveIterations);
409 strNewWalletPassphrase, pMasterKey.second.vchSalt,
410 pMasterKey.second.nDeriveIterations,
411 pMasterKey.second.nDerivationMethod)) {
415 if (!crypter.
Encrypt(_vMasterKey,
416 pMasterKey.second.vchCryptedKey)) {
441 if (nWalletVersion >= nVersion) {
447 if (fExplicit && nVersion > nWalletMaxVersion) {
451 nWalletVersion = nVersion;
453 if (nVersion > nWalletMaxVersion) {
454 nWalletMaxVersion = nVersion;
458 if (nWalletVersion > 40000) {
470 if (nWalletVersion > nVersion) {
474 nWalletMaxVersion = nVersion;
480 std::set<TxId> result;
483 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
484 if (it == mapWallet.end()) {
490 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
492 for (
const CTxIn &txin : wtx.
tx->vin) {
493 if (mapTxSpends.count(txin.
prevout) <= 1) {
498 range = mapTxSpends.equal_range(txin.
prevout);
499 for (TxSpends::const_iterator _it = range.first; _it != range.second;
501 result.insert(_it->second);
510 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
511 return (iter != mapTxSpends.end() && iter->first.GetTxId() == txid);
515 database->Flush(shutdown);
519 std::pair<TxSpends::iterator, TxSpends::iterator> range) {
524 int nMinOrderPos = std::numeric_limits<int>::max();
526 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
527 const CWalletTx *wtx = &mapWallet.at(it->second);
539 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
540 const TxId &txid = it->second;
542 if (copyFrom == copyTo) {
548 "Oldest wallet transaction in range assumed to have been found.");
568 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range =
569 mapTxSpends.equal_range(outpoint);
571 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
572 const TxId &wtxid = it->second;
573 std::map<TxId, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
574 if (mit != mapWallet.end()) {
575 int depth = mit->second.GetDepthInMainChain();
576 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) {
587 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
589 setLockedCoins.erase(outpoint);
591 std::pair<TxSpends::iterator, TxSpends::iterator> range;
592 range = mapTxSpends.equal_range(outpoint);
597 auto it = mapWallet.find(wtxid);
598 assert(it != mapWallet.end());
601 if (thisTx.IsCoinBase()) {
605 for (
const CTxIn &txin : thisTx.tx->vin) {
606 AddToSpends(txin.
prevout, wtxid);
646 WalletLogPrintf(
"Encrypting Wallet with an nDeriveIterations of %i\n",
661 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
664 delete encrypted_batch;
665 encrypted_batch =
nullptr;
670 for (
const auto &spk_man_pair : m_spk_managers) {
671 auto spk_man = spk_man_pair.second.get();
672 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
674 delete encrypted_batch;
675 encrypted_batch =
nullptr;
687 delete encrypted_batch;
688 encrypted_batch =
nullptr;
695 delete encrypted_batch;
696 encrypted_batch =
nullptr;
699 Unlock(strWalletPassphrase);
704 SetupDescriptorScriptPubKeyMans();
705 }
else if (
auto spk_man = GetLegacyScriptPubKeyMan()) {
707 if (spk_man->IsHDEnabled()) {
708 if (!spk_man->SetupGeneration(
true)) {
723 database->ReloadDbEnv();
726 NotifyStatusChanged(
this);
741 for (
auto &entry : mapWallet) {
747 std::vector<int64_t> nOrderPosOffsets;
748 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) {
752 if (nOrderPos == -1) {
753 nOrderPos = nOrderPosNext++;
754 nOrderPosOffsets.push_back(nOrderPos);
760 int64_t nOrderPosOff = 0;
761 for (
const int64_t &nOffsetStart : nOrderPosOffsets) {
762 if (nOrderPos >= nOffsetStart) {
767 nOrderPos += nOrderPosOff;
768 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
788 int64_t nRet = nOrderPosNext++;
800 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
801 item.second.MarkDirty();
806 unsigned int n,
bool used,
807 std::set<CTxDestination> &tx_destinations) {
809 const CWalletTx *srctx = GetWalletTx(txid);
817 if (used && !GetDestData(dst,
"used",
nullptr)) {
819 if (AddDestData(batch, dst,
"used",
"p")) {
820 tx_destinations.insert(dst);
822 }
else if (!used && GetDestData(dst,
"used",
nullptr)) {
823 EraseDestData(batch, dst,
"used");
832 const CWalletTx *srctx = GetWalletTx(txid);
834 assert(srctx->
tx->vout.size() > n);
839 if (GetDestData(dest,
"used",
nullptr)) {
844 assert(spk_man !=
nullptr);
845 for (
const auto &keyid :
848 if (GetDestData(pkh_dest,
"used",
nullptr)) {
866 std::set<CTxDestination> tx_destinations;
868 for (
const CTxIn &txin : wtxIn.
tx->vin) {
870 SetSpentKeyState(batch, op.
GetTxId(), op.
GetN(),
true,
874 MarkDestinationsDirty(tx_destinations);
878 std::pair<std::map<TxId, CWalletTx>::iterator,
bool> ret =
879 mapWallet.insert(std::make_pair(txid, wtxIn));
882 bool fInsertedNew = ret.second;
887 wtxOrdered.insert(std::make_pair(wtx.
nOrderPos, &wtx));
892 bool fUpdated =
false;
913 WalletLogPrintf(
"AddToWallet %s %s%s\n", wtxIn.
GetId().
ToString(),
914 (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
917 if ((fInsertedNew || fUpdated) && !batch.
WriteTx(wtx)) {
927 #if defined(HAVE_SYSTEM) 930 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
932 if (!strCmd.empty()) {
933 boost::replace_all(strCmd,
"%s", wtxIn.
GetId().
GetHex());
940 boost::replace_all(strCmd,
"%w",
ShellEscape(GetName()));
943 std::thread t(runCommand, strCmd);
956 std::optional<int> block_height =
976 const auto &ins = mapWallet.emplace(txid, wtxIn);
981 wtxOrdered.insert(std::make_pair(wtx.
nOrderPos, &wtx));
984 for (
const CTxIn &txin : wtx.
tx->vin) {
986 if (it != mapWallet.end()) {
1004 std::pair<TxSpends::const_iterator, TxSpends::const_iterator>
1005 range = mapTxSpends.equal_range(txin.
prevout);
1006 while (range.first != range.second) {
1007 if (range.first->second != tx.
GetId()) {
1009 "Transaction %s (in block %s) conflicts with wallet " 1010 "transaction %s (both spend %s:%i)\n",
1012 range.first->second.ToString(),
1013 range.first->first.GetTxId().ToString(),
1014 range.first->first.GetN());
1016 range.first->second);
1023 bool fExisted = mapWallet.count(tx.
GetId()) != 0;
1024 if (fExisted && !fUpdate) {
1027 if (fExisted || IsMine(tx) || IsFromMe(tx)) {
1038 for (
const auto &spk_man_pair : m_spk_managers) {
1039 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1049 return AddToWallet(wtx,
false);
1057 const CWalletTx *wtx = GetWalletTx(txid);
1063 for (
const CTxIn &txin : tx->vin) {
1065 if (it != mapWallet.end()) {
1066 it->second.MarkDirty();
1076 std::set<TxId> todo;
1077 std::set<TxId>
done;
1080 auto it = mapWallet.find(txid);
1081 assert(it != mapWallet.end());
1083 if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1089 while (!todo.empty()) {
1093 it = mapWallet.find(now);
1094 assert(it != mapWallet.end());
1098 assert(currentconfirm <= 0);
1101 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1104 assert(!wtx.InMempool());
1111 TxSpends::const_iterator iter =
1112 mapTxSpends.lower_bound(
COutPoint(now, 0));
1113 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1114 if (!done.count(iter->second)) {
1115 todo.insert(iter->second);
1123 MarkInputsDirty(wtx.tx);
1134 int conflictconfirms =
1135 (m_last_block_processed_height - conflicting_height + 1) * -1;
1140 if (conflictconfirms >= 0) {
1147 std::set<TxId> todo;
1148 std::set<TxId>
done;
1152 while (!todo.empty()) {
1156 auto it = mapWallet.find(now);
1157 assert(it != mapWallet.end());
1160 if (conflictconfirms < currentconfirm) {
1163 wtx.m_confirm.nIndex = 0;
1164 wtx.m_confirm.hashBlock = hashBlock;
1165 wtx.m_confirm.block_height = conflicting_height;
1166 wtx.setConflicted();
1171 TxSpends::const_iterator iter =
1172 mapTxSpends.lower_bound(
COutPoint(now, 0));
1173 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1174 if (!done.count(iter->second)) {
1175 todo.insert(iter->second);
1182 MarkInputsDirty(wtx.tx);
1189 if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx)) {
1197 MarkInputsDirty(ptx);
1205 SyncTransaction(ptx, confirm);
1207 auto it = mapWallet.find(ptx->GetId());
1208 if (it != mapWallet.end()) {
1209 it->second.fInMempool =
true;
1215 auto it = mapWallet.find(ptx->GetId());
1216 if (it != mapWallet.end()) {
1217 it->second.fInMempool =
false;
1225 m_last_block_processed_height = height;
1226 m_last_block_processed = block_hash;
1227 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1230 SyncTransaction(block.
vtx[index], confirm);
1231 transactionRemovedFromMempool(block.
vtx[index]);
1243 m_last_block_processed_height = height - 1;
1249 SyncTransaction(ptx, confirm);
1254 m_best_block_time =
GetTime();
1264 WITH_LOCK(cs_wallet,
return m_last_block_processed);
1265 chain().waitForNotificationsIfTipChanged(last_block_hash);
1270 std::map<TxId, CWalletTx>::const_iterator mi =
1272 if (mi != mapWallet.end()) {
1286 std::map<TxId, CWalletTx>::const_iterator mi =
1288 if (mi != mapWallet.end()) {
1310 for (
const auto &spk_man_pair : m_spk_managers) {
1311 result = std::max(result, spk_man_pair.second->IsMine(script));
1319 throw std::runtime_error(std::string(__func__) +
1320 ": value out of range");
1339 if (IsMine(script)) {
1346 if (!FindAddressBookEntry(address)) {
1356 throw std::runtime_error(std::string(__func__) +
1357 ": value out of range");
1365 if (IsMine(txout)) {
1381 nDebit += GetDebit(txin, filter);
1383 throw std::runtime_error(std::string(__func__) +
1384 ": value out of range");
1397 if (mi == mapWallet.end()) {
1409 if (!(IsMine(prev.
tx->vout[txin.
prevout.
GetN()]) & filter)) {
1421 nCredit += GetCredit(txout, filter);
1423 throw std::runtime_error(std::string(__func__) +
1424 ": value out of range");
1434 nChange += GetChange(txout);
1436 throw std::runtime_error(std::string(__func__) +
1437 ": value out of range");
1447 for (
const auto &spk_man : GetActiveScriptPubKeyMans()) {
1448 result &= spk_man->IsHDEnabled();
1455 if (m_spk_managers.empty()) {
1459 auto spk_man = GetScriptPubKeyMan(t,
internal);
1460 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1469 m_wallet_flags |=
flags;
1471 throw std::runtime_error(std::string(__func__) +
1472 ": writing wallet flags failed");
1478 UnsetWalletFlagWithDB(batch, flag);
1483 m_wallet_flags &= ~flag;
1485 throw std::runtime_error(std::string(__func__) +
1486 ": writing wallet flags failed");
1495 return (m_wallet_flags & flag);
1500 m_wallet_flags = overwriteFlags;
1502 (overwriteFlags >> 32)) {
1507 throw std::runtime_error(std::string(__func__) +
1508 ": writing wallet flags failed");
1515 int64_t n = nTimeSmart;
1516 return n ? n : nTimeReceived;
1527 std::unique_ptr<SigningProvider> provider =
1528 GetSolvingProvider(scriptPubKey);
1537 scriptPubKey, sigdata)) {
1548 const std::vector<CTxOut> &txouts,
1552 for (
const auto &txout : txouts) {
1553 if (!DummySignInput(txNew.
vin[nIn], txout, use_max_sig)) {
1563 int64_t timestamp) {
1564 auto spk_man = GetLegacyScriptPubKeyMan();
1568 LOCK(spk_man->cs_KeyStore);
1569 return spk_man->ImportScripts(scripts, timestamp);
1573 const int64_t timestamp) {
1574 auto spk_man = GetLegacyScriptPubKeyMan();
1578 LOCK(spk_man->cs_KeyStore);
1579 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1583 const std::vector<CKeyID> &ordered_pubkeys,
1584 const std::map<CKeyID, CPubKey> &pubkey_map,
1585 const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
1586 const bool add_keypool,
const bool internal,
const int64_t timestamp) {
1587 auto spk_man = GetLegacyScriptPubKeyMan();
1591 LOCK(spk_man->cs_KeyStore);
1592 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins,
1593 add_keypool,
internal, timestamp);
1597 const std::set<CScript> &script_pub_keys,
1598 const bool have_solving_data,
1599 const bool apply_label,
1600 const int64_t timestamp) {
1601 auto spk_man = GetLegacyScriptPubKeyMan();
1605 LOCK(spk_man->cs_KeyStore);
1606 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data,
1612 for (
const CScript &script : script_pub_keys) {
1616 SetAddressBookWithDB(batch, dest, label,
"receive");
1625 std::vector<CTxOut> txouts;
1626 for (
auto &input : tx.
vin) {
1627 const auto mi = wallet->mapWallet.find(input.prevout.GetTxId());
1629 if (mi == wallet->mapWallet.end()) {
1632 assert(input.prevout.GetN() < mi->second.tx->vout.size());
1633 txouts.emplace_back(mi->second.tx->vout[input.prevout.GetN()]);
1641 const std::vector<CTxOut> &txouts,
1644 if (!wallet->
DummySignTx(txNew, txouts, use_max_sig)) {
1661 std::list<COutputEntry> &listSent,
Amount &nFee,
1664 listReceived.clear();
1668 Amount nDebit = GetDebit(filter);
1671 Amount nValueOut =
tx->GetValueOut();
1672 nFee = (nDebit - nValueOut);
1676 for (
unsigned int i = 0;
i <
tx->vout.size(); ++
i) {
1684 if (pwallet->IsChange(txout)) {
1687 }
else if (!(fIsMine & filter)) {
1696 pwallet->WalletLogPrintf(
"CWalletTx::GetAmounts: Unknown " 1697 "transaction type found, txid %s\n",
1707 listSent.push_back(output);
1711 if (fIsMine & filter) {
1712 listReceived.push_back(output);
1731 int start_height = 0;
1733 bool start = chain().findFirstBlockWithTimeAndHeight(
1735 FoundBlock().hash(start_block).height(start_height));
1736 WalletLogPrintf(
"%s: Rescanning last %i blocks\n", __func__,
1737 start ?
WITH_LOCK(cs_wallet,
return GetLastBlockHeight()) -
1743 ScanResult result = ScanForWalletTransactions(
1744 start_block, start_height, {} , reserver, update);
1745 if (result.
status == ScanResult::FAILURE) {
1777 const BlockHash &start_block,
int start_height,
1788 WalletLogPrintf(
"Rescan started from block %s...\n",
1791 fAbortRescan =
false;
1795 strprintf(
"%s " +
_(
"Rescanning...").translated, GetDisplayName()), 0);
1799 chain().findAncestorByHeight(tip_hash, *max_height,
1802 double progress_begin = chain().guessVerificationProgress(block_hash);
1803 double progress_end = chain().guessVerificationProgress(end_hash);
1804 double progress_current = progress_begin;
1805 int block_height = start_height;
1806 while (!fAbortRescan && !chain().shutdownRequested()) {
1807 m_scanning_progress = (progress_current - progress_begin) /
1808 (progress_end - progress_begin);
1809 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1811 strprintf(
"%s " +
_(
"Rescanning...").translated,
1813 std::max(1, std::min(99, (
int)(m_scanning_progress * 100))));
1817 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n",
1818 block_height, progress_current);
1825 if (chain().findBlock(block_hash,
FoundBlock().data(block)) &&
1828 next_block = chain().findNextBlock(
1829 block_hash, block_height,
FoundBlock().hash(next_block_hash),
1837 result.
status = ScanResult::FAILURE;
1840 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size();
1843 block_height, block_hash,
1845 SyncTransaction(block.
vtx[posInBlock], confirm, fUpdate);
1855 result.
status = ScanResult::FAILURE;
1856 next_block = chain().findNextBlock(
1857 block_hash, block_height,
FoundBlock().hash(next_block_hash),
1860 if (max_height && block_height >= *max_height) {
1864 if (!next_block || reorg) {
1871 block_hash = next_block_hash;
1873 progress_current = chain().guessVerificationProgress(block_hash);
1876 const BlockHash prev_tip_hash = tip_hash;
1877 tip_hash =
WITH_LOCK(cs_wallet,
return GetLastBlockHash());
1878 if (!max_height && prev_tip_hash != tip_hash) {
1880 progress_end = chain().guessVerificationProgress(tip_hash);
1887 strprintf(
"%s " +
_(
"Rescanning...").translated, GetDisplayName()),
1889 if (block_height && fAbortRescan) {
1890 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n",
1891 block_height, progress_current);
1892 result.
status = ScanResult::USER_ABORT;
1893 }
else if (block_height && chain().shutdownRequested()) {
1895 "Rescan interrupted by shutdown request at block %d. Progress=%f\n",
1896 block_height, progress_current);
1897 result.
status = ScanResult::USER_ABORT;
1899 WalletLogPrintf(
"Rescan completed in %15dms\n",
1908 if (!fBroadcastTransactions) {
1912 std::map<int64_t, CWalletTx *> mapSorted;
1916 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1917 const TxId &wtxid = item.first;
1919 assert(wtx.
GetId() == wtxid);
1924 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1929 for (
const std::pair<const int64_t, CWalletTx *> &item : mapSorted) {
1931 std::string unused_err_string;
1938 if (!pwallet->GetBroadcastTransactions()) {
1942 if (isAbandoned()) {
1951 if (GetDepthInMainChain() != 0) {
1956 pwallet->WalletLogPrintf(
"Submitting wtx %s to mempool for relay\n",
1967 bool ret = pwallet->chain().broadcastTransaction(
1968 GetConfig(),
tx, pwallet->m_default_max_tx_fee, relay, err_string);
1974 std::set<TxId> result;
1975 if (pwallet !=
nullptr) {
1976 const TxId &txid = GetId();
1977 result = pwallet->GetConflicts(txid);
1985 bool recalculate)
const {
1986 auto &amount = m_amounts[type];
1987 if (recalculate || !amount.m_cached[filter]) {
1988 amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*
tx, filter)
1989 : pwallet->GetCredit(*
tx, filter));
1990 m_is_cache_empty =
false;
1992 return amount.m_value[filter];
1996 if (
tx->vin.empty()) {
2002 debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
2005 debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
2014 if (IsImmatureCoinBase()) {
2021 credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE);
2025 credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY);
2032 if (IsImmatureCoinBase() && IsInMainChain()) {
2041 if (pwallet ==
nullptr) {
2052 if (IsImmatureCoinBase()) {
2056 if (fUseCache && allow_cache &&
2057 m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
2058 return m_amounts[AVAILABLE_CREDIT].m_value[filter];
2061 bool allow_used_addresses =
2065 const TxId &txid = GetId();
2066 for (uint32_t
i = 0;
i <
tx->vout.size();
i++) {
2068 (allow_used_addresses || !pwallet->IsSpentKey(txid,
i))) {
2070 nCredit += pwallet->GetCredit(txout, filter);
2072 throw std::runtime_error(std::string(__func__) +
2073 " : value out of range");
2079 m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
2080 m_is_cache_empty =
false;
2087 if (IsImmatureCoinBase() && IsInMainChain()) {
2096 if (fChangeCached) {
2097 return nChangeCached;
2100 nChangeCached = pwallet->GetChange(*
tx);
2101 fChangeCached =
true;
2102 return nChangeCached;
2111 return IsTrusted(s);
2117 if (!pwallet->chain().contextualCheckTransactionForCurrentBlock(*
tx,
2122 int nDepth = GetDepthInMainChain();
2132 if (!pwallet->m_spend_zero_conf_change || !IsFromMe(
ISMINE_ALL)) {
2143 for (
const CTxIn &txin :
tx->vin) {
2146 if (parent ==
nullptr) {
2156 if (trusted_parents.count(parent->
GetId())) {
2160 if (!parent->
IsTrusted(trusted_parents)) {
2163 trusted_parents.insert(parent->
GetId());
2172 for (
auto &txin : tx1.vin) {
2176 for (
auto &txin : tx2.vin) {
2195 if (!chain().isReadyToBroadcast()) {
2201 if (
GetTime() < nNextResend || !fBroadcastTransactions) {
2205 bool fFirst = (nNextResend == 0);
2212 if (m_best_block_time < nLastResend) {
2218 int submitted_tx_count = 0;
2224 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
2232 std::string unused_err_string;
2234 ++submitted_tx_count;
2239 if (submitted_tx_count > 0) {
2240 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__,
2241 submitted_tx_count);
2248 for (
const std::shared_ptr<CWallet> &pwallet :
GetWallets()) {
2249 pwallet->ResendWalletTransactions();
2259 bool avoid_reuse)
const {
2263 std::set<TxId> trusted_parents;
2264 for (
const auto &entry : mapWallet) {
2266 const bool is_trusted{wtx.
IsTrusted(trusted_parents)};
2272 if (is_trusted && tx_depth >= min_depth) {
2276 if (!is_trusted && tx_depth == 0 && wtx.
InMempool()) {
2290 std::vector<COutput>
vCoins;
2291 AvailableCoins(vCoins,
true, coinControl);
2292 for (
const COutput &out : vCoins) {
2293 if (out.fSpendable) {
2294 balance += out.tx->tx->vout[out.i].nValue;
2302 const Amount nMinimumAmount,
2303 const Amount nMaximumAmount,
2304 const Amount nMinimumSumAmount,
2305 const uint64_t nMaximumCount)
const {
2314 bool allow_used_addresses =
2317 const int min_depth = {coinControl ? coinControl->
m_min_depth 2319 const int max_depth = {coinControl ? coinControl->
m_max_depth 2322 std::set<TxId> trusted_parents;
2323 for (
const auto &entry : mapWallet) {
2324 const TxId &wtxid = entry.first;
2328 if (!chain().contextualCheckTransactionForCurrentBlock(*wtx.
tx,
2349 bool safeTx = wtx.
IsTrusted(trusted_parents);
2367 if (nDepth == 0 && wtx.
mapValue.count(
"replaced_by_txid")) {
2371 if (fOnlySafe && !safeTx) {
2375 if (nDepth < min_depth || nDepth > max_depth) {
2379 for (uint32_t
i = 0;
i < wtx.
tx->vout.size();
i++) {
2386 if (wtx.
tx->vout[
i].nValue < nMinimumAmount ||
2387 wtx.
tx->vout[
i].nValue > nMaximumAmount) {
2399 if (IsLockedCoin(outpoint)) {
2403 if (IsSpent(outpoint)) {
2413 if (!allow_used_addresses && IsSpentKey(wtxid,
i)) {
2417 std::unique_ptr<SigningProvider> provider =
2418 GetSolvingProvider(wtx.
tx->vout[
i].scriptPubKey);
2421 provider ?
IsSolvable(*provider, wtx.
tx->vout[
i].scriptPubKey)
2429 COutput(&wtx,
i, nDepth, spendable, solvable, safeTx,
2434 nTotal += wtx.
tx->vout[
i].nValue;
2436 if (nTotal >= nMinimumSumAmount) {
2442 if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
2452 std::map<CTxDestination, std::vector<COutput>> result;
2453 std::vector<COutput> availableCoins;
2455 AvailableCoins(availableCoins);
2457 for (
const auto &coin : availableCoins) {
2459 if ((coin.fSpendable ||
2463 FindNonChangeParentOutput(*coin.tx->tx, coin.i).scriptPubKey,
2465 result[address].emplace_back(std::move(coin));
2469 std::vector<COutPoint> lockedCoins;
2470 ListLockedCoins(lockedCoins);
2472 const bool include_watch_only =
2473 GetLegacyScriptPubKeyMan() &&
2477 for (
const auto &output : lockedCoins) {
2478 auto it = mapWallet.find(output.GetTxId());
2479 if (it != mapWallet.end()) {
2480 int depth = it->second.GetDepthInMainChain();
2481 if (depth >= 0 && output.GetN() < it->second.tx->vout.size() &&
2482 IsMine(it->second.tx->vout[output.GetN()]) == is_mine_filter) {
2485 FindNonChangeParentOutput(*it->second.tx, output.GetN())
2488 result[address].emplace_back(
2489 &it->second, output.GetN(), depth,
true ,
2503 while (IsChange(ptx->
vout[n]) && ptx->
vin.size() > 0) {
2505 auto it = mapWallet.find(prevout.
GetTxId());
2506 if (it == mapWallet.end() ||
2507 it->second.tx->vout.size() <= prevout.
GetN() ||
2508 !IsMine(it->second.tx->vout[prevout.
GetN()])) {
2511 ptx = it->second.tx.get();
2514 return ptx->
vout[n];
2519 std::vector<OutputGroup> groups, std::set<CInputCoin> &setCoinsRet,
2521 bool &bnb_used)
const {
2522 setCoinsRet.clear();
2525 std::vector<OutputGroup> utxo_pool;
2526 if (coin_selection_params.
use_bnb) {
2533 Amount cost_of_change = chain().relayDustFee().GetFee(
2541 if (!group.EligibleForSpending(eligibility_filter)) {
2548 for (
auto it = group.m_outputs.begin();
2549 it != group.m_outputs.end();) {
2565 group.long_term_fee +=
2572 group.effective_value += effective_value;
2576 it = group.Discard(coin);
2580 utxo_pool.push_back(group);
2588 setCoinsRet, nValueRet, not_input_fees);
2592 if (!group.EligibleForSpending(eligibility_filter)) {
2595 utxo_pool.push_back(group);
2598 return KnapsackSolver(nTargetValue, utxo_pool, setCoinsRet, nValueRet);
2603 const Amount nTargetValue,
2604 std::set<CInputCoin> &setCoinsRet,
Amount &nValueRet,
2607 bool &bnb_used)
const {
2608 std::vector<COutput>
vCoins(vAvailableCoins);
2609 Amount value_to_select = nTargetValue;
2617 for (
const COutput &out : vCoins) {
2618 if (!out.fSpendable) {
2622 nValueRet += out.tx->tx->vout[out.i].nValue;
2623 setCoinsRet.insert(out.GetInputCoin());
2626 return (nValueRet >= nTargetValue);
2630 std::set<CInputCoin> setPresetCoins;
2633 std::vector<COutPoint> vPresetInputs;
2636 for (
const COutPoint &outpoint : vPresetInputs) {
2637 std::map<TxId, CWalletTx>::const_iterator it =
2638 mapWallet.find(outpoint.GetTxId());
2639 if (it != mapWallet.end()) {
2642 if (wtx.
tx->vout.size() <= outpoint.GetN()) {
2656 if (coin_selection_params.
use_bnb) {
2661 setPresetCoins.insert(coin);
2668 for (std::vector<COutput>::iterator it = vCoins.begin();
2669 it != vCoins.end() && coin_control.
HasSelected();) {
2670 if (setPresetCoins.count(it->GetInputCoin())) {
2671 it = vCoins.erase(it);
2677 size_t max_ancestors{0};
2678 size_t max_descendants{0};
2679 chain().getPackageLimits(max_ancestors, max_descendants);
2694 std::vector<OutputGroup> groups = GroupOutputs(
2700 groups, setCoinsRet, nValueRet,
2701 coin_selection_params, bnb_used) ||
2703 groups, setCoinsRet, nValueRet,
2704 coin_selection_params, bnb_used) ||
2705 (m_spend_zero_conf_change &&
2707 groups, setCoinsRet, nValueRet,
2708 coin_selection_params, bnb_used)) ||
2709 (m_spend_zero_conf_change &&
2713 std::min((
size_t)4, max_descendants / 3)),
2714 groups, setCoinsRet, nValueRet, coin_selection_params,
2716 (m_spend_zero_conf_change &&
2717 SelectCoinsMinConf(value_to_select,
2719 max_descendants / 2),
2720 groups, setCoinsRet, nValueRet,
2721 coin_selection_params, bnb_used)) ||
2722 (m_spend_zero_conf_change &&
2723 SelectCoinsMinConf(value_to_select,
2725 max_descendants - 1),
2726 groups, setCoinsRet, nValueRet,
2727 coin_selection_params, bnb_used)) ||
2728 (m_spend_zero_conf_change && !fRejectLongChains &&
2732 groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
2739 nValueRet += nValueFromPresetInputs;
2748 std::map<COutPoint, Coin> coins;
2749 for (
auto &input : tx.
vin) {
2750 auto mi = mapWallet.find(input.prevout.GetTxId());
2751 if (mi == mapWallet.end() ||
2752 input.prevout.GetN() >= mi->second.tx->vout.size()) {
2756 coins[input.prevout] =
2760 std::map<int, std::string> input_errors;
2765 const std::map<COutPoint, Coin> &coins,
2767 std::map<int, std::string> &input_errors)
const {
2772 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2779 for (
size_t i = 0;
i < tx.
vin.size();
i++) {
2782 auto coin = coins.find(txin.
prevout);
2783 if (coin == coins.end() || coin->second.IsSpent()) {
2784 input_errors[
i] =
"Input not found or already spent";
2792 input_errors[
i] =
"Unable to sign input, missing keys";
2799 auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2800 if (legacy_spk_man &&
2801 legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2810 bool sign,
bool bip32derivs)
const {
2813 for (
size_t i = 0;
i < psbtx.
tx->vin.size(); ++
i) {
2814 const CTxIn &txin = psbtx.
tx->vin[
i];
2829 const auto it = mapWallet.find(txid);
2830 if (it != mapWallet.end()) {
2842 spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
2850 for (
const auto &input : psbtx.
inputs) {
2859 std::string &str_sig)
const {
2862 for (
const auto &spk_man_pair : m_spk_managers) {
2863 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2864 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2873 const std::set<int> &setSubtractFeeFromOutputs,
2875 std::vector<CRecipient> vecSend;
2878 for (
size_t idx = 0; idx < tx.
vout.size(); idx++) {
2881 setSubtractFeeFromOutputs.count(idx) == 1};
2882 vecSend.push_back(recipient);
2896 if (!CreateTransaction(vecSend, tx_new, nFeeRet, nChangePosInOut, error,
2897 coinControl,
false)) {
2901 if (nChangePosInOut != -1) {
2902 tx.
vout.insert(tx.
vout.begin() + nChangePosInOut,
2903 tx_new->vout[nChangePosInOut]);
2908 for (
size_t idx = 0; idx < tx.
vout.size(); idx++) {
2909 tx.
vout[idx].nValue = tx_new->vout[idx].nValue;
2913 for (
const CTxIn &txin : tx_new->vin) {
2915 tx.
vin.push_back(txin);
2933 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
2936 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
2971 locktime = block_height;
2978 locktime = std::max(0,
int(locktime) -
GetRandInt(100));
2993 const std::vector<CRecipient> &vecSend) {
3005 return m_default_address_type;
3010 int &nChangePosInOut,
3015 const OutputType change_type = TransactionChangeType(
3017 : m_default_change_type,
3020 int nChangePosRequest = nChangePosInOut;
3021 unsigned int nSubtractFeeFromAmount = 0;
3022 for (
const auto &recipient : vecSend) {
3024 error =
_(
"Transaction amounts must not be negative");
3028 nValue += recipient.nAmount;
3030 if (recipient.fSubtractFeeFromAmount) {
3031 nSubtractFeeFromAmount++;
3035 if (vecSend.empty()) {
3036 error =
_(
"Transaction must have at least one recipient");
3043 std::set<CInputCoin> setCoins;
3046 chain(), GetLastBlockHash(), GetLastBlockHeight());
3047 std::vector<COutput> vAvailableCoins;
3048 AvailableCoins(vAvailableCoins,
true, &coin_control);
3058 if (!boost::get<CNoDestination>(&coin_control.
destChange)) {
3076 error =
_(
"Transaction needs a change address, but we can't " 3077 "generate it. Please call keypoolrefill first.");
3081 assert(!dest.empty() || scriptChange.
empty());
3091 bool pick_new_inputs =
true;
3096 coin_selection_params.
use_bnb =
true;
3100 nSubtractFeeFromAmount != 0;
3103 nChangePosInOut = nChangePosRequest;
3108 Amount nValueToSelect = nValue;
3109 if (nSubtractFeeFromAmount == 0) {
3110 nValueToSelect += nFeeRet;
3120 for (
const auto &recipient : vecSend) {
3121 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
3123 if (recipient.fSubtractFeeFromAmount) {
3124 assert(nSubtractFeeFromAmount != 0);
3126 txout.
nValue -= nFeeRet / int(nSubtractFeeFromAmount);
3132 txout.
nValue -= nFeeRet % int(nSubtractFeeFromAmount);
3143 if (
IsDust(txout, chain().relayDustFee())) {
3144 if (recipient.fSubtractFeeFromAmount &&
3147 error =
_(
"The transaction amount is too small to " 3150 error =
_(
"The transaction amount is too small to " 3151 "send after the fee has been deducted");
3154 error =
_(
"Transaction amount too small");
3160 txNew.
vout.push_back(txout);
3164 bool bnb_used =
false;
3165 if (pick_new_inputs) {
3169 change_prototype_txout,
this);
3172 if (change_spend_size == -1) {
3177 size_t(change_spend_size);
3180 if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins,
3181 nValueIn, coin_control, coin_selection_params,
3186 coin_selection_params.
use_bnb =
false;
3189 error =
_(
"Insufficient funds");
3197 const Amount nChange = nValueIn - nValueToSelect;
3200 CTxOut newTxOut(nChange, scriptChange);
3205 if (
IsDust(newTxOut, chain().relayDustFee()) || bnb_used) {
3206 nChangePosInOut = -1;
3209 if (nChangePosInOut == -1) {
3212 }
else if ((
unsigned int)nChangePosInOut >
3213 txNew.
vout.size()) {
3214 error =
_(
"Change index out of range");
3218 std::vector<CTxOut>::iterator position =
3219 txNew.
vout.begin() + nChangePosInOut;
3220 txNew.
vout.insert(position, newTxOut);
3223 nChangePosInOut = -1;
3228 for (
const auto &coin : setCoins) {
3236 error =
_(
"Signing transaction failed");
3242 if (nFeeRet >= nFeeNeeded) {
3253 if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 &&
3257 unsigned int tx_size_with_change =
3259 Amount fee_needed_with_change =
3262 change_prototype_txout, chain().relayDustFee());
3264 fee_needed_with_change + minimum_value_for_change) {
3265 pick_new_inputs =
false;
3266 nFeeRet = fee_needed_with_change;
3272 if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 &&
3273 nSubtractFeeFromAmount == 0) {
3274 Amount extraFeePaid = nFeeRet - nFeeNeeded;
3275 std::vector<CTxOut>::iterator change_position =
3276 txNew.
vout.begin() + nChangePosInOut;
3277 change_position->nValue += extraFeePaid;
3278 nFeeRet -= extraFeePaid;
3283 }
else if (!pick_new_inputs) {
3288 error =
_(
"Transaction fee and change calculation failed");
3293 if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3294 Amount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3295 std::vector<CTxOut>::iterator change_position =
3296 txNew.
vout.begin() + nChangePosInOut;
3299 if (change_position->nValue >=
3301 change_position->nValue -= additionalFeeNeeded;
3302 nFeeRet += additionalFeeNeeded;
3310 if (nSubtractFeeFromAmount > 0) {
3311 pick_new_inputs =
false;
3315 nFeeRet = nFeeNeeded;
3316 coin_selection_params.
use_bnb =
false;
3322 if (scriptChange.
empty() && nChangePosInOut != -1) {
3328 std::vector<CInputCoin> selected_coins(setCoins.begin(),
3330 Shuffle(selected_coins.begin(), selected_coins.end(),
3335 for (
const auto &coin : selected_coins) {
3336 txNew.
vin.push_back(
3338 std::numeric_limits<uint32_t>::max() - 1));
3342 error =
_(
"Signing transaction failed");
3351 error =
_(
"Transaction too large");
3356 if (nFeeRet > m_default_max_tx_fee) {
3364 if (!chain().checkChainLimits(tx)) {
3365 error =
_(
"Transaction has too long of a mempool chain");
3381 int nChangePosIn = nChangePosInOut;
3383 bool res = CreateTransactionInternal(vecSend, tx, nFeeRet, nChangePosInOut,
3384 error, coin_control, sign);
3389 && m_max_aps_fee > (-1 *
SATOSHI) &&
3394 int nChangePosInOut2 = nChangePosIn;
3397 if (CreateTransactionInternal(vecSend, tx2, nFeeRet2, nChangePosInOut2,
3398 error2, tmp_cc, sign)) {
3401 const bool use_aps = nFeeRet2 <= nFeeRet + m_max_aps_fee;
3403 "Fee non-grouped = %lld, grouped = %lld, using %s\n", nFeeRet,
3404 nFeeRet2, use_aps ?
"grouped" :
"non-grouped");
3408 nChangePosInOut = nChangePosInOut2;
3417 std::vector<std::pair<std::string, std::string>> orderForm) {
3421 wtxNew.
mapValue = std::move(mapValue);
3426 WalletLogPrintfToBeContinued(
"CommitTransaction:\n%s",
3427 wtxNew.
tx->ToString());
3431 AddToWallet(wtxNew);
3434 for (
const CTxIn &txin : wtxNew.
tx->vin) {
3444 if (!fBroadcastTransactions) {
3449 std::string err_string;
3450 if (!wtx.SubmitMemoryPoolAndRelay(err_string,
true)) {
3451 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast " 3452 "immediately, %s\n",
3462 fFirstRunRet =
false;
3465 if (database->Rewrite(
"\x04pool")) {
3466 for (
const auto &spk_man_pair : m_spk_managers) {
3467 spk_man_pair.second->RewriteDB();
3474 fFirstRunRet = m_spk_managers.empty() &&
3478 assert(m_external_spk_managers.empty());
3479 assert(m_internal_spk_managers.empty());
3483 return nLoadWalletRet;
3490 std::vector<TxId> &txIdsOut) {
3494 for (
const TxId &txid : txIdsOut) {
3495 const auto &it = mapWallet.find(txid);
3496 wtxOrdered.erase(it->second.m_it_wtxOrdered);
3497 mapWallet.erase(it);
3502 if (database->Rewrite(
"\x04pool")) {
3503 for (
const auto &spk_man_pair : m_spk_managers) {
3504 spk_man_pair.second->RewriteDB();
3510 return nZapSelectTxRet;
3521 if (database->Rewrite(
"\x04pool")) {
3522 for (
const auto &spk_man_pair : m_spk_managers) {
3523 spk_man_pair.second->RewriteDB();
3529 return nZapWalletTxRet;
3537 const std::string &strName,
3538 const std::string &strPurpose) {
3539 bool fUpdated =
false;
3542 std::map<CTxDestination, CAddressBookData>::iterator mi =
3543 m_address_book.find(address);
3544 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
3545 m_address_book[address].SetLabel(strName);
3547 if (!strPurpose.empty()) {
3548 m_address_book[address].purpose = strPurpose;
3553 IsMine(address) !=
ISMINE_NO, strPurpose,
3555 if (!strPurpose.empty() && !batch.
WritePurpose(address, strPurpose)) {
3558 return batch.
WriteName(address, strName);
3562 const std::string &strName,
3563 const std::string &strPurpose) {
3565 return SetAddressBookWithDB(batch, address, strName, strPurpose);
3576 if (IsMine(address)) {
3577 WalletLogPrintf(
"%s called with IsMine address, NOT SUPPORTED. Please " 3578 "report this bug! %s\n",
3579 __func__, PACKAGE_BUGREPORT);
3587 for (
const std::pair<const std::string, std::string> &item :
3588 m_address_book[address].destdata) {
3591 m_address_book.erase(address);
3604 unsigned int count = 0;
3605 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3606 count += spk_man->KeypoolCountExternalKeys();
3615 unsigned int count = 0;
3616 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3617 count += spk_man->GetKeyPoolSize();
3625 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
3626 res &= spk_man->TopUp(kpSize);
3635 bool result =
false;
3636 auto spk_man = GetScriptPubKeyMan(type,
false );
3639 result = spk_man->GetNewDestination(type, dest, error);
3641 error =
strprintf(
"Error: No %s addresses available.",
3645 SetAddressBook(dest, label,
"receive");
3653 std::string &
error) {
3659 error =
_(
"Error: Keypool ran out, please call keypoolrefill first")
3670 int64_t oldestKey = std::numeric_limits<int64_t>::max();
3671 for (
const auto &spk_man_pair : m_spk_managers) {
3673 std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
3679 const std::set<CTxDestination> &destinations) {
3680 for (
auto &entry : mapWallet) {
3686 for (
size_t i = 0;
i < wtx.
tx->vout.size();
i++) {
3690 destinations.count(dst)) {
3699 std::map<CTxDestination, Amount> balances;
3702 std::set<TxId> trusted_parents;
3703 for (
const auto &walletEntry : mapWallet) {
3704 const CWalletTx &wtx = walletEntry.second;
3719 for (uint32_t
i = 0;
i < wtx.
tx->vout.size();
i++) {
3721 if (!IsMine(wtx.
tx->vout[
i])) {
3731 : wtx.
tx->vout[
i].nValue;
3733 if (!balances.count(addr)) {
3736 balances[addr] += n;
3745 std::set<std::set<CTxDestination>> groupings;
3746 std::set<CTxDestination> grouping;
3748 for (
const auto &walletEntry : mapWallet) {
3749 const CWalletTx &wtx = walletEntry.second;
3751 if (wtx.
tx->vin.size() > 0) {
3752 bool any_mine =
false;
3754 for (
const auto &txin : wtx.
tx->vin) {
3757 if (!IsMine(txin)) {
3762 .
tx->vout[txin.prevout.GetN()]
3768 grouping.insert(address);
3774 for (
const auto &txout : wtx.
tx->vout) {
3775 if (IsChange(txout)) {
3782 grouping.insert(txoutAddr);
3787 if (grouping.size() > 0) {
3788 groupings.insert(grouping);
3794 for (
const auto &txout : wtx.
tx->vout) {
3795 if (IsMine(txout)) {
3801 grouping.insert(address);
3802 groupings.insert(grouping);
3809 std::set<std::set<CTxDestination> *> uniqueGroupings;
3811 std::map<CTxDestination, std::set<CTxDestination> *> setmap;
3812 for (std::set<CTxDestination> _grouping : groupings) {
3814 std::set<std::set<CTxDestination> *> hits;
3815 std::map<CTxDestination, std::set<CTxDestination> *>::iterator it;
3817 if ((it = setmap.find(address)) != setmap.end()) {
3818 hits.insert((*it).second);
3823 std::set<CTxDestination> *merged =
3824 new std::set<CTxDestination>(_grouping);
3825 for (std::set<CTxDestination> *hit : hits) {
3826 merged->insert(hit->begin(), hit->end());
3827 uniqueGroupings.erase(hit);
3830 uniqueGroupings.insert(merged);
3834 setmap[element] = merged;
3838 std::set<std::set<CTxDestination>> ret;
3839 for (
const std::set<CTxDestination> *uniqueGrouping : uniqueGroupings) {
3840 ret.insert(*uniqueGrouping);
3841 delete uniqueGrouping;
3847 std::set<CTxDestination>
3850 std::set<CTxDestination> result;
3851 for (
const std::pair<const CTxDestination, CAddressBookData> &item :
3853 if (item.second.IsChange()) {
3857 const std::string &strName = item.second.GetLabel();
3858 if (strName == label) {
3859 result.insert(address);
3868 m_spk_man = pwallet->GetScriptPubKeyMan(type,
internal);
3877 if (!m_spk_man->GetReservedDestination(type,
internal, address, nIndex,
3889 m_spk_man->KeepDestination(nIndex, type);
3898 m_spk_man->ReturnDestination(nIndex, fInternal, address);
3906 setLockedCoins.insert(output);
3911 setLockedCoins.erase(output);
3916 setLockedCoins.clear();
3922 return setLockedCoins.count(outpoint) > 0;
3927 for (
COutPoint outpoint : setLockedCoins) {
3928 vOutpts.push_back(outpoint);
3936 mapKeyBirth.clear();
3939 assert(spk_man !=
nullptr);
3943 for (
const auto &entry : spk_man->mapKeyMetadata) {
3944 if (entry.second.nCreateTime) {
3945 mapKeyBirth[entry.first] = entry.second.nCreateTime;
3950 std::map<CKeyID, const CWalletTx::Confirmation *> mapKeyFirstBlock;
3954 GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0;
3959 if (mapKeyBirth.count(keyid) == 0) {
3960 mapKeyFirstBlock[keyid] = &max_confirm;
3965 if (mapKeyFirstBlock.empty()) {
3970 for (
const auto &entry : mapWallet) {
3975 for (
const CTxOut &txout : wtx.
tx->vout) {
3977 for (
const auto &keyid :
3980 auto rit = mapKeyFirstBlock.find(keyid);
3981 if (rit != mapKeyFirstBlock.end() &&
3983 rit->second->block_height) {
3992 for (
const auto &entry : mapKeyFirstBlock) {
4029 int64_t latestEntry = 0;
4033 int64_t latestTolerated = latestNow + 300;
4034 const TxItems &txOrdered = wtxOrdered;
4035 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
4045 if (nSmartTime <= latestTolerated) {
4046 latestEntry = nSmartTime;
4047 if (nSmartTime > latestNow) {
4048 latestNow = nSmartTime;
4054 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
4056 WalletLogPrintf(
"%s: found %s in block %s not in index\n", __func__,
4065 const std::string &key,
const std::string &value) {
4066 if (boost::get<CNoDestination>(&dest)) {
4070 m_address_book[dest].destdata.insert(std::make_pair(key, value));
4075 const std::string &key) {
4076 if (!m_address_book[dest].destdata.erase(key)) {
4084 const std::string &value) {
4085 m_address_book[dest].destdata.insert(std::make_pair(key, value));
4089 std::string *value)
const {
4090 std::map<CTxDestination, CAddressBookData>::const_iterator
i =
4091 m_address_book.find(dest);
4092 if (i != m_address_book.end()) {
4093 CAddressBookData::StringMap::const_iterator j =
4094 i->second.destdata.find(key);
4095 if (j != i->second.destdata.end()) {
4106 std::vector<std::string>
4108 std::vector<std::string> values;
4109 for (
const auto &address : m_address_book) {
4110 for (
const auto &data : address.second.destdata) {
4111 if (!data.first.compare(0, prefix.size(),
prefix)) {
4112 values.emplace_back(data.second);
4122 std::vector<bilingual_str> &warnings) {
4130 const fs::path &wallet_path = location.
GetPath();
4131 fs::file_type path_type = fs::symlink_status(wallet_path).type();
4132 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
4133 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
4134 (path_type == fs::regular_file &&
4135 fs::path(location.
GetName()).filename() == location.
GetName()))) {
4137 strprintf(
"Invalid -wallet path '%s'. -wallet path should point to " 4138 "a directory where wallet.dat and " 4139 "database/log.?????????? files can be stored, a location " 4140 "where such a directory could be created, " 4141 "or (for backwards compatibility) the name of an " 4142 "existing data file in -walletdir (%s)",
4150 "Error loading wallet %s. Duplicate -wallet filename specified.",
4157 std::unique_ptr<WalletDatabase> database =
4161 return database->Verify(error_string);
4162 }
catch (
const fs::filesystem_error &e) {
4173 std::vector<bilingual_str> &warnings, uint64_t wallet_creation_flags) {
4174 const std::string walletFile =
4178 std::vector<CWalletTx> vWtx;
4182 _(
"Zapping all transactions from wallet...").translated);
4184 std::unique_ptr<CWallet> tempWallet = std::make_unique<CWallet>(
4186 DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
4189 strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
4197 bool fFirstRun =
true;
4200 std::shared_ptr<CWallet> walletInstance(
4204 DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
4208 strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
4214 strprintf(
_(
"Error reading %s! All keys read correctly, but " 4215 "transaction data or address book entries might be " 4216 "missing or incorrect."),
4220 _(
"Error loading %s: Wallet requires newer version of %s"),
4221 walletFile, PACKAGE_NAME);
4225 _(
"Wallet needed to be rewritten: restart %s to complete"),
4229 error =
strprintf(
_(
"Error loading %s"), walletFile);
4239 walletInstance->SetWalletFlags(wallet_creation_flags,
false);
4243 walletInstance->SetupLegacyScriptPubKeyMan();
4246 if (!(wallet_creation_flags &
4248 LOCK(walletInstance->cs_wallet);
4250 walletInstance->SetupDescriptorScriptPubKeyMans();
4256 walletInstance->GetActiveScriptPubKeyMans()) {
4257 if (!spk_man->SetupGeneration()) {
4258 error =
_(
"Unable to generate initial keys");
4268 error =
strprintf(
_(
"Error loading %s: Private keys can only be " 4269 "disabled during creation"),
4272 }
else if (walletInstance->IsWalletFlagSet(
4273 WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
4274 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
4275 if (spk_man->HavePrivateKeys()) {
4277 strprintf(
_(
"Warning: Private keys detected in wallet {%s} " 4278 "with disabled private keys"),
4293 _(
"This is the minimum transaction fee you pay " 4294 "on every transaction."));
4296 walletInstance->m_min_fee =
CFeeRate(n);
4310 _(
"This is the maximum transaction fee you pay to prioritize " 4311 "partial spend avoidance over regular coin selection."));
4313 walletInstance->m_max_aps_fee = n;
4320 strprintf(
_(
"Invalid amount for -fallbackfee=<amount>: '%s'"),
4327 _(
"This is the transaction fee you may pay when " 4328 "fee estimates are not available."));
4330 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
4333 walletInstance->m_allow_fallback_fee =
4334 walletInstance->m_fallback_fee.GetFeePerK() !=
Amount::zero();
4344 _(
"This is the transaction fee you will pay if " 4345 "you send a transaction."));
4347 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
4348 if (walletInstance->m_pay_tx_fee < chain.
relayMinFee()) {
4349 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' " 4350 "(must be at least %s)"),
4364 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large " 4365 "could be paid on a single transaction."));
4369 _(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at " 4370 "least the minrelay fee of %s to prevent stuck " 4375 walletInstance->m_default_max_tx_fee = nMaxFee;
4381 _(
"The wallet will avoid paying less than the minimum relay fee."));
4384 walletInstance->m_spend_zero_conf_change =
4390 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
4394 walletInstance->TopUpKeyPool();
4396 LOCK(walletInstance->cs_wallet);
4406 walletInstance->m_chain_notifications_handler =
4407 walletInstance->chain().handleNotifications(walletInstance);
4409 int rescan_height = 0;
4414 if (
const std::optional<int> fork_height =
4416 rescan_height = *fork_height;
4421 const std::optional<int> tip_height = chain.
getHeight();
4423 walletInstance->m_last_block_processed =
4425 walletInstance->m_last_block_processed_height = *tip_height;
4427 walletInstance->m_last_block_processed.
SetNull();
4428 walletInstance->m_last_block_processed_height = -1;
4431 if (tip_height && *tip_height != rescan_height) {
4440 int block_height = *tip_height;
4441 while (block_height > 0 &&
4443 rescan_height != block_height) {
4447 if (rescan_height != block_height) {
4448 error =
_(
"Prune: last wallet synchronisation goes beyond " 4449 "pruned data. You need to -reindex (download the " 4450 "whole blockchain again in case of pruned node)");
4456 walletInstance->WalletLogPrintf(
4457 "Rescanning last %i blocks (from block %i)...\n",
4458 *tip_height - rescan_height, rescan_height);
4462 std::optional<int64_t> time_first_key;
4463 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
4464 int64_t time = spk_man->GetTimeFirstKey();
4465 if (!time_first_key || time < *time_first_key) {
4466 time_first_key = time;
4469 if (time_first_key) {
4470 if (std::optional<int> first_block =
4474 rescan_height = *first_block;
4481 (ScanResult::SUCCESS !=
4483 ->ScanForWalletTransactions(
4485 {} , reserver,
true )
4487 error =
_(
"Failed to rescan the wallet during initialization");
4492 walletInstance->database->IncrementUpdateCounter();
4500 const TxId txid = wtxOld.GetId();
4501 std::map<TxId, CWalletTx>::iterator mi =
4502 walletInstance->mapWallet.find(txid);
4503 if (mi != walletInstance->mapWallet.end()) {
4520 for (
auto &load_wallet : g_load_wallet_fns) {
4525 walletInstance->SetBroadcastTransactions(
4528 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n",
4529 walletInstance->GetKeyPoolSize());
4530 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n",
4531 walletInstance->mapWallet.size());
4532 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n",
4533 walletInstance->m_address_book.size());
4535 return walletInstance;
4540 bool allow_change)
const {
4541 const auto &address_book_it = m_address_book.find(dest);
4542 if (address_book_it == m_address_book.end()) {
4545 if ((!allow_change) && address_book_it->second.IsChange()) {
4548 return &address_book_it->second;
4552 std::vector<bilingual_str> &warnings) {
4553 int prev_version = GetVersion();
4554 int nMaxVersion = version;
4556 if (nMaxVersion == 0) {
4557 WalletLogPrintf(
"Performing wallet upgrade to %i\n",
FEATURE_LATEST);
4562 WalletLogPrintf(
"Allowing wallet upgrade up to %i\n", nMaxVersion);
4565 if (nMaxVersion < GetVersion()) {
4566 error =
_(
"Cannot downgrade wallet");
4570 SetMaxVersion(nMaxVersion);
4576 int max_version = GetVersion();
4580 error =
_(
"Cannot upgrade a non HD split wallet without upgrading to " 4581 "support pre split keypool. Please use version 200300 or no " 4582 "version specified.");
4586 for (
auto spk_man : GetActiveScriptPubKeyMans()) {
4587 if (!spk_man->Upgrade(prev_version, error)) {
4600 ReacceptWalletTransactions();
4603 chain().requestMempoolTransactions(*
this);
4607 return database->Backup(strDest);
4613 m_pre_split =
false;
4618 vchPubKey = vchPubKeyIn;
4619 fInternal = internalIn;
4620 m_pre_split =
false;
4624 assert(pwallet !=
nullptr);
4626 if (isUnconfirmed() || isAbandoned()) {
4630 return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) *
4631 (isConflicted() ? -1 : 1);
4635 if (!IsCoinBase()) {
4639 int chain_depth = GetDepthInMainChain();
4641 assert(chain_depth >= 0);
4647 return GetBlocksToMaturity() > 0;
4650 std::vector<OutputGroup>
4652 const size_t max_ancestors)
const {
4653 std::vector<OutputGroup> groups;
4654 std::map<CTxDestination, OutputGroup> gmap;
4655 std::set<CTxDestination> full_groups;
4657 for (
const auto &output : outputs) {
4658 if (output.fSpendable) {
4660 CInputCoin input_coin = output.GetInputCoin();
4662 size_t ancestors, descendants;
4663 chain().getTransactionAncestry(output.tx->GetId(), ancestors,
4668 auto it = gmap.find(dst);
4669 if (it != gmap.end()) {
4676 if (it->second.m_outputs.size() >=
4678 groups.push_back(it->second);
4680 full_groups.insert(dst);
4682 it->second.
Insert(input_coin, output.nDepth,
4684 ancestors, descendants);
4686 gmap[dst].Insert(input_coin, output.nDepth,
4691 groups.emplace_back(input_coin, output.nDepth,
4698 for (
auto &it : gmap) {
4699 auto &group = it.second;
4700 if (full_groups.count(it.first) > 0) {
4703 group.m_ancestors = max_ancestors - 1;
4705 groups.push_back(group);
4712 return HasEncryptionKeys();
4720 return vMasterKey.empty();
4733 NotifyStatusChanged(
this);
4740 for (
const auto &spk_man_pair : m_spk_managers) {
4741 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn,
4746 vMasterKey = vMasterKeyIn;
4748 NotifyStatusChanged(
this);
4753 std::set<ScriptPubKeyMan *> spk_mans;
4754 for (
bool internal : {
false,
true}) {
4756 auto spk_man = GetScriptPubKeyMan(t,
internal);
4758 spk_mans.insert(spk_man);
4766 std::set<ScriptPubKeyMan *> spk_mans;
4767 for (
const auto &spk_man_pair : m_spk_managers) {
4768 spk_mans.insert(spk_man_pair.second.get());
4774 bool internal)
const {
4775 const std::map<OutputType, ScriptPubKeyMan *> &spk_managers =
4776 internal ? m_internal_spk_managers : m_external_spk_managers;
4777 std::map<OutputType, ScriptPubKeyMan *>::const_iterator it =
4778 spk_managers.find(type);
4779 if (it == spk_managers.end()) {
4781 "%s scriptPubKey Manager for output type %d does not exist\n",
4782 internal ?
"Internal" :
"External", static_cast<int>(type));
4788 std::set<ScriptPubKeyMan *>
4791 std::set<ScriptPubKeyMan *> spk_mans;
4792 for (
const auto &spk_man_pair : m_spk_managers) {
4793 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4794 spk_mans.insert(spk_man_pair.second.get());
4802 for (
const auto &spk_man_pair : m_spk_managers) {
4803 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4804 return spk_man_pair.second.get();
4811 if (m_spk_managers.count(
id) > 0) {
4812 return m_spk_managers.at(
id).get();
4817 std::unique_ptr<SigningProvider>
4820 return GetSolvingProvider(script, sigdata);
4823 std::unique_ptr<SigningProvider>
4826 for (
const auto &spk_man_pair : m_spk_managers) {
4827 if (spk_man_pair.second->CanProvide(script, sigdata)) {
4828 return spk_man_pair.second->GetSolvingProvider(script);
4842 if (it == m_internal_spk_managers.end()) {
4849 SetupLegacyScriptPubKeyMan();
4850 return GetLegacyScriptPubKeyMan();
4854 if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() ||
4862 m_internal_spk_managers[type] = spk_manager.get();
4863 m_external_spk_managers[type] = spk_manager.get();
4865 m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
4873 return !mapMasterKeys.empty();
4877 for (
const auto &spk_man : GetActiveScriptPubKeyMans()) {
4879 spk_man->NotifyCanGetAddressesChanged.connect(
4886 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(
4888 m_spk_managers[id] = std::move(spk_manager);
4904 for (
bool internal : {
false,
true}) {
4907 std::make_unique<DescriptorScriptPubKeyMan>(*
this, t,
internal);
4910 throw std::runtime_error(
4911 std::string(__func__) +
4912 ": Wallet is locked, cannot setup new descriptors");
4914 if (!spk_manager->CheckDecryptionKey(vMasterKey) &&
4915 !spk_manager->Encrypt(vMasterKey,
nullptr)) {
4916 throw std::runtime_error(
4917 std::string(__func__) +
4918 ": Could not encrypt new descriptors");
4921 spk_manager->SetupDescriptorGeneration(master_key);
4922 uint256 id = spk_manager->GetID();
4923 m_spk_managers[id] = std::move(spk_manager);
4924 SetActiveScriptPubKeyMan(
id, t,
internal);
4930 bool internal,
bool memonly) {
4932 "Setting spkMan to active: id = %s, type = %d, internal = %d\n",
4933 id.
ToString(), static_cast<int>(type), static_cast<int>(
internal));
4935 internal ? m_internal_spk_managers : m_external_spk_managers;
4936 auto spk_man = m_spk_managers.at(
id).get();
4937 spk_man->SetType(type,
internal);
4938 spk_mans[type] = spk_man;
4944 throw std::runtime_error(
4945 std::string(__func__) +
4946 ": writing active ScriptPubKeyMan id failed");
4958 return spk_man !=
nullptr;
4963 for (
auto &spk_man_pair : m_spk_managers) {
4968 spk_man_pair.second.get());
4980 const std::string &label) {
4983 "Cannot add WalletDescriptor to a non-descriptor wallet\n");
4988 auto new_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(*
this, desc);
4992 auto old_spk_man = GetDescriptorScriptPubKeyMan(desc);
4994 WalletLogPrintf(
"Update existing descriptor: %s\n",
4998 LOCK(old_spk_man->cs_desc_man);
4999 new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache);
5003 auto old_spk_man_id = old_spk_man->GetID();
5004 for (
bool internal : {
false,
true}) {
5006 auto active_spk_man = GetScriptPubKeyMan(t,
internal);
5007 if (active_spk_man &&
5008 active_spk_man->GetID() == old_spk_man_id) {
5010 m_internal_spk_managers.erase(t);
5012 m_external_spk_managers.erase(t);
5018 m_spk_managers.erase(old_spk_man_id);
5022 for (
const auto &entry : signing_provider.
keys) {
5023 const CKey &key = entry.second;
5024 new_spk_man->AddDescriptorKey(key, key.
GetPubKey());
5028 new_spk_man->TopUp();
5033 auto script_pub_keys = new_spk_man->GetScriptPubKeys();
5034 if (script_pub_keys.empty()) {
5036 "Could not generate scriptPubKeys (cache is empty)\n");
5042 SetAddressBook(dest, label,
"receive");
5047 auto ret = new_spk_man.get();
5048 m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
5051 ret->WriteDescriptor();
bool IsEquivalentTo(const CWalletTx &tx) const
std::shared_ptr< const CTransaction > CTransactionRef
bool TxnCommit()
Commit current transaction.
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!
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
const fs::path & GetPath() const
Get wallet absolute path.
Helper for findBlock to selectively return pieces of block data.
void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly=false)
Sets the active ScriptPubKeyMan for the specified type and internal.
Amount m_watchonly_immature
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
Amount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Amount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
void blockConnected(const CBlock &block, int height) override
uint64_t GetRand(uint64_t nMax) noexcept
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void BindWallet(CWallet *pwalletIn)
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 IsLegacy() const
Determine if we are a legacy wallet.
static std::vector< std::shared_ptr< CWallet > > vpwallets GUARDED_BY(cs_wallets)
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
static constexpr Amount zero()
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
bool ReadBestBlock(CBlockLocator &locator)
std::map< std::string, std::string > mapValue_t
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
static uint32_t GetLocktimeForNewTransaction(interfaces::Chain &chain, const BlockHash &block_hash, int block_height)
Return a height-based locktime for new transactions (uses the height of the current chain tip unless ...
std::shared_ptr< Descriptor > descriptor
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, SigHashType sighash_type=SigHashType().withForkId(), bool sign=true, bool bip32derivs=true) const
Fills out a PSBT with information from the wallet.
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
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
bool TransactionCanBeAbandoned(const TxId &txid) const
Return whether transaction can be abandoned.
std::shared_ptr< CWallet > GetWallet(const std::string &name)
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
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.
size_t change_output_size
int64_t GetTimeMillis()
Returns the system time (not mockable)
Amount GetAvailableBalance(const CCoinControl *coinControl=nullptr) const
static Mutex g_wallet_release_mutex
virtual BlockHash getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
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.
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
std::optional< int > last_scanned_height
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
constexpr OutputType DEFAULT_CHANGE_TYPE
Default for -changetype.
bool FundTransaction(CMutableTransaction &tx, Amount &nFeeRet, int &nChangePosInOut, bilingual_str &error, bool lockUnspents, const std::set< int > &setSubtractFeeFromOutputs, CCoinControl coinControl)
Insert additional inputs into the transaction by calling CreateTransaction();.
bool UpgradeWallet(int version, bilingual_str &error, std::vector< bilingual_str > &warnings)
Upgrade the wallet.
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)
CoinSelectionParams coin_selection_params(false, 0, 0, CFeeRate(Amount::zero()), 0)
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
virtual bool isInitialBlockDownload()=0
Check if in IBD.
int64_t GetOldestKeyPoolTime() const
void ListSelected(std::vector< COutPoint > &vOutpoints) const
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
static CTransactionRef MakeTransactionRef()
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
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)...
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(cs_main
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
bool SelectCoinsMinConf(const Amount nTargetValue, const CoinEligibilityFilter &eligibility_filter, std::vector< OutputGroup > groups, std::set< CInputCoin > &setCoinsRet, Amount &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...
const CKeyingMaterial & GetEncryptionKey() const override
bool CanGetAddresses(bool internal=false) const
Returns true if the wallet can give out new addresses.
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
const TxId & GetTxId() const
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
int m_min_depth
Minimum chain depth value for coin availability.
static constexpr Amount SATOSHI
static const Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
std::vector< CTxOut > vout
void MarkDirty()
make sure balances are recalculated
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
std::vector< std::shared_ptr< CWallet > > GetWallets()
bool IsLocked() const override
bool SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const Amount &target_value, const Amount &cost_of_change, std::set< CInputCoin > &out_set, Amount &value_ret, const Amount not_input_fees)
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
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.
constexpr Amount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
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.
DBErrors ZapWalletTx(std::vector< CWalletTx > &vWtx)
BlockHash last_scanned_block
Hash and height of most recent block that was successfully scanned.
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
bool WriteTx(const CWalletTx &wtx)
static RecursiveMutex cs_wallets
bool WriteName(const CTxDestination &address, const std::string &strName)
DBErrors LoadWallet(CWallet *pwallet)
isminetype IsMine(const CTxDestination &dest) const
void chainStateFlushed(const CBlockLocator &loc) override
static bool Verify(const CChainParams &chainParams, interfaces::Chain &chain, const WalletLocation &location, bilingual_str &error_string, std::vector< bilingual_str > &warnings)
Verify wallet naming and perform salvage on the wallet if required.
bool isUnconfirmed() const
DBErrors
Error statuses for the wallet database.
Amount GetImmatureCredit(bool fUseCache=true) const
bool EncryptWallet(const SecureString &strWalletPassphrase)
BlockHash last_failed_block
Hash of the most recent block that could not be scanned due to read errors or pruning.
bool WriteWalletFlags(const uint64_t flags)
enum CWallet::ScanResult::@23 status
bool Exists() const
Return whether the wallet exists.
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
bool IsChange(const CTxOut &txout) const
constexpr Amount HIGH_APS_FEE
discourage APS fee higher than this amount
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
ScanResult ScanForWalletTransactions(const BlockHash &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate)
Scan the block chain (starting in start_block) for transactions from or to us.
void LoadToWallet(CWalletTx &wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node...
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false) override
signify that a particular wallet feature is now used.
WalletFeature
(client) version numbers for particular wallet features
bool BackupWallet(const std::string &strDest) const
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
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)
std::string ToString() const
bool KnapsackSolver(const Amount nTargetValue, std::vector< OutputGroup > &groups, std::set< CInputCoin > &setCoinsRet, Amount &nValueRet)
bool CreateTransactionInternal(const std::vector< CRecipient > &vecSend, CTransactionRef &tx, Amount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, bool sign)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
void SetSpentKeyState(WalletBatch &batch, const TxId &txid, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
Amount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
bool WriteBestBlock(const CBlockLocator &locator)
bool TxnAbort()
Abort current transaction.
bool MoneyRange(const Amount nValue)
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
bool HasEncryptionKeys() const override
DBErrors ReorderTransactions()
Amount GetAvailableCredit(bool fUseCache=true, const isminefilter &filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in=false)
Amount GetCachableAmount(AmountType type, const isminefilter &filter, bool recalculate=false) const
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
static void NotifyCanGetAddressesChanged(WalletModel *walletmodel)
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
bool DelAddressBook(const CTxDestination &address)
void Insert(const CInputCoin &output, int depth, bool from_me, size_t ancestors, size_t descendants)
constexpr Amount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
Amount GetFee(size_t nBytes) const
Return the fee in satoshis for the given size in bytes.
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
void transactionRemovedFromMempool(const CTransactionRef &ptx) override
const int DEFAULT_MAX_DEPTH
static std::set< std::string > g_unloading_wallet_set
virtual std::optional< int > findFirstBlockWithTimeAndHeight(int64_t time, int height, BlockHash *hash)=0
Return height of the first block in the chain with timestamp equal or greater than the given time and...
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet...
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
Amount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
DBErrors LoadWallet(bool &fFirstRunRet)
std::map< CTxDestination, Amount > GetAddressBalances() const
const std::string & GetName() const
Get wallet name.
void SetSeed(const uint8_t *seed, unsigned int nSeedLen)
static std::shared_ptr< CWallet > CreateWalletFromFile(const CChainParams &chainParams, interfaces::Chain &chain, const WalletLocation &location, bilingual_str &error, std::vector< bilingual_str > &warnings, uint64_t wallet_creation_flags=0)
Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error...
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script, SignatureData &sigdata) const
Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e...
bool IsLockedCoin(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet...
void MarkConflicted(const BlockHash &hashBlock, int conflicting_height, const TxId &txid)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block...
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
bool AbandonTransaction(const TxId &txid)
Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent...
Amount GetCredit(const isminefilter &filter) const
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
An input of a transaction.
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)
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
int CalculateMaximumSignedInputSize(const CTxOut &txout, const CWallet *wallet, bool use_max_sig)
bool m_add_inputs
If false, only selected inputs are used.
static void NotifyAddressBookChanged(WalletModel *walletmodel, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)
bilingual_str _(const char *psz)
Translation function.
fs::path WalletDataFilePath(const fs::path &wallet_path)
Given a wallet directory path or legacy file path, return path to main data file in the wallet databa...
static const BlockHash ABANDON_HASH
Constant used in hashBlock to indicate tx has been abandoned, only used at serialization/deserializat...
CTxDestination destChange
bilingual_str AmountHighWarn(const std::string &optname)
void Select(const COutPoint &output)
An encapsulated public key.
bool fAllowOtherInputs
If false, allows unselected inputs, but requires all selected inputs be used.
Amount GetCredit(const CTxOut &txout, const isminefilter &filter) const
int GetBlocksToMaturity() const
void GetAmounts(std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, Amount &nFee, const isminefilter &filter) const
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)
const int DEFAULT_MIN_DEPTH
void Flush(bool shutdown=false)
Flush wallet (bitdb flush)
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EraseName(const CTxDestination &address)
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
bool EraseDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases a destination data tuple in the store and on disk.
const Config & GetConfig()
Amount m_watchonly_trusted
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()
constexpr OutputType DEFAULT_ADDRESS_TYPE
Default for -addresstype.
isminetype
IsMine() return codes.
unsigned int size() const
Simple read-only vector-like interface.
WalletCreationStatus CreateWallet(const CChainParams ¶ms, interfaces::Chain &chain, const SecureString &passphrase, uint64_t wallet_creation_flags, const std::string &name, bilingual_str &error, std::vector< bilingual_str > &warnings, std::shared_ptr< CWallet > &result)
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)
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Descriptor with some wallet metadata.
static void NotifyTransactionChanged(TransactionTableModel *ttm, const TxId &txid, ChangeType status)
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly)
Overwrite all flags by the given uint64_t.
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
An outpoint - a combination of a transaction hash and an index n into its vout.
bool HasWalletSpend(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Check if a given transaction has any of its outputs spent by another transaction in the wallet...
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
const uint8_t * begin() const
unsigned int fTimeReceivedIsTxTime
bool IsAllFromMe(const CTransaction &tx, const isminefilter &filter) const
Returns whether all of the inputs match the filter.
Amount GetChange(const CTxOut &txout) const
static const size_t OUTPUT_GROUP_MAX_ENTRIES
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
Special output type for change outputs only.
std::vector< PSBTInput > inputs
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose=true)
static std::unique_ptr< BerkeleyDatabase > Create(const fs::path &path)
Return object for accessing database at specified path.
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
Return implementation of Wallet interface.
void updatedBlockTip() override
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
std::shared_ptr< CWallet > LoadWallet(const CChainParams &chainParams, interfaces::Chain &chain, const WalletLocation &location, bilingual_str &error, std::vector< bilingual_str > &warnings)
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< uint8_t > vchCryptedKey
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys...
static void ReleaseWallet(CWallet *wallet)
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control)
Estimate the minimum fee rate considering user set parameters and the required fee.
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool IsImmatureCoinBase() const
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 ...
Amount m_watchonly_untrusted_pending
std::string ShellEscape(const std::string &arg)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
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)
void GetStrongRandBytes(uint8_t *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
std::optional< unsigned int > m_confirm_target
Override the default confirmation target if set.
std::string get_filesystem_error_message(const fs::filesystem_error &e)
void AddToSpends(const COutPoint &outpoint, const TxId &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ErasePurpose(const CTxDestination &address)
const unsigned int WALLET_CRYPTO_SALT_SIZE
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
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.
Amount GetMinimumFee(const CWallet &wallet, unsigned int nTxBytes, const CCoinControl &coin_control)
Estimate the minimum fee considering user set parameters and the required fee.
bool IsSpentKey(const TxId &txid, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
DBErrors ZapWalletTx(std::vector< CWalletTx > &vWtx)
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
void SetWalletFlag(uint64_t flags)
Set a single wallet flag.
A BlockHash is a unqiue identifier for a block.
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
int64_t GetTxTime() const
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &tx, Amount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, bool sign=true)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn, const CTxOut &txout)
Extract signature data from a transaction input, and insert it.
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
void transactionAddedToMempool(const CTransactionRef &tx) override
void ResendWalletTransactions()
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
const CChainParams & Params()
Return the currently selected parameters.
Amount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
Serialized script, used inside transaction inputs and outputs.
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction, spends it:
A TxId is the identifier of a transaction.
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
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet...
static std::condition_variable g_wallet_release_cv
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