9#include <chainparams.h>
34const std::string
FLAGS{
"flags"};
37const std::string
KEY{
"key"};
40const std::string
NAME{
"name"};
43const std::string
POOL{
"pool"};
46const std::string
TX{
"tx"};
120 std::vector<uint8_t> vchKey;
122 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
142 std::vector<uint8_t> val;
143 if (!
m_batch->Read(key, val)) {
230 std::vector<uint8_t> key;
232 key.insert(key.end(), pubkey.
begin(), pubkey.
end());
236 std::make_pair(
desc_id, pubkey)),
242 const std::vector<uint8_t> &
secret) {
244 std::make_pair(
desc_id, pubkey)),
249 std::make_pair(
desc_id, pubkey)));
295 std::map<std::pair<uint256, CKeyID>,
296 std::pair<CPubKey, std::vector<uint8_t>>>
341 if (wtx.GetId() != txid) {
346 if (31404 <= wtx.fTimeReceivedIsTxTime &&
347 wtx.fTimeReceivedIsTxTime <= 31703) {
348 if (!ssValue.
empty()) {
354 "LoadWallet() upgrading tx ver=%d %d %s",
356 wtx.fTimeReceivedIsTxTime =
fTmp;
359 "LoadWallet() repairing tx ver=%d %s",
360 wtx.fTimeReceivedIsTxTime, txid.
ToString());
361 wtx.fTimeReceivedIsTxTime = 0;
363 wss.vWalletUpgrade.push_back(txid);
366 if (wtx.nOrderPos == -1) {
367 wss.fAnyUnordered =
true;
389 strErr =
"Error reading wallet database: CPubKey corrupt";
414 std::vector<uint8_t> vchKey;
415 vchKey.reserve(vchPubKey.
size() +
pkey.size());
416 vchKey.insert(vchKey.end(), vchPubKey.
begin(), vchPubKey.
end());
417 vchKey.insert(vchKey.end(),
pkey.begin(),
pkey.end());
419 if (
Hash(vchKey) != hash) {
420 strErr =
"Error reading wallet database: CPubKey/CPrivKey "
429 strErr =
"Error reading wallet database: CPrivKey corrupt";
434 strErr =
"Error reading wallet database: "
435 "LegacyScriptPubKeyMan::LoadKey failed";
447 "Error reading wallet database: duplicate CMasterKey id %u",
459 strErr =
"Error reading wallet database: CPubKey corrupt";
467 if (!ssValue.
eof()) {
472 "Error reading wallet database: Crypted key corrupt";
481 strErr =
"Error reading wallet database: "
482 "LegacyScriptPubKeyMan::LoadCryptedKey failed";
485 wss.fIsEncrypted =
true;
505 std::vector<uint32_t> path;
508 path =
keyMeta.key_origin.path;
512 strErr =
"Error reading wallet database: keymeta "
513 "with invalid HD keypath";
523 if (path.size() != 3) {
524 strErr =
"Error reading wallet database: keymeta found "
525 "with unexpected path";
528 if (path[0] != 0x80000000) {
530 "Unexpected path index of 0x%08x (expected "
531 "0x80000000) for the element at index 0",
535 if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
537 strprintf(
"Unexpected path index of 0x%08x "
538 "(expected 0x80000000 or 0x80000001) for "
539 "the element at index 1",
543 if ((path[2] & 0x80000000) == 0) {
545 "Unexpected path index of 0x%08x (expected to be "
546 "greater than or equal to 0x80000000)",
550 internal = path[1] == (1 | 0x80000000);
551 index = path[2] & ~0x80000000;
586 ssValue >> vchPubKey;
588 strErr =
"Error reading wallet database: Default Key corrupt";
606 strErr =
"Error reading wallet database: "
607 "LegacyScriptPubKeyMan::LoadCScript failed";
611 ssValue >> pwallet->nOrderPosNext;
628 strErr =
"Error reading wallet database: Unknown non-tolerable "
629 "wallet flags found";
633 strErr =
"Found unsupported 'wkey' record, try loading with "
645 :
wss.m_active_external_spks;
648 "Multiple ScriptPubKeyMans specified for a single type";
657 if (
wss.m_descriptor_caches.count(
id) == 0) {
681 wss.m_descriptor_caches[
desc_id].CacheParentExtPubKey(
684 wss.m_descriptor_caches[
desc_id].CacheDerivedExtPubKey(
693 strErr =
"Error reading wallet database: CPubKey corrupt";
712 "Error reading wallet database: CPubKey/CPrivKey corrupt";
716 if (!key.
Load(
pkey, pubkey,
true)) {
717 strErr =
"Error reading wallet database: CPrivKey corrupt";
720 wss.m_descriptor_keys.insert(
721 std::make_pair(std::make_pair(
desc_id, pubkey.
GetID()), key));
728 strErr =
"Error reading wallet database: CPubKey corrupt";
737 std::make_pair(pubkey,
privkey)));
738 wss.fIsEncrypted =
true;
744 wss.m_unknown_records++;
746 }
catch (
const std::exception &
e) {
753 strErr =
"Caught unknown exception in ReadKeyValue";
800 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
807 "Error reading next record from wallet database\n");
894 "metadata, %u total. Unknown wallet records: %u\n",
896 wss.nKeys +
wss.nCKeys,
wss.m_unknown_records);
900 (
wss.nKeys +
wss.nCKeys +
wss.nWatchKeys) !=
wss.nKeyMeta) {
904 spk_man->UpdateTimeFirstKey(1);
908 for (
const TxId &txid :
wss.vWalletUpgrade) {
909 WriteTx(pwallet->mapWallet.at(txid));
922 if (
wss.fAnyUnordered) {
936 if (
wss.m_hd_chains.size() > 0) {
941 "Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
957 std::list<CWalletTx> &
vWtx) {
970 LogPrintf(
"Error getting wallet database cursor\n");
979 bool ret =
m_batch->ReadAtCursor(ssKey, ssValue, complete);
986 LogPrintf(
"Error reading next record from wallet database\n");
995 txIds.push_back(txid);
996 vWtx.emplace_back(
nullptr );
997 ssValue >>
vWtx.back();
1011 std::vector<TxId>
txIds;
1012 std::list<CWalletTx>
vWtx;
1023 std::vector<TxId>::iterator it =
txIdsIn.begin();
1025 while (it <
txIdsIn.end() && (*it) < txid) {
1032 if ((*it) == txid) {
1035 "Transaction was found for deletion but returned "
1036 "database error: %s\n",
1056 for (
const std::shared_ptr<CWallet> &pwallet :
GetWallets()) {
1061 if (
dbh.nLastSeen != nUpdateCounter) {
1062 dbh.nLastSeen = nUpdateCounter;
1066 if (
dbh.nLastFlushed != nUpdateCounter &&
1068 if (
dbh.PeriodicFlush()) {
1069 dbh.nLastFlushed = nUpdateCounter;
1078 const std::string &key,
1079 const std::string &value) {
1091 const std::string &key) {
1095 return EraseIC(std::make_pair(
1126 exists = fs::symlink_status(path).type() != fs::file_type::not_found;
1127 }
catch (
const fs::filesystem_error &
e) {
1135 std::optional<DatabaseFormat> format;
1142 strprintf(
"Failed to load database path '%s'. Path does not exist.",
1150 "Data is not in recognized format.",
1158 "Failed to create database path '%s'. Database already exists.",
1171 return std::make_unique<DummyDatabase>();
1176 return std::make_unique<BerkeleyDatabase>(
1177 std::make_shared<BerkeleyEnvironment>(),
"");
bool ExistsBerkeleyDatabase(const fs::path &path)
Check if Berkeley database exists at specified path.
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 ParseHDKeypath(const std::string &keypath_str, std::vector< uint32_t > &keypath)
Parse an HD keypaths like "m/7/0'/2000".
const CChainParams & Params()
Return the currently selected parameters.
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Double ended buffer combining vector and stream-like interfaces.
iterator insert(iterator it, const value_type x)
static const int VERSION_HD_BASE
uint32_t nInternalChainCounter
CKeyID seed_id
seed hash160
static const int VERSION_HD_CHAIN_SPLIT
uint32_t nExternalChainCounter
An encapsulated secp256k1 private key.
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
A key from a CWallet's keypool.
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
const uint8_t * end() const
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
const uint8_t * begin() const
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization (see script.h)
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
MasterKeyMap mapMasterKeys
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
bool IsLegacy() const
Determine if we are a legacy wallet.
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
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.
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
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
unsigned int m_unknown_records
std::map< uint160, CHDChain > m_hd_chains
std::map< uint256, DescriptorCache > m_descriptor_caches
std::vector< TxId > vWalletUpgrade
std::map< OutputType, uint256 > m_active_internal_spks
std::map< std::pair< uint256, CKeyID >, std::pair< CPubKey, std::vector< uint8_t > > > m_descriptor_crypt_keys
std::map< OutputType, uint256 > m_active_external_spks
std::map< std::pair< uint256, CKeyID >, CKey > m_descriptor_keys
A transaction with a bunch of additional info that only the owner cares about.
Cache for single descriptor's derived extended pubkeys.
const CHDChain & GetHDChain() const
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< uint8_t > &vchCryptedSecret, bool checksum_valid)
Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
Load a keypool entry.
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
void AddInactiveHDChain(const CHDChain &chain)
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
bool TxnCommit()
Commit current transaction.
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
bool WriteName(const CTxDestination &address, const std::string &strName)
bool ErasePool(int64_t nPool)
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
bool WriteMinVersion(int nVersion)
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
static bool IsKeyType(const std::string &strType)
bool ErasePurpose(const CTxDestination &address)
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
bool EraseWatchOnly(const CScript &script)
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
bool ReadPool(int64_t nPool, CKeyPool &keypool)
bool WriteWalletFlags(const uint64_t flags)
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
std::unique_ptr< DatabaseBatch > m_batch
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
bool ReadBestBlock(CBlockLocator &locator)
DBErrors FindWalletTx(std::vector< TxId > &txIds, std::list< CWalletTx > &vWtx)
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
bool WriteOrderPosNext(int64_t nOrderPosNext)
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
bool WriteTx(const CWalletTx &wtx)
bool EraseIC(const K &key)
bool TxnBegin()
Begin a new transaction.
bool TxnAbort()
Abort current transaction.
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
bool EraseName(const CTxDestination &address)
bool WritePool(int64_t nPool, const CKeyPool &keypool)
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< uint8_t > &vchCryptedSecret, const CKeyMetadata &keyMeta)
bool WriteBestBlock(const CBlockLocator &locator)
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< uint8_t > &secret)
bool EraseTx(uint256 hash)
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.
An instance of this class represents one database.
std::atomic< unsigned int > nUpdateCounter
Descriptor with some wallet metadata.
std::string ToString() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
bool LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
const CChainParams & GetChainParams() const override
DBErrors ReorderTransactions()
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
std::vector< uint8_t, secure_allocator< uint8_t > > CPrivKey
secure_allocator is defined in allocators.h CPrivKey is a serialized private key, with all parameters...
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams ¶ms)
bool error(const char *fmt, const Args &...args)
#define LogPrint(category,...)
const std::string ORDERPOSNEXT
const std::string DEFAULTKEY
const std::string CSCRIPT
const std::string BESTBLOCK_NOMERKLE
const std::string DESTDATA
const std::string WALLETDESCRIPTORKEY
const std::string SETTINGS
const std::string WALLETDESCRIPTORCKEY
const std::string ACTIVEEXTERNALSPK
const std::string MINVERSION
const std::string HDCHAIN
const std::string WALLETDESCRIPTORCACHE
const std::string WALLETDESCRIPTOR
const std::string VERSION
const std::string KEYMETA
const std::string WATCHMETA
const std::string ACENTRY
const std::string MASTER_KEY
const std::string ACTIVEINTERNALSPK
const std::string PURPOSE
const std::string OLD_KEY
const std::string CRYPTED_KEY
const std::string BESTBLOCK
static std::string PathToString(const path &path)
Convert path object to byte string.
std::string get_filesystem_error_message(const fs::filesystem_error &e)
const unsigned int BIP32_EXTKEY_SIZE
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
A TxId is the identifier of a transaction.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::vector< std::shared_ptr< CWallet > > GetWallets()
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
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)
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, std::string &strType, std::string &strErr, const KeyFilterFn &filter_fn=nullptr)
Unserialize a given Key-Value pair and load it into the wallet.
DBErrors
Error statuses for the wallet database.
std::function< bool(const std::string &)> KeyFilterFn
Callback for filtering key types to deserialize in ReadKeyValue.