Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/walletdb.cpp
Show All 10 Lines | |||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <fs.h> | #include <fs.h> | ||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <protocol.h> | #include <protocol.h> | ||||
#include <serialize.h> | #include <serialize.h> | ||||
#include <sync.h> | #include <sync.h> | ||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <util/time.h> | #include <util/time.h> | ||||
#include <wallet/scriptpubkeyman.h> | |||||
#include <wallet/wallet.h> | #include <wallet/wallet.h> | ||||
#include <atomic> | #include <atomic> | ||||
namespace DBKeys { | namespace DBKeys { | ||||
const std::string ACENTRY{"acentry"}; | const std::string ACENTRY{"acentry"}; | ||||
const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"}; | const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"}; | ||||
const std::string BESTBLOCK{"bestblock"}; | const std::string BESTBLOCK{"bestblock"}; | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | public: | ||||
std::vector<TxId> vWalletUpgrade; | std::vector<TxId> vWalletUpgrade; | ||||
CWalletScanState() {} | CWalletScanState() {} | ||||
}; | }; | ||||
static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, | static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, | ||||
CDataStream &ssValue, CWalletScanState &wss, | CDataStream &ssValue, CWalletScanState &wss, | ||||
std::string &strType, std::string &strErr) | std::string &strType, std::string &strErr) | ||||
EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { | EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet, | ||||
pwallet->GetLegacyScriptPubKeyMan()->cs_wallet) { | |||||
try { | try { | ||||
// Unserialize | // Unserialize | ||||
// Taking advantage of the fact that pair serialization is just the two | // Taking advantage of the fact that pair serialization is just the two | ||||
// items serialized one after the other. | // items serialized one after the other. | ||||
ssKey >> strType; | ssKey >> strType; | ||||
if (strType == DBKeys::NAME) { | if (strType == DBKeys::NAME) { | ||||
std::string strAddress; | std::string strAddress; | ||||
ssKey >> strAddress; | ssKey >> strAddress; | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | try { | ||||
pwallet->LoadToWallet(wtx); | pwallet->LoadToWallet(wtx); | ||||
} else if (strType == DBKeys::WATCHS) { | } else if (strType == DBKeys::WATCHS) { | ||||
wss.nWatchKeys++; | wss.nWatchKeys++; | ||||
CScript script; | CScript script; | ||||
ssKey >> script; | ssKey >> script; | ||||
char fYes; | char fYes; | ||||
ssValue >> fYes; | ssValue >> fYes; | ||||
if (fYes == '1') { | if (fYes == '1') { | ||||
pwallet->LoadWatchOnly(script); | pwallet->GetLegacyScriptPubKeyMan()->LoadWatchOnly(script); | ||||
} | } | ||||
} else if (strType == DBKeys::KEY) { | } else if (strType == DBKeys::KEY) { | ||||
CPubKey vchPubKey; | CPubKey vchPubKey; | ||||
ssKey >> vchPubKey; | ssKey >> vchPubKey; | ||||
if (!vchPubKey.IsValid()) { | if (!vchPubKey.IsValid()) { | ||||
strErr = "Error reading wallet database: CPubKey corrupt"; | strErr = "Error reading wallet database: CPubKey corrupt"; | ||||
return false; | return false; | ||||
} | } | ||||
Show All 32 Lines | try { | ||||
fSkipCheck = true; | fSkipCheck = true; | ||||
} | } | ||||
if (!key.Load(pkey, vchPubKey, fSkipCheck)) { | if (!key.Load(pkey, vchPubKey, fSkipCheck)) { | ||||
strErr = "Error reading wallet database: CPrivKey corrupt"; | strErr = "Error reading wallet database: CPrivKey corrupt"; | ||||
return false; | return false; | ||||
} | } | ||||
if (!pwallet->LoadKey(key, vchPubKey)) { | if (!pwallet->GetLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey)) { | ||||
strErr = "Error reading wallet database: LoadKey failed"; | strErr = "Error reading wallet database: " | ||||
"LegacyScriptPubKeyMan::LoadKey failed"; | |||||
return false; | return false; | ||||
} | } | ||||
} else if (strType == DBKeys::MASTER_KEY) { | } else if (strType == DBKeys::MASTER_KEY) { | ||||
// Master encryption key is loaded into only the wallet and not any | |||||
// of the ScriptPubKeyMans. | |||||
unsigned int nID; | unsigned int nID; | ||||
ssKey >> nID; | ssKey >> nID; | ||||
CMasterKey kMasterKey; | CMasterKey kMasterKey; | ||||
ssValue >> kMasterKey; | ssValue >> kMasterKey; | ||||
if (pwallet->mapMasterKeys.count(nID) != 0) { | if (pwallet->mapMasterKeys.count(nID) != 0) { | ||||
strErr = strprintf( | strErr = strprintf( | ||||
"Error reading wallet database: duplicate CMasterKey id %u", | "Error reading wallet database: duplicate CMasterKey id %u", | ||||
nID); | nID); | ||||
Show All 9 Lines | try { | ||||
if (!vchPubKey.IsValid()) { | if (!vchPubKey.IsValid()) { | ||||
strErr = "Error reading wallet database: CPubKey corrupt"; | strErr = "Error reading wallet database: CPubKey corrupt"; | ||||
return false; | return false; | ||||
} | } | ||||
std::vector<uint8_t> vchPrivKey; | std::vector<uint8_t> vchPrivKey; | ||||
ssValue >> vchPrivKey; | ssValue >> vchPrivKey; | ||||
wss.nCKeys++; | wss.nCKeys++; | ||||
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) { | if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCryptedKey( | ||||
strErr = "Error reading wallet database: LoadCryptedKey failed"; | vchPubKey, vchPrivKey)) { | ||||
strErr = "Error reading wallet database: " | |||||
"LegacyScriptPubKeyMan::LoadCryptedKey failed"; | |||||
return false; | return false; | ||||
} | } | ||||
wss.fIsEncrypted = true; | wss.fIsEncrypted = true; | ||||
} else if (strType == DBKeys::KEYMETA) { | } else if (strType == DBKeys::KEYMETA) { | ||||
CPubKey vchPubKey; | CPubKey vchPubKey; | ||||
ssKey >> vchPubKey; | ssKey >> vchPubKey; | ||||
CKeyMetadata keyMeta; | CKeyMetadata keyMeta; | ||||
ssValue >> keyMeta; | ssValue >> keyMeta; | ||||
wss.nKeyMeta++; | wss.nKeyMeta++; | ||||
pwallet->GetLegacyScriptPubKeyMan()->LoadKeyMetadata( | |||||
pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); | vchPubKey.GetID(), keyMeta); | ||||
} else if (strType == DBKeys::WATCHMETA) { | } else if (strType == DBKeys::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->GetLegacyScriptPubKeyMan()->LoadScriptMetadata( | ||||
CScriptID(script), keyMeta); | |||||
} else if (strType == DBKeys::DEFAULTKEY) { | } else if (strType == DBKeys::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 | // we want to make sure that it is valid so that we can detect | ||||
// corruption | // corruption | ||||
CPubKey vchPubKey; | CPubKey vchPubKey; | ||||
ssValue >> vchPubKey; | ssValue >> vchPubKey; | ||||
if (!vchPubKey.IsValid()) { | if (!vchPubKey.IsValid()) { | ||||
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 == DBKeys::POOL) { | ||||
int64_t nIndex; | int64_t nIndex; | ||||
ssKey >> nIndex; | ssKey >> nIndex; | ||||
CKeyPool keypool; | CKeyPool keypool; | ||||
ssValue >> keypool; | ssValue >> keypool; | ||||
pwallet->LoadKeyPool(nIndex, keypool); | pwallet->GetLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool); | ||||
} else if (strType == DBKeys::CSCRIPT) { | } else if (strType == DBKeys::CSCRIPT) { | ||||
uint160 hash; | uint160 hash; | ||||
ssKey >> hash; | ssKey >> hash; | ||||
CScript script; | CScript script; | ||||
ssValue >> script; | ssValue >> script; | ||||
if (!pwallet->LoadCScript(script)) { | if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCScript(script)) { | ||||
strErr = "Error reading wallet database: LoadCScript failed"; | strErr = "Error reading wallet database: " | ||||
"LegacyScriptPubKeyMan::LoadCScript failed"; | |||||
return false; | return false; | ||||
} | } | ||||
} else if (strType == DBKeys::ORDERPOSNEXT) { | } else if (strType == DBKeys::ORDERPOSNEXT) { | ||||
ssValue >> pwallet->nOrderPosNext; | ssValue >> pwallet->nOrderPosNext; | ||||
} else if (strType == DBKeys::DESTDATA) { | } else if (strType == DBKeys::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( | pwallet->LoadDestData( | ||||
DecodeDestination(strAddress, pwallet->chainParams), strKey, | DecodeDestination(strAddress, pwallet->chainParams), strKey, | ||||
strValue); | strValue); | ||||
} else if (strType == DBKeys::HDCHAIN) { | } else if (strType == DBKeys::HDCHAIN) { | ||||
CHDChain chain; | CHDChain chain; | ||||
ssValue >> chain; | ssValue >> chain; | ||||
pwallet->SetHDChain(chain, true); | pwallet->GetLegacyScriptPubKeyMan()->SetHDChain(chain, true); | ||||
} else if (strType == DBKeys::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 " | strErr = "Error reading wallet database: Unknown non-tolerable " | ||||
"wallet flags found"; | "wallet flags found"; | ||||
return false; | return false; | ||||
} | } | ||||
Show All 28 Lines | |||||
} | } | ||||
DBErrors WalletBatch::LoadWallet(CWallet *pwallet) { | DBErrors WalletBatch::LoadWallet(CWallet *pwallet) { | ||||
CWalletScanState wss; | CWalletScanState wss; | ||||
bool fNoncriticalErrors = false; | bool fNoncriticalErrors = false; | ||||
DBErrors result = DBErrors::LOAD_OK; | DBErrors result = DBErrors::LOAD_OK; | ||||
LOCK(pwallet->cs_wallet); | LOCK(pwallet->cs_wallet); | ||||
AssertLockHeld(pwallet->GetLegacyScriptPubKeyMan()->cs_wallet); | |||||
try { | try { | ||||
int nMinVersion = 0; | int nMinVersion = 0; | ||||
if (m_batch.Read(DBKeys::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); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | DBErrors WalletBatch::LoadWallet(CWallet *pwallet) { | ||||
pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ " | pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ " | ||||
"metadata, %u total. Unknown wallet records: %u\n", | "metadata, %u total. Unknown wallet records: %u\n", | ||||
wss.nKeys, wss.nCKeys, wss.nKeyMeta, | wss.nKeys, wss.nCKeys, wss.nKeyMeta, | ||||
wss.nKeys + wss.nCKeys, wss.m_unknown_records); | wss.nKeys + wss.nCKeys, wss.m_unknown_records); | ||||
// nTimeFirstKey is only reliable if all keys have metadata | // nTimeFirstKey is only reliable if all keys have metadata | ||||
if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) { | if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) { | ||||
pwallet->UpdateTimeFirstKey(1); | auto spk_man = pwallet->GetLegacyScriptPubKeyMan(); | ||||
if (spk_man) { | |||||
spk_man->UpdateTimeFirstKey(1); | |||||
} | |||||
} | } | ||||
for (const TxId &txid : wss.vWalletUpgrade) { | for (const TxId &txid : wss.vWalletUpgrade) { | ||||
WriteTx(pwallet->mapWallet.at(txid)); | WriteTx(pwallet->mapWallet.at(txid)); | ||||
} | } | ||||
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: | // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: | ||||
if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000)) { | if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000)) { | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | bool WalletBatch::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, | ||||
CDataStream ssValue) { | CDataStream ssValue) { | ||||
CWallet *dummyWallet = reinterpret_cast<CWallet *>(callbackData); | CWallet *dummyWallet = reinterpret_cast<CWallet *>(callbackData); | ||||
CWalletScanState dummyWss; | CWalletScanState dummyWss; | ||||
std::string strType, strErr; | std::string strType, strErr; | ||||
bool fReadOK; | bool fReadOK; | ||||
{ | { | ||||
// Required in LoadKeyMetadata(): | // Required in LoadKeyMetadata(): | ||||
LOCK(dummyWallet->cs_wallet); | LOCK(dummyWallet->cs_wallet); | ||||
AssertLockHeld(dummyWallet->GetLegacyScriptPubKeyMan()->cs_wallet); | |||||
fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, dummyWss, strType, | fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, dummyWss, strType, | ||||
strErr); | strErr); | ||||
} | } | ||||
if (!IsKeyType(strType) && strType != DBKeys::HDCHAIN) { | if (!IsKeyType(strType) && strType != DBKeys::HDCHAIN) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!fReadOK) { | if (!fReadOK) { | ||||
LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, | LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, | ||||
▲ Show 20 Lines • Show All 61 Lines • Show Last 20 Lines |