Bitcoin Core  0.18.99
P2P Digital Currency
walletdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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.
5 
6 #include <wallet/walletdb.h>
7 
8 #include <consensus/tx_check.h>
9 #include <consensus/validation.h>
10 #include <fs.h>
11 #include <key_io.h>
12 #include <protocol.h>
13 #include <serialize.h>
14 #include <sync.h>
15 #include <util/system.h>
16 #include <util/time.h>
17 #include <wallet/wallet.h>
18 
19 #include <atomic>
20 #include <string>
21 
22 #include <boost/thread.hpp>
23 
24 //
25 // WalletBatch
26 //
27 
28 bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName)
29 {
30  return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
31 }
32 
33 bool WalletBatch::EraseName(const std::string& strAddress)
34 {
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));
38 }
39 
40 bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
41 {
42  return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
43 }
44 
45 bool WalletBatch::ErasePurpose(const std::string& strAddress)
46 {
47  return EraseIC(std::make_pair(std::string("purpose"), strAddress));
48 }
49 
51 {
52  return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
53 }
54 
56 {
57  return EraseIC(std::make_pair(std::string("tx"), hash));
58 }
59 
60 bool WalletBatch::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite)
61 {
62  return WriteIC(std::make_pair(std::string("keymeta"), pubkey), meta, overwrite);
63 }
64 
65 bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
66 {
67  if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {
68  return false;
69  }
70 
71  // hash pubkey/privkey to accelerate wallet load
72  std::vector<unsigned char> vchKey;
73  vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
74  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
75  vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
76 
77  return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
78 }
79 
80 bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,
81  const std::vector<unsigned char>& vchCryptedSecret,
82  const CKeyMetadata &keyMeta)
83 {
84  if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {
85  return false;
86  }
87 
88  if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) {
89  return false;
90  }
91  EraseIC(std::make_pair(std::string("key"), vchPubKey));
92  EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
93  return true;
94 }
95 
96 bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
97 {
98  return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
99 }
100 
101 bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
102 {
103  return WriteIC(std::make_pair(std::string("cscript"), hash), redeemScript, false);
104 }
105 
106 bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
107 {
108  if (!WriteIC(std::make_pair(std::string("watchmeta"), dest), keyMeta)) {
109  return false;
110  }
111  return WriteIC(std::make_pair(std::string("watchs"), dest), '1');
112 }
113 
115 {
116  if (!EraseIC(std::make_pair(std::string("watchmeta"), dest))) {
117  return false;
118  }
119  return EraseIC(std::make_pair(std::string("watchs"), dest));
120 }
121 
123 {
124  WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
125  return WriteIC(std::string("bestblock_nomerkle"), locator);
126 }
127 
129 {
130  if (m_batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true;
131  return m_batch.Read(std::string("bestblock_nomerkle"), locator);
132 }
133 
134 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
135 {
136  return WriteIC(std::string("orderposnext"), nOrderPosNext);
137 }
138 
139 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool)
140 {
141  return m_batch.Read(std::make_pair(std::string("pool"), nPool), keypool);
142 }
143 
144 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool)
145 {
146  return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
147 }
148 
149 bool WalletBatch::ErasePool(int64_t nPool)
150 {
151  return EraseIC(std::make_pair(std::string("pool"), nPool));
152 }
153 
155 {
156  return WriteIC(std::string("minversion"), nVersion);
157 }
158 
160 public:
161  unsigned int nKeys{0};
162  unsigned int nCKeys{0};
163  unsigned int nWatchKeys{0};
164  unsigned int nKeyMeta{0};
165  unsigned int m_unknown_records{0};
166  bool fIsEncrypted{false};
167  bool fAnyUnordered{false};
168  int nFileVersion{0};
169  std::vector<uint256> vWalletUpgrade;
170 
172  }
173 };
174 
175 static bool
176 ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
177  CWalletScanState &wss, std::string& strType, std::string& strErr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
178 {
179  try {
180  // Unserialize
181  // Taking advantage of the fact that pair serialization
182  // is just the two items serialized one after the other
183  ssKey >> strType;
184  if (strType == "name")
185  {
186  std::string strAddress;
187  ssKey >> strAddress;
188  ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
189  }
190  else if (strType == "purpose")
191  {
192  std::string strAddress;
193  ssKey >> strAddress;
194  ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
195  }
196  else if (strType == "tx")
197  {
198  uint256 hash;
199  ssKey >> hash;
200  CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
201  ssValue >> wtx;
202  CValidationState state;
203  if (!(CheckTransaction(*wtx.tx, state) && (wtx.GetHash() == hash) && state.IsValid()))
204  return false;
205 
206  // Undo serialize changes in 31600
207  if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
208  {
209  if (!ssValue.empty())
210  {
211  char fTmp;
212  char fUnused;
213  std::string unused_string;
214  ssValue >> fTmp >> fUnused >> unused_string;
215  strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
216  wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
217  wtx.fTimeReceivedIsTxTime = fTmp;
218  }
219  else
220  {
221  strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
222  wtx.fTimeReceivedIsTxTime = 0;
223  }
224  wss.vWalletUpgrade.push_back(hash);
225  }
226 
227  if (wtx.nOrderPos == -1)
228  wss.fAnyUnordered = true;
229 
230  pwallet->LoadToWallet(wtx);
231  }
232  else if (strType == "watchs")
233  {
234  wss.nWatchKeys++;
235  CScript script;
236  ssKey >> script;
237  char fYes;
238  ssValue >> fYes;
239  if (fYes == '1')
240  pwallet->LoadWatchOnly(script);
241  }
242  else if (strType == "key" || strType == "wkey")
243  {
244  CPubKey vchPubKey;
245  ssKey >> vchPubKey;
246  if (!vchPubKey.IsValid())
247  {
248  strErr = "Error reading wallet database: CPubKey corrupt";
249  return false;
250  }
251  CKey key;
252  CPrivKey pkey;
253  uint256 hash;
254 
255  if (strType == "key")
256  {
257  wss.nKeys++;
258  ssValue >> pkey;
259  } else {
260  CWalletKey wkey;
261  ssValue >> wkey;
262  pkey = wkey.vchPrivKey;
263  }
264 
265  // Old wallets store keys as "key" [pubkey] => [privkey]
266  // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
267  // using EC operations as a checksum.
268  // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
269  // remaining backwards-compatible.
270  try
271  {
272  ssValue >> hash;
273  }
274  catch (...) {}
275 
276  bool fSkipCheck = false;
277 
278  if (!hash.IsNull())
279  {
280  // hash pubkey/privkey to accelerate wallet load
281  std::vector<unsigned char> vchKey;
282  vchKey.reserve(vchPubKey.size() + pkey.size());
283  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
284  vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
285 
286  if (Hash(vchKey.begin(), vchKey.end()) != hash)
287  {
288  strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
289  return false;
290  }
291 
292  fSkipCheck = true;
293  }
294 
295  if (!key.Load(pkey, vchPubKey, fSkipCheck))
296  {
297  strErr = "Error reading wallet database: CPrivKey corrupt";
298  return false;
299  }
300  if (!pwallet->LoadKey(key, vchPubKey))
301  {
302  strErr = "Error reading wallet database: LoadKey failed";
303  return false;
304  }
305  }
306  else if (strType == "mkey")
307  {
308  unsigned int nID;
309  ssKey >> nID;
310  CMasterKey kMasterKey;
311  ssValue >> kMasterKey;
312  if(pwallet->mapMasterKeys.count(nID) != 0)
313  {
314  strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
315  return false;
316  }
317  pwallet->mapMasterKeys[nID] = kMasterKey;
318  if (pwallet->nMasterKeyMaxID < nID)
319  pwallet->nMasterKeyMaxID = nID;
320  }
321  else if (strType == "ckey")
322  {
323  CPubKey vchPubKey;
324  ssKey >> vchPubKey;
325  if (!vchPubKey.IsValid())
326  {
327  strErr = "Error reading wallet database: CPubKey corrupt";
328  return false;
329  }
330  std::vector<unsigned char> vchPrivKey;
331  ssValue >> vchPrivKey;
332  wss.nCKeys++;
333 
334  if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
335  {
336  strErr = "Error reading wallet database: LoadCryptedKey failed";
337  return false;
338  }
339  wss.fIsEncrypted = true;
340  }
341  else if (strType == "keymeta")
342  {
343  CPubKey vchPubKey;
344  ssKey >> vchPubKey;
345  CKeyMetadata keyMeta;
346  ssValue >> keyMeta;
347  wss.nKeyMeta++;
348  pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
349  }
350  else if (strType == "watchmeta")
351  {
352  CScript script;
353  ssKey >> script;
354  CKeyMetadata keyMeta;
355  ssValue >> keyMeta;
356  wss.nKeyMeta++;
357  pwallet->LoadScriptMetadata(CScriptID(script), keyMeta);
358  }
359  else if (strType == "defaultkey")
360  {
361  // We don't want or need the default key, but if there is one set,
362  // we want to make sure that it is valid so that we can detect corruption
363  CPubKey vchPubKey;
364  ssValue >> vchPubKey;
365  if (!vchPubKey.IsValid()) {
366  strErr = "Error reading wallet database: Default Key corrupt";
367  return false;
368  }
369  }
370  else if (strType == "pool")
371  {
372  int64_t nIndex;
373  ssKey >> nIndex;
374  CKeyPool keypool;
375  ssValue >> keypool;
376 
377  pwallet->LoadKeyPool(nIndex, keypool);
378  }
379  else if (strType == "version")
380  {
381  ssValue >> wss.nFileVersion;
382  if (wss.nFileVersion == 10300)
383  wss.nFileVersion = 300;
384  }
385  else if (strType == "cscript")
386  {
387  uint160 hash;
388  ssKey >> hash;
389  CScript script;
390  ssValue >> script;
391  if (!pwallet->LoadCScript(script))
392  {
393  strErr = "Error reading wallet database: LoadCScript failed";
394  return false;
395  }
396  }
397  else if (strType == "orderposnext")
398  {
399  ssValue >> pwallet->nOrderPosNext;
400  }
401  else if (strType == "destdata")
402  {
403  std::string strAddress, strKey, strValue;
404  ssKey >> strAddress;
405  ssKey >> strKey;
406  ssValue >> strValue;
407  pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue);
408  }
409  else if (strType == "hdchain")
410  {
411  CHDChain chain;
412  ssValue >> chain;
413  pwallet->SetHDChain(chain, true);
414  } else if (strType == "flags") {
415  uint64_t flags;
416  ssValue >> flags;
417  if (!pwallet->SetWalletFlags(flags, true)) {
418  strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found";
419  return false;
420  }
421  } else if (strType != "bestblock" && strType != "bestblock_nomerkle" &&
422  strType != "minversion" && strType != "acentry") {
423  wss.m_unknown_records++;
424  }
425  } catch (const std::exception& e) {
426  if (strErr.empty()) {
427  strErr = e.what();
428  }
429  return false;
430  } catch (...) {
431  if (strErr.empty()) {
432  strErr = "Caught unknown exception in ReadKeyValue";
433  }
434  return false;
435  }
436  return true;
437 }
438 
439 bool WalletBatch::IsKeyType(const std::string& strType)
440 {
441  return (strType== "key" || strType == "wkey" ||
442  strType == "mkey" || strType == "ckey");
443 }
444 
446 {
447  CWalletScanState wss;
448  bool fNoncriticalErrors = false;
449  DBErrors result = DBErrors::LOAD_OK;
450 
451  LOCK(pwallet->cs_wallet);
452  try {
453  int nMinVersion = 0;
454  if (m_batch.Read((std::string)"minversion", nMinVersion))
455  {
456  if (nMinVersion > FEATURE_LATEST)
457  return DBErrors::TOO_NEW;
458  pwallet->LoadMinVersion(nMinVersion);
459  }
460 
461  // Get cursor
462  Dbc* pcursor = m_batch.GetCursor();
463  if (!pcursor)
464  {
465  pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
466  return DBErrors::CORRUPT;
467  }
468 
469  while (true)
470  {
471  // Read next record
472  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
473  CDataStream ssValue(SER_DISK, CLIENT_VERSION);
474  int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
475  if (ret == DB_NOTFOUND)
476  break;
477  else if (ret != 0)
478  {
479  pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
480  return DBErrors::CORRUPT;
481  }
482 
483  // Try to be tolerant of single corrupt records:
484  std::string strType, strErr;
485  if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
486  {
487  // losing keys is considered a catastrophic error, anything else
488  // we assume the user can live with:
489  if (IsKeyType(strType) || strType == "defaultkey") {
490  result = DBErrors::CORRUPT;
491  } else if(strType == "flags") {
492  // reading the wallet flags can only fail if unknown flags are present
493  result = DBErrors::TOO_NEW;
494  } else {
495  // Leave other errors alone, if we try to fix them we might make things worse.
496  fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
497  if (strType == "tx")
498  // Rescan if there is a bad transaction record:
499  gArgs.SoftSetBoolArg("-rescan", true);
500  }
501  }
502  if (!strErr.empty())
503  pwallet->WalletLogPrintf("%s\n", strErr);
504  }
505  pcursor->close();
506  }
507  catch (const boost::thread_interrupted&) {
508  throw;
509  }
510  catch (...) {
511  result = DBErrors::CORRUPT;
512  }
513 
514  if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
516 
517  // Any wallet corruption at all: skip any rewriting or
518  // upgrading, we don't want to make it worse.
519  if (result != DBErrors::LOAD_OK)
520  return result;
521 
522  pwallet->WalletLogPrintf("nFileVersion = %d\n", wss.nFileVersion);
523 
524  pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
525  wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys, wss.m_unknown_records);
526 
527  // nTimeFirstKey is only reliable if all keys have metadata
528  if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
529  pwallet->UpdateTimeFirstKey(1);
530 
531  for (const uint256& hash : wss.vWalletUpgrade)
532  WriteTx(pwallet->mapWallet.at(hash));
533 
534  // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
535  if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
536  return DBErrors::NEED_REWRITE;
537 
538  if (wss.nFileVersion < CLIENT_VERSION) // Update
539  WriteVersion(CLIENT_VERSION);
540 
541  if (wss.fAnyUnordered)
542  result = pwallet->ReorderTransactions();
543 
544  // Upgrade all of the wallet keymetadata to have the hd master key id
545  // This operation is not atomic, but if it fails, updated entries are still backwards compatible with older software
546  try {
547  pwallet->UpgradeKeyMetadata();
548  } catch (...) {
549  result = DBErrors::CORRUPT;
550  }
551 
552  return result;
553 }
554 
555 DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
556 {
557  DBErrors result = DBErrors::LOAD_OK;
558 
559  try {
560  int nMinVersion = 0;
561  if (m_batch.Read((std::string)"minversion", nMinVersion))
562  {
563  if (nMinVersion > FEATURE_LATEST)
564  return DBErrors::TOO_NEW;
565  }
566 
567  // Get cursor
568  Dbc* pcursor = m_batch.GetCursor();
569  if (!pcursor)
570  {
571  LogPrintf("Error getting wallet database cursor\n");
572  return DBErrors::CORRUPT;
573  }
574 
575  while (true)
576  {
577  // Read next record
578  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
579  CDataStream ssValue(SER_DISK, CLIENT_VERSION);
580  int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
581  if (ret == DB_NOTFOUND)
582  break;
583  else if (ret != 0)
584  {
585  LogPrintf("Error reading next record from wallet database\n");
586  return DBErrors::CORRUPT;
587  }
588 
589  std::string strType;
590  ssKey >> strType;
591  if (strType == "tx") {
592  uint256 hash;
593  ssKey >> hash;
594 
595  CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
596  ssValue >> wtx;
597 
598  vTxHash.push_back(hash);
599  vWtx.push_back(wtx);
600  }
601  }
602  pcursor->close();
603  }
604  catch (const boost::thread_interrupted&) {
605  throw;
606  }
607  catch (...) {
608  result = DBErrors::CORRUPT;
609  }
610 
611  return result;
612 }
613 
614 DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
615 {
616  // build list of wallet TXs and hashes
617  std::vector<uint256> vTxHash;
618  std::vector<CWalletTx> vWtx;
619  DBErrors err = FindWalletTx(vTxHash, vWtx);
620  if (err != DBErrors::LOAD_OK) {
621  return err;
622  }
623 
624  std::sort(vTxHash.begin(), vTxHash.end());
625  std::sort(vTxHashIn.begin(), vTxHashIn.end());
626 
627  // erase each matching wallet TX
628  bool delerror = false;
629  std::vector<uint256>::iterator it = vTxHashIn.begin();
630  for (const uint256& hash : vTxHash) {
631  while (it < vTxHashIn.end() && (*it) < hash) {
632  it++;
633  }
634  if (it == vTxHashIn.end()) {
635  break;
636  }
637  else if ((*it) == hash) {
638  if(!EraseTx(hash)) {
639  LogPrint(BCLog::DB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
640  delerror = true;
641  }
642  vTxHashOut.push_back(hash);
643  }
644  }
645 
646  if (delerror) {
647  return DBErrors::CORRUPT;
648  }
649  return DBErrors::LOAD_OK;
650 }
651 
652 DBErrors WalletBatch::ZapWalletTx(std::vector<CWalletTx>& vWtx)
653 {
654  // build list of wallet TXs
655  std::vector<uint256> vTxHash;
656  DBErrors err = FindWalletTx(vTxHash, vWtx);
657  if (err != DBErrors::LOAD_OK)
658  return err;
659 
660  // erase each wallet TX
661  for (const uint256& hash : vTxHash) {
662  if (!EraseTx(hash))
663  return DBErrors::CORRUPT;
664  }
665 
666  return DBErrors::LOAD_OK;
667 }
668 
670 {
671  static std::atomic<bool> fOneThread(false);
672  if (fOneThread.exchange(true)) {
673  return;
674  }
675  if (!gArgs.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
676  return;
677  }
678 
679  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
680  WalletDatabase& dbh = pwallet->GetDBHandle();
681 
682  unsigned int nUpdateCounter = dbh.nUpdateCounter;
683 
684  if (dbh.nLastSeen != nUpdateCounter) {
685  dbh.nLastSeen = nUpdateCounter;
686  dbh.nLastWalletUpdate = GetTime();
687  }
688 
689  if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
690  if (BerkeleyBatch::PeriodicFlush(dbh)) {
691  dbh.nLastFlushed = nUpdateCounter;
692  }
693  }
694  }
695 
696  fOneThread = false;
697 }
698 
699 //
700 // Try to (very carefully!) recover wallet file if there is a problem.
701 //
702 bool WalletBatch::Recover(const fs::path& wallet_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
703 {
704  return BerkeleyBatch::Recover(wallet_path, callbackDataIn, recoverKVcallback, out_backup_filename);
705 }
706 
707 bool WalletBatch::Recover(const fs::path& wallet_path, std::string& out_backup_filename)
708 {
709  // recover without a key filter callback
710  // results in recovering all record types
711  return WalletBatch::Recover(wallet_path, nullptr, nullptr, out_backup_filename);
712 }
713 
714 bool WalletBatch::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
715 {
716  CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
717  CWalletScanState dummyWss;
718  std::string strType, strErr;
719  bool fReadOK;
720  {
721  // Required in LoadKeyMetadata():
722  LOCK(dummyWallet->cs_wallet);
723  fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
724  dummyWss, strType, strErr);
725  }
726  if (!IsKeyType(strType) && strType != "hdchain")
727  return false;
728  if (!fReadOK)
729  {
730  LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr);
731  return false;
732  }
733 
734  return true;
735 }
736 
737 bool WalletBatch::VerifyEnvironment(const fs::path& wallet_path, std::string& errorStr)
738 {
739  return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr);
740 }
741 
742 bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr)
743 {
744  return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, WalletBatch::Recover);
745 }
746 
747 bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
748 {
749  return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
750 }
751 
752 bool WalletBatch::EraseDestData(const std::string &address, const std::string &key)
753 {
754  return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
755 }
756 
757 
759 {
760  return WriteIC(std::string("hdchain"), chain);
761 }
762 
764 {
765  return WriteIC(std::string("flags"), flags);
766 }
767 
769 {
770  return m_batch.TxnBegin();
771 }
772 
774 {
775  return m_batch.TxnCommit();
776 }
777 
779 {
780  return m_batch.TxnAbort();
781 }
782 
783 bool WalletBatch::ReadVersion(int& nVersion)
784 {
785  return m_batch.ReadVersion(nVersion);
786 }
787 
788 bool WalletBatch::WriteVersion(int nVersion)
789 {
790  return m_batch.WriteVersion(nVersion);
791 }
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:773
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition: walletdb.cpp:28
bool EraseIC(const K &key)
Definition: walletdb.h:169
bool WriteVersion(int nVersion)
Write wallet version.
Definition: walletdb.cpp:788
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
Definition: walletdb.cpp:752
unsigned int nKeyMeta
Definition: walletdb.cpp:164
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3337
unsigned int nKeys
Definition: walletdb.cpp:161
bool ErasePurpose(const std::string &strAddress)
Definition: walletdb.cpp:45
unsigned int nWatchKeys
Definition: walletdb.cpp:163
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:128
CPrivKey vchPrivKey
Definition: wallet.h:652
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: dummywallet.cpp:67
Describes a place in the block chain to another node such that if the other node doesn&#39;t have the sam...
Definition: block.h:126
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition: wallet.cpp:360
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:80
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: system.cpp:526
bool TxnCommit()
Definition: db.h:384
void SetHDChain(const CHDChain &chain, bool memonly)
Definition: wallet.cpp:1500
unsigned int nLastSeen
Definition: db.h:173
CCriticalSection cs_wallet
Definition: wallet.h:823
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1067
const uint256 & GetHash() const
Definition: wallet.h:409
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
Definition: walletdb.h:156
DBErrors FindWalletTx(std::vector< uint256 > &vTxHash, std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:555
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
Definition: walletdb.cpp:614
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:154
bool TxnBegin()
Definition: db.h:373
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Definition: walletdb.cpp:758
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
Definition: crypter.h:34
bool IsValid() const
Definition: validation.h:129
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition: walletdb.cpp:106
void LoadToWallet(const CWalletTx &wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1019
std::vector< uint256 > vWalletUpgrade
Definition: walletdb.cpp:169
static bool VerifyDatabaseFile(const fs::path &wallet_path, std::string &warningStr, std::string &errorStr)
Definition: walletdb.cpp:742
An instance of this class represents one database.
Definition: db.h:113
unsigned int m_unknown_records
Definition: walletdb.cpp:165
Dbc * GetCursor()
Definition: db.h:341
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:768
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:203
bool empty() const
Definition: streams.h:295
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:510
void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a destination data tuple to the store, without saving it to disk.
Definition: wallet.cpp:3917
DBErrors ZapWalletTx(std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:652
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:50
unsigned int nCKeys
Definition: walletdb.cpp:162
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:445
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:48
static bool PeriodicFlush(BerkeleyDatabase &database)
Definition: db.cpp:806
bool WriteWalletFlags(const uint64_t flags)
Definition: walletdb.cpp:763
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue)
Definition: db.h:352
bool IsNull() const
Definition: uint256.h:31
const unsigned char * begin() const
Definition: pubkey.h:111
static bool Recover(const fs::path &wallet_path, void *callbackDataIn, bool(*recoverKVcallback)(void *callbackData, CDataStream ssKey, CDataStream ssValue), std::string &out_backup_filename)
Definition: walletdb.cpp:702
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) ...
Definition: wallet.cpp:397
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:114
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:122
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
secure_allocator is defined in allocators.h CPrivKey is a serialized private key, with all parameters...
Definition: key.h:24
bool TxnAbort()
Abort current transaction.
Definition: walletdb.cpp:778
bool TxnAbort()
Definition: db.h:393
DBErrors ReorderTransactions()
Definition: wallet.cpp:828
bool Read(const K &key, T &value)
Definition: db.h:252
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
Definition: walletdb.cpp:747
unsigned int nMasterKeyMaxID
Definition: wallet.h:858
static bool IsKeyType(const std::string &strType)
Definition: walletdb.cpp:439
const unsigned char * end() const
Definition: pubkey.h:112
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:101
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:1305
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Update wallet first key creation time.
Definition: wallet.cpp:406
static bool VerifyEnvironment(const fs::path &wallet_path, std::string &errorStr)
Definition: walletdb.cpp:737
#define LOCK(cs)
Definition: sync.h:182
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Load metadata (used by LoadWallet)
Definition: wallet.cpp:346
An encapsulated public key.
Definition: pubkey.h:30
bool WriteVersion(int nVersion)
Definition: db.h:408
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:96
WalletDatabase & GetDBHandle()
Get database handle used by this wallet.
Definition: wallet.h:828
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
Definition: wallet.h:952
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:669
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:71
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:134
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:109
std::vector< uint256 > vHave
Definition: block.h:128
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly)
overwrite all flags by the given uint64_t returns false if unknown, non-tolerable flags are present ...
Definition: wallet.cpp:1565
static bool VerifyEnvironment(const fs::path &file_path, std::string &errorStr)
Definition: db.cpp:397
static bool Recover(const fs::path &file_path, void *callbackDataIn, bool(*recoverKVcallback)(void *callbackData, CDataStream ssKey, CDataStream ssValue), std::string &out_backup_filename)
Definition: db.cpp:328
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:421
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
Definition: walletdb.cpp:60
int flags
Definition: bitcoin-tx.cpp:507
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:149
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:144
Capture information about block/transaction validation.
Definition: validation.h:98
256-bit opaque blob.
Definition: uint256.h:121
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:216
BerkeleyBatch m_batch
Definition: walletdb.h:257
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
int64_t nLastWalletUpdate
Definition: db.h:175
MasterKeyMap mapMasterKeys
Definition: wallet.h:857
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:390
unsigned int nLastFlushed
Definition: db.h:174
Private key that includes an expiration date in case it never gets used.
Definition: wallet.h:649
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:692
ArgsManager gArgs
Definition: system.cpp:72
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition: walletdb.cpp:40
160-bit opaque blob.
Definition: uint256.h:110
bool LoadCScript(const CScript &redeemScript)
Definition: wallet.cpp:435
std::atomic< unsigned int > nUpdateCounter
Definition: db.h:172
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:139
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
bool ReadVersion(int &nVersion)
Definition: db.h:402
bool ReadVersion(int &nVersion)
Read wallet version.
Definition: walletdb.cpp:783
static bool VerifyDatabaseFile(const fs::path &file_path, std::string &warningStr, std::string &errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
Definition: db.cpp:414
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.h:959
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:65
An encapsulated private key.
Definition: key.h:27
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:353
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:55
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:20
static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
Definition: walletdb.cpp:714
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
Definition: wallet.cpp:495
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:261
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fCheckDuplicateInputs)
Definition: tx_check.cpp:10
A key from a CWallet&#39;s keypool.
Definition: wallet.h:188
bool EraseName(const std::string &strAddress)
Definition: walletdb.cpp:33