Merge #12079: Improve prioritisetransaction test coverage
[bitcoinplatinum.git] / src / wallet / walletdb.cpp
blobdd6835a06f6613da23c64c245b27004213332d6f
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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& strAddress)
46 return EraseIC(std::make_pair(std::string("purpose"), strAddress));
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), redeemScript, false);
100 bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
102 if (!WriteIC(std::make_pair(std::string("watchmeta"), dest), keyMeta)) {
103 return false;
105 return WriteIC(std::make_pair(std::string("watchs"), dest), '1');
108 bool CWalletDB::EraseWatchOnly(const CScript &dest)
110 if (!EraseIC(std::make_pair(std::string("watchmeta"), dest))) {
111 return false;
113 return EraseIC(std::make_pair(std::string("watchs"), 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::ReadPool(int64_t nPool, CKeyPool& keypool)
135 return batch.Read(std::make_pair(std::string("pool"), nPool), keypool);
138 bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
140 return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
143 bool CWalletDB::ErasePool(int64_t nPool)
145 return EraseIC(std::make_pair(std::string("pool"), nPool));
148 bool CWalletDB::WriteMinVersion(int nVersion)
150 return WriteIC(std::string("minversion"), nVersion);
153 bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
155 account.SetNull();
156 return batch.Read(std::make_pair(std::string("acc"), strAccount), account);
159 bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
161 return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
164 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
166 return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
169 CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
171 std::list<CAccountingEntry> entries;
172 ListAccountCreditDebit(strAccount, entries);
174 CAmount nCreditDebit = 0;
175 for (const CAccountingEntry& entry : entries)
176 nCreditDebit += entry.nCreditDebit;
178 return nCreditDebit;
181 void CWalletDB::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
183 bool fAllAccounts = (strAccount == "*");
185 Dbc* pcursor = batch.GetCursor();
186 if (!pcursor)
187 throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
188 bool setRange = true;
189 while (true)
191 // Read next record
192 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
193 if (setRange)
194 ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0)));
195 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
196 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange);
197 setRange = false;
198 if (ret == DB_NOTFOUND)
199 break;
200 else if (ret != 0)
202 pcursor->close();
203 throw std::runtime_error(std::string(__func__) + ": error scanning DB");
206 // Unserialize
207 std::string strType;
208 ssKey >> strType;
209 if (strType != "acentry")
210 break;
211 CAccountingEntry acentry;
212 ssKey >> acentry.strAccount;
213 if (!fAllAccounts && acentry.strAccount != strAccount)
214 break;
216 ssValue >> acentry;
217 ssKey >> acentry.nEntryNo;
218 entries.push_back(acentry);
221 pcursor->close();
224 class CWalletScanState {
225 public:
226 unsigned int nKeys;
227 unsigned int nCKeys;
228 unsigned int nWatchKeys;
229 unsigned int nKeyMeta;
230 bool fIsEncrypted;
231 bool fAnyUnordered;
232 int nFileVersion;
233 std::vector<uint256> vWalletUpgrade;
235 CWalletScanState() {
236 nKeys = nCKeys = nWatchKeys = nKeyMeta = 0;
237 fIsEncrypted = false;
238 fAnyUnordered = false;
239 nFileVersion = 0;
243 bool
244 ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
245 CWalletScanState &wss, std::string& strType, std::string& strErr)
247 try {
248 // Unserialize
249 // Taking advantage of the fact that pair serialization
250 // is just the two items serialized one after the other
251 ssKey >> strType;
252 if (strType == "name")
254 std::string strAddress;
255 ssKey >> strAddress;
256 ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
258 else if (strType == "purpose")
260 std::string strAddress;
261 ssKey >> strAddress;
262 ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
264 else if (strType == "tx")
266 uint256 hash;
267 ssKey >> hash;
268 CWalletTx wtx;
269 ssValue >> wtx;
270 CValidationState state;
271 if (!(CheckTransaction(*wtx.tx, state) && (wtx.GetHash() == hash) && state.IsValid()))
272 return false;
274 // Undo serialize changes in 31600
275 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
277 if (!ssValue.empty())
279 char fTmp;
280 char fUnused;
281 ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
282 strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
283 wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
284 wtx.fTimeReceivedIsTxTime = fTmp;
286 else
288 strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
289 wtx.fTimeReceivedIsTxTime = 0;
291 wss.vWalletUpgrade.push_back(hash);
294 if (wtx.nOrderPos == -1)
295 wss.fAnyUnordered = true;
297 pwallet->LoadToWallet(wtx);
299 else if (strType == "acentry")
301 std::string strAccount;
302 ssKey >> strAccount;
303 uint64_t nNumber;
304 ssKey >> nNumber;
305 if (nNumber > pwallet->nAccountingEntryNumber) {
306 pwallet->nAccountingEntryNumber = nNumber;
309 if (!wss.fAnyUnordered)
311 CAccountingEntry acentry;
312 ssValue >> acentry;
313 if (acentry.nOrderPos == -1)
314 wss.fAnyUnordered = true;
317 else if (strType == "watchs")
319 wss.nWatchKeys++;
320 CScript script;
321 ssKey >> script;
322 char fYes;
323 ssValue >> fYes;
324 if (fYes == '1')
325 pwallet->LoadWatchOnly(script);
327 else if (strType == "key" || strType == "wkey")
329 CPubKey vchPubKey;
330 ssKey >> vchPubKey;
331 if (!vchPubKey.IsValid())
333 strErr = "Error reading wallet database: CPubKey corrupt";
334 return false;
336 CKey key;
337 CPrivKey pkey;
338 uint256 hash;
340 if (strType == "key")
342 wss.nKeys++;
343 ssValue >> pkey;
344 } else {
345 CWalletKey wkey;
346 ssValue >> wkey;
347 pkey = wkey.vchPrivKey;
350 // Old wallets store keys as "key" [pubkey] => [privkey]
351 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
352 // using EC operations as a checksum.
353 // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
354 // remaining backwards-compatible.
357 ssValue >> hash;
359 catch (...) {}
361 bool fSkipCheck = false;
363 if (!hash.IsNull())
365 // hash pubkey/privkey to accelerate wallet load
366 std::vector<unsigned char> vchKey;
367 vchKey.reserve(vchPubKey.size() + pkey.size());
368 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
369 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
371 if (Hash(vchKey.begin(), vchKey.end()) != hash)
373 strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
374 return false;
377 fSkipCheck = true;
380 if (!key.Load(pkey, vchPubKey, fSkipCheck))
382 strErr = "Error reading wallet database: CPrivKey corrupt";
383 return false;
385 if (!pwallet->LoadKey(key, vchPubKey))
387 strErr = "Error reading wallet database: LoadKey failed";
388 return false;
391 else if (strType == "mkey")
393 unsigned int nID;
394 ssKey >> nID;
395 CMasterKey kMasterKey;
396 ssValue >> kMasterKey;
397 if(pwallet->mapMasterKeys.count(nID) != 0)
399 strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
400 return false;
402 pwallet->mapMasterKeys[nID] = kMasterKey;
403 if (pwallet->nMasterKeyMaxID < nID)
404 pwallet->nMasterKeyMaxID = nID;
406 else if (strType == "ckey")
408 CPubKey vchPubKey;
409 ssKey >> vchPubKey;
410 if (!vchPubKey.IsValid())
412 strErr = "Error reading wallet database: CPubKey corrupt";
413 return false;
415 std::vector<unsigned char> vchPrivKey;
416 ssValue >> vchPrivKey;
417 wss.nCKeys++;
419 if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
421 strErr = "Error reading wallet database: LoadCryptedKey failed";
422 return false;
424 wss.fIsEncrypted = true;
426 else if (strType == "keymeta")
428 CPubKey vchPubKey;
429 ssKey >> vchPubKey;
430 CKeyMetadata keyMeta;
431 ssValue >> keyMeta;
432 wss.nKeyMeta++;
433 pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
435 else if (strType == "watchmeta")
437 CScript script;
438 ssKey >> script;
439 CKeyMetadata keyMeta;
440 ssValue >> keyMeta;
441 wss.nKeyMeta++;
442 pwallet->LoadScriptMetadata(CScriptID(script), keyMeta);
444 else if (strType == "defaultkey")
446 // We don't want or need the default key, but if there is one set,
447 // we want to make sure that it is valid so that we can detect corruption
448 CPubKey vchPubKey;
449 ssValue >> vchPubKey;
450 if (!vchPubKey.IsValid()) {
451 strErr = "Error reading wallet database: Default Key corrupt";
452 return false;
455 else if (strType == "pool")
457 int64_t nIndex;
458 ssKey >> nIndex;
459 CKeyPool keypool;
460 ssValue >> keypool;
462 pwallet->LoadKeyPool(nIndex, keypool);
464 else if (strType == "version")
466 ssValue >> wss.nFileVersion;
467 if (wss.nFileVersion == 10300)
468 wss.nFileVersion = 300;
470 else if (strType == "cscript")
472 uint160 hash;
473 ssKey >> hash;
474 CScript script;
475 ssValue >> script;
476 if (!pwallet->LoadCScript(script))
478 strErr = "Error reading wallet database: LoadCScript failed";
479 return false;
482 else if (strType == "orderposnext")
484 ssValue >> pwallet->nOrderPosNext;
486 else if (strType == "destdata")
488 std::string strAddress, strKey, strValue;
489 ssKey >> strAddress;
490 ssKey >> strKey;
491 ssValue >> strValue;
492 if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
494 strErr = "Error reading wallet database: LoadDestData failed";
495 return false;
498 else if (strType == "hdchain")
500 CHDChain chain;
501 ssValue >> chain;
502 if (!pwallet->SetHDChain(chain, true))
504 strErr = "Error reading wallet database: SetHDChain failed";
505 return false;
508 } catch (...)
510 return false;
512 return true;
515 bool CWalletDB::IsKeyType(const std::string& strType)
517 return (strType== "key" || strType == "wkey" ||
518 strType == "mkey" || strType == "ckey");
521 DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
523 CWalletScanState wss;
524 bool fNoncriticalErrors = false;
525 DBErrors result = DB_LOAD_OK;
527 LOCK(pwallet->cs_wallet);
528 try {
529 int nMinVersion = 0;
530 if (batch.Read((std::string)"minversion", nMinVersion))
532 if (nMinVersion > CLIENT_VERSION)
533 return DB_TOO_NEW;
534 pwallet->LoadMinVersion(nMinVersion);
537 // Get cursor
538 Dbc* pcursor = batch.GetCursor();
539 if (!pcursor)
541 LogPrintf("Error getting wallet database cursor\n");
542 return DB_CORRUPT;
545 while (true)
547 // Read next record
548 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
549 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
550 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
551 if (ret == DB_NOTFOUND)
552 break;
553 else if (ret != 0)
555 LogPrintf("Error reading next record from wallet database\n");
556 return DB_CORRUPT;
559 // Try to be tolerant of single corrupt records:
560 std::string strType, strErr;
561 if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
563 // losing keys is considered a catastrophic error, anything else
564 // we assume the user can live with:
565 if (IsKeyType(strType) || strType == "defaultkey")
566 result = DB_CORRUPT;
567 else
569 // Leave other errors alone, if we try to fix them we might make things worse.
570 fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
571 if (strType == "tx")
572 // Rescan if there is a bad transaction record:
573 gArgs.SoftSetBoolArg("-rescan", true);
576 if (!strErr.empty())
577 LogPrintf("%s\n", strErr);
579 pcursor->close();
581 catch (const boost::thread_interrupted&) {
582 throw;
584 catch (...) {
585 result = DB_CORRUPT;
588 if (fNoncriticalErrors && result == DB_LOAD_OK)
589 result = DB_NONCRITICAL_ERROR;
591 // Any wallet corruption at all: skip any rewriting or
592 // upgrading, we don't want to make it worse.
593 if (result != DB_LOAD_OK)
594 return result;
596 LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
598 LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
599 wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
601 // nTimeFirstKey is only reliable if all keys have metadata
602 if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
603 pwallet->UpdateTimeFirstKey(1);
605 for (uint256 hash : wss.vWalletUpgrade)
606 WriteTx(pwallet->mapWallet[hash]);
608 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
609 if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
610 return DB_NEED_REWRITE;
612 if (wss.nFileVersion < CLIENT_VERSION) // Update
613 WriteVersion(CLIENT_VERSION);
615 if (wss.fAnyUnordered)
616 result = pwallet->ReorderTransactions();
618 pwallet->laccentries.clear();
619 ListAccountCreditDebit("*", pwallet->laccentries);
620 for (CAccountingEntry& entry : pwallet->laccentries) {
621 pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair(nullptr, &entry)));
624 return result;
627 DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
629 DBErrors result = DB_LOAD_OK;
631 try {
632 int nMinVersion = 0;
633 if (batch.Read((std::string)"minversion", nMinVersion))
635 if (nMinVersion > CLIENT_VERSION)
636 return DB_TOO_NEW;
639 // Get cursor
640 Dbc* pcursor = batch.GetCursor();
641 if (!pcursor)
643 LogPrintf("Error getting wallet database cursor\n");
644 return DB_CORRUPT;
647 while (true)
649 // Read next record
650 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
651 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
652 int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue);
653 if (ret == DB_NOTFOUND)
654 break;
655 else if (ret != 0)
657 LogPrintf("Error reading next record from wallet database\n");
658 return DB_CORRUPT;
661 std::string strType;
662 ssKey >> strType;
663 if (strType == "tx") {
664 uint256 hash;
665 ssKey >> hash;
667 CWalletTx wtx;
668 ssValue >> wtx;
670 vTxHash.push_back(hash);
671 vWtx.push_back(wtx);
674 pcursor->close();
676 catch (const boost::thread_interrupted&) {
677 throw;
679 catch (...) {
680 result = DB_CORRUPT;
683 return result;
686 DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
688 // build list of wallet TXs and hashes
689 std::vector<uint256> vTxHash;
690 std::vector<CWalletTx> vWtx;
691 DBErrors err = FindWalletTx(vTxHash, vWtx);
692 if (err != DB_LOAD_OK) {
693 return err;
696 std::sort(vTxHash.begin(), vTxHash.end());
697 std::sort(vTxHashIn.begin(), vTxHashIn.end());
699 // erase each matching wallet TX
700 bool delerror = false;
701 std::vector<uint256>::iterator it = vTxHashIn.begin();
702 for (uint256 hash : vTxHash) {
703 while (it < vTxHashIn.end() && (*it) < hash) {
704 it++;
706 if (it == vTxHashIn.end()) {
707 break;
709 else if ((*it) == hash) {
710 if(!EraseTx(hash)) {
711 LogPrint(BCLog::DB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
712 delerror = true;
714 vTxHashOut.push_back(hash);
718 if (delerror) {
719 return DB_CORRUPT;
721 return DB_LOAD_OK;
724 DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
726 // build list of wallet TXs
727 std::vector<uint256> vTxHash;
728 DBErrors err = FindWalletTx(vTxHash, vWtx);
729 if (err != DB_LOAD_OK)
730 return err;
732 // erase each wallet TX
733 for (uint256& hash : vTxHash) {
734 if (!EraseTx(hash))
735 return DB_CORRUPT;
738 return DB_LOAD_OK;
741 void MaybeCompactWalletDB()
743 static std::atomic<bool> fOneThread(false);
744 if (fOneThread.exchange(true)) {
745 return;
747 if (!gArgs.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
748 return;
751 for (CWalletRef pwallet : vpwallets) {
752 CWalletDBWrapper& dbh = pwallet->GetDBHandle();
754 unsigned int nUpdateCounter = dbh.nUpdateCounter;
756 if (dbh.nLastSeen != nUpdateCounter) {
757 dbh.nLastSeen = nUpdateCounter;
758 dbh.nLastWalletUpdate = GetTime();
761 if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
762 if (CDB::PeriodicFlush(dbh)) {
763 dbh.nLastFlushed = nUpdateCounter;
768 fOneThread = false;
772 // Try to (very carefully!) recover wallet file if there is a problem.
774 bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
776 return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename);
779 bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename)
781 // recover without a key filter callback
782 // results in recovering all record types
783 return CWalletDB::Recover(filename, nullptr, nullptr, out_backup_filename);
786 bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
788 CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
789 CWalletScanState dummyWss;
790 std::string strType, strErr;
791 bool fReadOK;
793 // Required in LoadKeyMetadata():
794 LOCK(dummyWallet->cs_wallet);
795 fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
796 dummyWss, strType, strErr);
798 if (!IsKeyType(strType) && strType != "hdchain")
799 return false;
800 if (!fReadOK)
802 LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
803 return false;
806 return true;
809 bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr)
811 return CDB::VerifyEnvironment(walletFile, walletDir, errorStr);
814 bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr)
816 return CDB::VerifyDatabaseFile(walletFile, walletDir, warningStr, errorStr, CWalletDB::Recover);
819 bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
821 return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
824 bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
826 return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
830 bool CWalletDB::WriteHDChain(const CHDChain& chain)
832 return WriteIC(std::string("hdchain"), chain);
835 bool CWalletDB::TxnBegin()
837 return batch.TxnBegin();
840 bool CWalletDB::TxnCommit()
842 return batch.TxnCommit();
845 bool CWalletDB::TxnAbort()
847 return batch.TxnAbort();
850 bool CWalletDB::ReadVersion(int& nVersion)
852 return batch.ReadVersion(nVersion);
855 bool CWalletDB::WriteVersion(int nVersion)
857 return batch.WriteVersion(nVersion);