45 #include <boost/algorithm/string/replace.hpp> 51 "You need to rescan the blockchain in order to correctly mark used " 52 "destinations in the past. Until this is done, some destinations may " 53 "be considered unused, even if the opposite is the case." 66 if (value.isStr() && value.get_str() == wallet_name)
return true;
75 if (!setting_value.
isArray())
return true;
78 if (!value.isStr() || value.get_str() != wallet_name) new_value.
push_back(value);
80 if (new_value.
size() == setting_value.
size())
return true;
85 const std::string& wallet_name,
86 std::optional<bool> load_on_startup,
87 std::vector<bilingual_str>& warnings)
89 if (!load_on_startup)
return;
91 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
93 warnings.emplace_back(
Untranslated(
"Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
101 std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(),
wallet);
102 if (i != vpwallets.end())
return false;
103 vpwallets.push_back(
wallet);
104 wallet->ConnectScriptPubKeyManNotifiers();
105 wallet->NotifyCanGetAddressesChanged();
109 bool RemoveWallet(
const std::shared_ptr<CWallet>&
wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
117 wallet->m_chain_notifications_handler.reset();
119 std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(),
wallet);
120 if (i == vpwallets.end())
return false;
131 std::vector<bilingual_str> warnings;
144 for (
const std::shared_ptr<CWallet>&
wallet : vpwallets) {
153 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
167 wallet->WalletLogPrintf(
"Releasing wallet\n");
173 if (g_unloading_wallet_set.erase(
name) == 0) {
187 auto it = g_unloading_wallet_set.insert(
name);
199 while (g_unloading_wallet_set.count(
name) == 1) {
223 wallet->postInitProcess();
229 }
catch (
const std::runtime_error& e) {
240 if (!result.second) {
245 auto wallet = LoadWalletInternal(chain,
name, load_on_start, options, status,
error, warnings);
261 if (!passphrase.empty()) {
267 error =
Untranslated(
"Private keys must be disabled when using an external signer");
274 error =
Untranslated(
"Descriptor support must be enabled when using an external signer");
289 error =
Untranslated(
"Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
305 if (!
wallet->EncryptWallet(passphrase)) {
312 if (!
wallet->Unlock(passphrase)) {
322 wallet->SetupDescriptorScriptPubKeyMans();
324 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
325 if (!spk_man->SetupGeneration()) {
339 wallet->postInitProcess();
356 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
357 if (it == mapWallet.end())
359 return &(it->second);
373 spk_man->UpgradeKeyMetadata();
397 for (
const MasterKeyMap::value_type& pMasterKey :
mapMasterKeys)
399 if(!crypter.
SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
401 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
403 if (
Unlock(_vMasterKey, accept_no_keys)) {
427 if(!crypter.
SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
429 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
434 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
435 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(
GetTimeMillis() - nStartTime))));
438 crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
439 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations +
static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
441 if (pMasterKey.second.nDeriveIterations < 25000)
442 pMasterKey.second.nDeriveIterations = 25000;
444 WalletLogPrintf(
"Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
446 if (!crypter.
SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
448 if (!crypter.
Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
470 if (nWalletVersion >= nVersion)
472 nWalletVersion = nVersion;
476 if (nWalletVersion > 40000)
485 std::set<uint256> result;
488 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
489 if (it == mapWallet.end())
493 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
495 for (
const CTxIn& txin : wtx.
tx->vin)
497 if (mapTxSpends.count(txin.
prevout) <= 1)
499 range = mapTxSpends.equal_range(txin.
prevout);
500 for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
501 result.insert(_it->second);
509 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
510 return (iter != mapTxSpends.end() && iter->first.hash == txid);
529 int nMinOrderPos = std::numeric_limits<int>::max();
531 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
532 const CWalletTx* wtx = &mapWallet.at(it->second);
544 for (TxSpends::iterator it = range.first; it != range.second; ++it)
546 const uint256& hash = it->second;
548 if (copyFrom == copyTo)
continue;
549 assert(copyFrom &&
"Oldest wallet transaction in range assumed to have been found.");
569 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
570 range = mapTxSpends.equal_range(outpoint);
572 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
574 const uint256& wtxid = it->second;
575 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
576 if (mit != mapWallet.end()) {
577 int depth = mit->second.GetDepthInMainChain();
578 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);
599 auto it = mapWallet.find(wtxid);
600 assert(it != mapWallet.end());
602 if (thisTx.IsCoinBase())
605 for (
const CTxIn& txin : thisTx.tx->vin)
626 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
627 kMasterKey.nDeriveIterations =
static_cast<unsigned int>(2500000 / ((double)(
GetTimeMillis() - nStartTime)));
630 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
631 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations +
static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(
GetTimeMillis() - nStartTime)))) / 2;
633 if (kMasterKey.nDeriveIterations < 25000)
634 kMasterKey.nDeriveIterations = 25000;
636 WalletLogPrintf(
"Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
638 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
640 if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
648 delete encrypted_batch;
649 encrypted_batch =
nullptr;
655 auto spk_man = spk_man_pair.second.get();
656 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
658 delete encrypted_batch;
659 encrypted_batch =
nullptr;
670 delete encrypted_batch;
671 encrypted_batch =
nullptr;
677 delete encrypted_batch;
678 encrypted_batch =
nullptr;
681 Unlock(strWalletPassphrase);
688 if (spk_man->IsHDEnabled()) {
689 if (!spk_man->SetupGeneration(
true)) {
720 typedef std::multimap<int64_t, CWalletTx*>
TxItems;
723 for (
auto& entry : mapWallet)
730 std::vector<int64_t> nOrderPosOffsets;
731 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
738 nOrderPos = nOrderPosNext++;
739 nOrderPosOffsets.push_back(nOrderPos);
746 int64_t nOrderPosOff = 0;
747 for (
const int64_t& nOffsetStart : nOrderPosOffsets)
749 if (nOrderPos >= nOffsetStart)
752 nOrderPos += nOrderPosOff;
753 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
771 int64_t nRet = nOrderPosNext++;
784 for (std::pair<const uint256, CWalletTx>& item : mapWallet)
785 item.second.MarkDirty();
793 auto mi = mapWallet.find(originalHash);
796 assert(mi != mapWallet.end());
801 assert(wtx.mapValue.count(
"replaced_by_txid") == 0);
803 wtx.mapValue[
"replaced_by_txid"] = newHash.
ToString();
815 WalletLogPrintf(
"%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
835 tx_destinations.insert(dst);
858 assert(spk_man !=
nullptr);
859 for (
const auto& keyid :
GetAffectedKeys(srctx->
tx->vout[n].scriptPubKey, *spk_man)) {
888 std::set<CTxDestination> tx_destinations;
890 for (
const CTxIn& txin : tx->vin) {
899 auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this, tx));
901 bool fInsertedNew = ret.second;
902 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
930 if (tx->HasWitness() && !wtx.
tx->HasWitness()) {
937 WalletLogPrintf(
"AddToWallet %s %s%s\n", hash.
ToString(), (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
940 if (fInsertedNew || fUpdated)
952 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
956 boost::replace_all(strCmd,
"%s", hash.
GetHex());
957 if (confirm.
status == CWalletTx::Status::CONFIRMED)
962 boost::replace_all(strCmd,
"%b",
"unconfirmed");
963 boost::replace_all(strCmd,
"%h",
"-1");
973 std::thread t(runCommand, strCmd);
983 const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(
this,
nullptr));
985 if (!fill_wtx(wtx, ins.second)) {
1013 for (
const CTxIn& txin : wtx.
tx->vin) {
1015 if (it != mapWallet.end()) {
1033 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.
prevout);
1034 while (range.first != range.second) {
1035 if (range.first->second != tx.
GetHash()) {
1036 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);
1044 bool fExisted = mapWallet.count(tx.
GetHash()) != 0;
1045 if (fExisted && !fUpdate)
return false;
1057 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1078 for (
const CTxIn& txin : tx->vin) {
1080 if (it != mapWallet.end()) {
1081 it->second.MarkDirty();
1092 std::set<uint256> todo;
1093 std::set<uint256> done;
1096 auto it = mapWallet.find(hashTx);
1097 assert(it != mapWallet.end());
1099 if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1103 todo.insert(hashTx);
1105 while (!todo.empty()) {
1109 auto it = mapWallet.find(now);
1110 assert(it != mapWallet.end());
1114 assert(currentconfirm <= 0);
1116 if (currentconfirm == 0 && !wtx.isAbandoned()) {
1118 assert(!wtx.InMempool());
1124 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1125 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1126 if (!done.count(iter->second)) {
1127 todo.insert(iter->second);
1144 int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1149 if (conflictconfirms >= 0)
1155 std::set<uint256> todo;
1156 std::set<uint256> done;
1158 todo.insert(hashTx);
1160 while (!todo.empty()) {
1164 auto it = mapWallet.find(now);
1165 assert(it != mapWallet.end());
1168 if (conflictconfirms < currentconfirm) {
1171 wtx.m_confirm.nIndex = 0;
1172 wtx.m_confirm.hashBlock = hashBlock;
1173 wtx.m_confirm.block_height = conflicting_height;
1174 wtx.setConflicted();
1178 TxSpends::const_iterator iter = mapTxSpends.lower_bound(
COutPoint(now, 0));
1179 while (iter != mapTxSpends.end() && iter->first.hash == now) {
1180 if (!done.count(iter->second)) {
1181 todo.insert(iter->second);
1207 auto it = mapWallet.find(tx->GetHash());
1208 if (it != mapWallet.end()) {
1209 it->second.fInMempool =
true;
1215 auto it = mapWallet.find(tx->GetHash());
1216 if (it != mapWallet.end()) {
1217 it->second.fInMempool =
false;
1255 m_last_block_processed_height = height;
1256 m_last_block_processed = block_hash;
1257 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1258 SyncTransaction(block.
vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1271 m_last_block_processed_height = height - 1;
1284 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1300 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.
prevout.
hash);
1301 if (mi != mapWallet.end())
1329 result = std::max(result, spk_man_pair.second->IsMine(script));
1355 throw std::runtime_error(std::string(__func__) +
": value out of range");
1365 result &= spk_man->IsHDEnabled();
1376 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1383 void CWallet::SetWalletFlag(uint64_t
flags)
1388 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1402 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1433 throw std::runtime_error(std::string(__func__) +
": writing wallet flags failed");
1465 for (
const auto& txout : txouts)
1482 LOCK(spk_man->cs_KeyStore);
1483 return spk_man->ImportScripts(scripts, timestamp);
1492 LOCK(spk_man->cs_KeyStore);
1493 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1496 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)
1502 LOCK(spk_man->cs_KeyStore);
1503 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool,
internal, timestamp);
1506 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)
1512 LOCK(spk_man->cs_KeyStore);
1513 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1518 for (
const CScript& script : script_pub_keys) {
1542 int start_height = 0;
1587 uint256 block_hash = start_block;
1599 double progress_current = progress_begin;
1600 int block_height = start_height;
1602 if (progress_end - progress_begin > 0.0) {
1603 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1607 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1612 WalletLogPrintf(
"Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1621 bool block_still_active =
false;
1622 bool next_block =
false;
1628 if (!block_still_active) {
1635 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size(); ++posInBlock) {
1636 SyncTransaction(block.
vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1646 if (max_height && block_height >= *max_height) {
1657 block_hash = next_block_hash;
1662 const uint256 prev_tip_hash = tip_hash;
1664 if (!max_height && prev_tip_hash != tip_hash) {
1672 WalletLogPrintf(
"Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1674 }
else if (block_height &&
chain().shutdownRequested()) {
1675 WalletLogPrintf(
"Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1688 std::map<int64_t, CWalletTx*> mapSorted;
1691 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1692 const uint256& wtxid = item.first;
1699 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1704 for (
const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1706 std::string unused_err_string;
1741 std::set<uint256> result;
1746 result.erase(myHash);
1764 if (!
chain().isReadyToBroadcast())
return;
1774 int submitted_tx_count = 0;
1780 for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1786 std::string unused_err_string;
1791 if (submitted_tx_count > 0) {
1792 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
1800 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
1801 pwallet->ResendWalletTransactions();
1816 std::map<COutPoint, Coin> coins;
1817 for (
auto& input : tx.
vin) {
1818 std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
1819 if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
1825 std::map<int, std::string> input_errors;
1835 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
1852 for (
unsigned int i = 0; i < psbtx.
tx->vin.size(); ++i) {
1853 const CTxIn& txin = psbtx.
tx->vin[i];
1863 const auto it = mapWallet.find(txhash);
1864 if (it != mapWallet.end()) {
1875 int n_signed_this_spkm = 0;
1876 TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
1882 (*n_signed) += n_signed_this_spkm;
1888 for (
const auto& input : psbtx.
inputs) {
1900 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
1901 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
1911 return *change_type;
1922 for (
const auto& recipient : vecSend) {
1924 int witnessversion = 0;
1925 std::vector<unsigned char> witnessprogram;
1926 if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
1951 wtx.
mapValue = std::move(mapValue);
1959 for (
const CTxIn& txin : tx->vin) {
1967 CWalletTx& wtx = mapWallet.at(tx->GetHash());
1974 std::string err_string;
1976 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
1991 spk_man_pair.second->RewriteDB();
2002 return nLoadWalletRet;
2011 for (
const uint256& hash : vHashOut) {
2012 const auto& it = mapWallet.find(hash);
2013 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2014 for (
const auto& txin : it->second.tx->vin)
2015 mapTxSpends.erase(txin.prevout);
2016 mapWallet.erase(it);
2025 spk_man_pair.second->RewriteDB();
2031 return nZapSelectTxRet;
2040 bool fUpdated =
false;
2044 std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2045 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2046 m_address_book[address].SetLabel(strName);
2047 if (!strPurpose.empty())
2048 m_address_book[address].purpose = strPurpose;
2079 for (
const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
2083 m_address_book.erase(address);
2098 if (legacy_spk_man) {
2099 return legacy_spk_man->KeypoolCountExternalKeys();
2102 unsigned int count = 0;
2104 count += spk_man.second->GetKeyPoolSize();
2114 unsigned int count = 0;
2116 count += spk_man->GetKeyPoolSize();
2126 res &= spk_man->TopUp(kpSize);
2135 bool result =
false;
2139 result = spk_man->GetNewDestination(type, dest,
error);
2167 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2169 oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2175 for (
auto& entry : mapWallet) {
2178 for (
unsigned int i = 0; i < wtx.
tx->vout.size(); i++) {
2191 std::set<CTxDestination> result;
2192 for (
const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
2194 if (item.second.IsChange())
continue;
2196 const std::string& strName = item.second.GetLabel();
2197 if (strName == label)
2198 result.insert(address);
2248 if (spk_man ==
nullptr) {
2252 if (signer_spk_man ==
nullptr) {
2256 return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2262 setLockedCoins.insert(output);
2268 setLockedCoins.erase(output);
2274 setLockedCoins.clear();
2282 return (setLockedCoins.count(outpt) > 0);
2288 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2289 it != setLockedCoins.end(); it++) {
2291 vOutpts.push_back(outpt);
2299 mapKeyBirth.clear();
2302 std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
2309 assert(spk_man !=
nullptr);
2313 for (
const auto& entry : spk_man->mapKeyMetadata) {
2314 if (entry.second.nCreateTime) {
2315 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2321 if (mapKeyBirth.count(keyid) == 0)
2322 mapKeyFirstBlock[keyid] = &max_confirm;
2326 if (mapKeyFirstBlock.empty())
2330 for (
const auto& entry : mapWallet) {
2335 for (
const CTxOut &txout : wtx.
tx->vout) {
2339 auto rit = mapKeyFirstBlock.find(keyid);
2350 for (
const auto& entry : mapKeyFirstBlock) {
2385 int64_t latestEntry = 0;
2388 int64_t latestTolerated = latestNow + 300;
2390 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2400 if (nSmartTime <= latestTolerated) {
2401 latestEntry = nSmartTime;
2402 if (nSmartTime > latestNow) {
2403 latestNow = nSmartTime;
2409 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2419 const std::string key{
"used"};
2420 if (std::get_if<CNoDestination>(&dest))
2424 if (
auto* data =
util::FindKey(m_address_book, dest)) data->destdata.erase(key);
2428 const std::string value{
"1"};
2429 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2435 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2440 const std::string key{
"used"};
2441 std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
2442 if(i != m_address_book.end())
2444 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2445 if(j != i->second.destdata.end())
2455 const std::string
prefix{
"rr"};
2456 std::vector<std::string> values;
2457 for (
const auto& address : m_address_book) {
2458 for (
const auto& data : address.second.destdata) {
2460 values.emplace_back(data.second);
2469 const std::string key{
"rr" +
id};
2471 if (value.empty()) {
2490 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2491 if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
2492 (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
2493 (path_type == fs::regular_file && fs::path(
name).filename() ==
name))) {
2495 "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " 2496 "database/log.?????????? files can be stored, a location where such a directory could be created, " 2497 "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2502 return MakeDatabase(wallet_path, options, status, error_string);
2507 const std::string& walletFile = database->Filename();
2513 DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2516 error =
strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2521 warnings.push_back(
strprintf(
_(
"Error reading %s! All keys read correctly, but transaction data" 2522 " or address book entries might be missing or incorrect."),
2541 const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2549 walletInstance->AddWalletFlags(wallet_creation_flags);
2553 walletInstance->SetupLegacyScriptPubKeyMan();
2557 LOCK(walletInstance->cs_wallet);
2559 walletInstance->SetupDescriptorScriptPubKeyMans();
2563 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2564 if (!spk_man->SetupGeneration()) {
2565 error =
_(
"Unable to generate initial keys");
2577 error =
strprintf(
_(
"Error loading %s: Private keys can only be disabled during creation"), walletFile);
2580 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2581 if (spk_man->HavePrivateKeys()) {
2582 warnings.push_back(
strprintf(
_(
"Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2601 walletInstance->m_default_change_type = out_type;
2612 _(
"This is the minimum transaction fee you pay on every transaction."));
2614 walletInstance->m_min_fee =
CFeeRate(n);
2618 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
2620 if (max_aps_fee ==
"-1") {
2628 _(
"This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2630 walletInstance->m_max_aps_fee = n;
2641 _(
"This is the transaction fee you may pay when fee estimates are not available."));
2643 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
2646 walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
2656 _(
"This is the transaction fee you may discard if change is smaller than dust at this level"));
2658 walletInstance->m_discard_rate =
CFeeRate(nFeePerK);
2668 _(
"This is the transaction fee you will pay if you send a transaction."));
2670 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
2672 error =
strprintf(
_(
"Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
2685 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
2688 error =
strprintf(
_(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
2692 walletInstance->m_default_max_tx_fee = nMaxFee;
2697 _(
"The wallet will avoid paying less than the minimum relay fee."));
2704 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
GetTimeMillis() - nStart);
2707 walletInstance->TopUpKeyPool();
2709 LOCK(walletInstance->cs_wallet);
2717 for (
auto& load_wallet : g_load_wallet_fns) {
2725 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
2726 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n", walletInstance->mapWallet.size());
2727 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n", walletInstance->m_address_book.size());
2730 return walletInstance;
2735 LOCK(walletInstance->cs_wallet);
2737 assert(!walletInstance->m_chain || walletInstance->m_chain == &
chain);
2738 walletInstance->m_chain = &
chain;
2748 walletInstance->m_chain_notifications_handler = walletInstance->chain().
handleNotifications(walletInstance);
2750 int rescan_height = 0;
2755 if (batch.ReadBestBlock(locator)) {
2757 rescan_height = *fork_height;
2765 walletInstance->m_last_block_processed_height = *tip_height;
2767 walletInstance->m_last_block_processed.
SetNull();
2768 walletInstance->m_last_block_processed_height = -1;
2771 if (tip_height && *tip_height != rescan_height)
2774 int block_height = *tip_height;
2775 while (block_height > 0 &&
chain.
haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
2779 if (rescan_height != block_height) {
2786 error =
_(
"Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
2792 walletInstance->WalletLogPrintf(
"Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
2796 std::optional<int64_t> time_first_key;
2797 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
2798 int64_t time = spk_man->GetTimeFirstKey();
2799 if (!time_first_key || time < *time_first_key) time_first_key = time;
2801 if (time_first_key) {
2808 error =
_(
"Failed to rescan the wallet during initialization");
2813 walletInstance->GetDatabase().IncrementUpdateCounter();
2821 const auto& address_book_it = m_address_book.find(dest);
2822 if (address_book_it == m_address_book.end())
return nullptr;
2823 if ((!allow_change) && address_book_it->second.IsChange()) {
2826 return &address_book_it->second;
2838 if (version < prev_version) {
2839 error =
strprintf(
_(
"Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
2847 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);
2855 if (!spk_man->Upgrade(prev_version, version,
error)) {
2908 assert(chain_depth >= 0);
2929 return vMasterKey.empty();
2951 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
2955 vMasterKey = vMasterKeyIn;
2963 std::set<ScriptPubKeyMan*> spk_mans;
2964 for (
bool internal : {
false,
true}) {
2968 spk_mans.insert(spk_man);
2977 std::set<ScriptPubKeyMan*> spk_mans;
2979 spk_mans.insert(spk_man_pair.second.get());
2987 std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
2988 if (it == spk_managers.end()) {
2996 std::set<ScriptPubKeyMan*> spk_mans;
2998 if (spk_man_pair.second->CanProvide(script, sigdata)) {
2999 spk_mans.insert(spk_man_pair.second.get());
3009 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3010 return spk_man_pair.second.get();
3033 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3034 return spk_man_pair.second->GetSolvingProvider(script);
3116 for (
bool internal : {
false,
true}) {
3126 throw std::runtime_error(std::string(__func__) +
": Wallet is locked, cannot setup new descriptors");
3128 if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3129 throw std::runtime_error(std::string(__func__) +
": Could not encrypt new descriptors");
3132 spk_manager->SetupDescriptorGeneration(master_key, t,
internal);
3133 uint256 id = spk_manager->GetID();
3145 if (!signer_res.
isObject())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3146 for (
bool internal : {
false,
true}) {
3147 const UniValue& descriptor_vals =
find_value(signer_res,
internal ?
"internal" :
"receive");
3148 if (!descriptor_vals.
isArray())
throw std::runtime_error(std::string(__func__) +
": Unexpected result");
3150 std::string desc_str = desc_val.getValStr();
3152 std::string dummy_error;
3153 std::unique_ptr<Descriptor> desc =
Parse(desc_str, keys, dummy_error,
false);
3154 if (!desc->GetOutputType()) {
3159 spk_manager->SetupDescriptor(std::move(desc));
3160 uint256 id = spk_manager->GetID();
3172 throw std::runtime_error(std::string(__func__) +
": writing active ScriptPubKeyMan id failed");
3183 WalletLogPrintf(
"Setting spkMan to active: id = %s, type = %d, internal = %d\n",
id.
ToString(), static_cast<int>(type), static_cast<int>(
internal));
3187 spk_mans[type] = spk_man;
3189 if (spk_mans_other[type] == spk_man) {
3190 spk_mans_other.erase(type);
3199 if (spk_man !=
nullptr && spk_man->GetID() == id) {
3200 WalletLogPrintf(
"Deactivate spkMan: id = %s, type = %d, internal = %d\n",
id.
ToString(), static_cast<int>(type), static_cast<int>(
internal));
3203 throw std::runtime_error(std::string(__func__) +
": erasing active ScriptPubKeyMan id failed");
3207 spk_mans.erase(type);
3219 return spk_man !=
nullptr;
3238 WalletLogPrintf(
"Cannot add WalletDescriptor to a non-descriptor wallet\n");
3246 spk_man->UpdateWalletDescriptor(desc);
3249 spk_man = new_spk_man.get();
3256 for (
const auto& entry : signing_provider.
keys) {
3257 const CKey& key = entry.second;
3258 spk_man->AddDescriptorKey(key, key.
GetPubKey());
3262 if (!spk_man->TopUp()) {
3270 auto script_pub_keys = spk_man->GetScriptPubKeys();
3271 if (script_pub_keys.empty()) {
3272 WalletLogPrintf(
"Could not generate scriptPubKeys (cache is empty)\n");
3283 spk_man->WriteDescriptor();
std::shared_ptr< const CTransaction > CTransactionRef
bool TxnCommit()
Commit current transaction.
virtual bool Backup(const std::string &strDest) const =0
Back up the entire database to a file.
constexpr CAmount HIGH_APS_FEE
discourage APS fee higher than this amount
bool WriteName(const std::string &strAddress, const std::string &strName)
virtual void Flush()=0
Make sure all changes are flushed to database file.
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)
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 Close()
Close wallet database.
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
int64_t nNextResend
The next scheduled rebroadcast of wallet transactions.
void UpgradeDescriptorCache()
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)
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.
Enables interaction with an external signing device or service, such as a hardware wallet...
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::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
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...
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
const unsigned int WALLET_CRYPTO_KEY_SIZE
virtual std::unique_ptr< Handler > handleNotifications(std::shared_ptr< Notifications > notifications)=0
Register handler for notifications.
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
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)
CTxDestination address
The destination.
std::shared_ptr< CWallet > GetWallet(const std::string &name)
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
static void ReleaseWallet(CWallet *wallet)
std::atomic< int64_t > m_best_block_time
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)
Encryption/decryption context with key information.
RecursiveMutex cs_KeyStore
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
CPubKey GetPubKey() const
Compute the public key from a private key.
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
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 WriteMinVersion(int nVersion)
virtual int64_t getAdjustedTime()=0
Get adjusted time.
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...
int64_t GetOldestKeyPoolTime() const
bool MoneyRange(const CAmount &nValue)
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
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
bool isConflicted() 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.
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
const UniValue & get_array() const
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.
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.
Indicates that the wallet needs an external signer.
CAmount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
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.
bool WriteTx(const CWalletTx &wtx)
const CWalletTx * GetWalletTx(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
std::atomic< bool > fAbortRescan
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)
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
bool WriteWalletFlags(const uint64_t flags)
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
virtual double guessVerificationProgress(const uint256 &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) 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...
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
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.
RecursiveMutex cs_wallets
const UniValue & find_value(const UniValue &obj, const std::string &name)
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
Access to the wallet database.
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)
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
interfaces::Chain & chain() const
Interface for accessing chain state.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
int64_t CAmount
Amount in satoshis (Can be negative)
virtual std::optional< int > findLocatorFork(const CBlockLocator &locator)=0
Return height of the highest block on chain in common with the locator, which will either be the orig...
bool WriteBestBlock(const CBlockLocator &locator)
virtual void KeepDestination(int64_t index, const OutputType &type)
bool TxnAbort()
Abort current transaction.
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bool HasEncryptionKeys() const override
std::string ToString(const T &t)
Locale-independent version of std::to_string.
DBErrors ReorderTransactions()
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
bool push_back(const UniValue &val)
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
unsigned int nMasterKeyMaxID
std::shared_ptr< CWallet > LoadWallet(interfaces::Chain &chain, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
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.
virtual bool isInMempool(const uint256 &txid)=0
Check if transaction is in mempool.
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
bool AbandonTransaction(const uint256 &hashTx)
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > database)
Construct wallet with specified name and database implementation.
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.
virtual bool Rewrite(const char *pszSkip=nullptr)=0
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
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...
virtual bool findAncestorByHeight(const uint256 &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
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
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
OutputType m_default_address_type
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
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...
static bool AttachChain(const std::shared_ptr< CWallet > &wallet, interfaces::Chain &chain, bilingual_str &error, std::vector< bilingual_str > &warnings)
Catch wallet up to current chain, scanning new blocks, updating the best block locator and m_last_blo...
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
const uint256 & GetHash() const
void SetTx(CTransactionRef arg)
bilingual_str _(const char *psz)
Translation function.
Removed for conflict with in-block transaction.
virtual void Close()=0
Flush to the database file and close the database.
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...
bilingual_str AmountHighWarn(const std::string &optname)
std::set< uint256 > GetConflicts() const NO_THREAD_SAFETY_ANALYSIS
An encapsulated public key.
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)
int64_t nIndex
The index of the address's key in the keypool.
ScanResult ScanForWalletTransactions(const uint256 &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 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.
virtual void waitForNotificationsIfTipChanged(const uint256 &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip...
uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Remove specified ScriptPubKeyMan from set of active SPK managers.
bool HaveChain() const
Interface to assert chain access.
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual void requestMempoolTransactions(Notifications ¬ifications)=0
Synchronously send transactionAddedToMempool notifications about all current mempool transactions to ...
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)
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
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
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.
unsigned int fTimeReceivedIsTxTime
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
std::map< std::string, std::string > mapValue_t
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
UniValue GetDescriptors(const int account)
Get receive and change Descriptor(s) from device for a given account.
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)
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.
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkConflicted(const uint256 &hashBlock, int conflicting_height, const uint256 &hashTx)
Mark a transaction (and its in-wallet descendants) as conflicting with a particular block...
static CTransactionRef MakeTransactionRef(Tx &&txIn)
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
std::vector< std::string > GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
bool fBroadcastTransactions
Whether this wallet will submit newly created transactions to the node's mempool and prompt rebroadca...
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 ...
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.
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static ExternalSigner GetExternalSigner()
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
CPubKey vchPubKey
The public key.
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool, std::string &error)
const unsigned int WALLET_CRYPTO_SALT_SIZE
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
std::vector< CTransactionRef > vtx
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
WalletDatabase & GetDatabase() const override
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)
std::atomic< uint64_t > m_wallet_flags
WalletFlags set on this wallet.
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
MasterKeyMap mapMasterKeys
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
void ResendWalletTransactions()
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet) ...
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
Serialized script, used inside transaction inputs and outputs.
bool GetReservedDestination(CTxDestination &pubkey, bool internal, std::string &error)
Reserve an address.
bool TopUpKeyPool(unsigned int kpSize=0)
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet...
bool SetAddressReceiveRequest(WalletBatch &batch, const CTxDestination &dest, const std::string &id, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
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
std::set< uint256 > GetConflicts(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs) ...
std::optional< DatabaseFormat > require_format
boost::signals2::signal< void(const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
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)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
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 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)
RecursiveMutex cs_wallet
Main wallet lock.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
std::string EncodeDestination(const CTxDestination &dest)
bool fInternal
Whether this is from the internal (change output) keypool.
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
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we support the named feature
bool IsSpent(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction spends it:
void Flush()
Flush wallet (bitdb flush)
virtual bool broadcastTransaction(const CTransactionRef &tx, const CAmount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
bool IsEquivalentTo(const CWalletTx &tx) const
True if only scriptSigs are different.
unsigned int nTimeReceived
time received by this node
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
std::optional< CMutableTransaction > tx
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
bool IsAddressUsed(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::atomic< double > m_scanning_progress
Indicate that this wallet supports DescriptorScriptPubKeyMan.
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
bool IsSpentKey(const uint256 &hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int64_t GetTime()
Return system time (or mocked time, if set)
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
std::multimap< int64_t, CWalletTx * > TxItems
virtual void ReloadDbEnv()=0
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
bool ParseOutputType(const std::string &type, OutputType &output_type)
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool error(const char *fmt, const Args &... args)
const CWallet *const pwallet
The wallet to reserve from.
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Fetch the inputs and sign with SIGHASH_ALL.
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
enum CWallet::ScanResult::@16 status
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
#define PACKAGE_BUGREPORT
std::set< CKeyID > GetKeys() const override
std::shared_ptr< CWallet > CreateWallet(interfaces::Chain &chain, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool AddWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t returns false if unknown, non-tolerable flags are present ...
virtual bool havePruned()=0
Check if any block has been pruned.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
#define Assert(val)
Identity function.
boost::signals2::signal< void(const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
bool SetAddressUsed(WalletBatch &batch, const CTxDestination &dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, std::string &error)
const CWallet *const pwallet
static constexpr uint64_t KNOWN_WALLET_FLAGS
void KeepDestination()
Keep the address. Do not return it's key to the keypool when this object goes out of scope...
A key from a CWallet's keypool.
constexpr CAmount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
bool SubmitMemoryPoolAndRelay(std::string &err_string, bool relay)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true...
bool EraseName(const std::string &strAddress)
std::vector< std::pair< std::string, std::string > > vOrderForm
void ReturnDestination()
Return reserved address.
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called...
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction &psbt)
Compute a PrecomputedTransactionData object from a psbt.