43 "You need to rescan the blockchain in order to correctly mark used "
44 "destinations in the past. Until this is done, some destinations may "
45 "be considered unused, even if the opposite is the case."},
53 const std::string &wallet_name) {
59 if (value.isStr() && value.get_str() == wallet_name) {
68 const std::string &wallet_name) {
75 if (!value.isStr() || value.get_str() != wallet_name) {
79 if (new_value.
size() == setting_value.
size()) {
86 const std::string &wallet_name,
87 std::optional<bool> load_on_startup,
88 std::vector<bilingual_str> &warnings) {
89 if (!load_on_startup) {
93 warnings.emplace_back(
94 Untranslated(
"Wallet load on startup setting could not be updated, "
95 "so wallet may not be loaded next node startup."));
96 }
else if (!load_on_startup.value() &&
98 warnings.emplace_back(
99 Untranslated(
"Wallet load on startup setting could not be updated, "
100 "so wallet may still be loaded next node startup."));
107 std::vector<std::shared_ptr<CWallet>>::const_iterator i =
108 std::find(vpwallets.begin(), vpwallets.end(),
wallet);
109 if (i != vpwallets.end()) {
112 vpwallets.push_back(
wallet);
113 wallet->ConnectScriptPubKeyManNotifiers();
114 wallet->NotifyCanGetAddressesChanged();
119 std::optional<bool> load_on_start,
120 std::vector<bilingual_str> &warnings) {
127 wallet->m_chain_notifications_handler.reset();
129 std::vector<std::shared_ptr<CWallet>>::iterator i =
130 std::find(vpwallets.begin(), vpwallets.end(),
wallet);
131 if (i == vpwallets.end()) {
143 std::optional<bool> load_on_start) {
144 std::vector<bilingual_str> warnings;
155 for (
const std::shared_ptr<CWallet> &
wallet : vpwallets) {
163 std::unique_ptr<interfaces::Handler>
166 auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(),
167 std::move(load_wallet));
170 g_load_wallet_fns.erase(it);
177 static std::set<std::string>
179 static std::set<std::string>
185 wallet->WalletLogPrintf(
"Releasing wallet\n");
191 if (g_unloading_wallet_set.erase(
name) == 0) {
204 auto it = g_unloading_wallet_set.insert(
name);
216 while (g_unloading_wallet_set.count(
name) == 1) {
223 std::shared_ptr<CWallet>
225 std::optional<bool> load_on_start,
229 std::unique_ptr<WalletDatabase> database =
237 std::shared_ptr<CWallet>
wallet =
247 wallet->postInitProcess();
253 }
catch (
const std::runtime_error &e) {
261 std::shared_ptr<CWallet>
265 std::vector<bilingual_str> &warnings) {
267 return g_loading_wallet_set.insert(
name));
268 if (!result.second) {
273 auto wallet = LoadWalletInternal(chain,
name, load_on_start, options,
274 status,
error, warnings);
279 std::shared_ptr<CWallet>
283 std::vector<bilingual_str> &warnings) {
292 if (!passphrase.empty()) {
298 std::unique_ptr<WalletDatabase> database =
308 if (!passphrase.empty() &&
311 "Passphrase provided but private keys are disabled. A passphrase "
312 "is only used to encrypt private keys, so cannot be used for "
313 "wallets with private keys disabled.");
319 std::shared_ptr<CWallet>
wallet =
330 if (!passphrase.empty() &&
332 if (!
wallet->EncryptWallet(passphrase)) {
334 Untranslated(
"Error: Wallet created but failed to encrypt.");
340 if (!
wallet->Unlock(passphrase)) {
342 "Error: Wallet was encrypted but could not be unlocked");
351 wallet->SetupDescriptorScriptPubKeyMans();
353 for (
auto spk_man :
wallet->GetActiveScriptPubKeyMans()) {
354 if (!spk_man->SetupGeneration()) {
369 wallet->postInitProcess();
391 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
392 if (it == mapWallet.end()) {
396 return &(it->second);
409 spk_man->UpgradeKeyMetadata();
414 bool accept_no_keys) {
420 for (
const MasterKeyMap::value_type &pMasterKey :
mapMasterKeys) {
422 strWalletPassphrase, pMasterKey.second.vchSalt,
423 pMasterKey.second.nDeriveIterations,
424 pMasterKey.second.nDerivationMethod)) {
427 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey,
432 if (
Unlock(_vMasterKey, accept_no_keys)) {
455 strOldWalletPassphrase, pMasterKey.second.vchSalt,
456 pMasterKey.second.nDeriveIterations,
457 pMasterKey.second.nDerivationMethod)) {
461 if (!crypter.
Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey)) {
465 if (
Unlock(_vMasterKey)) {
468 pMasterKey.second.vchSalt,
469 pMasterKey.second.nDeriveIterations,
470 pMasterKey.second.nDerivationMethod);
471 pMasterKey.second.nDeriveIterations =
static_cast<unsigned int>(
472 pMasterKey.second.nDeriveIterations *
477 pMasterKey.second.vchSalt,
478 pMasterKey.second.nDeriveIterations,
479 pMasterKey.second.nDerivationMethod);
480 pMasterKey.second.nDeriveIterations =
481 (pMasterKey.second.nDeriveIterations +
482 static_cast<unsigned int>(
483 pMasterKey.second.nDeriveIterations * 100 /
487 if (pMasterKey.second.nDeriveIterations < 25000) {
488 pMasterKey.second.nDeriveIterations = 25000;
492 "Wallet passphrase changed to an nDeriveIterations of %i\n",
493 pMasterKey.second.nDeriveIterations);
496 strNewWalletPassphrase, pMasterKey.second.vchSalt,
497 pMasterKey.second.nDeriveIterations,
498 pMasterKey.second.nDerivationMethod)) {
502 if (!crypter.
Encrypt(_vMasterKey,
503 pMasterKey.second.vchCryptedKey)) {
528 if (nWalletVersion >= nVersion) {
534 if (fExplicit && nVersion > nWalletMaxVersion) {
538 nWalletVersion = nVersion;
540 if (nVersion > nWalletMaxVersion) {
541 nWalletMaxVersion = nVersion;
545 if (nWalletVersion > 40000) {
557 if (nWalletVersion > nVersion) {
561 nWalletMaxVersion = nVersion;
567 std::set<TxId> result;
570 std::map<TxId, CWalletTx>::const_iterator it = mapWallet.find(txid);
571 if (it == mapWallet.end()) {
577 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
579 for (
const CTxIn &txin : wtx.
tx->vin) {
580 if (mapTxSpends.count(txin.
prevout) <= 1) {
585 range = mapTxSpends.equal_range(txin.
prevout);
586 for (TxSpends::const_iterator _it = range.first; _it != range.second;
588 result.insert(_it->second);
597 auto iter = mapTxSpends.lower_bound(
COutPoint(txid, 0));
598 return (iter != mapTxSpends.end() && iter->first.GetTxId() == txid);
610 std::pair<TxSpends::iterator, TxSpends::iterator> range) {
615 int nMinOrderPos = std::numeric_limits<int>::max();
617 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
618 const CWalletTx *wtx = &mapWallet.at(it->second);
630 for (TxSpends::iterator it = range.first; it != range.second; ++it) {
631 const TxId &txid = it->second;
633 if (copyFrom == copyTo) {
639 "Oldest wallet transaction in range assumed to have been found.");
661 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range =
662 mapTxSpends.equal_range(outpoint);
664 for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
665 const TxId &wtxid = it->second;
666 std::map<TxId, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
667 if (mit != mapWallet.end()) {
669 if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) {
680 mapTxSpends.insert(std::make_pair(outpoint, wtxid));
682 setLockedCoins.erase(outpoint);
684 std::pair<TxSpends::iterator, TxSpends::iterator> range;
685 range = mapTxSpends.equal_range(outpoint);
690 auto it = mapWallet.find(wtxid);
691 assert(it != mapWallet.end());
698 for (
const CTxIn &txin : thisTx.
tx->vin) {
757 delete encrypted_batch;
758 encrypted_batch =
nullptr;
764 auto spk_man = spk_man_pair.second.get();
765 if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
767 delete encrypted_batch;
768 encrypted_batch =
nullptr;
780 delete encrypted_batch;
781 encrypted_batch =
nullptr;
788 delete encrypted_batch;
789 encrypted_batch =
nullptr;
792 Unlock(strWalletPassphrase);
800 if (spk_man->IsHDEnabled()) {
801 if (!spk_man->SetupGeneration(
true)) {
834 for (
auto &entry : mapWallet) {
840 std::vector<int64_t> nOrderPosOffsets;
841 for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) {
845 if (nOrderPos == -1) {
846 nOrderPos = nOrderPosNext++;
847 nOrderPosOffsets.push_back(nOrderPos);
853 int64_t nOrderPosOff = 0;
854 for (
const int64_t &nOffsetStart : nOrderPosOffsets) {
855 if (nOrderPos >= nOffsetStart) {
860 nOrderPos += nOrderPosOff;
861 nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
881 int64_t nRet = nOrderPosNext++;
893 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
894 item.second.MarkDirty();
899 unsigned int n,
bool used,
900 std::set<CTxDestination> &tx_destinations) {
913 tx_destinations.insert(dst);
915 }
else if (!used &&
GetDestData(dst,
"used",
nullptr)) {
936 assert(spk_man !=
nullptr);
937 for (
const auto &keyid :
952 bool fFlushOnClose) {
957 const TxId &txid = tx->GetId();
961 std::set<CTxDestination> tx_destinations;
963 for (
const CTxIn &txin : tx->vin) {
974 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
975 std::forward_as_tuple(tx));
977 bool fInsertedNew = ret.second;
978 bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
1005 (fInsertedNew ?
"new" :
""), (fUpdated ?
"update" :
""));
1008 if ((fInsertedNew || fUpdated) && !batch.
WriteTx(wtx)) {
1018 #if defined(HAVE_SYSTEM)
1021 std::string strCmd =
gArgs.
GetArg(
"-walletnotify",
"");
1023 if (!strCmd.empty()) {
1034 std::thread t(runCommand, strCmd);
1045 mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid),
1046 std::forward_as_tuple(
nullptr));
1048 if (!fill_wtx(wtx, ins.second)) {
1056 if (
chain().findBlock(
1058 FoundBlock().inActiveChain(active).height(height)) &&
1081 for (
const CTxIn &txin : wtx.
tx->vin) {
1083 if (it != mapWallet.end()) {
1099 const TxId &txid = ptx->GetId();
1102 for (
const CTxIn &txin : ptx->vin) {
1103 std::pair<TxSpends::const_iterator, TxSpends::const_iterator>
1104 range = mapTxSpends.equal_range(txin.
prevout);
1105 while (range.first != range.second) {
1106 if (range.first->second != txid) {
1108 "Transaction %s (in block %s) conflicts with wallet "
1109 "transaction %s (both spend %s:%i)\n",
1111 range.first->second.ToString(),
1112 range.first->first.GetTxId().ToString(),
1113 range.first->first.GetN());
1115 range.first->second);
1122 bool fExisted = mapWallet.count(txid) != 0;
1123 if (fExisted && !fUpdate) {
1136 for (
const CTxOut &txout : ptx->vout) {
1138 spk_man_pair.second->MarkUnusedAddresses(txout.
scriptPubKey);
1159 for (
const CTxIn &txin : tx->vin) {
1161 if (it != mapWallet.end()) {
1162 it->second.MarkDirty();
1172 std::set<TxId> todo;
1173 std::set<TxId> done;
1176 auto it = mapWallet.find(txid);
1177 assert(it != mapWallet.end());
1185 while (!todo.empty()) {
1189 it = mapWallet.find(now);
1190 assert(it != mapWallet.end());
1194 assert(currentconfirm <= 0);
1207 TxSpends::const_iterator iter =
1208 mapTxSpends.lower_bound(
COutPoint(now, 0));
1209 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1210 if (!done.count(iter->second)) {
1211 todo.insert(iter->second);
1230 int conflictconfirms =
1231 (m_last_block_processed_height - conflicting_height + 1) * -1;
1236 if (conflictconfirms >= 0) {
1243 std::set<TxId> todo;
1244 std::set<TxId> done;
1248 while (!todo.empty()) {
1252 auto it = mapWallet.find(now);
1253 assert(it != mapWallet.end());
1256 if (conflictconfirms < currentconfirm) {
1267 TxSpends::const_iterator iter =
1268 mapTxSpends.lower_bound(
COutPoint(now, 0));
1269 while (iter != mapTxSpends.end() && iter->first.GetTxId() == now) {
1270 if (!done.count(iter->second)) {
1271 todo.insert(iter->second);
1297 uint64_t mempool_sequence) {
1303 auto it = mapWallet.find(tx->GetId());
1304 if (it != mapWallet.end()) {
1305 it->second.fInMempool =
true;
1311 uint64_t mempool_sequence) {
1313 auto it = mapWallet.find(tx->GetId());
1314 if (it != mapWallet.end()) {
1315 it->second.fInMempool =
false;
1346 {CWalletTx::Status::UNCONFIRMED, 0,
1355 m_last_block_processed_height = height;
1356 m_last_block_processed = block_hash;
1357 for (
size_t index = 0; index < block.
vtx.size(); index++) {
1359 block_hash, int(index)});
1374 m_last_block_processed_height = height - 1;
1378 {CWalletTx::Status::UNCONFIRMED, 0,
1387 void CWallet::BlockUntilSyncedToCurrentChain()
const {
1402 std::map<TxId, CWalletTx>::const_iterator mi =
1404 if (mi != mapWallet.end()) {
1430 result = std::max(result, spk_man_pair.second->IsMine(script));
1456 throw std::runtime_error(std::string(__func__) +
1457 ": value out of range");
1468 result &= spk_man->IsHDEnabled();
1480 if (spk_man && spk_man->CanGetAddresses(
internal)) {
1487 void CWallet::SetWalletFlag(uint64_t
flags) {
1491 throw std::runtime_error(std::string(__func__) +
1492 ": writing wallet flags failed");
1505 throw std::runtime_error(std::string(__func__) +
1506 ": writing wallet flags failed");
1534 throw std::runtime_error(std::string(__func__) +
1535 ": writing wallet flags failed");
1544 bool use_max_sig)
const {
1549 std::unique_ptr<SigningProvider> provider =
1559 scriptPubKey, sigdata)) {
1570 const std::vector<CTxOut> &txouts,
1571 bool use_max_sig)
const {
1574 for (
const auto &txout : txouts) {
1585 int64_t timestamp) {
1590 LOCK(spk_man->cs_KeyStore);
1591 return spk_man->ImportScripts(scripts, timestamp);
1595 const int64_t timestamp) {
1600 LOCK(spk_man->cs_KeyStore);
1601 return spk_man->ImportPrivKeys(privkey_map, timestamp);
1605 const std::vector<CKeyID> &ordered_pubkeys,
1606 const std::map<CKeyID, CPubKey> &pubkey_map,
1607 const std::map<
CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
1608 const bool add_keypool,
const bool internal,
const int64_t timestamp) {
1613 LOCK(spk_man->cs_KeyStore);
1614 return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins,
1615 add_keypool,
internal, timestamp);
1619 const std::set<CScript> &script_pub_keys,
1620 const bool have_solving_data,
1621 const bool apply_label,
1622 const int64_t timestamp) {
1627 LOCK(spk_man->cs_KeyStore);
1628 if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data,
1634 for (
const CScript &script : script_pub_keys) {
1659 int start_height = 0;
1663 FoundBlock().hash(start_block).height(start_height));
1672 start_block, start_height, {} , reserver, update);
1705 const BlockHash &start_block,
int start_height,
1732 double progress_current = progress_begin;
1733 int block_height = start_height;
1735 if (progress_end - progress_begin > 0.0) {
1737 (progress_end - progress_begin);
1743 if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1745 strprintf(
"%s " +
_(
"Rescanning...").translated,
1752 block_height, progress_current);
1761 bool block_still_active =
false;
1762 bool next_block =
false;
1766 .inActiveChain(block_still_active)
1768 .inActiveChain(next_block)
1769 .hash(next_block_hash)));
1773 if (!block_still_active) {
1780 for (
size_t posInBlock = 0; posInBlock < block.
vtx.size();
1783 block_height, block_hash,
1786 {CWalletTx::Status::CONFIRMED, block_height,
1787 block_hash, int(posInBlock)},
1800 if (max_height && block_height >= *max_height) {
1811 block_hash = next_block_hash;
1816 const BlockHash prev_tip_hash = tip_hash;
1818 if (!max_height && prev_tip_hash != tip_hash) {
1831 block_height, progress_current);
1833 }
else if (block_height &&
chain().shutdownRequested()) {
1835 "Rescan interrupted by shutdown request at block %d. Progress=%f\n",
1836 block_height, progress_current);
1854 std::map<int64_t, CWalletTx *> mapSorted;
1858 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1859 const TxId &wtxid = item.first;
1866 mapSorted.insert(std::make_pair(wtx.
nOrderPos, &wtx));
1871 for (
const std::pair<const int64_t, CWalletTx *> &item : mapSorted) {
1873 std::string unused_err_string;
1879 std::string &err_string,
1922 std::set<TxId> result;
1942 if (!
chain().isReadyToBroadcast()) {
1959 int submitted_tx_count = 0;
1965 for (std::pair<const TxId, CWalletTx> &item : mapWallet) {
1973 std::string unused_err_string;
1975 ++submitted_tx_count;
1980 if (submitted_tx_count > 0) {
1981 WalletLogPrintf(
"%s: resubmit %u unconfirmed transactions\n", __func__,
1982 submitted_tx_count);
1989 for (
const std::shared_ptr<CWallet> &pwallet :
GetWallets()) {
1990 pwallet->ResendWalletTransactions();
2004 std::map<COutPoint, Coin> coins;
2005 for (
auto &input : tx.
vin) {
2006 auto mi = mapWallet.find(input.prevout.GetTxId());
2007 if (mi == mapWallet.end() ||
2008 input.prevout.GetN() >= mi->second.tx->vout.size()) {
2012 coins[input.prevout] =
2016 std::map<int, std::string> input_errors;
2021 const std::map<COutPoint, Coin> &coins,
2023 std::map<int, std::string> &input_errors)
const {
2028 if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2039 if (legacy_spk_man &&
2040 legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2049 bool sign,
bool bip32derivs)
const {
2052 for (
size_t i = 0; i < psbtx.
tx->vin.size(); ++i) {
2053 const CTxIn &txin = psbtx.
tx->vin[i];
2063 const auto it = mapWallet.find(txid);
2064 if (it != mapWallet.end()) {
2076 spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
2084 for (
const auto &input : psbtx.
inputs) {
2093 std::string &str_sig)
const {
2097 if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2098 return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2106 const std::vector<CRecipient> &vecSend)
const {
2109 return *change_type;
2123 std::vector<std::pair<std::string, std::string>> orderForm,
2134 wtx.
mapValue = std::move(mapValue);
2142 for (
const CTxIn &txin : tx->vin) {
2150 CWalletTx &wtx = mapWallet.at(tx->GetId());
2158 std::string err_string;
2160 WalletLogPrintf(
"CommitTransaction(): Transaction cannot be broadcast "
2161 "immediately, %s\n",
2171 fFirstRunRet =
false;
2174 if (
database->Rewrite(
"\x04pool")) {
2176 spk_man_pair.second->RewriteDB();
2192 return nLoadWalletRet;
2199 std::vector<TxId> &txIdsOut) {
2203 for (
const TxId &txid : txIdsOut) {
2204 const auto &it = mapWallet.find(txid);
2205 wtxOrdered.erase(it->second.m_it_wtxOrdered);
2206 for (
const auto &txin : it->second.tx->vin) {
2207 mapTxSpends.erase(txin.prevout);
2209 mapWallet.erase(it);
2214 if (
database->Rewrite(
"\x04pool")) {
2216 spk_man_pair.second->RewriteDB();
2222 return nZapSelectTxRet;
2232 const std::string &strName,
2233 const std::string &strPurpose) {
2234 bool fUpdated =
false;
2238 std::map<CTxDestination, CAddressBookData>::iterator mi =
2239 m_address_book.find(address);
2240 fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2241 m_address_book[address].SetLabel(strName);
2243 if (!strPurpose.empty()) {
2244 m_address_book[address].purpose = strPurpose;
2251 if (!strPurpose.empty() && !batch.
WritePurpose(address, strPurpose)) {
2254 return batch.
WriteName(address, strName);
2258 const std::string &strName,
2259 const std::string &strPurpose) {
2278 "%s called with IsMine address, NOT SUPPORTED. Please "
2279 "report this bug! %s\n",
2280 __func__, PACKAGE_BUGREPORT);
2284 for (
const std::pair<const std::string, std::string> &item :
2285 m_address_book[address].destdata) {
2288 m_address_book.erase(address);
2301 unsigned int count = 0;
2303 count += spk_man->KeypoolCountExternalKeys();
2312 unsigned int count = 0;
2314 count += spk_man->GetKeyPoolSize();
2323 res &= spk_man->TopUp(kpSize);
2332 bool result =
false;
2336 result = spk_man->GetNewDestination(type, dest,
error);
2350 std::string &
error) {
2356 error =
_(
"Error: Keypool ran out, please call keypoolrefill first")
2367 int64_t oldestKey = std::numeric_limits<int64_t>::max();
2370 std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2376 const std::set<CTxDestination> &destinations) {
2377 for (
auto &entry : mapWallet) {
2383 for (
size_t i = 0; i < wtx.
tx->vout.size(); i++) {
2387 destinations.count(dst)) {
2395 std::set<CTxDestination>
2398 std::set<CTxDestination> result;
2399 for (
const std::pair<const CTxDestination, CAddressBookData> &item :
2401 if (item.second.IsChange()) {
2405 const std::string &strName = item.second.GetLabel();
2406 if (strName == label) {
2407 result.insert(address);
2454 setLockedCoins.insert(output);
2459 setLockedCoins.erase(output);
2464 setLockedCoins.clear();
2470 return setLockedCoins.count(outpoint) > 0;
2475 for (
COutPoint outpoint : setLockedCoins) {
2476 vOutpts.push_back(outpoint);
2484 mapKeyBirth.clear();
2487 std::map<CKeyID, const CWalletTx::Confirmation *> mapKeyFirstBlock;
2498 assert(spk_man !=
nullptr);
2502 for (
const auto &entry : spk_man->mapKeyMetadata) {
2503 if (entry.second.nCreateTime) {
2504 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2510 if (mapKeyBirth.count(keyid) == 0) {
2511 mapKeyFirstBlock[keyid] = &max_confirm;
2516 if (mapKeyFirstBlock.empty()) {
2521 for (
const auto &entry : mapWallet) {
2526 for (
const CTxOut &txout : wtx.
tx->vout) {
2528 for (
const auto &keyid :
2531 auto rit = mapKeyFirstBlock.find(keyid);
2532 if (rit != mapKeyFirstBlock.end() &&
2534 rit->second->block_height) {
2544 for (
const auto &entry : mapKeyFirstBlock) {
2581 int64_t latestEntry = 0;
2585 int64_t latestTolerated = latestNow + 300;
2587 for (
auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2597 if (nSmartTime <= latestTolerated) {
2598 latestEntry = nSmartTime;
2599 if (nSmartTime > latestNow) {
2600 latestNow = nSmartTime;
2606 nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2617 const std::string &key,
const std::string &value) {
2618 if (boost::get<CNoDestination>(&dest)) {
2622 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2627 const std::string &key) {
2628 if (!m_address_book[dest].destdata.erase(key)) {
2636 const std::string &value) {
2637 m_address_book[dest].destdata.insert(std::make_pair(key, value));
2641 std::string *value)
const {
2642 std::map<CTxDestination, CAddressBookData>::const_iterator i =
2643 m_address_book.find(dest);
2644 if (i != m_address_book.end()) {
2645 CAddressBookData::StringMap::const_iterator j =
2646 i->second.destdata.find(key);
2647 if (j != i->second.destdata.end()) {
2658 std::vector<std::string>
2660 std::vector<std::string> values;
2661 for (
const auto &address : m_address_book) {
2662 for (
const auto &data : address.second.destdata) {
2664 values.emplace_back(data.second);
2671 std::unique_ptr<WalletDatabase>
2682 fs::file_type path_type = fs::symlink_status(wallet_path).type();
2683 if (!(path_type == fs::file_type::not_found ||
2684 path_type == fs::file_type::directory ||
2685 (path_type == fs::file_type::symlink &&
2686 fs::is_directory(wallet_path)) ||
2687 (path_type == fs::file_type::regular &&
2690 strprintf(
"Invalid -wallet path '%s'. -wallet path should point to "
2691 "a directory where wallet.dat and "
2692 "database/log.?????????? files can be stored, a location "
2693 "where such a directory could be created, "
2694 "or (for backwards compatibility) the name of an "
2695 "existing data file in -walletdir (%s)",
2700 return MakeDatabase(wallet_path, options, status, error_string);
2703 std::shared_ptr<CWallet>
2705 std::unique_ptr<WalletDatabase> database,
2707 std::vector<bilingual_str> &warnings) {
2708 const std::string &walletFile =
database->Filename();
2713 bool fFirstRun =
true;
2716 std::shared_ptr<CWallet> walletInstance(
2718 DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
2722 strprintf(
_(
"Error loading %s: Wallet corrupted"), walletFile);
2728 strprintf(
_(
"Error reading %s! All keys read correctly, but "
2729 "transaction data or address book entries might be "
2730 "missing or incorrect."),
2734 _(
"Error loading %s: Wallet requires newer version of %s"),
2735 walletFile, PACKAGE_NAME);
2739 _(
"Wallet needed to be rewritten: restart %s to complete"),
2753 walletInstance->AddWalletFlags(wallet_creation_flags);
2757 walletInstance->SetupLegacyScriptPubKeyMan();
2760 if (!(wallet_creation_flags &
2762 LOCK(walletInstance->cs_wallet);
2764 walletInstance->SetupDescriptorScriptPubKeyMans();
2770 walletInstance->GetActiveScriptPubKeyMans()) {
2771 if (!spk_man->SetupGeneration()) {
2772 error =
_(
"Unable to generate initial keys");
2783 "disabled during creation"),
2786 }
else if (walletInstance->IsWalletFlagSet(
2788 for (
auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2789 if (spk_man->HavePrivateKeys()) {
2791 strprintf(
_(
"Warning: Private keys detected in wallet {%s} "
2792 "with disabled private keys"),
2807 _(
"This is the minimum transaction fee you pay "
2808 "on every transaction."));
2810 walletInstance->m_min_fee =
CFeeRate(n);
2814 const std::string max_aps_fee{
gArgs.
GetArg(
"-maxapsfee",
"")};
2816 if (max_aps_fee ==
"-1") {
2825 _(
"This is the maximum transaction fee you pay (in addition to"
2826 " the normal fee) to prioritize partial spend avoidance over"
2827 " regular coin selection."));
2829 walletInstance->m_max_aps_fee = n;
2836 strprintf(
_(
"Invalid amount for -fallbackfee=<amount>: '%s'"),
2843 _(
"This is the transaction fee you may pay when "
2844 "fee estimates are not available."));
2846 walletInstance->m_fallback_fee =
CFeeRate(nFeePerK);
2849 walletInstance->m_allow_fallback_fee =
2850 walletInstance->m_fallback_fee.GetFeePerK() !=
Amount::zero();
2860 _(
"This is the transaction fee you will pay if "
2861 "you send a transaction."));
2863 walletInstance->m_pay_tx_fee =
CFeeRate(nFeePerK, 1000);
2866 "(must be at least %s)"),
2880 warnings.push_back(
_(
"-maxtxfee is set very high! Fees this large "
2881 "could be paid on a single transaction."));
2885 _(
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at "
2886 "least the minrelay fee of %s to prevent stuck "
2891 walletInstance->m_default_max_tx_fee = nMaxFee;
2897 _(
"The wallet will avoid paying less than the minimum relay fee."));
2900 walletInstance->m_spend_zero_conf_change =
2905 walletInstance->WalletLogPrintf(
"Wallet completed loading in %15dms\n",
2909 walletInstance->TopUpKeyPool();
2911 LOCK(walletInstance->cs_wallet);
2921 walletInstance->m_chain_notifications_handler =
2922 walletInstance->chain().handleNotifications(walletInstance);
2924 int rescan_height = 0;
2929 if (
const std::optional<int> fork_height =
2931 rescan_height = *fork_height;
2938 walletInstance->m_last_block_processed =
2940 walletInstance->m_last_block_processed_height = *tip_height;
2942 walletInstance->m_last_block_processed.
SetNull();
2943 walletInstance->m_last_block_processed_height = -1;
2946 if (tip_height && *tip_height != rescan_height) {
2955 int block_height = *tip_height;
2956 while (block_height > 0 &&
2958 rescan_height != block_height) {
2962 if (rescan_height != block_height) {
2963 error =
_(
"Prune: last wallet synchronisation goes beyond "
2964 "pruned data. You need to -reindex (download the "
2965 "whole blockchain again in case of pruned node)");
2971 walletInstance->WalletLogPrintf(
2972 "Rescanning last %i blocks (from block %i)...\n",
2973 *tip_height - rescan_height, rescan_height);
2977 std::optional<int64_t> time_first_key;
2978 for (
auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
2979 int64_t time = spk_man->GetTimeFirstKey();
2980 if (!time_first_key || time < *time_first_key) {
2981 time_first_key = time;
2984 if (time_first_key) {
2995 ->ScanForWalletTransactions(
2997 {} , reserver,
true )
2999 error =
_(
"Failed to rescan the wallet during initialization");
3004 walletInstance->database->IncrementUpdateCounter();
3009 for (
auto &load_wallet : g_load_wallet_fns) {
3014 walletInstance->SetBroadcastTransactions(
3017 walletInstance->WalletLogPrintf(
"setKeyPool.size() = %u\n",
3018 walletInstance->GetKeyPoolSize());
3019 walletInstance->WalletLogPrintf(
"mapWallet.size() = %u\n",
3020 walletInstance->mapWallet.size());
3021 walletInstance->WalletLogPrintf(
"m_address_book.size() = %u\n",
3022 walletInstance->m_address_book.size());
3024 return walletInstance;
3029 bool allow_change)
const {
3030 const auto &address_book_it = m_address_book.find(dest);
3031 if (address_book_it == m_address_book.end()) {
3034 if ((!allow_change) && address_book_it->second.IsChange()) {
3037 return &address_book_it->second;
3042 int nMaxVersion = version;
3044 if (nMaxVersion == 0) {
3054 error =
_(
"Cannot downgrade wallet");
3068 error =
_(
"Cannot upgrade a non HD split wallet without upgrading to "
3069 "support pre split keypool. Please use version 200300 or no "
3070 "version specified.");
3075 if (!spk_man->Upgrade(prev_version,
error)) {
3129 assert(chain_depth >= 0);
3149 return vMasterKey.empty();
3159 if (!vMasterKey.empty()) {
3162 sizeof(decltype(vMasterKey)::value_type));
3175 if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn,
3180 vMasterKey = vMasterKeyIn;
3187 std::set<ScriptPubKeyMan *> spk_mans;
3188 for (
bool internal : {
false,
true}) {
3192 spk_mans.insert(spk_man);
3200 std::set<ScriptPubKeyMan *> spk_mans;
3202 spk_mans.insert(spk_man_pair.second.get());
3208 bool internal)
const {
3209 const std::map<OutputType, ScriptPubKeyMan *> &spk_managers =
3211 std::map<OutputType, ScriptPubKeyMan *>::const_iterator it =
3212 spk_managers.find(type);
3213 if (it == spk_managers.end()) {
3215 "%s scriptPubKey Manager for output type %d does not exist\n",
3216 internal ?
"Internal" :
"External",
static_cast<int>(type));
3222 std::set<ScriptPubKeyMan *>
3225 std::set<ScriptPubKeyMan *> spk_mans;
3227 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3228 spk_mans.insert(spk_man_pair.second.get());
3237 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3238 return spk_man_pair.second.get();
3251 std::unique_ptr<SigningProvider>
3257 std::unique_ptr<SigningProvider>
3261 if (spk_man_pair.second->CanProvide(script, sigdata)) {
3262 return spk_man_pair.second->GetSolvingProvider(script);
3313 spk_man->NotifyCanGetAddressesChanged.connect(
3320 auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(
3338 for (
bool internal : {
false,
true}) {
3341 std::make_unique<DescriptorScriptPubKeyMan>(*
this,
internal);
3344 throw std::runtime_error(
3345 std::string(__func__) +
3346 ": Wallet is locked, cannot setup new descriptors");
3348 if (!spk_manager->CheckDecryptionKey(vMasterKey) &&
3349 !spk_manager->Encrypt(vMasterKey,
nullptr)) {
3350 throw std::runtime_error(
3351 std::string(__func__) +
3352 ": Could not encrypt new descriptors");
3355 spk_manager->SetupDescriptorGeneration(master_key, t);
3356 uint256 id = spk_manager->GetID();
3368 throw std::runtime_error(std::string(__func__) +
3369 ": writing active ScriptPubKeyMan id failed");
3377 "Setting spkMan to active: id = %s, type = %d, internal = %d\n",
3378 id.
ToString(),
static_cast<int>(type),
static_cast<int>(
internal));
3382 spk_man->SetInternal(
internal);
3383 spk_mans[type] = spk_man;
3394 return spk_man !=
nullptr;
3404 spk_man_pair.second.get());
3416 const std::string &label,
bool internal) {
3419 "Cannot add WalletDescriptor to a non-descriptor wallet\n");
3424 auto new_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(*
this, desc);
3434 LOCK(old_spk_man->cs_desc_man);
3435 new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache);
3439 auto old_spk_man_id = old_spk_man->GetID();
3440 for (
bool internal_ : {
false,
true}) {
3443 if (active_spk_man &&
3444 active_spk_man->GetID() == old_spk_man_id) {
3458 for (
const auto &entry : signing_provider.
keys) {
3459 const CKey &key = entry.second;
3460 new_spk_man->AddDescriptorKey(key, key.
GetPubKey());
3464 if (!new_spk_man->TopUp()) {
3472 auto script_pub_keys = new_spk_man->GetScriptPubKeys();
3473 if (script_pub_keys.empty()) {
3475 "Could not generate scriptPubKeys (cache is empty)\n");
3486 auto ret = new_spk_man.get();
3490 ret->WriteDescriptor();
bool MoneyRange(const Amount nValue)
static constexpr Amount SATOSHI
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
const CChainParams & Params()
Return the currently selected parameters.
#define CHECK_NONFATAL(condition)
Identity function.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::vector< CTransactionRef > vtx
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Encryption/decryption context with key information.
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
bool Decrypt(const std::vector< uint8_t > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Fee rate in satoshis per kilobyte: Amount / kB.
std::string ToString() const
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
An encapsulated secp256k1 private key.
const uint8_t * begin() const
unsigned int size() const
Simple read-only vector-like interface.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
A reference to a CKey: the Hash160 of its serialized public key.
A key from a CWallet's keypool.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
CPubKey vchPubKey
The public key.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
std::vector< uint8_t > vchSalt
unsigned int nDerivationMethod
0 = EVP_sha512() 1 = scrypt()
unsigned int nDeriveIterations
std::vector< uint8_t > vchCryptedKey
A mutable version of CTransaction.
An outpoint - a combination of a transaction hash and an index n into its vout.
const TxId & GetTxId() const
An encapsulated public key.
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An input of a transaction.
An output of a transaction.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
std::atomic< int64_t > m_best_block_time
BlockHash GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< ScriptPubKeyMan * > GetScriptPubKeyMans(const CScript &script, SignatureData &sigdata) const
Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e....
bool HaveChain() const
Interface to assert chain access.
int GetTxBlocksToMaturity(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DummySignTx(CMutableTransaction &txNew, const std::set< CTxOut > &txouts, bool use_max_sig=false) const
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
void AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Adds the active ScriptPubKeyMan for the specified type and internal.
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
ScriptPubKeyMan * AddWalletDescriptor(WalletDescriptor &desc, const FlatSigningProvider &signing_provider, const std::string &label, bool internal)
Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type.
bool AddDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, and saves it to disk When adding new fields,...
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
MasterKeyMap mapMasterKeys
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
int GetTxDepthInMainChain(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
bool IsTxImmatureCoinBase(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys=false)
bool GetBroadcastTransactions() const
Inquire whether this wallet broadcasts transactions.
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
interfaces::Chain * m_chain
Interface for accessing chain state.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
std::map< OutputType, ScriptPubKeyMan * > m_external_spk_managers
bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Look up a destination data tuple in the store, return true if found false otherwise.
bool IsLegacy() const
Determine if we are a legacy wallet.
interfaces::Chain & chain() const
Interface for accessing chain state.
std::atomic< bool > fAbortRescan
std::map< uint256, std::unique_ptr< ScriptPubKeyMan > > m_spk_managers
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
static std::shared_ptr< CWallet > Create(interfaces::Chain &chain, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error.
boost::signals2::signal< void(CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
boost::signals2::signal< void(CWallet *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
OutputType m_default_address_type
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet.
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
std::atomic< uint64_t > m_wallet_flags
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we are allowed to upgrade (or already support) to the named feature
bool BackupWallet(const std::string &strDest) const
unsigned int ComputeTimeSmart(const CWalletTx &wtx) const
Compute smart timestamp for a transaction being added to the wallet.
void WalletLogPrintfToBeContinued(std::string fmt, Params... parameters) const
std::unique_ptr< WalletDatabase > database
Internal database handle.
std::set< ScriptPubKeyMan * > GetActiveScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers.
std::vector< std::string > GetDestValues(const std::string &prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get all destination values matching a prefix.
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
bool IsLocked() const override
std::map< OutputType, ScriptPubKeyMan * > m_internal_spk_managers
std::atomic< double > m_scanning_progress
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EraseDestData(WalletBatch &batch, const CTxDestination &dest, const std::string &key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Erases a destination data tuple in the store and on disk.
boost::signals2::signal< void(CWallet *wallet, const TxId &txid, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
bool HasEncryptionKeys() const override
CWallet(interfaces::Chain *chain, const std::string &name, std::unique_ptr< WalletDatabase > _database)
Construct wallet with specified name and database implementation.
Amount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
bool fBroadcastTransactions
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
std::set< ScriptPubKeyMan * > GetAllScriptPubKeyMans() const
Returns all unique ScriptPubKeyMans.
std::multimap< int64_t, CWalletTx * > TxItems
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
unsigned int nMasterKeyMaxID
std::function< bool(CWalletTx &wtx, bool new_tx)> UpdateWalletTxFn
Callback for updating transaction metadata in mapWallet.
void postInitProcess()
Wallet post-init setup Gives the wallet a chance to register repetitive tasks and complete post-init ...
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CKeyingMaterial & GetEncryptionKey() const override
A transaction with a bunch of additional info that only the owner cares about.
mapValue_t mapValue
Key/value map with information about the transaction.
bool isUnconfirmed() const
unsigned int nTimeSmart
Stable timestamp that never changes, and reflects the order a transaction was added to the wallet.
std::multimap< int64_t, CWalletTx * >::const_iterator m_it_wtxOrdered
bool IsEquivalentTo(const CWalletTx &tx) const
bool isConflicted() const
std::vector< std::pair< std::string, std::string > > vOrderForm
bool fFromMe
From me flag is set to 1 for transactions that were created by the wallet on this bitcoin node,...
unsigned int fTimeReceivedIsTxTime
void MarkDirty()
make sure balances are recalculated
bool m_is_cache_empty
This flag is true if all m_amounts caches are empty.
unsigned int nTimeReceived
time received by this node
int64_t nOrderPos
position in ordered transaction list
bool HasWalletDescriptor(const WalletDescriptor &desc) const
RecursiveMutex cs_KeyStore
std::set< CKeyID > GetKeys() const override
A wrapper to reserve an address from a wallet.
bool fInternal
Whether this is from the internal (change output) keypool.
ScriptPubKeyMan * m_spk_man
The ScriptPubKeyMan to reserve from.
int64_t nIndex
The index of the address's key in the keypool.
CTxDestination address
The destination.
const CWallet *const pwallet
The wallet to reserve from.
A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool)
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
Signature hash type wrapper class.
const std::vector< UniValue > & getValues() const
bool push_back(const UniValue &val)
Access to the wallet database.
bool TxnCommit()
Commit current transaction.
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteName(const CTxDestination &address, const std::string &strName)
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
bool WriteMinVersion(int nVersion)
bool ErasePurpose(const CTxDestination &address)
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
bool WriteWalletFlags(const uint64_t flags)
bool ReadBestBlock(CBlockLocator &locator)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool WriteTx(const CWalletTx &wtx)
bool TxnBegin()
Begin a new transaction.
bool TxnAbort()
Abort current transaction.
bool EraseName(const CTxDestination &address)
bool WriteBestBlock(const CBlockLocator &locator)
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut)
DBErrors LoadWallet(CWallet *pwallet)
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
std::string ToString() const
std::string GetHex() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual CBlockLocator getTipLocator()=0
Get locator for the current chain tip.
virtual BlockHash getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
virtual bool findBlock(const BlockHash &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
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,...
virtual bool broadcastTransaction(const Config &config, const CTransactionRef &tx, const Amount &max_tx_fee, bool relay, std::string &err_string)=0
Transaction is added to memory pool, if the transaction fee is below the amount specified by max_tx_f...
virtual util::SettingsValue getRwSetting(const std::string &name)=0
Return <datadir>/settings.json setting value.
virtual double guessVerificationProgress(const BlockHash &block_hash)=0
Estimate fraction of total transactions verified if blocks up to the specified block hash are verifie...
virtual bool havePruned()=0
Check if any block has been pruned.
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual bool updateRwSetting(const std::string &name, const util::SettingsValue &value)=0
Write a setting to <datadir>/settings.json.
virtual int64_t getAdjustedTime()=0
Get adjusted time.
virtual 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...
virtual bool findAncestorByHeight(const BlockHash &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual void initMessage(const std::string &message)=0
Send init message.
virtual bool haveBlockOnDisk(int height)=0
Check that the block is available on disk (i.e.
virtual void requestMempoolTransactions(Notifications ¬ifications)=0
Synchronously send transactionAddedToMempool notifications about all current mempool transactions to ...
virtual void waitForNotificationsIfTipChanged(const BlockHash &old_tip)=0
Wait for pending notifications to be processed unless block hash points to the current chain tip.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee settings).
virtual const CChainParams & params() const =0
This Chain's parameters.
Helper for findBlock to selectively return pieces of block data.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
const Config & GetConfig()
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
const unsigned int WALLET_CRYPTO_SALT_SIZE
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
const unsigned int WALLET_CRYPTO_KEY_SIZE
bilingual_str AmountHighWarn(const std::string &optname)
bilingual_str AmountErrMsg(const std::string &optname, const std::string &strValue)
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void MarkDestinationsDirty(const std::set< CTxDestination > &destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Marks all outputs in each one of the destinations dirty, so their cache is reset and does not return ...
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm, bool broadcast=true)
Add the transaction to the wallet and maybe attempt to broadcast it.
void KeepDestination()
Keep the address.
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsLockedCoin(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
DBErrors LoadWallet(bool &fFirstRunRet)
OutputType TransactionChangeType(const std::optional< OutputType > &change_type, const std::vector< CRecipient > &vecSend) const
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ReturnDestination()
Return reserved address.
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool TopUpKeyPool(unsigned int kpSize=0)
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address, const std::string &strName, const std::string &strPurpose)
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.
bool GetReservedDestination(CTxDestination &pubkey, bool internal)
Reserve an address.
int64_t GetOldestKeyPoolTime() const
bool DelAddressBook(const CTxDestination &address)
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, std::string &error)
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
bool AddWalletFlags(uint64_t flags)
Overwrite all flags by the given uint64_t.
void blockConnected(const CBlock &block, int height) override
bool LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_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 Flush()
Flush wallet (bitdb flush)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
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)
std::set< TxId > GetConflicts(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get wallet transactions that conflict with given transaction (spend same outputs)
bool SubmitTxMemoryPoolAndRelay(const CWalletTx &wtx, std::string &err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Pass this transaction to node for mempool insertion and relay to peers if flag set to true.
void AddToSpends(const COutPoint &outpoint, const TxId &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void SyncTransaction(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool update_tx=true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
bool 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.
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
bool IsFromMe(const CTransaction &tx) const
should probably be renamed to IsRelevantToMe
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
bool ImportScriptPubKeys(const std::string &label, const std::set< CScript > &script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool CanGetAddresses(bool internal=false) const
Returns true if the wallet can give out new addresses.
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.
bool IsSpentKey(const TxId &txid, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool TransactionCanBeAbandoned(const TxId &txid) const
Return whether transaction can be abandoned.
const CChainParams & GetChainParams() const override
Amount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
void MarkInputsDirty(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed.
bool AddToWalletIfInvolvingMe(const CTransactionRef &tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Add a transaction to the wallet, or update it.
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction, spends it:
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag)
Unsets a wallet flag and saves it to disk.
void SyncMetaData(std::pair< TxSpends::iterator, TxSpends::iterator >) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool EncryptWallet(const SecureString &strWalletPassphrase)
void updatedBlockTip() override
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
void transactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
bool AbandonTransaction(const TxId &txid)
Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent.
void UnsetBlankWalletFlag(WalletBatch &batch) override
Unset the blank wallet flag and saves it to disk.
void SetSpentKeyState(WalletBatch &batch, const TxId &txid, unsigned int n, bool used, std::set< CTxDestination > &tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
DBErrors ReorderTransactions()
void blockDisconnected(const CBlock &block, int height) override
void Close()
Close wallet database.
int64_t IncOrderPosNext(WalletBatch *batch=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Increment the next transaction order id.
const CWalletTx * GetWalletTx(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ResendWalletTransactions()
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false) override
signify that a particular wallet feature is now used.
std::set< TxId > GetTxConflicts(const CWalletTx &wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig=false) const
void chainStateFlushed(const CBlockLocator &loc) override
isminetype
IsMine() return codes.
@ PRIVATE_KEY_NOT_AVAILABLE
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
static auto quoted(const std::string &s)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
Return implementation of Wallet interface.
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
const std::string & FormatOutputType(OutputType type)
const std::array< OutputType, 1 > OUTPUT_TYPES
std::shared_ptr< const CTransaction > CTransactionRef
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed.
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...
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
void UpdateInput(CTxIn &input, const SignatureData &data)
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
void ReplaceAll(std::string &in_out, std::string_view search, std::string_view substitute)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr Amount zero() noexcept
A BlockHash is a unqiue identifier for a block.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
void SetSeed(const uint8_t *seed, unsigned int nSeedLen)
std::optional< int > last_scanned_height
BlockHash last_scanned_block
Hash and height of most recent block that was successfully scanned.
enum CWallet::ScanResult::@20 status
BlockHash last_failed_block
Hash of the most recent block that could not be scanned due to read errors or pruning.
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
SecureString create_passphrase
std::map< CKeyID, CKey > keys
A version of CTransaction with the PSBT format.
std::vector< PSBTInput > inputs
std::optional< CMutableTransaction > tx
A TxId is the identifier of a transaction.
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::string ShellEscape(const std::string &arg)
bool error(const char *fmt, const Args &...args)
int64_t GetTimeMillis()
Returns the system time (not mockable)
T GetTime()
Return system time (or mocked time, if set)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ BLOCK
Removed for block.
@ CONFLICT
Removed for conflict with in-block transaction.
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
std::map< std::string, std::string > mapValue_t
constexpr Amount HIGH_TX_FEE_PER_KB
Discourage users to set fees higher than this amount (in satoshis) per kB.
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
constexpr OutputType DEFAULT_ADDRESS_TYPE
Default for -addresstype.
constexpr Amount HIGH_MAX_TX_FEE
-maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE
Default for -spendzeroconfchange.
static constexpr uint64_t KNOWN_WALLET_FLAGS
static const bool DEFAULT_WALLETBROADCAST
constexpr Amount HIGH_APS_FEE
discourage APS fee higher than this amount
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)
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
static void ReleaseWallet(CWallet *wallet)
static Mutex g_wallet_release_mutex
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
static std::vector< std::shared_ptr< CWallet > > vpwallets GUARDED_BY(cs_wallets)
std::shared_ptr< CWallet > GetWallet(const std::string &name)
std::shared_ptr< CWallet > CreateWallet(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)
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
static std::condition_variable g_wallet_release_cv
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
RecursiveMutex cs_wallets
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
static void UpdateWalletSetting(interfaces::Chain &chain, const std::string &wallet_name, std::optional< bool > load_on_startup, std::vector< bilingual_str > &warnings)
std::vector< std::shared_ptr< CWallet > > GetWallets()
static Mutex g_loading_wallet_mutex
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
DBErrors
Error statuses for the wallet database.
fs::path GetWalletDir()
Get the path of the wallet directory.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_KEY_ORIGIN_METADATA
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
WalletFeature
(client) version numbers for particular wallet features
@ FEATURE_PRE_SPLIT_KEYPOOL