36 const std::string
FLAGS{
"flags"};
39 const std::string
KEY{
"key"};
42 const std::string
NAME{
"name"};
45 const std::string
POOL{
"pool"};
48 const std::string
TX{
"tx"};
106 std::vector<unsigned char> vchKey;
107 vchKey.reserve(vchPubKey.
size() + vchPrivKey.size());
108 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
109 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
115 const std::vector<unsigned char>& vchCryptedSecret,
126 if (!
WriteIC(key, std::make_pair(vchCryptedSecret, checksum),
false)) {
128 std::vector<unsigned char> val;
129 if (!
m_batch->Read(key, val)) {
132 if (!
WriteIC(key, std::make_pair(val, checksum),
true)) {
206 return WriteIC(make_pair(key, type),
id);
212 std::vector<unsigned char> key;
213 key.reserve(pubkey.
size() + privkey.size());
214 key.insert(key.end(), pubkey.
begin(), pubkey.
end());
215 key.insert(key.end(), privkey.begin(), privkey.end());
237 xpub.
Encode(ser_xpub.data());
244 xpub.
Encode(ser_xpub.data());
279 if (filter_fn && !filter_fn(strType)) {
283 std::string strAddress;
289 std::string strAddress;
297 auto fill_wtx = [&](
CWalletTx& wtx,
bool new_tx) {
300 if (wtx.GetHash() != hash)
304 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
306 if (!ssValue.
empty())
310 std::string unused_string;
311 ssValue >> fTmp >> fUnused >> unused_string;
312 strErr =
strprintf(
"LoadWallet() upgrading tx ver=%d %d %s",
313 wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
314 wtx.fTimeReceivedIsTxTime = fTmp;
318 strErr =
strprintf(
"LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
319 wtx.fTimeReceivedIsTxTime = 0;
324 if (wtx.nOrderPos == -1)
344 if (!vchPubKey.IsValid())
346 strErr =
"Error reading wallet database: CPubKey corrupt";
367 bool fSkipCheck =
false;
372 std::vector<unsigned char> vchKey;
373 vchKey.reserve(vchPubKey.size() + pkey.size());
374 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
375 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
377 if (
Hash(vchKey) != hash)
379 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
386 if (!key.
Load(pkey, vchPubKey, fSkipCheck))
388 strErr =
"Error reading wallet database: CPrivKey corrupt";
393 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed";
401 ssValue >> kMasterKey;
404 strErr =
strprintf(
"Error reading wallet database: duplicate CMasterKey id %u", nID);
413 if (!vchPubKey.IsValid())
415 strErr =
"Error reading wallet database: CPubKey corrupt";
418 std::vector<unsigned char> vchPrivKey;
419 ssValue >> vchPrivKey;
422 bool checksum_valid =
false;
423 if (!ssValue.
eof()) {
426 if ((checksum_valid =
Hash(vchPrivKey) != checksum)) {
427 strErr =
"Error reading wallet database: Crypted key corrupt";
436 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadCryptedKey failed";
453 bool internal =
false;
455 if (keyMeta.hdKeypath !=
"s" && keyMeta.hdKeypath !=
"m") {
456 std::vector<uint32_t> path;
457 if (keyMeta.has_key_origin) {
459 path = keyMeta.key_origin.path;
463 strErr =
"Error reading wallet database: keymeta with invalid HD keypath";
472 if (path.size() != 3) {
473 strErr =
"Error reading wallet database: keymeta found with unexpected path";
476 if (path[0] != 0x80000000) {
477 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000) for the element at index 0", path[0]);
480 if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
481 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected 0x80000000 or 0x80000001) for the element at index 1", path[1]);
484 if ((path[2] & 0x80000000) == 0) {
485 strErr =
strprintf(
"Unexpected path index of 0x%08x (expected to be greater than or equal to 0x80000000)", path[2]);
488 internal = path[1] == (1 | 0x80000000);
489 index = path[2] & ~0x80000000;
494 CHDChain& chain = ins.first->second;
498 chain.
seed_id = keyMeta.hd_seed_id;
518 ssValue >> vchPubKey;
519 if (!vchPubKey.IsValid()) {
520 strErr =
"Error reading wallet database: Default Key corrupt";
537 strErr =
"Error reading wallet database: LegacyScriptPubKeyMan::LoadCScript failed";
541 ssValue >> pwallet->nOrderPosNext;
543 std::string strAddress, strKey, strValue;
556 strErr =
"Error reading wallet database: Unknown non-tolerable wallet flags found";
560 strErr =
"Found unsupported 'wkey' record, try loading with version 0.18";
570 if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
571 strErr =
"Multiple ScriptPubKeyMans specified for a single type";
587 uint32_t key_exp_index;
590 ssKey >> key_exp_index;
603 xpub.
Decode(ser_xpub.data());
614 if (!pubkey.IsValid())
616 strErr =
"Error reading wallet database: CPubKey corrupt";
628 std::vector<unsigned char> to_hash;
629 to_hash.reserve(pubkey.size() + pkey.size());
630 to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
631 to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
633 if (
Hash(to_hash) != hash)
635 strErr =
"Error reading wallet database: CPubKey/CPrivKey corrupt";
639 if (!key.
Load(pkey, pubkey,
true))
641 strErr =
"Error reading wallet database: CPrivKey corrupt";
644 wss.
m_descriptor_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
650 if (!pubkey.IsValid())
652 strErr =
"Error reading wallet database: CPubKey corrupt";
655 std::vector<unsigned char> privkey;
659 wss.
m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey)));
666 }
catch (
const std::exception& e) {
667 if (strErr.empty()) {
672 if (strErr.empty()) {
673 strErr =
"Caught unknown exception in ReadKeyValue";
684 return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr, filter_fn);
696 bool fNoncriticalErrors =
false;
721 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
728 pwallet->
WalletLogPrintf(
"Error reading next record from wallet database\n");
733 std::string strType, strErr;
734 if (!
ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
745 fNoncriticalErrors =
true;
781 ((
DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
797 pwallet->
WalletLogPrintf(
"Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client);
799 pwallet->
WalletLogPrintf(
"Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
806 LOCK(spk_man->cs_KeyStore);
807 spk_man->UpdateTimeFirstKey(1);
812 WriteTx(pwallet->mapWallet.at(hash));
815 if (wss.
fIsEncrypted && (last_client == 40000 || last_client == 50000))
836 pwallet->
WalletLogPrintf(
"Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
863 LogPrintf(
"Error getting wallet database cursor\n");
873 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
878 LogPrintf(
"Error reading next record from wallet database\n");
887 vTxHash.push_back(hash);
888 vWtx.emplace_back(
nullptr ,
nullptr );
889 ssValue >> vWtx.back();
903 std::vector<uint256> vTxHash;
904 std::list<CWalletTx> vWtx;
910 std::sort(vTxHash.begin(), vTxHash.end());
911 std::sort(vTxHashIn.begin(), vTxHashIn.end());
914 bool delerror =
false;
915 std::vector<uint256>::iterator
it = vTxHashIn.begin();
916 for (
const uint256& hash : vTxHash) {
917 while (
it < vTxHashIn.end() && (*it) < hash) {
920 if (
it == vTxHashIn.end()) {
923 else if ((*
it) == hash) {
925 LogPrint(
BCLog::WALLETDB,
"Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
928 vTxHashOut.push_back(hash);
940 static std::atomic<bool> fOneThread(
false);
941 if (fOneThread.exchange(
true)) {
945 for (
const std::shared_ptr<CWallet>& pwallet :
GetWallets()) {
1005 exists = fs::symlink_status(path).type() != fs::file_not_found;
1006 }
catch (
const fs::filesystem_error& e) {
1069 return MakeUnique<DummyDatabase>();
1075 return MakeUnique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(),
"");
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
const CHDChain & GetHDChain() const
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
bool ErasePurpose(const std::string &strAddress)
bool IsLegacy() const
Determine if we are a legacy wallet.
std::deque< CInv >::iterator it
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 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
static void LogPrintf(const char *fmt, const Args &... args)
uint32_t nExternalChainCounter
std::vector< std::shared_ptr< CWallet > > GetWallets()
unsigned int m_unknown_records
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)
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)
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.
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
bool ExistsBerkeleyDatabase(const fs::path &path)
Check if Berkeley database exists at specified path.
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) ...
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 WALLETDESCRIPTORCACHE
std::map< std::pair< uint256, CKeyID >, std::pair< CPubKey, std::vector< unsigned char > > > m_descriptor_crypt_keys
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)
CTxDestination DecodeDestination(const std::string &str)
#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
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.
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
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
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.
#define ExistsSQLiteDatabase(path)
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
boost::optional< T > Optional
Substitute for C++17 std::optional.
const std::string BESTBLOCK
Optional< DatabaseFormat > require_format
const std::string CSCRIPT
bool EraseTx(uint256 hash)
DBErrors FindWalletTx(std::vector< uint256 > &vTxHash, std::list< CWalletTx > &vWtx)
CKeyID seed_id
seed hash160
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.