Remove unreachable or otherwise redundant code
[bitcoinplatinum.git] / src / wallet / walletdb.cpp
blobd839beca88176f8c1d6c5631c845b00d3296de34
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "wallet/walletdb.h"
8 #include "base58.h"
9 #include "consensus/tx_verify.h"
10 #include "consensus/validation.h"
11 #include "fs.h"
12 #include "protocol.h"
13 #include "serialize.h"
14 #include "sync.h"
15 #include "util.h"
16 #include "utiltime.h"
17 #include "wallet/wallet.h"
19 #include <atomic>
21 #include <boost/foreach.hpp>
22 #include <boost/thread.hpp>
25 // CWalletDB
28 bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
30 return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
33 bool CWalletDB::EraseName(const std::string& strAddress)
35 // This should only be used for sending addresses, never for receiving addresses,
36 // receiving addresses must always have an address book entry if they're not change return.
37 return EraseIC(std::make_pair(std::string("name"), strAddress));
40 bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
42 return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
45 bool CWalletDB::ErasePurpose(const std::string& strPurpose)
47 return EraseIC(std::make_pair(std::string("purpose"), strPurpose));
50 bool CWalletDB::WriteTx(const CWalletTx& wtx)
52 return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
55 bool CWalletDB::EraseTx(uint256 hash)
57 return EraseIC(std::make_pair(std::string("tx"), hash));
60 bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
62 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
63 return false;
66 // hash pubkey/privkey to accelerate wallet load
67 std::vector<unsigned char> vchKey;
68 vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
69 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
70 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
72 return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
75 bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
76 const std::vector<unsigned char>& vchCryptedSecret,
77 const CKeyMetadata &keyMeta)
79 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
80 return false;
83 if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) {
84 return false;
86 EraseIC(std::make_pair(std::string("key"), vchPubKey));
87 EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
88 return true;
91 bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
93 return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
96 bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
98 return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
101 bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
103 if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) {
104 return false;
106 return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
109 bool CWalletDB::EraseWatchOnly(const CScript &dest)
111 if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) {
112 return false;
114 return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
117 bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
119 WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
120 return WriteIC(std::string("bestblock_nomerkle"), locator);
123 bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
125 if (batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true;
126 return batch.Read(std::string("bestblock_nomerkle"), locator);
129 bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
131 return WriteIC(std::string("orderposnext"), nOrderPosNext);
134 bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
136 return WriteIC(std::string("defaultkey"), vchPubKey);
139 bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
141 return batch.Read(std::make_pair(std::string("pool"), nPool), keypool);
144 bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
146 return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
149 bool CWalletDB::ErasePool(int64_t nPool)
151 return EraseIC(std::make_pair(std::string("pool"), nPool));
154 bool CWalletDB::WriteMinVersion(int nVersion)
156 return WriteIC(std::string("minversion"), nVersion);
159 bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
161 account.SetNull();
162 return batch.Read(std::make_pair(std::string("acc"), strAccount), account);
165 bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
167 return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
170 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
172 return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
175 CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
177 std::list<CAccountingEntry> entries;
178 ListAccountCreditDebit(strAccount, entries);
180 CAmount nCreditDebit = 0;
181 BOOST_FOREACH (const CAccountingEntry& entry, entries)
182 nCreditDebit += entry.nCreditDebit;
184 return nCreditDebit;
187 void CWalletDB::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
189 bool fAllAccounts = (strAccount == "*");
191 Dbc* pcursor = batch.GetCursor();
192 if (!pcursor)
193 throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
194 bool setRange = true;
195 while (true)
197 // Read next record
198 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
199 if (setRange)
200 ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0)));
201 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
202 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange);
203 setRange = false;
204 if (ret == DB_NOTFOUND)
205 break;
206 else if (ret != 0)
208 pcursor->close();
209 throw std::runtime_error(std::string(__func__) + ": error scanning DB");
212 // Unserialize
213 std::string strType;
214 ssKey >> strType;
215 if (strType != "acentry")
216 break;
217 CAccountingEntry acentry;
218 ssKey >> acentry.strAccount;
219 if (!fAllAccounts && acentry.strAccount != strAccount)
220 break;
222 ssValue >> acentry;
223 ssKey >> acentry.nEntryNo;
224 entries.push_back(acentry);
227 pcursor->close();
230 class CWalletScanState {
231 public:
232 unsigned int nKeys;
233 unsigned int nCKeys;
234 unsigned int nWatchKeys;
235 unsigned int nKeyMeta;
236 bool fIsEncrypted;
237 bool fAnyUnordered;
238 int nFileVersion;
239 std::vector<uint256> vWalletUpgrade;
241 CWalletScanState() {
242 nKeys = nCKeys = nWatchKeys = nKeyMeta = 0;
243 fIsEncrypted = false;
244 fAnyUnordered = false;
245 nFileVersion = 0;
249 bool
250 ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
251 CWalletScanState &wss, std::string& strType, std::string& strErr)
253 try {
254 // Unserialize
255 // Taking advantage of the fact that pair serialization
256 // is just the two items serialized one after the other
257 ssKey >> strType;
258 if (strType == "name")
260 std::string strAddress;
261 ssKey >> strAddress;
262 ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
264 else if (strType == "purpose")
266 std::string strAddress;
267 ssKey >> strAddress;
268 ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
270 else if (strType == "tx")
272 uint256 hash;
273 ssKey >> hash;
274 CWalletTx wtx;
275 ssValue >> wtx;
276 CValidationState state;
277 if (!(CheckTransaction(wtx, state) && (wtx.GetHash() == hash) && state.IsValid()))
278 return false;
280 // Undo serialize changes in 31600
281 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
283 if (!ssValue.empty())
285 char fTmp;
286 char fUnused;
287 ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
288 strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
289 wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
290 wtx.fTimeReceivedIsTxTime = fTmp;
292 else
294 strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
295 wtx.fTimeReceivedIsTxTime = 0;
297 wss.vWalletUpgrade.push_back(hash);
300 if (wtx.nOrderPos == -1)
301 wss.fAnyUnordered = true;
303 pwallet->LoadToWallet(wtx);
305 else if (strType == "acentry")
307 std::string strAccount;
308 ssKey >> strAccount;
309 uint64_t nNumber;
310 ssKey >> nNumber;
311 if (nNumber > pwallet->nAccountingEntryNumber) {
312 pwallet->nAccountingEntryNumber = nNumber;
315 if (!wss.fAnyUnordered)
317 CAccountingEntry acentry;
318 ssValue >> acentry;
319 if (acentry.nOrderPos == -1)
320 wss.fAnyUnordered = true;
323 else if (strType == "watchs")
325 wss.nWatchKeys++;
326 CScript script;
327 ssKey >> *(CScriptBase*)(&script);
328 char fYes;
329 ssValue >> fYes;
330 if (fYes == '1')
331 pwallet->LoadWatchOnly(script);
333 else if (strType == "key" || strType == "wkey")
335 CPubKey vchPubKey;
336 ssKey >> vchPubKey;
337 if (!vchPubKey.IsValid())
339 strErr = "Error reading wallet database: CPubKey corrupt";
340 return false;
342 CKey key;
343 CPrivKey pkey;
344 uint256 hash;
346 if (strType == "key")
348 wss.nKeys++;
349 ssValue >> pkey;
350 } else {
351 CWalletKey wkey;
352 ssValue >> wkey;
353 pkey = wkey.vchPrivKey;
356 // Old wallets store keys as "key" [pubkey] => [privkey]
357 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
358 // using EC operations as a checksum.
359 // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
360 // remaining backwards-compatible.
363 ssValue >> hash;
365 catch (...) {}
367 bool fSkipCheck = false;
369 if (!hash.IsNull())
371 // hash pubkey/privkey to accelerate wallet load
372 std::vector<unsigned char> vchKey;
373 vchKey.reserve(vchPubKey.size() + pkey.size());
374 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
375 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
377 if (Hash(vchKey.begin(), vchKey.end()) != hash)
379 strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
380 return false;
383 fSkipCheck = true;
386 if (!key.Load(pkey, vchPubKey, fSkipCheck))
388 strErr = "Error reading wallet database: CPrivKey corrupt";
389 return false;
391 if (!pwallet->LoadKey(key, vchPubKey))
393 strErr = "Error reading wallet database: LoadKey failed";
394 return false;
397 else if (strType == "mkey")
399 unsigned int nID;
400 ssKey >> nID;
401 CMasterKey kMasterKey;
402 ssValue >> kMasterKey;
403 if(pwallet->mapMasterKeys.count(nID) != 0)
405 strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
406 return false;
408 pwallet->mapMasterKeys[nID] = kMasterKey;
409 if (pwallet->nMasterKeyMaxID < nID)
410 pwallet->nMasterKeyMaxID = nID;
412 else if (strType == "ckey")
414 CPubKey vchPubKey;
415 ssKey >> vchPubKey;
416 if (!vchPubKey.IsValid())
418 strErr = "Error reading wallet database: CPubKey corrupt";
419 return false;
421 std::vector<unsigned char> vchPrivKey;
422 ssValue >> vchPrivKey;
423 wss.nCKeys++;
425 if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
427 strErr = "Error reading wallet database: LoadCryptedKey failed";
428 return false;
430 wss.fIsEncrypted = true;
432 else if (strType == "keymeta" || strType == "watchmeta")
434 CTxDestination keyID;
435 if (strType == "keymeta")
437 CPubKey vchPubKey;
438 ssKey >> vchPubKey;
439 keyID = vchPubKey.GetID();
441 else if (strType == "watchmeta")
443 CScript script;
444 ssKey >> *(CScriptBase*)(&script);
445 keyID = CScriptID(script);
448 CKeyMetadata keyMeta;
449 ssValue >> keyMeta;
450 wss.nKeyMeta++;
452 pwallet->LoadKeyMetadata(keyID, keyMeta);
454 else if (strType == "defaultkey")
456 ssValue >> pwallet->vchDefaultKey;
458 else if (strType == "pool")
460 int64_t nIndex;
461 ssKey >> nIndex;
462 CKeyPool keypool;
463 ssValue >> keypool;
465 pwallet->LoadKeyPool(nIndex, keypool);
467 else if (strType == "version")
469 ssValue >> wss.nFileVersion;
470 if (wss.nFileVersion == 10300)
471 wss.nFileVersion = 300;
473 else if (strType == "cscript")
475 uint160 hash;
476 ssKey >> hash;
477 CScript script;
478 ssValue >> *(CScriptBase*)(&script);
479 if (!pwallet->LoadCScript(script))
481 strErr = "Error reading wallet database: LoadCScript failed";
482 return false;
485 else if (strType == "orderposnext")
487 ssValue >> pwallet->nOrderPosNext;
489 else if (strType == "destdata")
491 std::string strAddress, strKey, strValue;
492 ssKey >> strAddress;
493 ssKey >> strKey;
494 ssValue >> strValue;
495 if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue))
497 strErr = "Error reading wallet database: LoadDestData failed";
498 return false;
501 else if (strType == "hdchain")
503 CHDChain chain;
504 ssValue >> chain;
505 if (!pwallet->SetHDChain(chain, true))
507 strErr = "Error reading wallet database: SetHDChain failed";
508 return false;
511 } catch (...)
513 return false;
515 return true;
518 bool CWalletDB::IsKeyType(const std::string& strType)
520 return (strType== "key" || strType == "wkey" ||
521 strType == "mkey" || strType == "ckey");
524 DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
526 pwallet->vchDefaultKey = CPubKey();
527 CWalletScanState wss;
528 bool fNoncriticalErrors = false;
529 DBErrors result = DB_LOAD_OK;
531 LOCK(pwallet->cs_wallet);
532 try {
533 int nMinVersion = 0;
534 if (batch.Read((std::string)"minversion", nMinVersion))
536 if (nMinVersion > CLIENT_VERSION)
537 return DB_TOO_NEW;
538 pwallet->LoadMinVersion(nMinVersion);
541 // Get cursor
542 Dbc* pcursor = batch.GetCursor();
543 if (!pcursor)
545 LogPrintf("Error getting wallet database cursor\n");
546 return DB_CORRUPT;
549 while (true)
551 // Read next record
552 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
553 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
554 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
555 if (ret == DB_NOTFOUND)
556 break;
557 else if (ret != 0)
559 LogPrintf("Error reading next record from wallet database\n");
560 return DB_CORRUPT;
563 // Try to be tolerant of single corrupt records:
564 std::string strType, strErr;
565 if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
567 // losing keys is considered a catastrophic error, anything else
568 // we assume the user can live with:
569 if (IsKeyType(strType))
570 result = DB_CORRUPT;
571 else
573 // Leave other errors alone, if we try to fix them we might make things worse.
574 fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
575 if (strType == "tx")
576 // Rescan if there is a bad transaction record:
577 SoftSetBoolArg("-rescan", true);
580 if (!strErr.empty())
581 LogPrintf("%s\n", strErr);
583 pcursor->close();
585 catch (const boost::thread_interrupted&) {
586 throw;
588 catch (...) {
589 result = DB_CORRUPT;
592 if (fNoncriticalErrors && result == DB_LOAD_OK)
593 result = DB_NONCRITICAL_ERROR;
595 // Any wallet corruption at all: skip any rewriting or
596 // upgrading, we don't want to make it worse.
597 if (result != DB_LOAD_OK)
598 return result;
600 LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
602 LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
603 wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
605 // nTimeFirstKey is only reliable if all keys have metadata
606 if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
607 pwallet->UpdateTimeFirstKey(1);
609 BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade)
610 WriteTx(pwallet->mapWallet[hash]);
612 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
613 if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
614 return DB_NEED_REWRITE;
616 if (wss.nFileVersion < CLIENT_VERSION) // Update
617 WriteVersion(CLIENT_VERSION);
619 if (wss.fAnyUnordered)
620 result = pwallet->ReorderTransactions();
622 pwallet->laccentries.clear();
623 ListAccountCreditDebit("*", pwallet->laccentries);
624 BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) {
625 pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
628 return result;
631 DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
633 bool fNoncriticalErrors = false;
634 DBErrors result = DB_LOAD_OK;
636 try {
637 int nMinVersion = 0;
638 if (batch.Read((std::string)"minversion", nMinVersion))
640 if (nMinVersion > CLIENT_VERSION)
641 return DB_TOO_NEW;
644 // Get cursor
645 Dbc* pcursor = batch.GetCursor();
646 if (!pcursor)
648 LogPrintf("Error getting wallet database cursor\n");
649 return DB_CORRUPT;
652 while (true)
654 // Read next record
655 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
656 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
657 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
658 if (ret == DB_NOTFOUND)
659 break;
660 else if (ret != 0)
662 LogPrintf("Error reading next record from wallet database\n");
663 return DB_CORRUPT;
666 std::string strType;
667 ssKey >> strType;
668 if (strType == "tx") {
669 uint256 hash;
670 ssKey >> hash;
672 CWalletTx wtx;
673 ssValue >> wtx;
675 vTxHash.push_back(hash);
676 vWtx.push_back(wtx);
679 pcursor->close();
681 catch (const boost::thread_interrupted&) {
682 throw;
684 catch (...) {
685 result = DB_CORRUPT;
688 if (fNoncriticalErrors && result == DB_LOAD_OK)
689 result = DB_NONCRITICAL_ERROR;
691 return result;
694 DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
696 // build list of wallet TXs and hashes
697 std::vector<uint256> vTxHash;
698 std::vector<CWalletTx> vWtx;
699 DBErrors err = FindWalletTx(vTxHash, vWtx);
700 if (err != DB_LOAD_OK) {
701 return err;
704 std::sort(vTxHash.begin(), vTxHash.end());
705 std::sort(vTxHashIn.begin(), vTxHashIn.end());
707 // erase each matching wallet TX
708 bool delerror = false;
709 std::vector<uint256>::iterator it = vTxHashIn.begin();
710 BOOST_FOREACH (uint256 hash, vTxHash) {
711 while (it < vTxHashIn.end() && (*it) < hash) {
712 it++;
714 if (it == vTxHashIn.end()) {
715 break;
717 else if ((*it) == hash) {
718 if(!EraseTx(hash)) {
719 LogPrint(BCLog::DB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
720 delerror = true;
722 vTxHashOut.push_back(hash);
726 if (delerror) {
727 return DB_CORRUPT;
729 return DB_LOAD_OK;
732 DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
734 // build list of wallet TXs
735 std::vector<uint256> vTxHash;
736 DBErrors err = FindWalletTx(vTxHash, vWtx);
737 if (err != DB_LOAD_OK)
738 return err;
740 // erase each wallet TX
741 BOOST_FOREACH (uint256& hash, vTxHash) {
742 if (!EraseTx(hash))
743 return DB_CORRUPT;
746 return DB_LOAD_OK;
749 void MaybeCompactWalletDB()
751 static std::atomic<bool> fOneThread;
752 if (fOneThread.exchange(true)) {
753 return;
755 if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
756 return;
759 for (CWalletRef pwallet : vpwallets) {
760 CWalletDBWrapper& dbh = pwallet->GetDBHandle();
762 unsigned int nUpdateCounter = dbh.nUpdateCounter;
764 if (dbh.nLastSeen != nUpdateCounter) {
765 dbh.nLastSeen = nUpdateCounter;
766 dbh.nLastWalletUpdate = GetTime();
769 if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
770 if (CDB::PeriodicFlush(dbh)) {
771 dbh.nLastFlushed = nUpdateCounter;
776 fOneThread = false;
780 // Try to (very carefully!) recover wallet file if there is a problem.
782 bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
784 return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename);
787 bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename)
789 // recover without a key filter callback
790 // results in recovering all record types
791 return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename);
794 bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
796 CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
797 CWalletScanState dummyWss;
798 std::string strType, strErr;
799 bool fReadOK;
801 // Required in LoadKeyMetadata():
802 LOCK(dummyWallet->cs_wallet);
803 fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
804 dummyWss, strType, strErr);
806 if (!IsKeyType(strType) && strType != "hdchain")
807 return false;
808 if (!fReadOK)
810 LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
811 return false;
814 return true;
817 bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr)
819 return CDB::VerifyEnvironment(walletFile, dataDir, errorStr);
822 bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr)
824 return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover);
827 bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
829 return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
832 bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
834 return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
838 bool CWalletDB::WriteHDChain(const CHDChain& chain)
840 return WriteIC(std::string("hdchain"), chain);
843 bool CWalletDB::TxnBegin()
845 return batch.TxnBegin();
848 bool CWalletDB::TxnCommit()
850 return batch.TxnCommit();
853 bool CWalletDB::TxnAbort()
855 return batch.TxnAbort();
858 bool CWalletDB::ReadVersion(int& nVersion)
860 return batch.ReadVersion(nVersion);
863 bool CWalletDB::WriteVersion(int nVersion)
865 return batch.WriteVersion(nVersion);