Fix uninitialized atomic variables
[bitcoinplatinum.git] / src / wallet / walletdb.cpp
blob2a33dca240c3b827a258c2714a54a6b61055d4c2
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/thread.hpp>
24 // CWalletDB
27 bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
29 return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
32 bool CWalletDB::EraseName(const std::string& strAddress)
34 // This should only be used for sending addresses, never for receiving addresses,
35 // receiving addresses must always have an address book entry if they're not change return.
36 return EraseIC(std::make_pair(std::string("name"), strAddress));
39 bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
41 return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
44 bool CWalletDB::ErasePurpose(const std::string& strPurpose)
46 return EraseIC(std::make_pair(std::string("purpose"), strPurpose));
49 bool CWalletDB::WriteTx(const CWalletTx& wtx)
51 return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
54 bool CWalletDB::EraseTx(uint256 hash)
56 return EraseIC(std::make_pair(std::string("tx"), hash));
59 bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
61 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
62 return false;
65 // hash pubkey/privkey to accelerate wallet load
66 std::vector<unsigned char> vchKey;
67 vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
68 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
69 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
71 return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
74 bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
75 const std::vector<unsigned char>& vchCryptedSecret,
76 const CKeyMetadata &keyMeta)
78 if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
79 return false;
82 if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) {
83 return false;
85 EraseIC(std::make_pair(std::string("key"), vchPubKey));
86 EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
87 return true;
90 bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
92 return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
95 bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
97 return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
100 bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
102 if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) {
103 return false;
105 return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
108 bool CWalletDB::EraseWatchOnly(const CScript &dest)
110 if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) {
111 return false;
113 return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
116 bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
118 WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
119 return WriteIC(std::string("bestblock_nomerkle"), locator);
122 bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
124 if (batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true;
125 return batch.Read(std::string("bestblock_nomerkle"), locator);
128 bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
130 return WriteIC(std::string("orderposnext"), nOrderPosNext);
133 bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
135 return WriteIC(std::string("defaultkey"), vchPubKey);
138 bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
140 return batch.Read(std::make_pair(std::string("pool"), nPool), keypool);
143 bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
145 return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
148 bool CWalletDB::ErasePool(int64_t nPool)
150 return EraseIC(std::make_pair(std::string("pool"), nPool));
153 bool CWalletDB::WriteMinVersion(int nVersion)
155 return WriteIC(std::string("minversion"), nVersion);
158 bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
160 account.SetNull();
161 return batch.Read(std::make_pair(std::string("acc"), strAccount), account);
164 bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
166 return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
169 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
171 return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
174 CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
176 std::list<CAccountingEntry> entries;
177 ListAccountCreditDebit(strAccount, entries);
179 CAmount nCreditDebit = 0;
180 for (const CAccountingEntry& entry : entries)
181 nCreditDebit += entry.nCreditDebit;
183 return nCreditDebit;
186 void CWalletDB::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
188 bool fAllAccounts = (strAccount == "*");
190 Dbc* pcursor = batch.GetCursor();
191 if (!pcursor)
192 throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
193 bool setRange = true;
194 while (true)
196 // Read next record
197 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
198 if (setRange)
199 ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0)));
200 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
201 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange);
202 setRange = false;
203 if (ret == DB_NOTFOUND)
204 break;
205 else if (ret != 0)
207 pcursor->close();
208 throw std::runtime_error(std::string(__func__) + ": error scanning DB");
211 // Unserialize
212 std::string strType;
213 ssKey >> strType;
214 if (strType != "acentry")
215 break;
216 CAccountingEntry acentry;
217 ssKey >> acentry.strAccount;
218 if (!fAllAccounts && acentry.strAccount != strAccount)
219 break;
221 ssValue >> acentry;
222 ssKey >> acentry.nEntryNo;
223 entries.push_back(acentry);
226 pcursor->close();
229 class CWalletScanState {
230 public:
231 unsigned int nKeys;
232 unsigned int nCKeys;
233 unsigned int nWatchKeys;
234 unsigned int nKeyMeta;
235 bool fIsEncrypted;
236 bool fAnyUnordered;
237 int nFileVersion;
238 std::vector<uint256> vWalletUpgrade;
240 CWalletScanState() {
241 nKeys = nCKeys = nWatchKeys = nKeyMeta = 0;
242 fIsEncrypted = false;
243 fAnyUnordered = false;
244 nFileVersion = 0;
248 bool
249 ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
250 CWalletScanState &wss, std::string& strType, std::string& strErr)
252 try {
253 // Unserialize
254 // Taking advantage of the fact that pair serialization
255 // is just the two items serialized one after the other
256 ssKey >> strType;
257 if (strType == "name")
259 std::string strAddress;
260 ssKey >> strAddress;
261 ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
263 else if (strType == "purpose")
265 std::string strAddress;
266 ssKey >> strAddress;
267 ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
269 else if (strType == "tx")
271 uint256 hash;
272 ssKey >> hash;
273 CWalletTx wtx;
274 ssValue >> wtx;
275 CValidationState state;
276 if (!(CheckTransaction(wtx, state) && (wtx.GetHash() == hash) && state.IsValid()))
277 return false;
279 // Undo serialize changes in 31600
280 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
282 if (!ssValue.empty())
284 char fTmp;
285 char fUnused;
286 ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
287 strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
288 wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
289 wtx.fTimeReceivedIsTxTime = fTmp;
291 else
293 strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
294 wtx.fTimeReceivedIsTxTime = 0;
296 wss.vWalletUpgrade.push_back(hash);
299 if (wtx.nOrderPos == -1)
300 wss.fAnyUnordered = true;
302 pwallet->LoadToWallet(wtx);
304 else if (strType == "acentry")
306 std::string strAccount;
307 ssKey >> strAccount;
308 uint64_t nNumber;
309 ssKey >> nNumber;
310 if (nNumber > pwallet->nAccountingEntryNumber) {
311 pwallet->nAccountingEntryNumber = nNumber;
314 if (!wss.fAnyUnordered)
316 CAccountingEntry acentry;
317 ssValue >> acentry;
318 if (acentry.nOrderPos == -1)
319 wss.fAnyUnordered = true;
322 else if (strType == "watchs")
324 wss.nWatchKeys++;
325 CScript script;
326 ssKey >> *(CScriptBase*)(&script);
327 char fYes;
328 ssValue >> fYes;
329 if (fYes == '1')
330 pwallet->LoadWatchOnly(script);
332 else if (strType == "key" || strType == "wkey")
334 CPubKey vchPubKey;
335 ssKey >> vchPubKey;
336 if (!vchPubKey.IsValid())
338 strErr = "Error reading wallet database: CPubKey corrupt";
339 return false;
341 CKey key;
342 CPrivKey pkey;
343 uint256 hash;
345 if (strType == "key")
347 wss.nKeys++;
348 ssValue >> pkey;
349 } else {
350 CWalletKey wkey;
351 ssValue >> wkey;
352 pkey = wkey.vchPrivKey;
355 // Old wallets store keys as "key" [pubkey] => [privkey]
356 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
357 // using EC operations as a checksum.
358 // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
359 // remaining backwards-compatible.
362 ssValue >> hash;
364 catch (...) {}
366 bool fSkipCheck = false;
368 if (!hash.IsNull())
370 // hash pubkey/privkey to accelerate wallet load
371 std::vector<unsigned char> vchKey;
372 vchKey.reserve(vchPubKey.size() + pkey.size());
373 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
374 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
376 if (Hash(vchKey.begin(), vchKey.end()) != hash)
378 strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
379 return false;
382 fSkipCheck = true;
385 if (!key.Load(pkey, vchPubKey, fSkipCheck))
387 strErr = "Error reading wallet database: CPrivKey corrupt";
388 return false;
390 if (!pwallet->LoadKey(key, vchPubKey))
392 strErr = "Error reading wallet database: LoadKey failed";
393 return false;
396 else if (strType == "mkey")
398 unsigned int nID;
399 ssKey >> nID;
400 CMasterKey kMasterKey;
401 ssValue >> kMasterKey;
402 if(pwallet->mapMasterKeys.count(nID) != 0)
404 strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
405 return false;
407 pwallet->mapMasterKeys[nID] = kMasterKey;
408 if (pwallet->nMasterKeyMaxID < nID)
409 pwallet->nMasterKeyMaxID = nID;
411 else if (strType == "ckey")
413 CPubKey vchPubKey;
414 ssKey >> vchPubKey;
415 if (!vchPubKey.IsValid())
417 strErr = "Error reading wallet database: CPubKey corrupt";
418 return false;
420 std::vector<unsigned char> vchPrivKey;
421 ssValue >> vchPrivKey;
422 wss.nCKeys++;
424 if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
426 strErr = "Error reading wallet database: LoadCryptedKey failed";
427 return false;
429 wss.fIsEncrypted = true;
431 else if (strType == "keymeta" || strType == "watchmeta")
433 CTxDestination keyID;
434 if (strType == "keymeta")
436 CPubKey vchPubKey;
437 ssKey >> vchPubKey;
438 keyID = vchPubKey.GetID();
440 else if (strType == "watchmeta")
442 CScript script;
443 ssKey >> *(CScriptBase*)(&script);
444 keyID = CScriptID(script);
447 CKeyMetadata keyMeta;
448 ssValue >> keyMeta;
449 wss.nKeyMeta++;
451 pwallet->LoadKeyMetadata(keyID, keyMeta);
453 else if (strType == "defaultkey")
455 ssValue >> pwallet->vchDefaultKey;
457 else if (strType == "pool")
459 int64_t nIndex;
460 ssKey >> nIndex;
461 CKeyPool keypool;
462 ssValue >> keypool;
464 pwallet->LoadKeyPool(nIndex, keypool);
466 else if (strType == "version")
468 ssValue >> wss.nFileVersion;
469 if (wss.nFileVersion == 10300)
470 wss.nFileVersion = 300;
472 else if (strType == "cscript")
474 uint160 hash;
475 ssKey >> hash;
476 CScript script;
477 ssValue >> *(CScriptBase*)(&script);
478 if (!pwallet->LoadCScript(script))
480 strErr = "Error reading wallet database: LoadCScript failed";
481 return false;
484 else if (strType == "orderposnext")
486 ssValue >> pwallet->nOrderPosNext;
488 else if (strType == "destdata")
490 std::string strAddress, strKey, strValue;
491 ssKey >> strAddress;
492 ssKey >> strKey;
493 ssValue >> strValue;
494 if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue))
496 strErr = "Error reading wallet database: LoadDestData failed";
497 return false;
500 else if (strType == "hdchain")
502 CHDChain chain;
503 ssValue >> chain;
504 if (!pwallet->SetHDChain(chain, true))
506 strErr = "Error reading wallet database: SetHDChain failed";
507 return false;
510 } catch (...)
512 return false;
514 return true;
517 bool CWalletDB::IsKeyType(const std::string& strType)
519 return (strType== "key" || strType == "wkey" ||
520 strType == "mkey" || strType == "ckey");
523 DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
525 pwallet->vchDefaultKey = CPubKey();
526 CWalletScanState wss;
527 bool fNoncriticalErrors = false;
528 DBErrors result = DB_LOAD_OK;
530 LOCK(pwallet->cs_wallet);
531 try {
532 int nMinVersion = 0;
533 if (batch.Read((std::string)"minversion", nMinVersion))
535 if (nMinVersion > CLIENT_VERSION)
536 return DB_TOO_NEW;
537 pwallet->LoadMinVersion(nMinVersion);
540 // Get cursor
541 Dbc* pcursor = batch.GetCursor();
542 if (!pcursor)
544 LogPrintf("Error getting wallet database cursor\n");
545 return DB_CORRUPT;
548 while (true)
550 // Read next record
551 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
552 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
553 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
554 if (ret == DB_NOTFOUND)
555 break;
556 else if (ret != 0)
558 LogPrintf("Error reading next record from wallet database\n");
559 return DB_CORRUPT;
562 // Try to be tolerant of single corrupt records:
563 std::string strType, strErr;
564 if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
566 // losing keys is considered a catastrophic error, anything else
567 // we assume the user can live with:
568 if (IsKeyType(strType))
569 result = DB_CORRUPT;
570 else
572 // Leave other errors alone, if we try to fix them we might make things worse.
573 fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
574 if (strType == "tx")
575 // Rescan if there is a bad transaction record:
576 SoftSetBoolArg("-rescan", true);
579 if (!strErr.empty())
580 LogPrintf("%s\n", strErr);
582 pcursor->close();
584 catch (const boost::thread_interrupted&) {
585 throw;
587 catch (...) {
588 result = DB_CORRUPT;
591 if (fNoncriticalErrors && result == DB_LOAD_OK)
592 result = DB_NONCRITICAL_ERROR;
594 // Any wallet corruption at all: skip any rewriting or
595 // upgrading, we don't want to make it worse.
596 if (result != DB_LOAD_OK)
597 return result;
599 LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
601 LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
602 wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
604 // nTimeFirstKey is only reliable if all keys have metadata
605 if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
606 pwallet->UpdateTimeFirstKey(1);
608 for (uint256 hash : wss.vWalletUpgrade)
609 WriteTx(pwallet->mapWallet[hash]);
611 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
612 if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
613 return DB_NEED_REWRITE;
615 if (wss.nFileVersion < CLIENT_VERSION) // Update
616 WriteVersion(CLIENT_VERSION);
618 if (wss.fAnyUnordered)
619 result = pwallet->ReorderTransactions();
621 pwallet->laccentries.clear();
622 ListAccountCreditDebit("*", pwallet->laccentries);
623 for (CAccountingEntry& entry : pwallet->laccentries) {
624 pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
627 return result;
630 DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
632 bool fNoncriticalErrors = false;
633 DBErrors result = DB_LOAD_OK;
635 try {
636 int nMinVersion = 0;
637 if (batch.Read((std::string)"minversion", nMinVersion))
639 if (nMinVersion > CLIENT_VERSION)
640 return DB_TOO_NEW;
643 // Get cursor
644 Dbc* pcursor = batch.GetCursor();
645 if (!pcursor)
647 LogPrintf("Error getting wallet database cursor\n");
648 return DB_CORRUPT;
651 while (true)
653 // Read next record
654 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
655 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
656 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
657 if (ret == DB_NOTFOUND)
658 break;
659 else if (ret != 0)
661 LogPrintf("Error reading next record from wallet database\n");
662 return DB_CORRUPT;
665 std::string strType;
666 ssKey >> strType;
667 if (strType == "tx") {
668 uint256 hash;
669 ssKey >> hash;
671 CWalletTx wtx;
672 ssValue >> wtx;
674 vTxHash.push_back(hash);
675 vWtx.push_back(wtx);
678 pcursor->close();
680 catch (const boost::thread_interrupted&) {
681 throw;
683 catch (...) {
684 result = DB_CORRUPT;
687 if (fNoncriticalErrors && result == DB_LOAD_OK)
688 result = DB_NONCRITICAL_ERROR;
690 return result;
693 DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
695 // build list of wallet TXs and hashes
696 std::vector<uint256> vTxHash;
697 std::vector<CWalletTx> vWtx;
698 DBErrors err = FindWalletTx(vTxHash, vWtx);
699 if (err != DB_LOAD_OK) {
700 return err;
703 std::sort(vTxHash.begin(), vTxHash.end());
704 std::sort(vTxHashIn.begin(), vTxHashIn.end());
706 // erase each matching wallet TX
707 bool delerror = false;
708 std::vector<uint256>::iterator it = vTxHashIn.begin();
709 for (uint256 hash : vTxHash) {
710 while (it < vTxHashIn.end() && (*it) < hash) {
711 it++;
713 if (it == vTxHashIn.end()) {
714 break;
716 else if ((*it) == hash) {
717 if(!EraseTx(hash)) {
718 LogPrint(BCLog::DB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
719 delerror = true;
721 vTxHashOut.push_back(hash);
725 if (delerror) {
726 return DB_CORRUPT;
728 return DB_LOAD_OK;
731 DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
733 // build list of wallet TXs
734 std::vector<uint256> vTxHash;
735 DBErrors err = FindWalletTx(vTxHash, vWtx);
736 if (err != DB_LOAD_OK)
737 return err;
739 // erase each wallet TX
740 for (uint256& hash : vTxHash) {
741 if (!EraseTx(hash))
742 return DB_CORRUPT;
745 return DB_LOAD_OK;
748 void MaybeCompactWalletDB()
750 static std::atomic<bool> fOneThread(false);
751 if (fOneThread.exchange(true)) {
752 return;
754 if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
755 return;
758 for (CWalletRef pwallet : vpwallets) {
759 CWalletDBWrapper& dbh = pwallet->GetDBHandle();
761 unsigned int nUpdateCounter = dbh.nUpdateCounter;
763 if (dbh.nLastSeen != nUpdateCounter) {
764 dbh.nLastSeen = nUpdateCounter;
765 dbh.nLastWalletUpdate = GetTime();
768 if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
769 if (CDB::PeriodicFlush(dbh)) {
770 dbh.nLastFlushed = nUpdateCounter;
775 fOneThread = false;
779 // Try to (very carefully!) recover wallet file if there is a problem.
781 bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
783 return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename);
786 bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename)
788 // recover without a key filter callback
789 // results in recovering all record types
790 return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename);
793 bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
795 CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
796 CWalletScanState dummyWss;
797 std::string strType, strErr;
798 bool fReadOK;
800 // Required in LoadKeyMetadata():
801 LOCK(dummyWallet->cs_wallet);
802 fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
803 dummyWss, strType, strErr);
805 if (!IsKeyType(strType) && strType != "hdchain")
806 return false;
807 if (!fReadOK)
809 LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
810 return false;
813 return true;
816 bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr)
818 return CDB::VerifyEnvironment(walletFile, dataDir, errorStr);
821 bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr)
823 return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover);
826 bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
828 return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
831 bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
833 return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
837 bool CWalletDB::WriteHDChain(const CHDChain& chain)
839 return WriteIC(std::string("hdchain"), chain);
842 bool CWalletDB::TxnBegin()
844 return batch.TxnBegin();
847 bool CWalletDB::TxnCommit()
849 return batch.TxnCommit();
852 bool CWalletDB::TxnAbort()
854 return batch.TxnAbort();
857 bool CWalletDB::ReadVersion(int& nVersion)
859 return batch.ReadVersion(nVersion);
862 bool CWalletDB::WriteVersion(int nVersion)
864 return batch.WriteVersion(nVersion);