Dash Core  0.12.2.1
P2P Digital Currency
walletdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Copyright (c) 2014-2017 The Dash Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "wallet/walletdb.h"
8 
9 #include "base58.h"
10 #include "consensus/validation.h"
11 #include "validation.h" // For CheckTransaction
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"
18 
19 #include <boost/filesystem.hpp>
20 #include <boost/foreach.hpp>
21 #include <boost/scoped_ptr.hpp>
22 #include <boost/thread.hpp>
23 
24 using namespace std;
25 
26 static uint64_t nAccountingEntryNumber = 0;
27 
28 //
29 // CWalletDB
30 //
31 
32 bool CWalletDB::WriteName(const string& strAddress, const string& strName)
33 {
35  return Write(make_pair(string("name"), strAddress), strName);
36 }
37 
38 bool CWalletDB::EraseName(const string& strAddress)
39 {
40  // This should only be used for sending addresses, never for receiving addresses,
41  // receiving addresses must always have an address book entry if they're not change return.
43  return Erase(make_pair(string("name"), strAddress));
44 }
45 
46 bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
47 {
49  return Write(make_pair(string("purpose"), strAddress), strPurpose);
50 }
51 
52 bool CWalletDB::ErasePurpose(const string& strPurpose)
53 {
55  return Erase(make_pair(string("purpose"), strPurpose));
56 }
57 
58 bool CWalletDB::WriteTx(uint256 hash, const CWalletTx& wtx)
59 {
61  return Write(std::make_pair(std::string("tx"), hash), wtx);
62 }
63 
65 {
67  return Erase(std::make_pair(std::string("tx"), hash));
68 }
69 
70 bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
71 {
73 
74  if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
75  keyMeta, false))
76  return false;
77 
78  // hash pubkey/privkey to accelerate wallet load
79  std::vector<unsigned char> vchKey;
80  vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
81  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
82  vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
83 
84  return Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
85 }
86 
87 bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
88  const std::vector<unsigned char>& vchCryptedSecret,
89  const CKeyMetadata &keyMeta)
90 {
91  const bool fEraseUnencryptedKey = true;
93 
94  if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
95  keyMeta))
96  return false;
97 
98  if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
99  return false;
100  if (fEraseUnencryptedKey)
101  {
102  Erase(std::make_pair(std::string("key"), vchPubKey));
103  Erase(std::make_pair(std::string("wkey"), vchPubKey));
104  }
105  return true;
106 }
107 
108 bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
109 {
111  return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
112 }
113 
114 bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
115 {
117  return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
118 }
119 
121 {
123  return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
124 }
125 
127 {
129  return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
130 }
131 
133 {
135  Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
136  return Write(std::string("bestblock_nomerkle"), locator);
137 }
138 
140 {
141  if (Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true;
142  return Read(std::string("bestblock_nomerkle"), locator);
143 }
144 
145 bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
146 {
148  return Write(std::string("orderposnext"), nOrderPosNext);
149 }
150 
151 bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
152 {
154  return Write(std::string("defaultkey"), vchPubKey);
155 }
156 
157 bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
158 {
159  return Read(std::make_pair(std::string("pool"), nPool), keypool);
160 }
161 
162 bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
163 {
165  return Write(std::make_pair(std::string("pool"), nPool), keypool);
166 }
167 
168 bool CWalletDB::ErasePool(int64_t nPool)
169 {
171  return Erase(std::make_pair(std::string("pool"), nPool));
172 }
173 
174 bool CWalletDB::WriteMinVersion(int nVersion)
175 {
176  return Write(std::string("minversion"), nVersion);
177 }
178 
179 bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
180 {
181  account.SetNull();
182  return Read(make_pair(string("acc"), strAccount), account);
183 }
184 
185 bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
186 {
187  return Write(make_pair(string("acc"), strAccount), account);
188 }
189 
190 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
191 {
192  return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
193 }
194 
196 {
197  return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
198 }
199 
200 CAmount CWalletDB::GetAccountCreditDebit(const string& strAccount)
201 {
202  list<CAccountingEntry> entries;
203  ListAccountCreditDebit(strAccount, entries);
204 
205  CAmount nCreditDebit = 0;
206  BOOST_FOREACH (const CAccountingEntry& entry, entries)
207  nCreditDebit += entry.nCreditDebit;
208 
209  return nCreditDebit;
210 }
211 
212 void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
213 {
214  bool fAllAccounts = (strAccount == "*");
215 
216  Dbc* pcursor = GetCursor();
217  if (!pcursor)
218  throw runtime_error("CWalletDB::ListAccountCreditDebit(): cannot create DB cursor");
219  unsigned int fFlags = DB_SET_RANGE;
220  while (true)
221  {
222  // Read next record
224  if (fFlags == DB_SET_RANGE)
225  ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? string("") : strAccount), uint64_t(0)));
227  int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
228  fFlags = DB_NEXT;
229  if (ret == DB_NOTFOUND)
230  break;
231  else if (ret != 0)
232  {
233  pcursor->close();
234  throw runtime_error("CWalletDB::ListAccountCreditDebit(): error scanning DB");
235  }
236 
237  // Unserialize
238  string strType;
239  ssKey >> strType;
240  if (strType != "acentry")
241  break;
242  CAccountingEntry acentry;
243  ssKey >> acentry.strAccount;
244  if (!fAllAccounts && acentry.strAccount != strAccount)
245  break;
246 
247  ssValue >> acentry;
248  ssKey >> acentry.nEntryNo;
249  entries.push_back(acentry);
250  }
251 
252  pcursor->close();
253 }
254 
256 {
257  LOCK(pwallet->cs_wallet);
258  // Old wallets didn't have any defined order for transactions
259  // Probably a bad idea to change the output of this
260 
261  // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
262  typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
263  typedef multimap<int64_t, TxPair > TxItems;
264  TxItems txByTime;
265 
266  for (map<uint256, CWalletTx>::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it)
267  {
268  CWalletTx* wtx = &((*it).second);
269  txByTime.insert(make_pair(wtx->nTimeReceived, TxPair(wtx, (CAccountingEntry*)0)));
270  }
271  list<CAccountingEntry> acentries;
272  ListAccountCreditDebit("", acentries);
273  BOOST_FOREACH(CAccountingEntry& entry, acentries)
274  {
275  txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
276  }
277 
278  int64_t& nOrderPosNext = pwallet->nOrderPosNext;
279  nOrderPosNext = 0;
280  std::vector<int64_t> nOrderPosOffsets;
281  for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
282  {
283  CWalletTx *const pwtx = (*it).second.first;
284  CAccountingEntry *const pacentry = (*it).second.second;
285  int64_t& nOrderPos = (pwtx != 0) ? pwtx->nOrderPos : pacentry->nOrderPos;
286 
287  if (nOrderPos == -1)
288  {
289  nOrderPos = nOrderPosNext++;
290  nOrderPosOffsets.push_back(nOrderPos);
291 
292  if (pwtx)
293  {
294  if (!WriteTx(pwtx->GetHash(), *pwtx))
295  return DB_LOAD_FAIL;
296  }
297  else
298  if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
299  return DB_LOAD_FAIL;
300  }
301  else
302  {
303  int64_t nOrderPosOff = 0;
304  BOOST_FOREACH(const int64_t& nOffsetStart, nOrderPosOffsets)
305  {
306  if (nOrderPos >= nOffsetStart)
307  ++nOrderPosOff;
308  }
309  nOrderPos += nOrderPosOff;
310  nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
311 
312  if (!nOrderPosOff)
313  continue;
314 
315  // Since we're changing the order, write it back
316  if (pwtx)
317  {
318  if (!WriteTx(pwtx->GetHash(), *pwtx))
319  return DB_LOAD_FAIL;
320  }
321  else
322  if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
323  return DB_LOAD_FAIL;
324  }
325  }
326  WriteOrderPosNext(nOrderPosNext);
327 
328  return DB_LOAD_OK;
329 }
330 
332 public:
333  unsigned int nKeys;
334  unsigned int nCKeys;
335  unsigned int nKeyMeta;
339  vector<uint256> vWalletUpgrade;
340 
342  nKeys = nCKeys = nKeyMeta = 0;
343  fIsEncrypted = false;
344  fAnyUnordered = false;
345  nFileVersion = 0;
346  }
347 };
348 
349 bool
350 ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
351  CWalletScanState &wss, string& strType, string& strErr)
352 {
353  try {
354  // Unserialize
355  // Taking advantage of the fact that pair serialization
356  // is just the two items serialized one after the other
357  ssKey >> strType;
358  if (strType == "name")
359  {
360  string strAddress;
361  ssKey >> strAddress;
362  ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
363  }
364  else if (strType == "purpose")
365  {
366  string strAddress;
367  ssKey >> strAddress;
368  ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
369  }
370  else if (strType == "tx")
371  {
372  uint256 hash;
373  ssKey >> hash;
374  CWalletTx wtx;
375  ssValue >> wtx;
376  CValidationState state;
377  if (!(CheckTransaction(wtx, state) && (wtx.GetHash() == hash) && state.IsValid()))
378  return false;
379 
380  // Undo serialize changes in 31600
381  if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
382  {
383  if (!ssValue.empty())
384  {
385  char fTmp;
386  char fUnused;
387  ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
388  strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
389  wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
390  wtx.fTimeReceivedIsTxTime = fTmp;
391  }
392  else
393  {
394  strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
395  wtx.fTimeReceivedIsTxTime = 0;
396  }
397  wss.vWalletUpgrade.push_back(hash);
398  }
399 
400  if (wtx.nOrderPos == -1)
401  wss.fAnyUnordered = true;
402 
403  pwallet->AddToWallet(wtx, true, NULL);
404  }
405  else if (strType == "acentry")
406  {
407  string strAccount;
408  ssKey >> strAccount;
409  uint64_t nNumber;
410  ssKey >> nNumber;
411  if (nNumber > nAccountingEntryNumber)
412  nAccountingEntryNumber = nNumber;
413 
414  if (!wss.fAnyUnordered)
415  {
416  CAccountingEntry acentry;
417  ssValue >> acentry;
418  if (acentry.nOrderPos == -1)
419  wss.fAnyUnordered = true;
420  }
421  }
422  else if (strType == "watchs")
423  {
424  CScript script;
425  ssKey >> *(CScriptBase*)(&script);
426  char fYes;
427  ssValue >> fYes;
428  if (fYes == '1')
429  pwallet->LoadWatchOnly(script);
430 
431  // Watch-only addresses have no birthday information for now,
432  // so set the wallet birthday to the beginning of time.
433  pwallet->nTimeFirstKey = 1;
434  }
435  else if (strType == "key" || strType == "wkey")
436  {
437  CPubKey vchPubKey;
438  ssKey >> vchPubKey;
439  if (!vchPubKey.IsValid())
440  {
441  strErr = "Error reading wallet database: CPubKey corrupt";
442  return false;
443  }
444  CKey key;
445  CPrivKey pkey;
446  uint256 hash;
447 
448  if (strType == "key")
449  {
450  wss.nKeys++;
451  ssValue >> pkey;
452  } else {
453  CWalletKey wkey;
454  ssValue >> wkey;
455  pkey = wkey.vchPrivKey;
456  }
457 
458  // Old wallets store keys as "key" [pubkey] => [privkey]
459  // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
460  // using EC operations as a checksum.
461  // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
462  // remaining backwards-compatible.
463  try
464  {
465  ssValue >> hash;
466  }
467  catch (...) {}
468 
469  bool fSkipCheck = false;
470 
471  if (!hash.IsNull())
472  {
473  // hash pubkey/privkey to accelerate wallet load
474  std::vector<unsigned char> vchKey;
475  vchKey.reserve(vchPubKey.size() + pkey.size());
476  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
477  vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
478 
479  if (Hash(vchKey.begin(), vchKey.end()) != hash)
480  {
481  strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
482  return false;
483  }
484 
485  fSkipCheck = true;
486  }
487 
488  if (!key.Load(pkey, vchPubKey, fSkipCheck))
489  {
490  strErr = "Error reading wallet database: CPrivKey corrupt";
491  return false;
492  }
493  if (!pwallet->LoadKey(key, vchPubKey))
494  {
495  strErr = "Error reading wallet database: LoadKey failed";
496  return false;
497  }
498  }
499  else if (strType == "mkey")
500  {
501  unsigned int nID;
502  ssKey >> nID;
503  CMasterKey kMasterKey;
504  ssValue >> kMasterKey;
505  if(pwallet->mapMasterKeys.count(nID) != 0)
506  {
507  strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
508  return false;
509  }
510  pwallet->mapMasterKeys[nID] = kMasterKey;
511  if (pwallet->nMasterKeyMaxID < nID)
512  pwallet->nMasterKeyMaxID = nID;
513  }
514  else if (strType == "ckey")
515  {
516  CPubKey vchPubKey;
517  ssKey >> vchPubKey;
518  if (!vchPubKey.IsValid())
519  {
520  strErr = "Error reading wallet database: CPubKey corrupt";
521  return false;
522  }
523  vector<unsigned char> vchPrivKey;
524  ssValue >> vchPrivKey;
525  wss.nCKeys++;
526 
527  if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
528  {
529  strErr = "Error reading wallet database: LoadCryptedKey failed";
530  return false;
531  }
532  wss.fIsEncrypted = true;
533  }
534  else if (strType == "keymeta")
535  {
536  CPubKey vchPubKey;
537  ssKey >> vchPubKey;
538  CKeyMetadata keyMeta;
539  ssValue >> keyMeta;
540  wss.nKeyMeta++;
541 
542  pwallet->LoadKeyMetadata(vchPubKey, keyMeta);
543 
544  // find earliest key creation time, as wallet birthday
545  if (!pwallet->nTimeFirstKey ||
546  (keyMeta.nCreateTime < pwallet->nTimeFirstKey))
547  pwallet->nTimeFirstKey = keyMeta.nCreateTime;
548  }
549  else if (strType == "defaultkey")
550  {
551  ssValue >> pwallet->vchDefaultKey;
552  }
553  else if (strType == "pool")
554  {
555  int64_t nIndex;
556  ssKey >> nIndex;
558  ssValue >> keypool;
559  pwallet->LoadKeyPool(nIndex, keypool);
560  }
561  else if (strType == "version")
562  {
563  ssValue >> wss.nFileVersion;
564  if (wss.nFileVersion == 10300)
565  wss.nFileVersion = 300;
566  }
567  else if (strType == "cscript")
568  {
569  uint160 hash;
570  ssKey >> hash;
571  CScript script;
572  ssValue >> *(CScriptBase*)(&script);
573  if (!pwallet->LoadCScript(script))
574  {
575  strErr = "Error reading wallet database: LoadCScript failed";
576  return false;
577  }
578  }
579  else if (strType == "orderposnext")
580  {
581  ssValue >> pwallet->nOrderPosNext;
582  }
583  else if (strType == "destdata")
584  {
585  std::string strAddress, strKey, strValue;
586  ssKey >> strAddress;
587  ssKey >> strKey;
588  ssValue >> strValue;
589  if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue))
590  {
591  strErr = "Error reading wallet database: LoadDestData failed";
592  return false;
593  }
594  }
595  else if (strType == "hdchain")
596  {
597  CHDChain chain;
598  ssValue >> chain;
599  if (!pwallet->SetHDChain(chain, true))
600  {
601  strErr = "Error reading wallet database: SetHDChain failed";
602  return false;
603  }
604  }
605  else if (strType == "chdchain")
606  {
607  CHDChain chain;
608  ssValue >> chain;
609  if (!pwallet->SetCryptedHDChain(chain, true))
610  {
611  strErr = "Error reading wallet database: SetHDCryptedChain failed";
612  return false;
613  }
614  }
615  else if (strType == "hdpubkey")
616  {
617  CPubKey vchPubKey;
618  ssKey >> vchPubKey;
619 
620  CHDPubKey hdPubKey;
621  ssValue >> hdPubKey;
622 
623  if(vchPubKey != hdPubKey.extPubKey.pubkey)
624  {
625  strErr = "Error reading wallet database: CHDPubKey corrupt";
626  return false;
627  }
628  if (!pwallet->LoadHDPubKey(hdPubKey))
629  {
630  strErr = "Error reading wallet database: LoadHDPubKey failed";
631  return false;
632  }
633  }
634  } catch (...)
635  {
636  return false;
637  }
638  return true;
639 }
640 
641 static bool IsKeyType(string strType)
642 {
643  return (strType== "key" || strType == "wkey" ||
644  strType == "mkey" || strType == "ckey" ||
645  strType == "hdchain" || strType == "chdchain");
646 }
647 
649 {
650  pwallet->vchDefaultKey = CPubKey();
651  CWalletScanState wss;
652  bool fNoncriticalErrors = false;
654 
655  try {
656  LOCK(pwallet->cs_wallet);
657  int nMinVersion = 0;
658  if (Read((string)"minversion", nMinVersion))
659  {
660  if (nMinVersion > CLIENT_VERSION)
661  return DB_TOO_NEW;
662  pwallet->LoadMinVersion(nMinVersion);
663  }
664 
665  // Get cursor
666  Dbc* pcursor = GetCursor();
667  if (!pcursor)
668  {
669  LogPrintf("Error getting wallet database cursor\n");
670  return DB_CORRUPT;
671  }
672 
673  while (true)
674  {
675  // Read next record
678  int ret = ReadAtCursor(pcursor, ssKey, ssValue);
679  if (ret == DB_NOTFOUND)
680  break;
681  else if (ret != 0)
682  {
683  LogPrintf("Error reading next record from wallet database\n");
684  return DB_CORRUPT;
685  }
686 
687  // Try to be tolerant of single corrupt records:
688  string strType, strErr;
689  if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
690  {
691  // losing keys is considered a catastrophic error, anything else
692  // we assume the user can live with:
693  if (IsKeyType(strType))
694  result = DB_CORRUPT;
695  else
696  {
697  // Leave other errors alone, if we try to fix them we might make things worse.
698  fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
699  if (strType == "tx")
700  // Rescan if there is a bad transaction record:
701  SoftSetBoolArg("-rescan", true);
702  }
703  }
704  if (!strErr.empty())
705  LogPrintf("%s\n", strErr);
706  }
707  pcursor->close();
708 
709  // Store initial external keypool size since we mostly use external keys in mixing
711  LogPrintf("nKeysLeftSinceAutoBackup: %d\n", pwallet->nKeysLeftSinceAutoBackup);
712  }
713  catch (const boost::thread_interrupted&) {
714  throw;
715  }
716  catch (...) {
717  result = DB_CORRUPT;
718  }
719 
720  if (fNoncriticalErrors && result == DB_LOAD_OK)
722 
723  // Any wallet corruption at all: skip any rewriting or
724  // upgrading, we don't want to make it worse.
725  if (result != DB_LOAD_OK)
726  return result;
727 
728  LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
729 
730  LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
731  wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
732 
733  // nTimeFirstKey is only reliable if all keys have metadata
734  if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta)
735  pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value'
736 
737  BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade)
738  WriteTx(hash, pwallet->mapWallet[hash]);
739 
740  // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
741  if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
742  return DB_NEED_REWRITE;
743 
744  if (wss.nFileVersion < CLIENT_VERSION) // Update
745  WriteVersion(CLIENT_VERSION);
746 
747  if (wss.fAnyUnordered)
748  result = ReorderTransactions(pwallet);
749 
750  pwallet->laccentries.clear();
751  ListAccountCreditDebit("*", pwallet->laccentries);
752  BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) {
753  pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
754  }
755 
756  return result;
757 }
758 
759 DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vector<CWalletTx>& vWtx)
760 {
761  pwallet->vchDefaultKey = CPubKey();
762  bool fNoncriticalErrors = false;
764 
765  try {
766  LOCK(pwallet->cs_wallet);
767  int nMinVersion = 0;
768  if (Read((string)"minversion", nMinVersion))
769  {
770  if (nMinVersion > CLIENT_VERSION)
771  return DB_TOO_NEW;
772  pwallet->LoadMinVersion(nMinVersion);
773  }
774 
775  // Get cursor
776  Dbc* pcursor = GetCursor();
777  if (!pcursor)
778  {
779  LogPrintf("Error getting wallet database cursor\n");
780  return DB_CORRUPT;
781  }
782 
783  while (true)
784  {
785  // Read next record
788  int ret = ReadAtCursor(pcursor, ssKey, ssValue);
789  if (ret == DB_NOTFOUND)
790  break;
791  else if (ret != 0)
792  {
793  LogPrintf("Error reading next record from wallet database\n");
794  return DB_CORRUPT;
795  }
796 
797  string strType;
798  ssKey >> strType;
799  if (strType == "tx") {
800  uint256 hash;
801  ssKey >> hash;
802 
803  CWalletTx wtx;
804  ssValue >> wtx;
805 
806  vTxHash.push_back(hash);
807  vWtx.push_back(wtx);
808  }
809  }
810  pcursor->close();
811  }
812  catch (const boost::thread_interrupted&) {
813  throw;
814  }
815  catch (...) {
816  result = DB_CORRUPT;
817  }
818 
819  if (fNoncriticalErrors && result == DB_LOAD_OK)
821 
822  return result;
823 }
824 
825 DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
826 {
827  // build list of wallet TXs
828  vector<uint256> vTxHash;
829  DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx);
830  if (err != DB_LOAD_OK)
831  return err;
832 
833  // erase each wallet TX
834  BOOST_FOREACH (uint256& hash, vTxHash) {
835  if (!EraseTx(hash))
836  return DB_CORRUPT;
837  }
838 
839  return DB_LOAD_OK;
840 }
841 
842 void ThreadFlushWalletDB(const string& strFile)
843 {
844  // Make this thread recognisable as the wallet flushing thread
845  RenameThread("dash-wallet");
846 
847  static bool fOneThread;
848  if (fOneThread)
849  return;
850  fOneThread = true;
851  if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
852  return;
853 
854  unsigned int nLastSeen = nWalletDBUpdated;
855  unsigned int nLastFlushed = nWalletDBUpdated;
856  int64_t nLastWalletUpdate = GetTime();
857  while (true)
858  {
859  MilliSleep(500);
860 
861  if (nLastSeen != nWalletDBUpdated)
862  {
863  nLastSeen = nWalletDBUpdated;
864  nLastWalletUpdate = GetTime();
865  }
866 
867  if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
868  {
869  TRY_LOCK(bitdb.cs_db,lockDb);
870  if (lockDb)
871  {
872  // Don't do this if any databases are in use
873  int nRefCount = 0;
874  map<string, int>::iterator mi = bitdb.mapFileUseCount.begin();
875  while (mi != bitdb.mapFileUseCount.end())
876  {
877  nRefCount += (*mi).second;
878  mi++;
879  }
880 
881  if (nRefCount == 0)
882  {
883  boost::this_thread::interruption_point();
884  map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
885  if (mi != bitdb.mapFileUseCount.end())
886  {
887  LogPrint("db", "Flushing wallet.dat\n");
888  nLastFlushed = nWalletDBUpdated;
889  int64_t nStart = GetTimeMillis();
890 
891  // Flush wallet.dat so it's self contained
892  bitdb.CloseDb(strFile);
893  bitdb.CheckpointLSN(strFile);
894 
895  bitdb.mapFileUseCount.erase(mi++);
896  LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart);
897  }
898  }
899  }
900  }
901  }
902 }
903 
904 bool BackupWallet(const CWallet& wallet, const string& strDest)
905 {
906  if (!wallet.fFileBacked)
907  return false;
908  while (true)
909  {
910  {
911  LOCK(bitdb.cs_db);
912  if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0)
913  {
914  // Flush log data to the dat file
915  bitdb.CloseDb(wallet.strWalletFile);
916  bitdb.CheckpointLSN(wallet.strWalletFile);
917  bitdb.mapFileUseCount.erase(wallet.strWalletFile);
918 
919  // Copy wallet.dat
920  boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
921  boost::filesystem::path pathDest(strDest);
922  if (boost::filesystem::is_directory(pathDest))
923  pathDest /= wallet.strWalletFile;
924 
925  try {
926 #if BOOST_VERSION >= 104000
927  boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
928 #else
929  boost::filesystem::copy_file(pathSrc, pathDest);
930 #endif
931  LogPrintf("copied wallet.dat to %s\n", pathDest.string());
932  return true;
933  } catch (const boost::filesystem::filesystem_error& e) {
934  LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string(), e.what());
935  return false;
936  }
937  }
938  }
939  MilliSleep(100);
940  }
941  return false;
942 }
943 
944 // This should be called carefully:
945 // either supply "wallet" (if already loaded) or "strWalletFile" (if wallet wasn't loaded yet)
946 bool AutoBackupWallet (CWallet* wallet, std::string strWalletFile, std::string& strBackupWarning, std::string& strBackupError)
947 {
948  namespace fs = boost::filesystem;
949 
950  strBackupWarning = strBackupError = "";
951 
952  if(nWalletBackups > 0)
953  {
954  fs::path backupsDir = GetBackupsDir();
955 
956  if (!fs::exists(backupsDir))
957  {
958  // Always create backup folder to not confuse the operating system's file browser
959  LogPrintf("Creating backup folder %s\n", backupsDir.string());
960  if(!fs::create_directories(backupsDir)) {
961  // smth is wrong, we shouldn't continue until it's resolved
962  strBackupError = strprintf(_("Wasn't able to create wallet backup folder %s!"), backupsDir.string());
963  LogPrintf("%s\n", strBackupError);
964  nWalletBackups = -1;
965  return false;
966  }
967  }
968 
969  // Create backup of the ...
970  std::string dateTimeStr = DateTimeStrFormat(".%Y-%m-%d-%H-%M", GetTime());
971  if (wallet)
972  {
973  // ... opened wallet
974  LOCK2(cs_main, wallet->cs_wallet);
975  strWalletFile = wallet->strWalletFile;
976  fs::path backupFile = backupsDir / (strWalletFile + dateTimeStr);
977  if(!BackupWallet(*wallet, backupFile.string())) {
978  strBackupWarning = strprintf(_("Failed to create backup %s!"), backupFile.string());
979  LogPrintf("%s\n", strBackupWarning);
980  nWalletBackups = -1;
981  return false;
982  }
983  // Update nKeysLeftSinceAutoBackup using current external keypool size
984  wallet->nKeysLeftSinceAutoBackup = wallet->KeypoolCountExternalKeys();
985  LogPrintf("nKeysLeftSinceAutoBackup: %d\n", wallet->nKeysLeftSinceAutoBackup);
986  if(wallet->IsLocked(true)) {
987  strBackupWarning = _("Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool.");
988  LogPrintf("%s\n", strBackupWarning);
989  nWalletBackups = -2;
990  return false;
991  }
992  } else {
993  // ... strWalletFile file
994  fs::path sourceFile = GetDataDir() / strWalletFile;
995  fs::path backupFile = backupsDir / (strWalletFile + dateTimeStr);
996  sourceFile.make_preferred();
997  backupFile.make_preferred();
998  if (fs::exists(backupFile))
999  {
1000  strBackupWarning = _("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this.");
1001  LogPrintf("%s\n", strBackupWarning);
1002  return false;
1003  }
1004  if(fs::exists(sourceFile)) {
1005  try {
1006  fs::copy_file(sourceFile, backupFile);
1007  LogPrintf("Creating backup of %s -> %s\n", sourceFile.string(), backupFile.string());
1008  } catch(fs::filesystem_error &error) {
1009  strBackupWarning = strprintf(_("Failed to create backup, error: %s"), error.what());
1010  LogPrintf("%s\n", strBackupWarning);
1011  nWalletBackups = -1;
1012  return false;
1013  }
1014  }
1015  }
1016 
1017  // Keep only the last 10 backups, including the new one of course
1018  typedef std::multimap<std::time_t, fs::path> folder_set_t;
1019  folder_set_t folder_set;
1020  fs::directory_iterator end_iter;
1021  backupsDir.make_preferred();
1022  // Build map of backup files for current(!) wallet sorted by last write time
1023  fs::path currentFile;
1024  for (fs::directory_iterator dir_iter(backupsDir); dir_iter != end_iter; ++dir_iter)
1025  {
1026  // Only check regular files
1027  if ( fs::is_regular_file(dir_iter->status()))
1028  {
1029  currentFile = dir_iter->path().filename();
1030  // Only add the backups for the current wallet, e.g. wallet.dat.*
1031  if(dir_iter->path().stem().string() == strWalletFile)
1032  {
1033  folder_set.insert(folder_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
1034  }
1035  }
1036  }
1037 
1038  // Loop backward through backup files and keep the N newest ones (1 <= N <= 10)
1039  int counter = 0;
1040  BOOST_REVERSE_FOREACH(PAIRTYPE(const std::time_t, fs::path) file, folder_set)
1041  {
1042  counter++;
1043  if (counter > nWalletBackups)
1044  {
1045  // More than nWalletBackups backups: delete oldest one(s)
1046  try {
1047  fs::remove(file.second);
1048  LogPrintf("Old backup deleted: %s\n", file.second);
1049  } catch(fs::filesystem_error &error) {
1050  strBackupWarning = strprintf(_("Failed to delete backup, error: %s"), error.what());
1051  LogPrintf("%s\n", strBackupWarning);
1052  return false;
1053  }
1054  }
1055  }
1056  return true;
1057  }
1058 
1059  LogPrintf("Automatic wallet backups are disabled!\n");
1060  return false;
1061 }
1062 
1063 //
1064 // Try to (very carefully!) recover wallet.dat if there is a problem.
1065 //
1066 bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys)
1067 {
1068  // Recovery procedure:
1069  // move wallet.dat to wallet.timestamp.bak
1070  // Call Salvage with fAggressive=true to
1071  // get as much data as possible.
1072  // Rewrite salvaged data to wallet.dat
1073  // Set -rescan so any missing transactions will be
1074  // found.
1075  int64_t now = GetTime();
1076  std::string newFilename = strprintf("wallet.%d.bak", now);
1077 
1078  int result = dbenv.dbenv->dbrename(NULL, filename.c_str(), NULL,
1079  newFilename.c_str(), DB_AUTO_COMMIT);
1080  if (result == 0)
1081  LogPrintf("Renamed %s to %s\n", filename, newFilename);
1082  else
1083  {
1084  LogPrintf("Failed to rename %s to %s\n", filename, newFilename);
1085  return false;
1086  }
1087 
1088  std::vector<CDBEnv::KeyValPair> salvagedData;
1089  bool fSuccess = dbenv.Salvage(newFilename, true, salvagedData);
1090  if (salvagedData.empty())
1091  {
1092  LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename);
1093  return false;
1094  }
1095  LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size());
1096 
1097  boost::scoped_ptr<Db> pdbCopy(new Db(dbenv.dbenv, 0));
1098  int ret = pdbCopy->open(NULL, // Txn pointer
1099  filename.c_str(), // Filename
1100  "main", // Logical db name
1101  DB_BTREE, // Database type
1102  DB_CREATE, // Flags
1103  0);
1104  if (ret > 0)
1105  {
1106  LogPrintf("Cannot create database file %s\n", filename);
1107  return false;
1108  }
1109  CWallet dummyWallet;
1110  CWalletScanState wss;
1111 
1112  DbTxn* ptxn = dbenv.TxnBegin();
1113  BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData)
1114  {
1115  if (fOnlyKeys)
1116  {
1117  CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
1118  CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
1119  string strType, strErr;
1120  bool fReadOK;
1121  {
1122  // Required in LoadKeyMetadata():
1123  LOCK(dummyWallet.cs_wallet);
1124  fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue,
1125  wss, strType, strErr);
1126  }
1127  if (!IsKeyType(strType) && strType != "hdpubkey")
1128  continue;
1129  if (!fReadOK)
1130  {
1131  LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
1132  continue;
1133  }
1134  }
1135  Dbt datKey(&row.first[0], row.first.size());
1136  Dbt datValue(&row.second[0], row.second.size());
1137  int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE);
1138  if (ret2 > 0)
1139  fSuccess = false;
1140  }
1141  ptxn->commit(0);
1142  pdbCopy->close(0);
1143 
1144  return fSuccess;
1145 }
1146 
1147 bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
1148 {
1149  return CWalletDB::Recover(dbenv, filename, false);
1150 }
1151 
1152 bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
1153 {
1154  nWalletDBUpdated++;
1155  return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
1156 }
1157 
1158 bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
1159 {
1160  nWalletDBUpdated++;
1161  return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
1162 }
1163 
1165 {
1166  nWalletDBUpdated++;
1167  return Write(std::string("hdchain"), chain);
1168 }
1169 
1171 {
1172  nWalletDBUpdated++;
1173 
1174  if (!Write(std::string("chdchain"), chain))
1175  return false;
1176 
1177  Erase(std::string("hdchain"));
1178 
1179  return true;
1180 }
1181 
1182 bool CWalletDB::WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta)
1183 {
1184  nWalletDBUpdated++;
1185 
1186  if (!Write(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false))
1187  return false;
1188 
1189  return Write(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false);
1190 }
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:547
unsigned int nWalletDBUpdated
Definition: db.cpp:27
bool ErasePurpose(const std::string &strAddress)
Definition: walletdb.cpp:52
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:114
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry &acentry)
Definition: walletdb.cpp:190
int64_t nOrderPosNext
Definition: wallet.h:745
CExtPubKey extPubKey
Definition: hdchain.h:130
void MilliSleep(int64_t n)
Definition: utiltime.cpp:63
unsigned int nKeys
Definition: walletdb.cpp:333
#define TRY_LOCK(cs, name)
Definition: sync.h:170
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:95
TxItems wtxOrdered
Definition: wallet.h:743
DbEnv * dbenv
Definition: db.h:41
#define strprintf
Definition: tinyformat.h:1011
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:1152
CCriticalSection cs_wallet
Definition: wallet.h:672
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Definition: util.cpp:470
bool empty() const
Definition: streams.h:123
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
Definition: utiltime.cpp:81
bool LoadMinVersion(int nVersion)
Definition: wallet.h:829
bool AddToWallet(const CWalletTx &wtxIn, bool fFromLoadWallet, CWalletDB *pwalletdb)
Definition: wallet.cpp:880
CCriticalSection cs_main
Definition: validation.cpp:62
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:344
bool WriteHDPubKey(const CHDPubKey &hdPubKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:1182
unsigned int nCKeys
Definition: walletdb.cpp:334
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
Definition: db.h:69
DBErrors ZapWalletTx(CWallet *pwallet, std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:825
std::pair< CWalletTx *, CAccountingEntry * > TxPair
Definition: wallet.h:741
unsigned int nMasterKeyMaxID
Definition: wallet.h:699
bool BackupWallet(const CWallet &wallet, const string &strDest)
Definition: walletdb.cpp:904
DBErrors
Definition: walletdb.h:34
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:87
void RenameThread(const char *name)
Definition: util.cpp:873
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:64
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:145
bool IsNull() const
Definition: uint256.h:33
bool LoadCScript(const CScript &redeemScript)
Definition: wallet.cpp:358
Definition: db.h:28
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:738
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:139
unsigned int nTimeReceived
Definition: wallet.h:284
CDBEnv bitdb
Definition: db.cpp:34
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Definition: walletdb.cpp:1164
DBErrors FindWalletTx(CWallet *pwallet, std::vector< uint256 > &vTxHash, std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:759
int64_t CAmount
Definition: amount.h:14
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
Definition: key.h:32
std::map< std::string, int > mapFileUseCount
Definition: db.h:42
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:648
#define LOCK2(cs1, cs2)
Definition: sync.h:169
CAmount nCreditDebit
Definition: wallet.h:539
int nWalletBackups
Definition: util.cpp:117
bool GetBoolArg(const std::string &strArg, bool fDefault)
Definition: util.cpp:455
#define LogPrintf(...)
Definition: util.h:98
bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
Definition: wallet.cpp:334
void ListAccountCreditDebit(const std::string &strAccount, std::list< CAccountingEntry > &acentries)
Definition: walletdb.cpp:212
const unsigned char * begin() const
Definition: pubkey.h:96
uint64_t nEntryNo
position in ordered transaction list
Definition: wallet.h:545
bool ReadAccount(const std::string &strAccount, CAccount &account)
Definition: walletdb.cpp:179
std::list< CAccountingEntry > laccentries
Definition: wallet.h:739
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:162
bool WriteCryptedHDChain(const CHDChain &chain)
Definition: walletdb.cpp:1170
bool SetHDChain(const CHDChain &chain, bool memonly)
Definition: wallet.cpp:1429
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:132
static bool Recover(CDBEnv &dbenv, const std::string &filename, bool fOnlyKeys)
Definition: walletdb.cpp:1066
bool WriteTx(uint256 hash, const CWalletTx &wtx)
Definition: walletdb.cpp:58
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:108
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Definition: db.h:80
static bool error(const char *format)
Definition: util.h:131
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition: walletdb.cpp:32
CPubKey vchDefaultKey
Definition: wallet.h:750
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:70
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:126
uint256 Hash(const T1 pbegin, const T1 pend)
Definition: hash.h:123
bool SetCryptedHDChain(const CHDChain &chain, bool memonly)
Definition: wallet.cpp:1442
bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
Adds a destination data tuple to the store, without saving it to disk.
Definition: wallet.cpp:4345
Definition: wallet.py:1
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:168
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:174
const unsigned char * end() const
Definition: pubkey.h:97
void SetNull()
Definition: wallet.h:1090
int64_t nOrderPos
Definition: wallet.h:288
bool IsValid() const
Definition: validation.h:61
size_t KeypoolCountExternalKeys()
Definition: wallet.cpp:3767
void ThreadFlushWalletDB(const string &strFile)
Definition: walletdb.cpp:842
CTxDestination Get() const
Definition: base58.cpp:260
const boost::filesystem::path & GetBackupsDir()
Definition: util.cpp:580
CPubKey pubkey
Definition: pubkey.h:200
bool WriteDefaultKey(const CPubKey &vchPubKey)
Definition: walletdb.cpp:151
bool WriteAccountingEntry_Backend(const CAccountingEntry &acentry)
Definition: walletdb.cpp:195
void CheckpointLSN(const std::string &strFile)
Definition: db.cpp:218
DBErrors ReorderTransactions(CWallet *pwallet)
Definition: walletdb.cpp:255
static bool IsKeyType(string strType)
Definition: walletdb.cpp:641
static uint64_t nAccountingEntryNumber
Definition: walletdb.cpp:26
bool EraseName(const std::string &strAddress)
Definition: walletdb.cpp:38
int64_t GetTimeMillis()
Definition: utiltime.cpp:34
const uint256 & GetHash() const
Definition: transaction.h:262
CAmount GetAccountCreditDebit(const std::string &strAccount)
Definition: walletdb.cpp:200
static const bool DEFAULT_FLUSHWALLET
Definition: walletdb.h:20
bool Salvage(const std::string &strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
Definition: db.cpp:168
MasterKeyMap mapMasterKeys
Definition: wallet.h:698
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:825
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:157
bool WriteAccount(const std::string &strAccount, const CAccount &account)
Definition: walletdb.cpp:185
bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, string &strType, string &strErr)
Definition: walletdb.cpp:350
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:748
unsigned int nKeyMeta
Definition: walletdb.cpp:335
bool CheckTransaction(const CTransaction &tx, CValidationState &state)
Definition: validation.cpp:470
bool WriteWatchOnly(const CScript &script)
Definition: walletdb.cpp:120
Definition: pubkey.h:37
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
Definition: wallet.cpp:399
void CloseDb(const std::string &strFile)
Definition: db.cpp:317
bool EraseDestData(const std::string &address, const std::string &key)
Erase destination data tuple from wallet database.
Definition: walletdb.cpp:1158
bool LoadHDPubKey(const CHDPubKey &hdPubKey)
loads a HDPubKey into the wallets memory
Definition: wallet.cpp:252
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
std::string strAccount
Definition: wallet.h:538
CPrivKey vchPrivKey
Definition: wallet.h:509
int64_t nTimeFirstKey
Definition: wallet.h:754
int64_t nTime
Definition: wallet.h:540
int64_t nOrderPos
Definition: wallet.h:544
Definition: key.h:35
static const int CLIENT_VERSION
Definition: clientversion.h:54
#define PAIRTYPE(t1, t2)
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition: walletdb.cpp:46
int64_t nKeysLeftSinceAutoBackup
Definition: wallet.h:755
bool AutoBackupWallet(CWallet *wallet, std::string strWalletFile, std::string &strBackupWarning, std::string &strBackupError)
Definition: walletdb.cpp:946
void LoadKeyPool(int nIndex, const CKeyPool &keypool)
Definition: wallet.h:677
std::string _(const char *psz)
Definition: util.h:84
vector< uint256 > vWalletUpgrade
Definition: walletdb.cpp:339
result
Definition: rpcuser.py:37
std::vector< uint256 > vHave
Definition: block.h:134
CCriticalSection cs_db
Definition: db.h:40
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:87