merge bitcoin#16475: Enumerate walletdb keys

This commit is contained in:
Kittywhiskers Van Gogh 2021-12-12 19:08:12 +05:30
parent f67199bbb0
commit 1f61b27399
4 changed files with 145 additions and 129 deletions

View File

@ -5481,12 +5481,6 @@ CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool fInternalIn)
fInternal = fInternalIn; fInternal = fInternalIn;
} }
CWalletKey::CWalletKey(int64_t nExpires)
{
nTimeCreated = (nExpires ? GetTime() : 0);
nTimeExpires = nExpires;
}
void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock) void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock)
{ {
// Update the tx's hashBlock // Update the tx's hashBlock

View File

@ -601,21 +601,17 @@ public:
} }
}; };
/** Private key that includes an expiration date in case it never gets used. */ /** Private key that was serialized by an old wallet (only used for deserialization) */
class CWalletKey struct OldKey {
{
public:
CPrivKey vchPrivKey; CPrivKey vchPrivKey;
int64_t nTimeCreated;
int64_t nTimeExpires;
std::string strComment;
// todo: add something to note what created it (user, getnewaddress, change)
// maybe should have a map<string, string> property map
explicit CWalletKey(int64_t nExpires=0);
SERIALIZE_METHODS(CWalletKey, obj) SERIALIZE_METHODS(CWalletKey, obj)
{ {
// no longer used by the wallet, thus dropped after deserialization:
int64_t nTimeCreated;
int64_t nTimeExpires;
std::string strComment;
int nVersion = s.GetVersion(); int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion); READWRITE(nVersion);

View File

@ -22,50 +22,80 @@
#include <atomic> #include <atomic>
#include <string> #include <string>
namespace DBKeys {
const std::string ACENTRY{"acentry"};
const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
const std::string BESTBLOCK{"bestblock"};
const std::string CRYPTED_KEY{"ckey"};
const std::string CRYPTED_HDCHAIN{"chdchain"};
const std::string COINJOIN_SALT{"cj_salt"};
const std::string CSCRIPT{"cscript"};
const std::string DEFAULTKEY{"defaultkey"};
const std::string DESTDATA{"destdata"};
const std::string FLAGS{"flags"};
const std::string G_OBJECT{"g_object"};
const std::string HDCHAIN{"hdchain"};
const std::string HDPUBKEY{"hdpubkey"};
const std::string KEYMETA{"keymeta"};
const std::string KEY{"key"};
const std::string MASTER_KEY{"mkey"};
const std::string MINVERSION{"minversion"};
const std::string NAME{"name"};
const std::string OLD_KEY{"wkey"};
const std::string ORDERPOSNEXT{"orderposnext"};
const std::string POOL{"pool"};
const std::string PURPOSE{"purpose"};
const std::string PRIVATESEND_SALT{"ps_salt"};
const std::string TX{"tx"};
const std::string VERSION{"version"};
const std::string WATCHMETA{"watchmeta"};
const std::string WATCHS{"watchs"};
} // namespace DBKeys
// //
// WalletBatch // WalletBatch
// //
bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName) bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName)
{ {
return WriteIC(std::make_pair(std::string("name"), strAddress), strName); return WriteIC(std::make_pair(DBKeys::NAME, strAddress), strName);
} }
bool WalletBatch::EraseName(const std::string& strAddress) bool WalletBatch::EraseName(const std::string& strAddress)
{ {
// This should only be used for sending addresses, never for receiving addresses, // This should only be used for sending addresses, never for receiving addresses,
// receiving addresses must always have an address book entry if they're not change return. // receiving addresses must always have an address book entry if they're not change return.
return EraseIC(std::make_pair(std::string("name"), strAddress)); return EraseIC(std::make_pair(DBKeys::NAME, strAddress));
} }
bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose) bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
{ {
return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose); return WriteIC(std::make_pair(DBKeys::PURPOSE, strAddress), strPurpose);
} }
bool WalletBatch::ErasePurpose(const std::string& strAddress) bool WalletBatch::ErasePurpose(const std::string& strAddress)
{ {
return EraseIC(std::make_pair(std::string("purpose"), strAddress)); return EraseIC(std::make_pair(DBKeys::PURPOSE, strAddress));
} }
bool WalletBatch::WriteTx(const CWalletTx& wtx) bool WalletBatch::WriteTx(const CWalletTx& wtx)
{ {
return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); return WriteIC(std::make_pair(DBKeys::TX, wtx.GetHash()), wtx);
} }
bool WalletBatch::EraseTx(uint256 hash) bool WalletBatch::EraseTx(uint256 hash)
{ {
return EraseIC(std::make_pair(std::string("tx"), hash)); return EraseIC(std::make_pair(DBKeys::TX, hash));
} }
bool WalletBatch::WriteKeyMeta(const CPubKey& vchPubKey, const CKeyMetadata& keyMeta) bool WalletBatch::WriteKeyMeta(const CPubKey& vchPubKey, const CKeyMetadata& keyMeta)
{ {
return WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, true); return WriteIC(std::make_pair(DBKeys::KEYMETA, vchPubKey), keyMeta, true);
} }
bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
{ {
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) { if (!WriteIC(std::make_pair(DBKeys::KEYMETA, vchPubKey), keyMeta, false)) {
return false; return false;
} }
@ -75,102 +105,102 @@ bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey,
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); return WriteIC(std::make_pair(DBKeys::KEY, vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
} }
bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey, bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,
const std::vector<unsigned char>& vchCryptedSecret, const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta) const CKeyMetadata &keyMeta)
{ {
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { if (!WriteIC(std::make_pair(DBKeys::KEYMETA, vchPubKey), keyMeta)) {
return false; return false;
} }
if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) { if (!WriteIC(std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey), vchCryptedSecret, false)) {
return false; return false;
} }
EraseIC(std::make_pair(std::string("key"), vchPubKey)); EraseIC(std::make_pair(DBKeys::KEY, vchPubKey));
EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); EraseIC(std::make_pair(DBKeys::OLD_KEY, vchPubKey));
return true; return true;
} }
bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
{ {
return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true); return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);
} }
bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript) bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
{ {
return WriteIC(std::make_pair(std::string("cscript"), hash), redeemScript, false); return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
} }
bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
{ {
if (!WriteIC(std::make_pair(std::string("watchmeta"), dest), keyMeta)) { if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {
return false; return false;
} }
return WriteIC(std::make_pair(std::string("watchs"), dest), '1'); return WriteIC(std::make_pair(DBKeys::WATCHS, dest), '1');
} }
bool WalletBatch::EraseWatchOnly(const CScript &dest) bool WalletBatch::EraseWatchOnly(const CScript &dest)
{ {
if (!EraseIC(std::make_pair(std::string("watchmeta"), dest))) { if (!EraseIC(std::make_pair(DBKeys::WATCHMETA, dest))) {
return false; return false;
} }
return EraseIC(std::make_pair(std::string("watchs"), dest)); return EraseIC(std::make_pair(DBKeys::WATCHS, dest));
} }
bool WalletBatch::WriteBestBlock(const CBlockLocator& locator) bool WalletBatch::WriteBestBlock(const CBlockLocator& locator)
{ {
WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan WriteIC(DBKeys::BESTBLOCK, CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
return WriteIC(std::string("bestblock_nomerkle"), locator); return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator);
} }
bool WalletBatch::ReadBestBlock(CBlockLocator& locator) bool WalletBatch::ReadBestBlock(CBlockLocator& locator)
{ {
if (m_batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true; if (m_batch.Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) return true;
return m_batch.Read(std::string("bestblock_nomerkle"), locator); return m_batch.Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
} }
bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
{ {
return WriteIC(std::string("orderposnext"), nOrderPosNext); return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);
} }
bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool) bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool)
{ {
return m_batch.Read(std::make_pair(std::string("pool"), nPool), keypool); return m_batch.Read(std::make_pair(DBKeys::POOL, nPool), keypool);
} }
bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool) bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool)
{ {
return WriteIC(std::make_pair(std::string("pool"), nPool), keypool); return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool);
} }
bool WalletBatch::ErasePool(int64_t nPool) bool WalletBatch::ErasePool(int64_t nPool)
{ {
return EraseIC(std::make_pair(std::string("pool"), nPool)); return EraseIC(std::make_pair(DBKeys::POOL, nPool));
} }
bool WalletBatch::WriteMinVersion(int nVersion) bool WalletBatch::WriteMinVersion(int nVersion)
{ {
return WriteIC(std::string("minversion"), nVersion); return WriteIC(DBKeys::MINVERSION, nVersion);
} }
bool WalletBatch::ReadCoinJoinSalt(uint256& salt, bool fLegacy) bool WalletBatch::ReadCoinJoinSalt(uint256& salt, bool fLegacy)
{ {
// TODO: Remove legacy checks after few major releases // TODO: Remove legacy checks after few major releases
return m_batch.Read(std::string(fLegacy ? "ps_salt" : "cj_salt"), salt); return m_batch.Read(std::string(fLegacy ? DBKeys::PRIVATESEND_SALT : DBKeys::COINJOIN_SALT), salt);
} }
bool WalletBatch::WriteCoinJoinSalt(const uint256& salt) bool WalletBatch::WriteCoinJoinSalt(const uint256& salt)
{ {
return WriteIC(std::string("cj_salt"), salt); return WriteIC(DBKeys::COINJOIN_SALT, salt);
} }
bool WalletBatch::WriteGovernanceObject(const CGovernanceObject& obj) bool WalletBatch::WriteGovernanceObject(const CGovernanceObject& obj)
{ {
return WriteIC(std::make_pair(std::string("gobject"), obj.GetHash()), obj, false); return WriteIC(std::make_pair(DBKeys::G_OBJECT, obj.GetHash()), obj, false);
} }
@ -199,20 +229,15 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
// Taking advantage of the fact that pair serialization // Taking advantage of the fact that pair serialization
// is just the two items serialized one after the other // is just the two items serialized one after the other
ssKey >> strType; ssKey >> strType;
if (strType == "name") if (strType == DBKeys::NAME) {
{
std::string strAddress; std::string strAddress;
ssKey >> strAddress; ssKey >> strAddress;
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name; ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
} } else if (strType == DBKeys::PURPOSE) {
else if (strType == "purpose")
{
std::string strAddress; std::string strAddress;
ssKey >> strAddress; ssKey >> strAddress;
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose; ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
} } else if (strType == DBKeys::TX) {
else if (strType == "tx")
{
uint256 hash; uint256 hash;
ssKey >> hash; ssKey >> hash;
CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef()); CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
@ -246,9 +271,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
wss.fAnyUnordered = true; wss.fAnyUnordered = true;
pwallet->LoadToWallet(wtx); pwallet->LoadToWallet(wtx);
} } else if (strType == DBKeys::WATCHS) {
else if (strType == "watchs")
{
wss.nWatchKeys++; wss.nWatchKeys++;
CScript script; CScript script;
ssKey >> script; ssKey >> script;
@ -256,9 +279,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssValue >> fYes; ssValue >> fYes;
if (fYes == '1') if (fYes == '1')
pwallet->LoadWatchOnly(script); pwallet->LoadWatchOnly(script);
} } else if (strType == DBKeys::KEY || strType == DBKeys::OLD_KEY) {
else if (strType == "key" || strType == "wkey")
{
CPubKey vchPubKey; CPubKey vchPubKey;
ssKey >> vchPubKey; ssKey >> vchPubKey;
if (!vchPubKey.IsValid()) if (!vchPubKey.IsValid())
@ -270,20 +291,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CPrivKey pkey; CPrivKey pkey;
uint256 hash; uint256 hash;
if (strType == "key") if (strType == DBKeys::KEY) {
{
wss.nKeys++; wss.nKeys++;
ssValue >> pkey; ssValue >> pkey;
} else { } else {
CWalletKey wkey; OldKey wkey;
ssValue >> wkey; ssValue >> wkey;
pkey = wkey.vchPrivKey; pkey = wkey.vchPrivKey;
} }
// Old wallets store keys as "key" [pubkey] => [privkey] // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey]
// ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
// using EC operations as a checksum. // using EC operations as a checksum.
// Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while // Newer wallets store keys as DBKeys::KEY [pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
// remaining backwards-compatible. // remaining backwards-compatible.
try try
{ {
@ -320,9 +340,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: LoadKey failed"; strErr = "Error reading wallet database: LoadKey failed";
return false; return false;
} }
} } else if (strType == DBKeys::MASTER_KEY) {
else if (strType == "mkey")
{
unsigned int nID; unsigned int nID;
ssKey >> nID; ssKey >> nID;
CMasterKey kMasterKey; CMasterKey kMasterKey;
@ -335,9 +353,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
pwallet->mapMasterKeys[nID] = kMasterKey; pwallet->mapMasterKeys[nID] = kMasterKey;
if (pwallet->nMasterKeyMaxID < nID) if (pwallet->nMasterKeyMaxID < nID)
pwallet->nMasterKeyMaxID = nID; pwallet->nMasterKeyMaxID = nID;
} } else if (strType == DBKeys::CRYPTED_KEY) {
else if (strType == "ckey")
{
CPubKey vchPubKey; CPubKey vchPubKey;
ssKey >> vchPubKey; ssKey >> vchPubKey;
if (!vchPubKey.IsValid()) if (!vchPubKey.IsValid())
@ -355,27 +371,21 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
return false; return false;
} }
wss.fIsEncrypted = true; wss.fIsEncrypted = true;
} } else if (strType == DBKeys::KEYMETA) {
else if (strType == "keymeta")
{
CPubKey vchPubKey; CPubKey vchPubKey;
ssKey >> vchPubKey; ssKey >> vchPubKey;
CKeyMetadata keyMeta; CKeyMetadata keyMeta;
ssValue >> keyMeta; ssValue >> keyMeta;
wss.nKeyMeta++; wss.nKeyMeta++;
pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
} } else if (strType == DBKeys::WATCHMETA) {
else if (strType == "watchmeta")
{
CScript script; CScript script;
ssKey >> script; ssKey >> script;
CKeyMetadata keyMeta; CKeyMetadata keyMeta;
ssValue >> keyMeta; ssValue >> keyMeta;
wss.nKeyMeta++; wss.nKeyMeta++;
pwallet->LoadScriptMetadata(CScriptID(script), keyMeta); pwallet->LoadScriptMetadata(CScriptID(script), keyMeta);
} } else if (strType == DBKeys::DEFAULTKEY) {
else if (strType == "defaultkey")
{
// We don't want or need the default key, but if there is one set, // We don't want or need the default key, but if there is one set,
// we want to make sure that it is valid so that we can detect corruption // we want to make sure that it is valid so that we can detect corruption
CPubKey vchPubKey; CPubKey vchPubKey;
@ -384,17 +394,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: Default Key corrupt"; strErr = "Error reading wallet database: Default Key corrupt";
return false; return false;
} }
} } else if (strType == DBKeys::POOL) {
else if (strType == "pool")
{
int64_t nIndex; int64_t nIndex;
ssKey >> nIndex; ssKey >> nIndex;
CKeyPool keypool; CKeyPool keypool;
ssValue >> keypool; ssValue >> keypool;
pwallet->LoadKeyPool(nIndex, keypool); pwallet->LoadKeyPool(nIndex, keypool);
} } else if (strType == DBKeys::CSCRIPT) {
else if (strType == "cscript")
{
uint160 hash; uint160 hash;
ssKey >> hash; ssKey >> hash;
CScript script; CScript script;
@ -404,21 +410,15 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: LoadCScript failed"; strErr = "Error reading wallet database: LoadCScript failed";
return false; return false;
} }
} } else if (strType == DBKeys::ORDERPOSNEXT) {
else if (strType == "orderposnext")
{
ssValue >> pwallet->nOrderPosNext; ssValue >> pwallet->nOrderPosNext;
} } else if (strType == DBKeys::DESTDATA) {
else if (strType == "destdata")
{
std::string strAddress, strKey, strValue; std::string strAddress, strKey, strValue;
ssKey >> strAddress; ssKey >> strAddress;
ssKey >> strKey; ssKey >> strKey;
ssValue >> strValue; ssValue >> strValue;
pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue); pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue);
} } else if (strType == DBKeys::HDCHAIN) {
else if (strType == "hdchain")
{
CHDChain chain; CHDChain chain;
ssValue >> chain; ssValue >> chain;
if (!pwallet->SetHDChainSingle(chain, true)) if (!pwallet->SetHDChainSingle(chain, true))
@ -426,9 +426,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: SetHDChain failed"; strErr = "Error reading wallet database: SetHDChain failed";
return false; return false;
} }
} } else if (strType == DBKeys::CRYPTED_HDCHAIN) {
else if (strType == "chdchain")
{
CHDChain chain; CHDChain chain;
ssValue >> chain; ssValue >> chain;
if (!pwallet->SetCryptedHDChainSingle(chain, true)) if (!pwallet->SetCryptedHDChainSingle(chain, true))
@ -436,9 +434,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: SetHDCryptedChain failed"; strErr = "Error reading wallet database: SetHDCryptedChain failed";
return false; return false;
} }
} } else if (strType == DBKeys::HDPUBKEY) {
else if (strType == "hdpubkey")
{
wss.nHDPubKeys++; wss.nHDPubKeys++;
CPubKey vchPubKey; CPubKey vchPubKey;
ssKey >> vchPubKey; ssKey >> vchPubKey;
@ -456,7 +452,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: LoadHDPubKey failed"; strErr = "Error reading wallet database: LoadHDPubKey failed";
return false; return false;
} }
} else if (strType == "gobject") { } else if (strType == DBKeys::G_OBJECT) {
uint256 nObjectHash; uint256 nObjectHash;
CGovernanceObject obj; CGovernanceObject obj;
ssKey >> nObjectHash; ssKey >> nObjectHash;
@ -471,15 +467,15 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Invalid governance object: LoadGovernanceObject"; strErr = "Invalid governance object: LoadGovernanceObject";
return false; return false;
} }
} else if (strType == "flags") { } else if (strType == DBKeys::FLAGS) {
uint64_t flags; uint64_t flags;
ssValue >> flags; ssValue >> flags;
if (!pwallet->SetWalletFlags(flags, true)) { if (!pwallet->SetWalletFlags(flags, true)) {
strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found"; strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found";
return false; return false;
} }
} else if (strType != "bestblock" && strType != "bestblock_nomerkle" && } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
strType != "minversion" && strType != "acentry" && strType != "version") { strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && strType != DBKeys::VERSION) {
wss.m_unknown_records++; wss.m_unknown_records++;
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -498,9 +494,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
bool WalletBatch::IsKeyType(const std::string& strType) bool WalletBatch::IsKeyType(const std::string& strType)
{ {
return (strType== "key" || strType == "wkey" || return (strType == DBKeys::KEY || strType == DBKeys::OLD_KEY ||
strType == "mkey" || strType == "ckey" || strType == DBKeys::MASTER_KEY || strType == DBKeys::CRYPTED_KEY ||
strType == "hdchain" || strType == "chdchain"); strType == DBKeys::HDCHAIN || strType == DBKeys::CRYPTED_HDCHAIN);
} }
DBErrors WalletBatch::LoadWallet(CWallet* pwallet) DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
@ -514,8 +510,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
try { try {
int nMinVersion = 0; int nMinVersion = 0;
if (m_batch.Read((std::string)"minversion", nMinVersion)) if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
{
if (nMinVersion > FEATURE_LATEST) if (nMinVersion > FEATURE_LATEST)
return DBErrors::TOO_NEW; return DBErrors::TOO_NEW;
pwallet->LoadMinVersion(nMinVersion); pwallet->LoadMinVersion(nMinVersion);
@ -549,15 +544,15 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
{ {
// losing keys is considered a catastrophic error, anything else // losing keys is considered a catastrophic error, anything else
// we assume the user can live with: // we assume the user can live with:
if (IsKeyType(strType) || strType == "defaultkey") { if (IsKeyType(strType) || strType == DBKeys::DEFAULTKEY) {
result = DBErrors::CORRUPT; result = DBErrors::CORRUPT;
} else if(strType == "flags") { } else if (strType == DBKeys::FLAGS) {
// reading the wallet flags can only fail if unknown flags are present // reading the wallet flags can only fail if unknown flags are present
result = DBErrors::TOO_NEW; result = DBErrors::TOO_NEW;
} else { } else {
// Leave other errors alone, if we try to fix them we might make things worse. // Leave other errors alone, if we try to fix them we might make things worse.
fNoncriticalErrors = true; // ... but do warn the user there is something wrong. fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
if (strType == "tx") if (strType == DBKeys::TX)
// Rescan if there is a bad transaction record: // Rescan if there is a bad transaction record:
gArgs.SoftSetBoolArg("-rescan", true); gArgs.SoftSetBoolArg("-rescan", true);
} }
@ -584,7 +579,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
// Last client version to open this wallet, was previously the file version number // Last client version to open this wallet, was previously the file version number
int last_client = CLIENT_VERSION; int last_client = CLIENT_VERSION;
m_batch.Read(std::string("version"), last_client); m_batch.Read(DBKeys::VERSION, last_client);
int wallet_version = pwallet->GetVersion(); int wallet_version = pwallet->GetVersion();
pwallet->WalletLogPrintf("Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client); pwallet->WalletLogPrintf("Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client);
@ -605,7 +600,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
return DBErrors::NEED_REWRITE; return DBErrors::NEED_REWRITE;
if (last_client < CLIENT_VERSION) // Update if (last_client < CLIENT_VERSION) // Update
m_batch.Write(std::string("version"), CLIENT_VERSION); m_batch.Write(DBKeys::VERSION, CLIENT_VERSION);
if (wss.fAnyUnordered) if (wss.fAnyUnordered)
result = pwallet->ReorderTransactions(); result = pwallet->ReorderTransactions();
@ -619,8 +614,7 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CW
try { try {
int nMinVersion = 0; int nMinVersion = 0;
if (m_batch.Read((std::string)"minversion", nMinVersion)) if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
{
if (nMinVersion > FEATURE_LATEST) if (nMinVersion > FEATURE_LATEST)
return DBErrors::TOO_NEW; return DBErrors::TOO_NEW;
} }
@ -649,7 +643,7 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CW
std::string strType; std::string strType;
ssKey >> strType; ssKey >> strType;
if (strType == "tx") { if (strType == DBKeys::TX) {
uint256 hash; uint256 hash;
ssKey >> hash; ssKey >> hash;
@ -780,8 +774,10 @@ bool WalletBatch::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, C
fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
dummyWss, strType, strErr); dummyWss, strType, strErr);
} }
if (!IsKeyType(strType) && strType != "hdpubkey") if (!IsKeyType(strType) && strType != DBKeys::HDCHAIN) {
return false; return false;
}
if (!fReadOK) if (!fReadOK)
{ {
LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr); LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr);
@ -803,40 +799,40 @@ bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& w
bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value) bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
{ {
return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); return WriteIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(address, key)), value);
} }
bool WalletBatch::EraseDestData(const std::string &address, const std::string &key) bool WalletBatch::EraseDestData(const std::string &address, const std::string &key)
{ {
return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key))); return EraseIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(address, key)));
} }
bool WalletBatch::WriteHDChain(const CHDChain& chain) bool WalletBatch::WriteHDChain(const CHDChain& chain)
{ {
return WriteIC(std::string("hdchain"), chain); return WriteIC(DBKeys::HDCHAIN, chain);
} }
bool WalletBatch::WriteCryptedHDChain(const CHDChain& chain) bool WalletBatch::WriteCryptedHDChain(const CHDChain& chain)
{ {
if (!WriteIC(std::string("chdchain"), chain)) if (!WriteIC(DBKeys::CRYPTED_HDCHAIN, chain))
return false; return false;
EraseIC(std::string("hdchain")); EraseIC(DBKeys::HDCHAIN);
return true; return true;
} }
bool WalletBatch::WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta) bool WalletBatch::WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta)
{ {
if (!WriteIC(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false)) if (!WriteIC(std::make_pair(DBKeys::KEYMETA, hdPubKey.extPubKey.pubkey), keyMeta, false))
return false; return false;
return WriteIC(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false); return WriteIC(std::make_pair(DBKeys::HDPUBKEY, hdPubKey.extPubKey.pubkey), hdPubKey, false);
} }
bool WalletBatch::WriteWalletFlags(const uint64_t flags) bool WalletBatch::WriteWalletFlags(const uint64_t flags)
{ {
return WriteIC(std::string("flags"), flags); return WriteIC(DBKeys::FLAGS, flags);
} }
bool WalletBatch::TxnBegin() bool WalletBatch::TxnBegin()

View File

@ -55,6 +55,36 @@ enum class DBErrors
NEED_REWRITE NEED_REWRITE
}; };
namespace DBKeys {
extern const std::string ACENTRY;
extern const std::string BESTBLOCK;
extern const std::string BESTBLOCK_NOMERKLE;
extern const std::string CRYPTED_HDCHAIN;
extern const std::string CRYPTED_KEY;
extern const std::string COINJOIN_SALT;
extern const std::string CSCRIPT;
extern const std::string DEFAULTKEY;
extern const std::string DESTDATA;
extern const std::string FLAGS;
extern const std::string G_OBJECT;
extern const std::string HDCHAIN;
extern const std::string HDPUBKEY;
extern const std::string KEY;
extern const std::string KEYMETA;
extern const std::string MASTER_KEY;
extern const std::string MINVERSION;
extern const std::string NAME;
extern const std::string OLD_KEY;
extern const std::string ORDERPOSNEXT;
extern const std::string POOL;
extern const std::string PURPOSE;
extern const std::string PRIVATESEND_SALT;
extern const std::string TX;
extern const std::string VERSION;
extern const std::string WATCHMETA;
extern const std::string WATCHS;
} // namespace DBKeys
class CKeyMetadata class CKeyMetadata
{ {
public: public: