Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/walletdb.cpp
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
bool CWalletDB::ErasePurpose(const std::string &strPurpose) { | bool CWalletDB::ErasePurpose(const std::string &strPurpose) { | ||||
nWalletDBUpdateCounter++; | nWalletDBUpdateCounter++; | ||||
return Erase(std::make_pair(std::string("purpose"), strPurpose)); | return Erase(std::make_pair(std::string("purpose"), strPurpose)); | ||||
} | } | ||||
bool CWalletDB::WriteTx(const CWalletTx &wtx) { | bool CWalletDB::WriteTx(const CWalletTx &wtx) { | ||||
nWalletDBUpdateCounter++; | nWalletDBUpdateCounter++; | ||||
return Write(std::make_pair(std::string("tx"), wtx.GetId()), wtx); | return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); | ||||
} | } | ||||
bool CWalletDB::EraseTx(uint256 hash) { | bool CWalletDB::EraseTx(uint256 hash) { | ||||
nWalletDBUpdateCounter++; | nWalletDBUpdateCounter++; | ||||
return Erase(std::make_pair(std::string("tx"), hash)); | return Erase(std::make_pair(std::string("tx"), hash)); | ||||
} | } | ||||
bool CWalletDB::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, | bool CWalletDB::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | |||||
public: | public: | ||||
unsigned int nKeys; | unsigned int nKeys; | ||||
unsigned int nCKeys; | unsigned int nCKeys; | ||||
unsigned int nWatchKeys; | unsigned int nWatchKeys; | ||||
unsigned int nKeyMeta; | unsigned int nKeyMeta; | ||||
bool fIsEncrypted; | bool fIsEncrypted; | ||||
bool fAnyUnordered; | bool fAnyUnordered; | ||||
int nFileVersion; | int nFileVersion; | ||||
std::vector<uint256> vWalletUpgrade; | std::vector<txhash_t> vWalletUpgrade; | ||||
CWalletScanState() { | CWalletScanState() { | ||||
nKeys = nCKeys = nWatchKeys = nKeyMeta = 0; | nKeys = nCKeys = nWatchKeys = nKeyMeta = 0; | ||||
fIsEncrypted = false; | fIsEncrypted = false; | ||||
fAnyUnordered = false; | fAnyUnordered = false; | ||||
nFileVersion = 0; | nFileVersion = 0; | ||||
} | } | ||||
}; | }; | ||||
Show All 20 Lines | try { | ||||
uint256 hash; | uint256 hash; | ||||
ssKey >> hash; | ssKey >> hash; | ||||
CWalletTx wtx; | CWalletTx wtx; | ||||
ssValue >> wtx; | ssValue >> wtx; | ||||
CValidationState state; | CValidationState state; | ||||
bool isValid = wtx.IsCoinBase() | bool isValid = wtx.IsCoinBase() | ||||
? CheckCoinbase(wtx, state) | ? CheckCoinbase(wtx, state) | ||||
: CheckRegularTransaction(wtx, state); | : CheckRegularTransaction(wtx, state); | ||||
if (wtx.GetId() != hash || !isValid) return false; | if (wtx.GetHash() != hash || !isValid) return false; | ||||
// Undo serialize changes in 31600 | // Undo serialize changes in 31600 | ||||
if (31404 <= wtx.fTimeReceivedIsTxTime && | if (31404 <= wtx.fTimeReceivedIsTxTime && | ||||
wtx.fTimeReceivedIsTxTime <= 31703) { | wtx.fTimeReceivedIsTxTime <= 31703) { | ||||
if (!ssValue.empty()) { | if (!ssValue.empty()) { | ||||
char fTmp; | char fTmp; | ||||
char fUnused; | char fUnused; | ||||
ssValue >> fTmp >> fUnused >> wtx.strFromAccount; | ssValue >> fTmp >> fUnused >> wtx.strFromAccount; | ||||
strErr = | strErr = | ||||
strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s", | strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s", | ||||
wtx.fTimeReceivedIsTxTime, fTmp, | wtx.fTimeReceivedIsTxTime, fTmp, | ||||
wtx.strFromAccount, hash.ToString()); | wtx.strFromAccount, hash.ToString()); | ||||
wtx.fTimeReceivedIsTxTime = fTmp; | wtx.fTimeReceivedIsTxTime = fTmp; | ||||
} else { | } else { | ||||
strErr = | strErr = | ||||
strprintf("LoadWallet() repairing tx ver=%d %s", | strprintf("LoadWallet() repairing tx ver=%d %s", | ||||
wtx.fTimeReceivedIsTxTime, hash.ToString()); | wtx.fTimeReceivedIsTxTime, hash.ToString()); | ||||
wtx.fTimeReceivedIsTxTime = 0; | wtx.fTimeReceivedIsTxTime = 0; | ||||
} | } | ||||
wss.vWalletUpgrade.push_back(hash); | wss.vWalletUpgrade.push_back(wtx.GetHash()); | ||||
} | } | ||||
if (wtx.nOrderPos == -1) wss.fAnyUnordered = true; | if (wtx.nOrderPos == -1) wss.fAnyUnordered = true; | ||||
pwallet->LoadToWallet(wtx); | pwallet->LoadToWallet(wtx); | ||||
} else if (strType == "acentry") { | } else if (strType == "acentry") { | ||||
std::string strAccount; | std::string strAccount; | ||||
ssKey >> strAccount; | ssKey >> strAccount; | ||||
▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | DBErrors CWalletDB::LoadWallet(CWallet *pwallet) { | ||||
LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n", | LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n", | ||||
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys); | wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys); | ||||
// 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); | pwallet->UpdateTimeFirstKey(1); | ||||
for (uint256 hash : wss.vWalletUpgrade) { | for (txhash_t hash : wss.vWalletUpgrade) { | ||||
WriteTx(pwallet->mapWallet[hash]); | WriteTx(pwallet->mapWallet[hash]); | ||||
} | } | ||||
// 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 && | if (wss.fIsEncrypted && | ||||
(wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) | (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) | ||||
return DB_NEED_REWRITE; | return DB_NEED_REWRITE; | ||||
if (wss.nFileVersion < CLIENT_VERSION) // Update | if (wss.nFileVersion < CLIENT_VERSION) // Update | ||||
WriteVersion(CLIENT_VERSION); | WriteVersion(CLIENT_VERSION); | ||||
if (wss.fAnyUnordered) result = pwallet->ReorderTransactions(); | if (wss.fAnyUnordered) result = pwallet->ReorderTransactions(); | ||||
pwallet->laccentries.clear(); | pwallet->laccentries.clear(); | ||||
ListAccountCreditDebit("*", pwallet->laccentries); | ListAccountCreditDebit("*", pwallet->laccentries); | ||||
for (CAccountingEntry &entry : pwallet->laccentries) { | for (CAccountingEntry &entry : pwallet->laccentries) { | ||||
pwallet->wtxOrdered.insert(std::make_pair( | pwallet->wtxOrdered.insert(std::make_pair( | ||||
entry.nOrderPos, CWallet::TxPair((CWalletTx *)0, &entry))); | entry.nOrderPos, CWallet::TxPair((CWalletTx *)0, &entry))); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
DBErrors CWalletDB::FindWalletTx(CWallet *pwallet, | DBErrors CWalletDB::FindWalletTx(CWallet *pwallet, | ||||
std::vector<uint256> &vTxHash, | std::vector<txhash_t> &vTxHash, | ||||
std::vector<CWalletTx> &vWtx) { | std::vector<CWalletTx> &vWtx) { | ||||
pwallet->vchDefaultKey = CPubKey(); | pwallet->vchDefaultKey = CPubKey(); | ||||
bool fNoncriticalErrors = false; | bool fNoncriticalErrors = false; | ||||
DBErrors result = DB_LOAD_OK; | DBErrors result = DB_LOAD_OK; | ||||
try { | try { | ||||
LOCK(pwallet->cs_wallet); | LOCK(pwallet->cs_wallet); | ||||
int nMinVersion = 0; | int nMinVersion = 0; | ||||
Show All 19 Lines | try { | ||||
else if (ret != 0) { | else if (ret != 0) { | ||||
LogPrintf("Error reading next record from wallet database\n"); | LogPrintf("Error reading next record from wallet database\n"); | ||||
return DB_CORRUPT; | return DB_CORRUPT; | ||||
} | } | ||||
std::string strType; | std::string strType; | ||||
ssKey >> strType; | ssKey >> strType; | ||||
if (strType == "tx") { | if (strType == "tx") { | ||||
uint256 hash; | txhash_t hash; | ||||
ssKey >> hash; | ssKey >> hash; | ||||
CWalletTx wtx; | CWalletTx wtx; | ||||
ssValue >> wtx; | ssValue >> wtx; | ||||
vTxHash.push_back(hash); | vTxHash.push_back(hash); | ||||
vWtx.push_back(wtx); | vWtx.push_back(wtx); | ||||
} | } | ||||
} | } | ||||
pcursor->close(); | pcursor->close(); | ||||
} catch (const boost::thread_interrupted &) { | } catch (const boost::thread_interrupted &) { | ||||
throw; | throw; | ||||
} catch (...) { | } catch (...) { | ||||
result = DB_CORRUPT; | result = DB_CORRUPT; | ||||
} | } | ||||
if (fNoncriticalErrors && result == DB_LOAD_OK) | if (fNoncriticalErrors && result == DB_LOAD_OK) | ||||
result = DB_NONCRITICAL_ERROR; | result = DB_NONCRITICAL_ERROR; | ||||
return result; | return result; | ||||
} | } | ||||
DBErrors CWalletDB::ZapSelectTx(CWallet *pwallet, | DBErrors CWalletDB::ZapSelectTx(CWallet *pwallet, | ||||
std::vector<uint256> &vTxHashIn, | std::vector<txhash_t> &vTxHashIn, | ||||
std::vector<uint256> &vTxHashOut) { | std::vector<txhash_t> &vTxHashOut) { | ||||
// Build list of wallet TXs and hashes. | // Build list of wallet TXs and hashes. | ||||
std::vector<uint256> vTxHash; | std::vector<txhash_t> vTxHash; | ||||
std::vector<CWalletTx> vWtx; | std::vector<CWalletTx> vWtx; | ||||
DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); | DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); | ||||
if (err != DB_LOAD_OK) { | if (err != DB_LOAD_OK) { | ||||
return err; | return err; | ||||
} | } | ||||
std::sort(vTxHash.begin(), vTxHash.end()); | std::sort(vTxHash.begin(), vTxHash.end()); | ||||
std::sort(vTxHashIn.begin(), vTxHashIn.end()); | std::sort(vTxHashIn.begin(), vTxHashIn.end()); | ||||
// Erase each matching wallet TX. | // Erase each matching wallet TX. | ||||
bool delerror = false; | bool delerror = false; | ||||
std::vector<uint256>::iterator it = vTxHashIn.begin(); | std::vector<txhash_t>::iterator it = vTxHashIn.begin(); | ||||
for (uint256 hash : vTxHash) { | for (txhash_t hash : vTxHash) { | ||||
while (it < vTxHashIn.end() && (*it) < hash) { | while (it < vTxHashIn.end() && (*it) < hash) { | ||||
it++; | it++; | ||||
} | } | ||||
if (it == vTxHashIn.end()) { | if (it == vTxHashIn.end()) { | ||||
break; | break; | ||||
} else if ((*it) == hash) { | } else if ((*it) == hash) { | ||||
pwallet->mapWallet.erase(hash); | pwallet->mapWallet.erase(hash); | ||||
if (!EraseTx(hash)) { | if (!EraseTx(hash)) { | ||||
Show All 10 Lines | if (delerror) { | ||||
return DB_CORRUPT; | return DB_CORRUPT; | ||||
} | } | ||||
return DB_LOAD_OK; | return DB_LOAD_OK; | ||||
} | } | ||||
DBErrors CWalletDB::ZapWalletTx(CWallet *pwallet, | DBErrors CWalletDB::ZapWalletTx(CWallet *pwallet, | ||||
std::vector<CWalletTx> &vWtx) { | std::vector<CWalletTx> &vWtx) { | ||||
// Build list of wallet TXs. | // Build list of wallet TXs. | ||||
std::vector<uint256> vTxHash; | std::vector<txhash_t> vTxHash; | ||||
DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); | DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); | ||||
if (err != DB_LOAD_OK) return err; | if (err != DB_LOAD_OK) return err; | ||||
// Erase each wallet TX. | // Erase each wallet TX. | ||||
for (uint256 &hash : vTxHash) { | for (txhash_t &hash : vTxHash) { | ||||
if (!EraseTx(hash)) return DB_CORRUPT; | if (!EraseTx(hash)) return DB_CORRUPT; | ||||
} | } | ||||
return DB_LOAD_OK; | return DB_LOAD_OK; | ||||
} | } | ||||
void ThreadFlushWalletDB() { | void ThreadFlushWalletDB() { | ||||
// Make this thread recognisable as the wallet flushing thread. | // Make this thread recognisable as the wallet flushing thread. | ||||
▲ Show 20 Lines • Show All 162 Lines • Show Last 20 Lines |