39 const std::string
FLAGS{
"flags"};
42 const std::string
KEY{
"key"};
45 const std::string
NAME{
"name"};
48 const std::string
POOL{
"pool"};
51 const std::string
TX{
"tx"};
110 std::vector<unsigned char> vchKey;
111 vchKey.reserve(vchPubKey.
size() + vchPrivKey.size());
112 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
113 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
119 const std::vector<unsigned char>& vchCryptedSecret,
130 if (!
WriteIC(key, std::make_pair(vchCryptedSecret, checksum),
false)) {
132 std::vector<unsigned char> val;
133 if (!
m_batch->Read(key, val)) {
136 if (!
WriteIC(key, std::make_pair(val, checksum),
true)) {
210 return WriteIC(make_pair(key, type),
id);
216 return EraseIC(make_pair(key, type));
222 std::vector<unsigned char> key;
223 key.reserve(pubkey.
size() + privkey.size());
224 key.insert(key.end(), pubkey.
begin(), pubkey.
end());
225 key.insert(key.end(), privkey.begin(), privkey.end());
247 xpub.
Encode(ser_xpub.data());
254 xpub.
Encode(ser_xpub.data());
261 xpub.
Encode(ser_xpub.data());
273 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
318 if (filter_fn && !filter_fn(strType)) {
322 std::string strAddress;
328 std::string strAddress;
336 auto fill_wtx = [&](
CWalletTx& wtx,
bool new_tx) {
339 if (wtx.GetHash() != hash)
343 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
345 if (!ssValue.
empty())
349 std::string unused_string;
350 ssValue >> fTmp >> fUnused >> unused_string;
351 strErr =
strprintf(
"LoadWallet() upgrading tx ver=%d %d %s",
352 wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
353 wtx.fTimeReceivedIsTxTime = fTmp;
357 strErr =
strprintf(
"LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
358 wtx.fTimeReceivedIsTxTime = 0;
363 if (wtx.nOrderPos == -1)
383 if (!vchPubKey.IsValid())
385 strErr =
"Error reading wallet database: CPubKey corrupt";
404 catch (
const std::ios_base::failure&) {}
406 bool fSkipCheck =
false;
411 std::vector<unsigned char> vchKey;
412 vchKey.reserve(vchPubKey.size() + pkey.size());
413 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
414 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
416 if (
Hash(vchKey) != hash)
418 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
425 if (!key.
Load(pkey, vchPubKey, fSkipCheck))
427 strErr =
"Error reading wallet database: CPrivKey corrupt";
432 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed";
440 ssValue >> kMasterKey;
443 strErr =
strprintf(
"Error reading wallet database: duplicate CMasterKey id %u", nID);
452 if (!vchPubKey.IsValid())
454 strErr =
"Error reading wallet database: CPubKey corrupt";
457 std::vector<unsigned char> vchPrivKey;
458 ssValue >> vchPrivKey;
461 bool checksum_valid =
false;
462 if (!ssValue.
eof()) {
465 if ((checksum_valid =
Hash(vchPrivKey) != checksum)) {
466 strErr =
"Error reading wallet database: Encrypted key corrupt";
475 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadCryptedKey failed";
492 bool internal =
false;
494 if (keyMeta.hdKeypath !=
"s" && keyMeta.hdKeypath !=
"m") {
495 std::vector<uint32_t> path;
496 if (keyMeta.has_key_origin) {
498 path = keyMeta.key_origin.path;
502 strErr =
"Error reading wallet database: keymeta with invalid HD keypath";
511 if (path.size() != 3) {
512 strErr =
"Error reading wallet database: keymeta found with unexpected path";
515 if (path[0] != 0x80000000) {
516 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000) for the element at index 0", path[0]);
519 if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
520 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000 or 0x80000001) for the element at index 1", path[1]);
523 if ((path[2] & 0x80000000) == 0) {
524 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected to be greater than or equal to 0x80000000)", path[2]);
527 internal = path[1] == (1 | 0x80000000);
528 index = path[2] & ~0x80000000;
533 CHDChain& chain = ins.first->second;
537 chain.
seed_id = keyMeta.hd_seed_id;
557 ssValue >> vchPubKey;
558 if (!vchPubKey.IsValid()) {
559 strErr =
"Error reading wallet database: Default Key corrupt";
576 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadCScript failed";
580 ssValue >> pwallet->nOrderPosNext;
582 std::string strAddress, strKey, strValue;
592 strErr =
"Found unsupported 'wkey' record, try loading with version 0.18";
602 if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
603 strErr =
"Multiple ScriptPubKeyMans specified for a single type";
619 uint32_t key_exp_index;
622 ssKey >> key_exp_index;
635 xpub.
Decode(ser_xpub.data());
643 uint32_t key_exp_index;
645 ssKey >> key_exp_index;
650 xpub.
Decode(ser_xpub.data());
657 if (!pubkey.IsValid())
659 strErr =
"Error reading wallet database: CPubKey corrupt";
671 std::vector<unsigned char> to_hash;
672 to_hash.reserve(pubkey.size() + pkey.size());
673 to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
674 to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
676 if (
Hash(to_hash) != hash)
678 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
682 if (!key.
Load(pkey, pubkey,
true))
684 strErr =
"Error reading wallet database: CPrivKey corrupt";
687 wss.
m_descriptor_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
693 if (!pubkey.IsValid())
695 strErr =
"Error reading wallet database: CPubKey corrupt";
698 std::vector<unsigned char> privkey;
702 wss.
m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey)));
710 }
catch (
const std::exception& e) {
711 if (strErr.empty()) {
716 if (strErr.empty()) {
717 strErr =
"Caught unknown exception in ReadKeyValue";
728 return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr, filter_fn);
740 bool fNoncriticalErrors =
false;
757 pwallet->
WalletLogPrintf(
"Error reading wallet database: Unknown non-tolerable wallet flags found\n");
762 #ifndef ENABLE_EXTERNAL_SIGNER 764 pwallet->
WalletLogPrintf(
"Error: External signer wallet being loaded without external signer support compiled\n");
782 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
789 pwallet->
WalletLogPrintf(
"Error reading next record from wallet database\n");
794 std::string strType, strErr;
795 if (!
ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
806 fNoncriticalErrors =
true;
842 ((
DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
858 pwallet->
WalletLogPrintf(
"Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client);
860 pwallet->
WalletLogPrintf(
"Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
867 LOCK(spk_man->cs_KeyStore);
868 spk_man->UpdateTimeFirstKey(1);
873 WriteTx(pwallet->mapWallet.at(hash));
876 if (wss.
fIsEncrypted && (last_client == 40000 || last_client == 50000))
905 pwallet->
WalletLogPrintf(
"Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
932 LogPrintf(
"Error getting wallet database cursor\n");
942 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
947 LogPrintf(
"Error reading next record from wallet database\n");
956 vTxHash.push_back(hash);
957 vWtx.emplace_back(
nullptr ,
nullptr );
958 ssValue >> vWtx.back();
972 std::vector<uint256> vTxHash;
973 std::list<CWalletTx> vWtx;
979 std::sort(vTxHash.begin(), vTxHash.end());
980 std::sort(vTxHashIn.begin(), vTxHashIn.end());
983 bool delerror =
false;
984 std::vector<uint256>::iterator it = vTxHashIn.begin();
985 for (
const uint256& hash : vTxHash) {
986 while (it < vTxHashIn.end() && (*it) < hash) {
989 if (it == vTxHashIn.end()) {
992 else if ((*it) == hash) {
994 LogPrint(
BCLog::WALLETDB,
"Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
997 vTxHashOut.push_back(hash);
1009 static std::atomic<bool> fOneThread(
false);
1010 if (fOneThread.exchange(
true)) {
1014 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
1074 exists = fs::symlink_status(path).type() != fs::file_not_found;
1075 }
catch (
const fs::filesystem_error& e) {
1081 std::optional<DatabaseFormat>
format;
1136 error =
Untranslated(
strprintf(
"Failed to open database path '%s'. Build does not support SQLite database format.", path.string()));
1144 error =
Untranslated(
strprintf(
"Failed to open database path '%s'. Build does not support Berkeley DB database format.", path.string()));
1152 return std::make_unique<DummyDatabase>();
1159 return std::make_unique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(),
"");
1161 return std::make_unique<SQLiteDatabase>(
"",
"",
true);
bool TxnCommit()
Commit current transaction.
bool WriteName(const std::string &strAddress, const std::string &strName)
bool EraseIC(const K &key)
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
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 EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
int64_t nLastWalletUpdate
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
const CHDChain & GetHDChain() const
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
bool ErasePurpose(const std::string &strAddress)
bool IsLegacy() const
Determine if we are a legacy wallet.
fs::path BDBDataFile(const fs::path &wallet_path)
bool ReadBestBlock(CBlockLocator &locator)
std::map< OutputType, uint256 > m_active_internal_spks
#define LogPrint(category,...)
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
const std::string SETTINGS
const std::string WALLETDESCRIPTORCKEY
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
std::map< OutputType, uint256 > m_active_external_spks
const std::string CRYPTED_KEY
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
const std::string DEFAULTKEY
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
bool WriteMinVersion(int nVersion)
virtual bool PeriodicFlush()=0
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
const std::string KEYMETA
std::vector< uint256 > vWalletUpgrade
std::map< uint160, CHDChain > m_hd_chains
bool WriteDescriptorCacheItems(const uint256 &desc_id, const DescriptorCache &cache)
uint32_t nExternalChainCounter
unsigned int m_unknown_records
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
bool TxnBegin()
Begin a new transaction.
Double ended buffer combining vector and stream-like interfaces.
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
Indicates that the wallet needs an external signer.
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
bool WriteTx(const CWalletTx &wtx)
DBErrors LoadWallet(CWallet *pwallet)
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
DBErrors
Error statuses for the wallet database.
const std::string ORDERPOSNEXT
bool WriteWalletFlags(const uint64_t flags)
const std::string VERSION
const unsigned char * begin() const
const std::string MASTER_KEY
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
void AddInactiveHDChain(const CHDChain &chain)
bool EraseWatchOnly(const CScript &script)
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< unsigned char > &secret)
bool WriteBestBlock(const CBlockLocator &locator)
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
secure_allocator is defined in allocators.h CPrivKey is a serialized private key, with all parameters...
bool TxnAbort()
Abort current transaction.
const std::string OLD_KEY
DBErrors ReorderTransactions()
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
bool IsSQLiteFile(const fs::path &path)
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
const std::string HDCHAIN
unsigned int nMasterKeyMaxID
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
static bool IsKeyType(const std::string &strType)
const std::string WALLETDESCRIPTOR
const unsigned char * end() const
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
std::unique_ptr< DatabaseBatch > m_batch
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
const std::string ACTIVEINTERNALSPK
An encapsulated public key.
const std::string WATCHMETA
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
const std::string WALLETDESCRIPTORKEY
const std::string DESTDATA
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
bool WriteOrderPosNext(int64_t nOrderPosNext)
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
std::vector< uint256 > vHave
Descriptor with some wallet metadata.
const uint256 & GetHash() const
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
bool IsBDBFile(const fs::path &path)
A transaction with a bunch of additional info that only the owner cares about.
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
std::map< uint256, DescriptorCache > m_descriptor_caches
const std::string WALLETDESCRIPTORLHCACHE
const std::string WALLETDESCRIPTORCACHE
std::map< std::pair< uint256, CKeyID >, std::pair< CPubKey, std::vector< unsigned char > > > m_descriptor_crypt_keys
std::vector< std::shared_ptr< CWallet > > GetWallets()
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.
bool ErasePool(int64_t nPool)
bool WritePool(int64_t nPool, const CKeyPool &keypool)
std::string get_filesystem_error_message(const fs::filesystem_error &e)
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
const std::string ACENTRY
bool WriteDescriptorLastHardenedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
MasterKeyMap mapMasterKeys
std::map< std::pair< uint256, CKeyID >, CKey > m_descriptor_keys
std::atomic< unsigned int > nUpdateCounter
bool ParseHDKeypath(const std::string &keypath_str, std::vector< uint32_t > &keypath)
Parse an HD keypaths like "m/7/0'/2000".
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet) ...
Cache for single descriptor's derived extended pubkeys.
Serialized script, used inside transaction inputs and outputs.
fs::path SQLiteDataFile(const fs::path &path)
const std::string MINVERSION
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
Load a keypool entry.
const unsigned int BIP32_EXTKEY_SIZE
unsigned int nLastFlushed
std::optional< DatabaseFormat > require_format
const std::string ACTIVEEXTERNALSPK
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
bool ReadPool(int64_t nPool, CKeyPool &keypool)
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
static const int VERSION_HD_CHAIN_SPLIT
RecursiveMutex cs_wallet
Main wallet lock.
A reference to a CScript: the Hash160 of its serialization (see script.h)
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, std::string &strType, std::string &strErr, const KeyFilterFn &filter_fn=nullptr) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
An encapsulated private key.
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
const std::string BESTBLOCK
const std::string CSCRIPT
bool EraseTx(uint256 hash)
DBErrors FindWalletTx(std::vector< uint256 > &vTxHash, std::list< CWalletTx > &vWtx)
CKeyID seed_id
seed hash160
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
int64_t GetTime()
Return system time (or mocked time, if set)
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
std::function< bool(const std::string &)> KeyFilterFn
Callback for filtering key types to deserialize in ReadKeyValue.
const std::string BESTBLOCK_NOMERKLE
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
bool error(const char *fmt, const Args &... args)
static const int VERSION_HD_BASE
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
uint32_t nInternalChainCounter
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
A key from a CWallet's keypool.
bool EraseName(const std::string &strAddress)
const std::string PURPOSE
An instance of this class represents one database.