|
|
|
@ -180,11 +180,27 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
@@ -180,11 +180,27 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
|
|
|
|
|
return DB_LOAD_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class CWalletScanState { |
|
|
|
|
public: |
|
|
|
|
unsigned int nKeys; |
|
|
|
|
unsigned int nCKeys; |
|
|
|
|
unsigned int nKeyMeta; |
|
|
|
|
bool fIsEncrypted; |
|
|
|
|
bool fAnyUnordered; |
|
|
|
|
int nFileVersion; |
|
|
|
|
vector<uint256> vWalletUpgrade; |
|
|
|
|
|
|
|
|
|
CWalletScanState() { |
|
|
|
|
nKeys = nCKeys = nKeyMeta = 0; |
|
|
|
|
fIsEncrypted = false; |
|
|
|
|
fAnyUnordered = false; |
|
|
|
|
nFileVersion = 0; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, |
|
|
|
|
int& nFileVersion, vector<uint256>& vWalletUpgrade, |
|
|
|
|
bool& fIsEncrypted, bool& fAnyUnordered, string& strType, string& strErr) |
|
|
|
|
CWalletScanState &wss, string& strType, string& strErr) |
|
|
|
|
{ |
|
|
|
|
try { |
|
|
|
|
// Unserialize
|
|
|
|
@ -229,11 +245,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
@@ -229,11 +245,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|
|
|
|
strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str()); |
|
|
|
|
wtx.fTimeReceivedIsTxTime = 0; |
|
|
|
|
} |
|
|
|
|
vWalletUpgrade.push_back(hash); |
|
|
|
|
wss.vWalletUpgrade.push_back(hash); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (wtx.nOrderPos == -1) |
|
|
|
|
fAnyUnordered = true; |
|
|
|
|
wss.fAnyUnordered = true; |
|
|
|
|
|
|
|
|
|
//// debug print
|
|
|
|
|
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
|
|
|
|
@ -252,12 +268,12 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
@@ -252,12 +268,12 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|
|
|
|
if (nNumber > nAccountingEntryNumber) |
|
|
|
|
nAccountingEntryNumber = nNumber; |
|
|
|
|
|
|
|
|
|
if (!fAnyUnordered) |
|
|
|
|
if (!wss.fAnyUnordered) |
|
|
|
|
{ |
|
|
|
|
CAccountingEntry acentry; |
|
|
|
|
ssValue >> acentry; |
|
|
|
|
if (acentry.nOrderPos == -1) |
|
|
|
|
fAnyUnordered = true; |
|
|
|
|
wss.fAnyUnordered = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (strType == "key" || strType == "wkey") |
|
|
|
@ -272,8 +288,10 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
@@ -272,8 +288,10 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|
|
|
|
CKey key; |
|
|
|
|
CPrivKey pkey; |
|
|
|
|
if (strType == "key") |
|
|
|
|
{ |
|
|
|
|
wss.nKeys++; |
|
|
|
|
ssValue >> pkey; |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
CWalletKey wkey; |
|
|
|
|
ssValue >> wkey; |
|
|
|
|
pkey = wkey.vchPrivKey; |
|
|
|
@ -315,12 +333,27 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
@@ -315,12 +333,27 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|
|
|
|
ssKey >> vchPubKey; |
|
|
|
|
vector<unsigned char> vchPrivKey; |
|
|
|
|
ssValue >> vchPrivKey; |
|
|
|
|
wss.nCKeys++; |
|
|
|
|
|
|
|
|
|
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) |
|
|
|
|
{ |
|
|
|
|
strErr = "Error reading wallet database: LoadCryptedKey failed"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
fIsEncrypted = true; |
|
|
|
|
wss.fIsEncrypted = true; |
|
|
|
|
} |
|
|
|
|
else if (strType == "keymeta") |
|
|
|
|
{ |
|
|
|
|
vector<unsigned char> vchPubKey; |
|
|
|
|
ssKey >> vchPubKey; |
|
|
|
|
CKeyMetadata keyMeta; |
|
|
|
|
ssValue >> keyMeta; |
|
|
|
|
wss.nKeyMeta++; |
|
|
|
|
|
|
|
|
|
// find earliest key creation time, as wallet birthday
|
|
|
|
|
if (!pwallet->nTimeFirstKey || |
|
|
|
|
(keyMeta.nCreateTime < pwallet->nTimeFirstKey)) |
|
|
|
|
pwallet->nTimeFirstKey = keyMeta.nCreateTime; |
|
|
|
|
} |
|
|
|
|
else if (strType == "defaultkey") |
|
|
|
|
{ |
|
|
|
@ -334,9 +367,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
@@ -334,9 +367,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|
|
|
|
} |
|
|
|
|
else if (strType == "version") |
|
|
|
|
{ |
|
|
|
|
ssValue >> nFileVersion; |
|
|
|
|
if (nFileVersion == 10300) |
|
|
|
|
nFileVersion = 300; |
|
|
|
|
ssValue >> wss.nFileVersion; |
|
|
|
|
if (wss.nFileVersion == 10300) |
|
|
|
|
wss.nFileVersion = 300; |
|
|
|
|
} |
|
|
|
|
else if (strType == "cscript") |
|
|
|
|
{ |
|
|
|
@ -370,10 +403,7 @@ static bool IsKeyType(string strType)
@@ -370,10 +403,7 @@ static bool IsKeyType(string strType)
|
|
|
|
|
DBErrors CWalletDB::LoadWallet(CWallet* pwallet) |
|
|
|
|
{ |
|
|
|
|
pwallet->vchDefaultKey = CPubKey(); |
|
|
|
|
int nFileVersion = 0; |
|
|
|
|
vector<uint256> vWalletUpgrade; |
|
|
|
|
bool fIsEncrypted = false; |
|
|
|
|
bool fAnyUnordered = false; |
|
|
|
|
CWalletScanState wss; |
|
|
|
|
bool fNoncriticalErrors = false; |
|
|
|
|
DBErrors result = DB_LOAD_OK; |
|
|
|
|
|
|
|
|
@ -411,8 +441,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
@@ -411,8 +441,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
|
|
|
|
|
|
|
|
|
|
// Try to be tolerant of single corrupt records:
|
|
|
|
|
string strType, strErr; |
|
|
|
|
if (!ReadKeyValue(pwallet, ssKey, ssValue, nFileVersion, |
|
|
|
|
vWalletUpgrade, fIsEncrypted, fAnyUnordered, strType, strErr)) |
|
|
|
|
if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) |
|
|
|
|
{ |
|
|
|
|
// losing keys is considered a catastrophic error, anything else
|
|
|
|
|
// we assume the user can live with:
|
|
|
|
@ -447,19 +476,26 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
@@ -447,19 +476,26 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
|
|
|
|
|
if (result != DB_LOAD_OK) |
|
|
|
|
return result; |
|
|
|
|
|
|
|
|
|
printf("nFileVersion = %d\n", nFileVersion); |
|
|
|
|
printf("nFileVersion = %d\n", wss.nFileVersion); |
|
|
|
|
|
|
|
|
|
BOOST_FOREACH(uint256 hash, vWalletUpgrade) |
|
|
|
|
printf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n", |
|
|
|
|
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys); |
|
|
|
|
|
|
|
|
|
// nTimeFirstKey is only reliable if all keys have metadata
|
|
|
|
|
if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta) |
|
|
|
|
pwallet->nTimeFirstKey = 0; |
|
|
|
|
|
|
|
|
|
BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade) |
|
|
|
|
WriteTx(hash, pwallet->mapWallet[hash]); |
|
|
|
|
|
|
|
|
|
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
|
|
|
|
|
if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000)) |
|
|
|
|
if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) |
|
|
|
|
return DB_NEED_REWRITE; |
|
|
|
|
|
|
|
|
|
if (nFileVersion < CLIENT_VERSION) // Update
|
|
|
|
|
if (wss.nFileVersion < CLIENT_VERSION) // Update
|
|
|
|
|
WriteVersion(CLIENT_VERSION); |
|
|
|
|
|
|
|
|
|
if (fAnyUnordered) |
|
|
|
|
if (wss.fAnyUnordered) |
|
|
|
|
result = ReorderTransactions(pwallet); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
@ -615,10 +651,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
@@ -615,10 +651,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
CWallet dummyWallet; |
|
|
|
|
int nFileVersion = 0; |
|
|
|
|
vector<uint256> vWalletUpgrade; |
|
|
|
|
bool fIsEncrypted = false; |
|
|
|
|
bool fAnyUnordered = false; |
|
|
|
|
CWalletScanState wss; |
|
|
|
|
|
|
|
|
|
DbTxn* ptxn = dbenv.TxnBegin(); |
|
|
|
|
BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData) |
|
|
|
@ -629,9 +662,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
@@ -629,9 +662,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
|
|
|
|
|
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); |
|
|
|
|
string strType, strErr; |
|
|
|
|
bool fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, |
|
|
|
|
nFileVersion, vWalletUpgrade, |
|
|
|
|
fIsEncrypted, fAnyUnordered, |
|
|
|
|
strType, strErr); |
|
|
|
|
wss, strType, strErr); |
|
|
|
|
if (!IsKeyType(strType)) |
|
|
|
|
continue; |
|
|
|
|
if (!fReadOK) |
|
|
|
|