6#include <bitcoin-build-config.h>
43const std::string
FLAGS{
"flags"};
46const std::string
KEY{
"key"};
50const std::string
NAME{
"name"};
53const std::string
POOL{
"pool"};
56const std::string
TX{
"tx"};
116 std::vector<unsigned char> vchKey;
117 vchKey.reserve(vchPubKey.
size() + vchPrivKey.size());
118 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
119 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
125 const std::vector<unsigned char>& vchCryptedSecret,
136 if (!
WriteIC(key, std::make_pair(vchCryptedSecret, checksum),
false)) {
138 std::vector<unsigned char> val;
139 if (!
m_batch->Read(key, val)) {
142 if (!
WriteIC(key, std::make_pair(val, checksum),
true)) {
232 return WriteIC(make_pair(key, type),
id);
238 return EraseIC(make_pair(key, type));
244 std::vector<unsigned char> key;
245 key.reserve(pubkey.
size() + privkey.size());
246 key.insert(key.end(), pubkey.
begin(), pubkey.
end());
247 key.insert(key.end(), privkey.begin(), privkey.end());
269 xpub.
Encode(ser_xpub.data());
276 xpub.
Encode(ser_xpub.data());
283 xpub.
Encode(ser_xpub.data());
295 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
327 strErr =
"Error reading wallet database: CPubKey corrupt";
345 catch (
const std::ios_base::failure&) {}
347 bool fSkipCheck =
false;
352 std::vector<unsigned char> vchKey;
353 vchKey.reserve(vchPubKey.
size() + pkey.size());
354 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
355 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
357 if (
Hash(vchKey) != hash)
359 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
366 if (!key.
Load(pkey, vchPubKey, fSkipCheck))
368 strErr =
"Error reading wallet database: CPrivKey corrupt";
373 strErr =
"Error reading wallet database: LegacyDataSPKM::LoadKey failed";
376 }
catch (
const std::exception& e) {
377 if (strErr.empty()) {
393 strErr =
"Error reading wallet database: CPubKey corrupt";
396 std::vector<unsigned char> vchPrivKey;
397 ssValue >> vchPrivKey;
400 bool checksum_valid =
false;
401 if (!ssValue.
eof()) {
404 if (!(checksum_valid =
Hash(vchPrivKey) == checksum)) {
405 strErr =
"Error reading wallet database: Encrypted key corrupt";
412 strErr =
"Error reading wallet database: LegacyDataSPKM::LoadCryptedKey failed";
415 }
catch (
const std::exception& e) {
416 if (strErr.empty()) {
432 ssValue >> kMasterKey;
435 strErr =
strprintf(
"Error reading wallet database: duplicate CMasterKey id %u", nID);
442 }
catch (
const std::exception& e) {
443 if (strErr.empty()) {
458 }
catch (
const std::exception& e) {
459 if (strErr.empty()) {
474 pwallet->LoadMinVersion(nMinVersion);
484 if (!pwallet->LoadWalletFlags(
flags)) {
485 pwallet->WalletLogPrintf(
"Error reading wallet database: Unknown non-tolerable wallet flags found\n");
508 pwallet->
WalletLogPrintf(
"Error getting database cursor for '%s' records\n", key);
518 pwallet->
WalletLogPrintf(
"Error reading next '%s' record for wallet database\n", key);
526 DBErrors record_res = load_func(pwallet, ssKey, ssValue, error);
545 const auto& batch =
wallet.GetDatabase().MakeBatch();
560 wallet.WalletLogPrintf(
"Error getting database cursor for '%s' records", type);
561 throw std::runtime_error(
strprintf(
"Error getting database cursor for '%s' records", type));
580 pwallet->WalletLogPrintf(
"Error: Unexpected legacy entry found in descriptor wallet %s. The wallet might have been tampered with or created with malicious intent.\n", pwallet->GetName());
593 result = std::max(result, hd_chain_res.
m_result);
600 result = std::max(result, key_res.
m_result);
607 result = std::max(result, ckey_res.
m_result);
618 strErr =
"Error reading wallet database: LegacyDataSPKM::LoadCScript failed";
619 return DBErrors::NONCRITICAL_ERROR;
623 result = std::max(result, script_res.
m_result);
632 std::map<uint160, CHDChain> hd_chains;
646 bool internal = false;
648 if (keyMeta.hdKeypath !=
"s" && keyMeta.hdKeypath !=
"m") {
649 std::vector<uint32_t> path;
650 if (keyMeta.has_key_origin) {
652 path = keyMeta.key_origin.path;
655 if (!ParseHDKeypath(keyMeta.hdKeypath, path)) {
656 strErr =
"Error reading wallet database: keymeta with invalid HD keypath";
657 return DBErrors::NONCRITICAL_ERROR;
665 if (path.size() != 3) {
666 strErr =
"Error reading wallet database: keymeta found with unexpected path";
667 return DBErrors::NONCRITICAL_ERROR;
669 if (path[0] != 0x80000000) {
670 strErr = strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000) for the element at index 0", path[0]);
671 return DBErrors::NONCRITICAL_ERROR;
673 if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
674 strErr = strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000 or 0x80000001) for the element at index 1", path[1]);
675 return DBErrors::NONCRITICAL_ERROR;
677 if ((path[2] & 0x80000000) == 0) {
678 strErr = strprintf(
"Unexpected path index of 0x%08x (expected to be greater than or equal to 0x80000000)", path[2]);
679 return DBErrors::NONCRITICAL_ERROR;
681 internal = path[1] == (1 | 0x80000000);
682 index = path[2] & ~0x80000000;
702 result = std::max(result, keymeta_res.m_result);
705 if (!hd_chains.empty()) {
706 LegacyDataSPKM* legacy_spkm = pwallet->GetLegacyDataSPKM();
708 for (
const auto& [hd_seed_id, chain] : hd_chains) {
709 if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) {
710 legacy_spkm->AddInactiveHDChain(chain);
714 pwallet->WalletLogPrintf(
"Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
727 pwallet->GetOrCreateLegacyDataSPKM()->LoadWatchOnly(
script);
731 result = std::max(result, watch_script_res.m_result);
738 CKeyMetadata keyMeta;
740 pwallet->GetOrCreateLegacyDataSPKM()->LoadScriptMetadata(
CScriptID(
script), keyMeta);
743 result = std::max(result, watch_meta_res.m_result);
752 pwallet->GetOrCreateLegacyDataSPKM()->LoadKeyPool(nIndex, keypool);
755 result = std::max(result, pool_res.m_result);
767 value >> default_pubkey;
768 }
catch (
const std::exception& e) {
772 if (!default_pubkey.
IsValid()) {
773 err =
"Error reading wallet database: Default Key corrupt";
774 return DBErrors::CORRUPT;
778 result = std::max(result, default_key_res.m_result);
783 err =
"Found unsupported 'wkey' record, try loading with version 0.18";
786 result = std::max(result, wkey_res.m_result);
790 pwallet->WalletLogPrintf(
"Legacy Wallet Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total.\n",
791 key_res.m_records, ckey_res.m_records, keymeta_res.m_records, key_res.m_records + ckey_res.m_records);
794 if (pwallet->IsLegacy() && (key_res.m_records + ckey_res.m_records + watch_script_res.m_records) != (keymeta_res.m_records + watch_meta_res.m_records)) {
795 auto spk_man = pwallet->GetLegacyScriptPubKeyMan();
797 LOCK(spk_man->cs_KeyStore);
798 spk_man->UpdateTimeFirstKey(1);
806template<
typename... Args>
823 DBErrors result = DBErrors::LOAD_OK;
830 }
catch (
const std::ios_base::failure& e) {
831 strErr =
strprintf(
"Error: Unrecognized descriptor found in wallet %s. ", pwallet->
GetName());
832 strErr += (last_client >
CLIENT_VERSION) ?
"The wallet might had been created on a newer version. " :
833 "The database might be corrupted or the software version is not compatible with one of your wallet descriptors. ";
834 strErr +=
"Please try running the latest software version";
836 strErr =
strprintf(
"%s\nDetails: %s", strErr, e.what());
837 return DBErrors::UNKNOWN_DESCRIPTOR;
842 if (
id != spkm.
GetID()) {
843 strErr =
"The descriptor ID calculated by the wallet differs from the one in DB";
844 return DBErrors::CORRUPT;
855 uint32_t key_exp_index;
859 key >> key_exp_index;
872 xpub.
Decode(ser_xpub.data());
878 return DBErrors::LOAD_OK;
880 result = std::max(result, key_cache_res.
m_result);
887 uint32_t key_exp_index;
890 key >> key_exp_index;
895 xpub.
Decode(ser_xpub.data());
897 return DBErrors::LOAD_OK;
899 result = std::max(result, lh_cache_res.
m_result);
904 spk_man->SetCache(cache);
917 strErr =
"Error reading wallet database: descriptor unencrypted key CPubKey corrupt";
918 return DBErrors::CORRUPT;
928 std::vector<unsigned char> to_hash;
929 to_hash.reserve(pubkey.
size() + pkey.size());
930 to_hash.insert(to_hash.end(), pubkey.
begin(), pubkey.
end());
931 to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
933 if (
Hash(to_hash) != hash)
935 strErr =
"Error reading wallet database: descriptor unencrypted key CPubKey/CPrivKey corrupt";
936 return DBErrors::CORRUPT;
939 if (!privkey.
Load(pkey, pubkey,
true))
941 strErr =
"Error reading wallet database: descriptor unencrypted key CPrivKey corrupt";
942 return DBErrors::CORRUPT;
944 spk_man->AddKey(pubkey.
GetID(), privkey);
945 return DBErrors::LOAD_OK;
947 result = std::max(result, key_res.
m_result);
961 err =
"Error reading wallet database: descriptor encrypted key CPubKey corrupt";
962 return DBErrors::CORRUPT;
964 std::vector<unsigned char> privkey;
967 spk_man->AddCryptedKey(pubkey.
GetID(), pubkey, privkey);
968 return DBErrors::LOAD_OK;
970 result = std::max(result, ckey_res.
m_result);
976 if (desc_res.
m_result <= DBErrors::NONCRITICAL_ERROR) {
978 pwallet->
WalletLogPrintf(
"Descriptors: %u, Descriptor Keys: %u plaintext, %u encrypted, %u total.\n",
979 desc_res.
m_records, num_keys, num_ckeys, num_keys + num_ckeys);
988 DBErrors result = DBErrors::LOAD_OK;
993 std::string strAddress;
997 pwallet->m_address_book[DecodeDestination(strAddress)].SetLabel(label);
998 return DBErrors::LOAD_OK;
1000 result = std::max(result, name_res.
m_result);
1005 std::string strAddress;
1007 std::string purpose_str;
1008 value >> purpose_str;
1009 std::optional<AddressPurpose> purpose{PurposeFromString(purpose_str)};
1011 pwallet->
WalletLogPrintf(
"Warning: nonstandard purpose string '%s' for address '%s'\n", purpose_str, strAddress);
1014 return DBErrors::LOAD_OK;
1016 result = std::max(result, purpose_res.m_result);
1021 std::string strAddress, strKey, strValue;
1025 const CTxDestination& dest{DecodeDestination(strAddress)};
1026 if (strKey.compare(
"used") == 0) {
1033 pwallet->LoadAddressPreviouslySpent(dest);
1034 }
else if (strKey.starts_with(
"rr")) {
1037 pwallet->LoadAddressReceiveRequest(dest, strKey.substr(2), strValue);
1039 return DBErrors::LOAD_OK;
1041 result = std::max(result, dest_res.m_result);
1049 DBErrors result = DBErrors::LOAD_OK;
1052 any_unordered =
false;
1055 DBErrors result = DBErrors::LOAD_OK;
1060 auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) {
1063 err =
"Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning.";
1064 result = DBErrors::CORRUPT;
1068 if (wtx.GetHash() != hash)
1072 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
1078 std::string unused_string;
1079 value >> fTmp >> fUnused >> unused_string;
1080 pwallet->WalletLogPrintf(
"LoadWallet() upgrading tx ver=%d %d %s\n",
1081 wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
1082 wtx.fTimeReceivedIsTxTime = fTmp;
1086 pwallet->WalletLogPrintf(
"LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString());
1087 wtx.fTimeReceivedIsTxTime = 0;
1089 upgraded_txs.push_back(hash);
1092 if (wtx.nOrderPos == -1)
1093 any_unordered = true;
1099 result = std::max(result, DBErrors::NEED_RESCAN);
1103 result = std::max(result, tx_res.m_result);
1112 pwallet->LockCoin(COutPoint(hash, n));
1113 return DBErrors::LOAD_OK;
1115 result = std::max(result, locked_utxo_res.m_result);
1122 value >> pwallet->nOrderPosNext;
1123 }
catch (
const std::exception& e) {
1125 return DBErrors::NONCRITICAL_ERROR;
1127 return DBErrors::LOAD_OK;
1129 result = std::max(result, order_pos_res.m_result);
1133 for (
auto& [
id, wtx] : pwallet->mapWallet) {
1134 if (wtx.IsCoinBase() && wtx.isInactive()) {
1135 pwallet->AbandonTransaction(wtx);
1145 DBErrors result = DBErrors::LOAD_OK;
1148 std::set<std::pair<OutputType, bool>> seen_spks;
1152 uint8_t output_type;
1158 auto [it,
insert] = seen_spks.emplace(
static_cast<OutputType>(output_type), internal);
1160 strErr =
"Multiple ScriptpubKeyMans specified for a single type";
1161 return DBErrors::CORRUPT;
1164 return DBErrors::LOAD_OK;
1166 result = std::max(result, spkm_res.
m_result);
1179 return DBErrors::CORRUPT;
1181 return DBErrors::LOAD_OK;
1188 DBErrors result = DBErrors::LOAD_OK;
1189 bool any_unordered =
false;
1190 std::vector<uint256> upgraded_txs;
1200 if ((result =
LoadMinVersion(pwallet, *m_batch)) != DBErrors::LOAD_OK)
return result;
1204 if ((result =
LoadWalletFlags(pwallet, *m_batch)) != DBErrors::LOAD_OK)
return result;
1206#ifndef ENABLE_EXTERNAL_SIGNER
1208 pwallet->
WalletLogPrintf(
"Error: External signer wallet being loaded without external signer support compiled\n");
1209 return DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED;
1221 if (result == DBErrors::UNKNOWN_DESCRIPTOR)
return result;
1227 result = std::max(
LoadTxRecords(pwallet, *m_batch, upgraded_txs, any_unordered), result);
1237 result = DBErrors::CORRUPT;
1242 if (result != DBErrors::LOAD_OK)
1245 for (
const uint256& hash : upgraded_txs)
1246 WriteTx(pwallet->mapWallet.at(hash));
1259 result = DBErrors::CORRUPT;
1267 result = DBErrors::CORRUPT;
1275 pwallet->
WalletLogPrintf(
"Detected extraneous encryption keys in this wallet without private keys. Removing extraneous encryption keys.\n");
1277 if (!EraseMasterKey(
id)) {
1278 pwallet->
WalletLogPrintf(
"Error: Unable to remove extraneous encryption key '%u'. Wallet corrupt.\n",
id);
1279 return DBErrors::CORRUPT;
1319 static std::atomic<bool> fOneThread(
false);
1320 if (fOneThread.exchange(
true)) {
1324 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets(context)) {
1344bool WalletBatch::WriteAddressPreviouslySpent(
const CTxDestination& dest,
bool previously_spent)
1347 return previously_spent ? WriteIC(key, std::string(
"1")) : EraseIC(key);
1350bool WalletBatch::WriteAddressReceiveRequest(
const CTxDestination& dest,
const std::string&
id,
const std::string& receive_request)
1355bool WalletBatch::EraseAddressReceiveRequest(
const CTxDestination& dest,
const std::string&
id)
1364 return m_batch->ErasePrefix(
prefix);
1372bool WalletBatch::WriteWalletFlags(
const uint64_t
flags)
1377bool WalletBatch::EraseRecords(
const std::unordered_set<std::string>& types)
1379 return std::all_of(types.begin(), types.end(), [&](
const std::string& type) {
1380 return m_batch->ErasePrefix(DataStream() << type);
1384bool WalletBatch::TxnBegin()
1386 return m_batch->TxnBegin();
1389bool WalletBatch::TxnCommit()
1391 bool res = m_batch->TxnCommit();
1393 for (
const auto& listener : m_txn_listeners) {
1394 listener.on_commit();
1397 m_txn_listeners.clear();
1402bool WalletBatch::TxnAbort()
1404 bool res = m_batch->TxnAbort();
1406 for (
const auto& listener : m_txn_listeners) {
1407 listener.on_abort();
1410 m_txn_listeners.clear();
1417 assert(m_batch->HasActiveTxn());
1418 m_txn_listeners.emplace_back(l);
1425 exists = fs::symlink_status(path).type() != fs::file_type::not_found;
1426 }
catch (
const fs::filesystem_error& e) {
1428 status = DatabaseStatus::FAILED_BAD_PATH;
1432 std::optional<DatabaseFormat>
format;
1435 format = DatabaseFormat::BERKELEY;
1440 status = DatabaseStatus::FAILED_BAD_FORMAT;
1443 format = DatabaseFormat::SQLITE;
1447 status = DatabaseStatus::FAILED_NOT_FOUND;
1453 status = DatabaseStatus::FAILED_BAD_FORMAT;
1459 status = DatabaseStatus::FAILED_ALREADY_EXISTS;
1465 format = DatabaseFormat::BERKELEY_RO;
1471 status = DatabaseStatus::FAILED_BAD_FORMAT;
1480 format = DatabaseFormat::SQLITE;
1482 format = DatabaseFormat::BERKELEY;
1486 if (
format == DatabaseFormat::SQLITE) {
1490 if (
format == DatabaseFormat::BERKELEY_RO) {
1495 if constexpr (
true) {
1501 status = DatabaseStatus::FAILED_BAD_FORMAT;
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
catch(const std::exception &e)
#define Assume(val)
Assume is the identity function.
An encapsulated private key.
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
const unsigned char * end() const
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
const unsigned char * begin() const
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization.
Double ended buffer combining vector and stream-like interfaces.
Cache for single descriptor's derived extended pubkeys.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
constexpr bool IsNull() const
uint32_t nInternalChainCounter
static const int VERSION_HD_BASE
uint32_t nExternalChainCounter
static const int VERSION_HD_CHAIN_SPLIT
CKeyID seed_id
seed hash160
A key from a CWallet's keypool.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
unsigned int nMasterKeyMaxID
DescriptorScriptPubKeyMan & LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
bool HaveCryptedKeys() const
LegacyDataSPKM * GetOrCreateLegacyDataSPKM()
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
void WalletLogPrintf(util::ConstevalFormatString< sizeof...(Params)> wallet_fmt, const Params &... params) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
bool HasEncryptionKeys() const override
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
MasterKeyMap mapMasterKeys
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
RecursiveMutex cs_wallet
Main wallet lock.
A transaction with a bunch of additional info that only the owner cares about.
const Txid & GetHash() const LIFETIMEBOUND
RAII class that provides access to a WalletDatabase.
virtual std::unique_ptr< DatabaseCursor > GetNewPrefixCursor(std::span< const std::byte > prefix)=0
uint256 GetID() const override
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, bool checksum_valid)
Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
Access to the wallet database.
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
bool TxnAbort()
Abort current transaction.
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
bool EraseName(const std::string &strAddress)
bool WriteBestBlock(const CBlockLocator &locator)
bool ReadBestBlock(CBlockLocator &locator)
bool WriteDescriptorCacheItems(const uint256 &desc_id, const DescriptorCache &cache)
bool EraseTx(uint256 hash)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteMinVersion(int nVersion)
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
bool TxnBegin()
Begin a new transaction.
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
std::unique_ptr< DatabaseBatch > m_batch
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
bool WriteDescriptorLastHardenedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool WriteTx(const CWalletTx &wtx)
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
bool ReadPool(int64_t nPool, CKeyPool &keypool)
bool EraseIC(const K &key)
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
bool ErasePurpose(const std::string &strAddress)
bool EraseLockedUTXO(const COutPoint &output)
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< unsigned char > &secret)
bool WriteLockedUTXO(const COutPoint &output)
bool EraseMasterKey(unsigned int id)
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool WritePool(int64_t nPool, const CKeyPool &keypool)
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
bool ErasePool(int64_t nPool)
bool EraseWatchOnly(const CScript &script)
An instance of this class represents one database.
virtual bool PeriodicFlush()=0
int64_t nLastWalletUpdate
std::atomic< unsigned int > nUpdateCounter
unsigned int nLastFlushed
Descriptor with some wallet metadata.
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
static std::string PathToString(const path &path)
Convert path object to a byte string.
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
DBErrors ReorderTransactions()
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
CPrivKey is a serialized private key, with all parameters included (SIZE bytes)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
std::string EncodeDestination(const CTxDestination &dest)
#define LogDebug(category,...)
std::string get_filesystem_error_message(const fs::filesystem_error &e)
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
const std::string BESTBLOCK
const std::string WALLETDESCRIPTORCKEY
const std::string WALLETDESCRIPTORLHCACHE
const std::string MINVERSION
const std::string WATCHMETA
const std::string DEFAULTKEY
const std::string OLD_KEY
const std::string WALLETDESCRIPTORKEY
const std::string ACENTRY
const std::string ACTIVEEXTERNALSPK
const std::string CRYPTED_KEY
const std::string DESTDATA
const std::string CSCRIPT
const std::unordered_set< std::string > LEGACY_TYPES
const std::string SETTINGS
const std::string BESTBLOCK_NOMERKLE
const std::string LOCKED_UTXO
const std::string ACTIVEINTERNALSPK
const std::string HDCHAIN
const std::string ORDERPOSNEXT
const std::string VERSION
const std::string WALLETDESCRIPTORCACHE
const std::string MASTER_KEY
const std::string KEYMETA
const std::string PURPOSE
const std::string WALLETDESCRIPTOR
std::unique_ptr< BerkeleyDatabase > MakeBerkeleyDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Return object giving access to Berkeley database at specified path.
static LoadResult LoadRecords(CWallet *pwallet, DatabaseBatch &batch, const std::string &key, LoadFunc load_func)
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, 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< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
bool RunWithinTxn(WalletDatabase &database, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
Executes the provided function 'func' within a database transaction context.
bool LoadKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
static DataStream PrefixStream(const Args &... args)
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
void MaybeCompactWalletDB(WalletContext &context)
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
static DBErrors LoadLegacyWalletRecords(CWallet *pwallet, DatabaseBatch &batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
bool LoadCryptedKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
std::function< DBErrors(CWallet *pwallet, DataStream &key, DataStream &value, std::string &err)> LoadFunc
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
fs::path SQLiteDataFile(const fs::path &path)
DBErrors
Error statuses for the wallet database.
@ UNEXPECTED_LEGACY_ENTRY
static DBErrors LoadWalletFlags(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static DBErrors LoadActiveSPKMs(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static DBErrors LoadDecryptionKeys(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
bool LoadEncryptionKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
bool HasLegacyRecords(CWallet &wallet)
Returns true if there are any DBKeys::LEGACY_TYPES record in the wallet db.
bool IsBDBFile(const fs::path &path)
fs::path BDBDataFile(const fs::path &wallet_path)
bool LoadHDChain(CWallet *pwallet, DataStream &ssValue, std::string &strErr)
std::unique_ptr< BerkeleyRODatabase > MakeBerkeleyRODatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Return object giving access to Berkeley Read Only database at specified path.
bool IsSQLiteFile(const fs::path &path)
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
static DBErrors LoadTxRecords(CWallet *pwallet, DatabaseBatch &batch, std::vector< uint256 > &upgraded_txs, bool &any_unordered) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static DBErrors LoadAddressBookRecords(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static LoadResult LoadRecords(CWallet *pwallet, DatabaseBatch &batch, const std::string &key, DataStream &prefix, LoadFunc load_func)
static DBErrors LoadDescriptorWalletRecords(CWallet *pwallet, DatabaseBatch &batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static DBErrors LoadMinVersion(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
const unsigned int BIP32_EXTKEY_SIZE
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
std::optional< DatabaseFormat > require_format
WalletContext struct containing references to state shared between CWallet instances,...
#define EXCLUSIVE_LOCKS_REQUIRED(...)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.