Bitcoin ABC  0.22.12
P2P Digital Currency
walletdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2020 The Bitcoin 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 <chainparams.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 
21 namespace DBKeys {
22 const std::string ACENTRY{"acentry"};
23 const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};
24 const std::string ACTIVEINTERNALSPK{"activeinternalspk"};
25 const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
26 const std::string BESTBLOCK{"bestblock"};
27 const std::string CRYPTED_KEY{"ckey"};
28 const std::string CSCRIPT{"cscript"};
29 const std::string DEFAULTKEY{"defaultkey"};
30 const std::string DESTDATA{"destdata"};
31 const std::string FLAGS{"flags"};
32 const std::string HDCHAIN{"hdchain"};
33 const std::string KEYMETA{"keymeta"};
34 const std::string KEY{"key"};
35 const std::string MASTER_KEY{"mkey"};
36 const std::string MINVERSION{"minversion"};
37 const std::string NAME{"name"};
38 const std::string OLD_KEY{"wkey"};
39 const std::string ORDERPOSNEXT{"orderposnext"};
40 const std::string POOL{"pool"};
41 const std::string PURPOSE{"purpose"};
42 const std::string SETTINGS{"settings"};
43 const std::string TX{"tx"};
44 const std::string VERSION{"version"};
45 const std::string WALLETDESCRIPTOR{"walletdescriptor"};
46 const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
47 const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
48 const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
49 const std::string WATCHMETA{"watchmeta"};
50 const std::string WATCHS{"watchs"};
51 } // namespace DBKeys
52 
53 //
54 // WalletBatch
55 //
56 
58  const std::string &strName) {
59  if (!IsValidDestination(address)) {
60  return false;
61  }
62  return WriteIC(
63  std::make_pair(DBKeys::NAME, EncodeLegacyAddr(address, Params())),
64  strName);
65 }
66 
67 bool WalletBatch::EraseName(const CTxDestination &address) {
68  // This should only be used for sending addresses, never for receiving
69  // addresses, receiving addresses must always have an address book entry if
70  // they're not change return.
71  if (!IsValidDestination(address)) {
72  return false;
73  }
74  return EraseIC(
75  std::make_pair(DBKeys::NAME, EncodeLegacyAddr(address, Params())));
76 }
77 
79  const std::string &strPurpose) {
80  if (!IsValidDestination(address)) {
81  return false;
82  }
83  return WriteIC(
84  std::make_pair(DBKeys::PURPOSE, EncodeLegacyAddr(address, Params())),
85  strPurpose);
86 }
87 
89  if (!IsValidDestination(address)) {
90  return false;
91  }
92  return EraseIC(
93  std::make_pair(DBKeys::PURPOSE, EncodeLegacyAddr(address, Params())));
94 }
95 
96 bool WalletBatch::WriteTx(const CWalletTx &wtx) {
97  return WriteIC(std::make_pair(DBKeys::TX, wtx.GetId()), wtx);
98 }
99 
101  return EraseIC(std::make_pair(DBKeys::TX, hash));
102 }
103 
105  const CPubKey &pubkey,
106  const bool overwrite) {
107  return WriteIC(std::make_pair(DBKeys::KEYMETA, pubkey), meta, overwrite);
108 }
109 
110 bool WalletBatch::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey,
111  const CKeyMetadata &keyMeta) {
112  if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {
113  return false;
114  }
115 
116  // hash pubkey/privkey to accelerate wallet load
117  std::vector<uint8_t> vchKey;
118  vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
119  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
120  vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
121 
122  return WriteIC(
123  std::make_pair(DBKeys::KEY, vchPubKey),
124  std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
125 }
126 
127 bool WalletBatch::WriteCryptedKey(const CPubKey &vchPubKey,
128  const std::vector<uint8_t> &vchCryptedSecret,
129  const CKeyMetadata &keyMeta) {
130  if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {
131  return false;
132  }
133 
134  if (!WriteIC(std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey),
135  vchCryptedSecret, false)) {
136  return false;
137  }
138  EraseIC(std::make_pair(DBKeys::KEY, vchPubKey));
139  return true;
140 }
141 
142 bool WalletBatch::WriteMasterKey(unsigned int nID,
143  const CMasterKey &kMasterKey) {
144  return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);
145 }
146 
148  const CScript &redeemScript) {
149  return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
150 }
151 
153  const CKeyMetadata &keyMeta) {
154  if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {
155  return false;
156  }
157  return WriteIC(std::make_pair(DBKeys::WATCHS, dest), '1');
158 }
159 
161  if (!EraseIC(std::make_pair(DBKeys::WATCHMETA, dest))) {
162  return false;
163  }
164  return EraseIC(std::make_pair(DBKeys::WATCHS, dest));
165 }
166 
168  // Write empty block locator so versions that require a merkle branch
169  // automatically rescan
170  WriteIC(DBKeys::BESTBLOCK, CBlockLocator());
171  return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator);
172 }
173 
175  if (m_batch.Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) {
176  return true;
177  }
178  return m_batch.Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
179 }
180 
181 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) {
182  return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);
183 }
184 
185 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool &keypool) {
186  return m_batch.Read(std::make_pair(DBKeys::POOL, nPool), keypool);
187 }
188 
189 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool &keypool) {
190  return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool);
191 }
192 
193 bool WalletBatch::ErasePool(int64_t nPool) {
194  return EraseIC(std::make_pair(DBKeys::POOL, nPool));
195 }
196 
197 bool WalletBatch::WriteMinVersion(int nVersion) {
198  return WriteIC(DBKeys::MINVERSION, nVersion);
199 }
200 
202  bool internal) {
203  std::string key =
205  return WriteIC(make_pair(key, type), id);
206 }
207 
209  const CPubKey &pubkey,
210  const CPrivKey &privkey) {
211  // hash pubkey/privkey to accelerate wallet load
212  std::vector<uint8_t> key;
213  key.reserve(pubkey.size() + privkey.size());
214  key.insert(key.end(), pubkey.begin(), pubkey.end());
215  key.insert(key.end(), privkey.begin(), privkey.end());
216 
217  return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY,
218  std::make_pair(desc_id, pubkey)),
219  std::make_pair(privkey, Hash(key.begin(), key.end())),
220  false);
221 }
222 
224  const uint256 &desc_id, const CPubKey &pubkey,
225  const std::vector<uint8_t> &secret) {
226  if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY,
227  std::make_pair(desc_id, pubkey)),
228  secret, false)) {
229  return false;
230  }
231  EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY,
232  std::make_pair(desc_id, pubkey)));
233  return true;
234 }
235 
237  const WalletDescriptor &descriptor) {
238  return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor);
239 }
240 
242  const uint256 &desc_id,
243  uint32_t key_exp_index,
244  uint32_t der_index) {
245  std::vector<uint8_t> ser_xpub(BIP32_EXTKEY_SIZE);
246  xpub.Encode(ser_xpub.data());
247  return WriteIC(
248  std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id),
249  std::make_pair(key_exp_index, der_index)),
250  ser_xpub);
251 }
252 
254  const uint256 &desc_id,
255  uint32_t key_exp_index) {
256  std::vector<uint8_t> ser_xpub(BIP32_EXTKEY_SIZE);
257  xpub.Encode(ser_xpub.data());
258  return WriteIC(
259  std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id),
260  key_exp_index),
261  ser_xpub);
262 }
263 
265 public:
266  unsigned int nKeys{0};
267  unsigned int nCKeys{0};
268  unsigned int nWatchKeys{0};
269  unsigned int nKeyMeta{0};
270  unsigned int m_unknown_records{0};
271  bool fIsEncrypted{false};
272  bool fAnyUnordered{false};
273  std::vector<TxId> vWalletUpgrade;
274  std::map<OutputType, uint256> m_active_external_spks;
275  std::map<OutputType, uint256> m_active_internal_spks;
276  std::map<uint256, DescriptorCache> m_descriptor_caches;
277  std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys;
278  std::map<std::pair<uint256, CKeyID>,
279  std::pair<CPubKey, std::vector<uint8_t>>>
281 
283 };
284 
285 static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey,
286  CDataStream &ssValue, CWalletScanState &wss,
287  std::string &strType, std::string &strErr)
288  EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
289  try {
290  // Unserialize
291  // Taking advantage of the fact that pair serialization is just the two
292  // items serialized one after the other.
293  ssKey >> strType;
294  if (strType == DBKeys::NAME) {
295  std::string strAddress;
296  ssKey >> strAddress;
297  std::string label;
298  ssValue >> label;
299  pwallet
300  ->m_address_book[DecodeDestination(strAddress,
301  pwallet->GetChainParams())]
302  .SetLabel(label);
303  } else if (strType == DBKeys::PURPOSE) {
304  std::string strAddress;
305  ssKey >> strAddress;
306  ssValue >> pwallet
307  ->m_address_book[DecodeDestination(
308  strAddress, pwallet->GetChainParams())]
309  .purpose;
310  } else if (strType == DBKeys::TX) {
311  TxId txid;
312  ssKey >> txid;
313  CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
314  ssValue >> wtx;
315  if (wtx.GetId() != txid) {
316  return false;
317  }
318 
319  // Undo serialize changes in 31600
320  if (31404 <= wtx.fTimeReceivedIsTxTime &&
321  wtx.fTimeReceivedIsTxTime <= 31703) {
322  if (!ssValue.empty()) {
323  char fTmp;
324  char fUnused;
325  std::string unused_string;
326  ssValue >> fTmp >> fUnused >> unused_string;
327  strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
328  wtx.fTimeReceivedIsTxTime, fTmp,
329  txid.ToString());
330  wtx.fTimeReceivedIsTxTime = fTmp;
331  } else {
332  strErr =
333  strprintf("LoadWallet() repairing tx ver=%d %s",
334  wtx.fTimeReceivedIsTxTime, txid.ToString());
335  wtx.fTimeReceivedIsTxTime = 0;
336  }
337  wss.vWalletUpgrade.push_back(txid);
338  }
339 
340  if (wtx.nOrderPos == -1) {
341  wss.fAnyUnordered = true;
342  }
343 
344  pwallet->LoadToWallet(wtx);
345  } else if (strType == DBKeys::WATCHS) {
346  wss.nWatchKeys++;
347  CScript script;
348  ssKey >> script;
349  char fYes;
350  ssValue >> fYes;
351  if (fYes == '1') {
352  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadWatchOnly(
353  script);
354  }
355  } else if (strType == DBKeys::KEY) {
356  CPubKey vchPubKey;
357  ssKey >> vchPubKey;
358  if (!vchPubKey.IsValid()) {
359  strErr = "Error reading wallet database: CPubKey corrupt";
360  return false;
361  }
362  CKey key;
363  CPrivKey pkey;
364  uint256 hash;
365 
366  wss.nKeys++;
367  ssValue >> pkey;
368 
369  // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey] ...
370  // which was slow for wallets with lots of keys, because the public
371  // key is re-derived from the private key using EC operations as a
372  // checksum. Newer wallets store keys as DBKeys::KEY [pubkey] =>
373  // [privkey][hash(pubkey,privkey)], which is much faster while
374  // remaining backwards-compatible.
375  try {
376  ssValue >> hash;
377  } catch (...) {
378  }
379 
380  bool fSkipCheck = false;
381 
382  if (!hash.IsNull()) {
383  // hash pubkey/privkey to accelerate wallet load
384  std::vector<uint8_t> vchKey;
385  vchKey.reserve(vchPubKey.size() + pkey.size());
386  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
387  vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
388 
389  if (Hash(vchKey.begin(), vchKey.end()) != hash) {
390  strErr = "Error reading wallet database: CPubKey/CPrivKey "
391  "corrupt";
392  return false;
393  }
394 
395  fSkipCheck = true;
396  }
397 
398  if (!key.Load(pkey, vchPubKey, fSkipCheck)) {
399  strErr = "Error reading wallet database: CPrivKey corrupt";
400  return false;
401  }
402  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(
403  key, vchPubKey)) {
404  strErr = "Error reading wallet database: "
405  "LegacyScriptPubKeyMan::LoadKey failed";
406  return false;
407  }
408  } else if (strType == DBKeys::MASTER_KEY) {
409  // Master encryption key is loaded into only the wallet and not any
410  // of the ScriptPubKeyMans.
411  unsigned int nID;
412  ssKey >> nID;
413  CMasterKey kMasterKey;
414  ssValue >> kMasterKey;
415  if (pwallet->mapMasterKeys.count(nID) != 0) {
416  strErr = strprintf(
417  "Error reading wallet database: duplicate CMasterKey id %u",
418  nID);
419  return false;
420  }
421  pwallet->mapMasterKeys[nID] = kMasterKey;
422  if (pwallet->nMasterKeyMaxID < nID) {
423  pwallet->nMasterKeyMaxID = nID;
424  }
425  } else if (strType == DBKeys::CRYPTED_KEY) {
426  CPubKey vchPubKey;
427  ssKey >> vchPubKey;
428  if (!vchPubKey.IsValid()) {
429  strErr = "Error reading wallet database: CPubKey corrupt";
430  return false;
431  }
432  std::vector<uint8_t> vchPrivKey;
433  ssValue >> vchPrivKey;
434  wss.nCKeys++;
435 
436  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey(
437  vchPubKey, vchPrivKey)) {
438  strErr = "Error reading wallet database: "
439  "LegacyScriptPubKeyMan::LoadCryptedKey failed";
440  return false;
441  }
442  wss.fIsEncrypted = true;
443  } else if (strType == DBKeys::KEYMETA) {
444  CPubKey vchPubKey;
445  ssKey >> vchPubKey;
446  CKeyMetadata keyMeta;
447  ssValue >> keyMeta;
448  wss.nKeyMeta++;
449  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyMetadata(
450  vchPubKey.GetID(), keyMeta);
451  } else if (strType == DBKeys::WATCHMETA) {
452  CScript script;
453  ssKey >> script;
454  CKeyMetadata keyMeta;
455  ssValue >> keyMeta;
456  wss.nKeyMeta++;
457  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata(
458  CScriptID(script), keyMeta);
459  } else if (strType == DBKeys::DEFAULTKEY) {
460  // We don't want or need the default key, but if there is one set,
461  // we want to make sure that it is valid so that we can detect
462  // corruption
463  CPubKey vchPubKey;
464  ssValue >> vchPubKey;
465  if (!vchPubKey.IsValid()) {
466  strErr = "Error reading wallet database: Default Key corrupt";
467  return false;
468  }
469  } else if (strType == DBKeys::POOL) {
470  int64_t nIndex;
471  ssKey >> nIndex;
472  CKeyPool keypool;
473  ssValue >> keypool;
474 
475  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex,
476  keypool);
477  } else if (strType == DBKeys::CSCRIPT) {
478  uint160 hash;
479  ssKey >> hash;
480  CScript script;
481  ssValue >> script;
482  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript(
483  script)) {
484  strErr = "Error reading wallet database: "
485  "LegacyScriptPubKeyMan::LoadCScript failed";
486  return false;
487  }
488  } else if (strType == DBKeys::ORDERPOSNEXT) {
489  ssValue >> pwallet->nOrderPosNext;
490  } else if (strType == DBKeys::DESTDATA) {
491  std::string strAddress, strKey, strValue;
492  ssKey >> strAddress;
493  ssKey >> strKey;
494  ssValue >> strValue;
495  pwallet->LoadDestData(
496  DecodeDestination(strAddress, pwallet->GetChainParams()),
497  strKey, strValue);
498  } else if (strType == DBKeys::HDCHAIN) {
499  CHDChain chain;
500  ssValue >> chain;
501  pwallet->GetOrCreateLegacyScriptPubKeyMan()->SetHDChain(chain,
502  true);
503  } else if (strType == DBKeys::FLAGS) {
504  uint64_t flags;
505  ssValue >> flags;
506  if (!pwallet->SetWalletFlags(flags, true)) {
507  strErr = "Error reading wallet database: Unknown non-tolerable "
508  "wallet flags found";
509  return false;
510  }
511  } else if (strType == DBKeys::OLD_KEY) {
512  strErr = "Found unsupported 'wkey' record, try loading with "
513  "version 0.20";
514  return false;
515  } else if (strType == DBKeys::ACTIVEEXTERNALSPK ||
516  strType == DBKeys::ACTIVEINTERNALSPK) {
517  uint8_t type;
518  ssKey >> type;
519  uint256 id;
520  ssValue >> id;
521 
522  bool internal = strType == DBKeys::ACTIVEINTERNALSPK;
523  auto &spk_mans = internal ? wss.m_active_internal_spks
524  : wss.m_active_external_spks;
525  if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
526  strErr =
527  "Multiple ScriptPubKeyMans specified for a single type";
528  return false;
529  }
530  spk_mans[static_cast<OutputType>(type)] = id;
531  } else if (strType == DBKeys::WALLETDESCRIPTOR) {
532  uint256 id;
533  ssKey >> id;
534  WalletDescriptor desc;
535  ssValue >> desc;
536  if (wss.m_descriptor_caches.count(id) == 0) {
537  wss.m_descriptor_caches[id] = DescriptorCache();
538  }
539  pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
540  } else if (strType == DBKeys::WALLETDESCRIPTORCACHE) {
541  bool parent = true;
542  uint256 desc_id;
543  uint32_t key_exp_index;
544  uint32_t der_index;
545  ssKey >> desc_id;
546  ssKey >> key_exp_index;
547 
548  // if the der_index exists, it's a derived xpub
549  try {
550  ssKey >> der_index;
551  parent = false;
552  } catch (...) {
553  }
554 
555  std::vector<uint8_t> ser_xpub(BIP32_EXTKEY_SIZE);
556  ssValue >> ser_xpub;
557  CExtPubKey xpub;
558  xpub.Decode(ser_xpub.data());
559  if (wss.m_descriptor_caches.count(desc_id)) {
560  wss.m_descriptor_caches[desc_id] = DescriptorCache();
561  }
562  if (parent) {
563  wss.m_descriptor_caches[desc_id].CacheParentExtPubKey(
564  key_exp_index, xpub);
565  } else {
566  wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(
567  key_exp_index, der_index, xpub);
568  }
569  } else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
570  uint256 desc_id;
571  CPubKey pubkey;
572  ssKey >> desc_id;
573  ssKey >> pubkey;
574  if (!pubkey.IsValid()) {
575  strErr = "Error reading wallet database: CPubKey corrupt";
576  return false;
577  }
578  CKey key;
579  CPrivKey pkey;
580  uint256 hash;
581 
582  wss.nKeys++;
583  ssValue >> pkey;
584  ssValue >> hash;
585 
586  // hash pubkey/privkey to accelerate wallet load
587  std::vector<uint8_t> to_hash;
588  to_hash.reserve(pubkey.size() + pkey.size());
589  to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
590  to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
591 
592  if (Hash(to_hash.begin(), to_hash.end()) != hash) {
593  strErr =
594  "Error reading wallet database: CPubKey/CPrivKey corrupt";
595  return false;
596  }
597 
598  if (!key.Load(pkey, pubkey, true)) {
599  strErr = "Error reading wallet database: CPrivKey corrupt";
600  return false;
601  }
602  wss.m_descriptor_keys.insert(
603  std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
604  } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
605  uint256 desc_id;
606  CPubKey pubkey;
607  ssKey >> desc_id;
608  ssKey >> pubkey;
609  if (!pubkey.IsValid()) {
610  strErr = "Error reading wallet database: CPubKey corrupt";
611  return false;
612  }
613  std::vector<uint8_t> privkey;
614  ssValue >> privkey;
615  wss.nCKeys++;
616 
617  wss.m_descriptor_crypt_keys.insert(
618  std::make_pair(std::make_pair(desc_id, pubkey.GetID()),
619  std::make_pair(pubkey, privkey)));
620  wss.fIsEncrypted = true;
621  } else if (strType != DBKeys::BESTBLOCK &&
622  strType != DBKeys::BESTBLOCK_NOMERKLE &&
623  strType != DBKeys::MINVERSION &&
624  strType != DBKeys::ACENTRY && strType != DBKeys::VERSION &&
625  strType != DBKeys::SETTINGS) {
626  wss.m_unknown_records++;
627  }
628  } catch (const std::exception &e) {
629  if (strErr.empty()) {
630  strErr = e.what();
631  }
632  return false;
633  } catch (...) {
634  if (strErr.empty()) {
635  strErr = "Caught unknown exception in ReadKeyValue";
636  }
637  return false;
638  }
639  return true;
640 }
641 
642 bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue,
643  std::string &strType, std::string &strErr) {
644  CWalletScanState dummy_wss;
645  LOCK(pwallet->cs_wallet);
646  return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr);
647 }
648 
649 bool WalletBatch::IsKeyType(const std::string &strType) {
650  return (strType == DBKeys::KEY || strType == DBKeys::MASTER_KEY ||
651  strType == DBKeys::CRYPTED_KEY);
652 }
653 
655  CWalletScanState wss;
656  bool fNoncriticalErrors = false;
657  DBErrors result = DBErrors::LOAD_OK;
658 
659  LOCK(pwallet->cs_wallet);
660  try {
661  int nMinVersion = 0;
662  if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
663  if (nMinVersion > FEATURE_LATEST) {
664  return DBErrors::TOO_NEW;
665  }
666  pwallet->LoadMinVersion(nMinVersion);
667  }
668 
669  // Get cursor
670  Dbc *pcursor = m_batch.GetCursor();
671  if (!pcursor) {
672  pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
673  return DBErrors::CORRUPT;
674  }
675 
676  while (true) {
677  // Read next record
680  int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
681  if (ret == DB_NOTFOUND) {
682  break;
683  }
684 
685  if (ret != 0) {
686  pwallet->WalletLogPrintf(
687  "Error reading next record from wallet database\n");
688  return DBErrors::CORRUPT;
689  }
690 
691  // Try to be tolerant of single corrupt records:
692  std::string strType, strErr;
693  if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) {
694  // losing keys is considered a catastrophic error, anything else
695  // we assume the user can live with:
696  if (IsKeyType(strType) || strType == DBKeys::DEFAULTKEY) {
697  result = DBErrors::CORRUPT;
698  } else if (strType == DBKeys::FLAGS) {
699  // Reading the wallet flags can only fail if unknown flags
700  // are present.
701  result = DBErrors::TOO_NEW;
702  } else {
703  // Leave other errors alone, if we try to fix them we might
704  // make things worse. But do warn the user there is
705  // something wrong.
706  fNoncriticalErrors = true;
707  if (strType == DBKeys::TX) {
708  // Rescan if there is a bad transaction record:
709  gArgs.SoftSetBoolArg("-rescan", true);
710  }
711  }
712  }
713  if (!strErr.empty()) {
714  pwallet->WalletLogPrintf("%s\n", strErr);
715  }
716  }
717  pcursor->close();
718  } catch (...) {
719  result = DBErrors::CORRUPT;
720  }
721 
722  // Set the active ScriptPubKeyMans
723  for (auto spk_man_pair : wss.m_active_external_spks) {
724  pwallet->SetActiveScriptPubKeyMan(
725  spk_man_pair.second, spk_man_pair.first, /* internal */ false,
726  /* memonly */ true);
727  }
728  for (auto spk_man_pair : wss.m_active_internal_spks) {
729  pwallet->SetActiveScriptPubKeyMan(
730  spk_man_pair.second, spk_man_pair.first, /* internal */ true,
731  /* memonly */ true);
732  }
733 
734  // Set the descriptor caches
735  for (auto desc_cache_pair : wss.m_descriptor_caches) {
736  auto spk_man = pwallet->GetScriptPubKeyMan(desc_cache_pair.first);
737  assert(spk_man);
738  ((DescriptorScriptPubKeyMan *)spk_man)
739  ->SetCache(desc_cache_pair.second);
740  }
741 
742  // Set the descriptor keys
743  for (auto desc_key_pair : wss.m_descriptor_keys) {
744  auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
745  ((DescriptorScriptPubKeyMan *)spk_man)
746  ->AddKey(desc_key_pair.first.second, desc_key_pair.second);
747  }
748  for (auto desc_key_pair : wss.m_descriptor_crypt_keys) {
749  auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
750  ((DescriptorScriptPubKeyMan *)spk_man)
751  ->AddCryptedKey(desc_key_pair.first.second,
752  desc_key_pair.second.first,
753  desc_key_pair.second.second);
754  }
755 
756  if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
758  }
759 
760  // Any wallet corruption at all: skip any rewriting or upgrading, we don't
761  // want to make it worse.
762  if (result != DBErrors::LOAD_OK) {
763  return result;
764  }
765 
766  // Last client version to open this wallet, was previously the file version
767  // number
768  int last_client = CLIENT_VERSION;
769  m_batch.Read(DBKeys::VERSION, last_client);
770 
771  int wallet_version = pwallet->GetVersion();
772  pwallet->WalletLogPrintf("Wallet File Version = %d\n",
773  wallet_version > 0 ? wallet_version : last_client);
774 
775  pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ "
776  "metadata, %u total. Unknown wallet records: %u\n",
777  wss.nKeys, wss.nCKeys, wss.nKeyMeta,
778  wss.nKeys + wss.nCKeys, wss.m_unknown_records);
779 
780  // nTimeFirstKey is only reliable if all keys have metadata
781  if (pwallet->IsLegacy() &&
782  (wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) {
783  auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan();
784  if (spk_man) {
785  LOCK(spk_man->cs_KeyStore);
786  spk_man->UpdateTimeFirstKey(1);
787  }
788  }
789 
790  for (const TxId &txid : wss.vWalletUpgrade) {
791  WriteTx(pwallet->mapWallet.at(txid));
792  }
793 
794  // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
795  if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000)) {
796  return DBErrors::NEED_REWRITE;
797  }
798 
799  if (last_client < CLIENT_VERSION) {
800  // Update
801  m_batch.Write(DBKeys::VERSION, CLIENT_VERSION);
802  }
803 
804  if (wss.fAnyUnordered) {
805  result = pwallet->ReorderTransactions();
806  }
807 
808  // Upgrade all of the wallet keymetadata to have the hd master key id
809  // This operation is not atomic, but if it fails, updated entries are still
810  // backwards compatible with older software
811  try {
812  pwallet->UpgradeKeyMetadata();
813  } catch (...) {
814  result = DBErrors::CORRUPT;
815  }
816 
817  return result;
818 }
819 
820 DBErrors WalletBatch::FindWalletTx(std::vector<TxId> &txIds,
821  std::vector<CWalletTx> &vWtx) {
822  DBErrors result = DBErrors::LOAD_OK;
823 
824  try {
825  int nMinVersion = 0;
826  if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
827  if (nMinVersion > FEATURE_LATEST) {
828  return DBErrors::TOO_NEW;
829  }
830  }
831 
832  // Get cursor
833  Dbc *pcursor = m_batch.GetCursor();
834  if (!pcursor) {
835  LogPrintf("Error getting wallet database cursor\n");
836  return DBErrors::CORRUPT;
837  }
838 
839  while (true) {
840  // Read next record
843  int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
844  if (ret == DB_NOTFOUND) {
845  break;
846  }
847 
848  if (ret != 0) {
849  LogPrintf("Error reading next record from wallet database\n");
850  return DBErrors::CORRUPT;
851  }
852 
853  std::string strType;
854  ssKey >> strType;
855  if (strType == DBKeys::TX) {
856  TxId txid;
857  ssKey >> txid;
858 
859  CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
860  ssValue >> wtx;
861 
862  txIds.push_back(txid);
863  vWtx.push_back(wtx);
864  }
865  }
866  pcursor->close();
867  } catch (...) {
868  result = DBErrors::CORRUPT;
869  }
870 
871  return result;
872 }
873 
874 DBErrors WalletBatch::ZapSelectTx(std::vector<TxId> &txIdsIn,
875  std::vector<TxId> &txIdsOut) {
876  // Build list of wallet TXs and hashes.
877  std::vector<TxId> txIds;
878  std::vector<CWalletTx> vWtx;
879  DBErrors err = FindWalletTx(txIds, vWtx);
880  if (err != DBErrors::LOAD_OK) {
881  return err;
882  }
883 
884  std::sort(txIds.begin(), txIds.end());
885  std::sort(txIdsIn.begin(), txIdsIn.end());
886 
887  // Erase each matching wallet TX.
888  bool delerror = false;
889  std::vector<TxId>::iterator it = txIdsIn.begin();
890  for (const TxId &txid : txIds) {
891  while (it < txIdsIn.end() && (*it) < txid) {
892  it++;
893  }
894  if (it == txIdsIn.end()) {
895  break;
896  }
897 
898  if ((*it) == txid) {
899  if (!EraseTx(txid)) {
901  "Transaction was found for deletion but returned "
902  "database error: %s\n",
903  txid.GetHex());
904  delerror = true;
905  }
906  txIdsOut.push_back(txid);
907  }
908  }
909 
910  if (delerror) {
911  return DBErrors::CORRUPT;
912  }
913  return DBErrors::LOAD_OK;
914 }
915 
916 DBErrors WalletBatch::ZapWalletTx(std::vector<CWalletTx> &vWtx) {
917  // Build list of wallet TXs.
918  std::vector<TxId> txIds;
919  DBErrors err = FindWalletTx(txIds, vWtx);
920  if (err != DBErrors::LOAD_OK) {
921  return err;
922  }
923 
924  // Erase each wallet TX.
925  for (const TxId &txid : txIds) {
926  if (!EraseTx(txid)) {
927  return DBErrors::CORRUPT;
928  }
929  }
930 
931  return DBErrors::LOAD_OK;
932 }
933 
935  static std::atomic<bool> fOneThread;
936  if (fOneThread.exchange(true)) {
937  return;
938  }
939 
940  for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) {
941  WalletDatabase &dbh = pwallet->GetDBHandle();
942 
943  unsigned int nUpdateCounter = dbh.nUpdateCounter;
944 
945  if (dbh.nLastSeen != nUpdateCounter) {
946  dbh.nLastSeen = nUpdateCounter;
947  dbh.nLastWalletUpdate = GetTime();
948  }
949 
950  if (dbh.nLastFlushed != nUpdateCounter &&
951  GetTime() - dbh.nLastWalletUpdate >= 2) {
952  if (dbh.PeriodicFlush()) {
953  dbh.nLastFlushed = nUpdateCounter;
954  }
955  }
956  }
957 
958  fOneThread = false;
959 }
960 
962  const std::string &key,
963  const std::string &value) {
964  if (!IsValidDestination(address)) {
965  return false;
966  }
967  return WriteIC(
968  std::make_pair(
970  std::make_pair(EncodeLegacyAddr(address, Params()), key)),
971  value);
972 }
973 
975  const std::string &key) {
976  if (!IsValidDestination(address)) {
977  return false;
978  }
979  return EraseIC(std::make_pair(
981  std::make_pair(EncodeLegacyAddr(address, Params()), key)));
982 }
983 
985  return WriteIC(DBKeys::HDCHAIN, chain);
986 }
987 
988 bool WalletBatch::WriteWalletFlags(const uint64_t flags) {
989  return WriteIC(DBKeys::FLAGS, flags);
990 }
991 
993  return m_batch.TxnBegin();
994 }
995 
997  return m_batch.TxnCommit();
998 }
999 
1001  return m_batch.TxnAbort();
1002 }
1003 
1004 bool IsWalletLoaded(const fs::path &wallet_path) {
1005  return IsBDBWalletLoaded(wallet_path);
1006 }
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:996
void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly=false)
Sets the active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:4929
unsigned int nKeyMeta
Definition: walletdb.cpp:269
const std::string POOL
Definition: walletdb.cpp:40
unsigned int nKeys
Definition: walletdb.cpp:266
const std::string FLAGS
Definition: walletdb.cpp:31
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:4952
unsigned int nWatchKeys
Definition: walletdb.cpp:268
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:174
std::map< OutputType, uint256 > m_active_internal_spks
Definition: walletdb.cpp:275
#define LogPrint(category,...)
Definition: logging.h:189
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: dummywallet.cpp:53
const std::string NAME
Definition: walletdb.cpp:37
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:110
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition: wallet.cpp:312
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: system.cpp:515
const std::string SETTINGS
Definition: walletdb.cpp:42
const std::string WALLETDESCRIPTORCKEY
Definition: walletdb.cpp:47
unsigned int nLastSeen
Definition: bdb.h:174
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
Definition: walletdb.cpp:241
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
std::map< OutputType, uint256 > m_active_external_spks
Definition: walletdb.cpp:274
const std::string CRYPTED_KEY
Definition: walletdb.cpp:27
const std::string DEFAULTKEY
Definition: walletdb.cpp:29
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:197
static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, std::string &strType, std::string &strErr) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:285
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Definition: walletdb.cpp:984
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
Definition: walletdb.cpp:236
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
Definition: crypter.h:31
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
Definition: walletdb.cpp:974
bool PeriodicFlush()
Definition: bdb.cpp:689
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:339
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:269
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition: walletdb.cpp:152
const std::string KEYMETA
Definition: walletdb.cpp:33
std::vector< BlockHash > vHave
Definition: block.h:111
An instance of this class represents one database.
Definition: bdb.h:97
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:171
unsigned int m_unknown_records
Definition: walletdb.cpp:270
std::map< std::pair< uint256, CKeyID >, std::pair< CPubKey, std::vector< uint8_t > > > m_descriptor_crypt_keys
Definition: walletdb.cpp:280
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:992
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:196
DBErrors ZapWalletTx(std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:916
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:96
bool WriteName(const CTxDestination &address, const std::string &strName)
Definition: walletdb.cpp:57
unsigned int nCKeys
Definition: walletdb.cpp:267
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:654
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
Definition: walletdb.cpp:253
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:49
DBErrors FindWalletTx(std::vector< TxId > &txIds, std::vector< CWalletTx > &vWtx)
Definition: walletdb.cpp:820
const std::string ORDERPOSNEXT
Definition: walletdb.cpp:39
bool WriteWalletFlags(const uint64_t flags)
Definition: walletdb.cpp:988
const std::string VERSION
Definition: walletdb.cpp:44
const uint8_t * begin() const
Definition: pubkey.h:100
bool IsNull() const
Definition: uint256.h:26
OutputType
Definition: outputtype.h:17
const std::string MASTER_KEY
Definition: walletdb.cpp:35
std::vector< uint8_t, secure_allocator< uint8_t > > CPrivKey
secure_allocator is defined in allocators.h CPrivKey is a serialized private key, with all parameters...
Definition: key.h:22
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:160
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:326
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:167
bool TxnAbort()
Abort current transaction.
Definition: walletdb.cpp:1000
const std::string OLD_KEY
Definition: walletdb.cpp:38
DBErrors ReorderTransactions()
Definition: wallet.cpp:730
bool IsBDBWalletLoaded(const fs::path &wallet_path)
Return whether a BDB wallet database is currently loaded.
Definition: bdb.cpp:65
const std::string HDCHAIN
Definition: walletdb.cpp:32
static bool IsKeyType(const std::string &strType)
Definition: walletdb.cpp:649
const std::string WALLETDESCRIPTOR
Definition: walletdb.cpp:45
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:147
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:1437
const std::string ACTIVEINTERNALSPK
Definition: walletdb.cpp:24
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
Definition: walletdb.cpp:78
#define LOCK(cs)
Definition: sync.h:230
An encapsulated public key.
Definition: pubkey.h:31
const std::string WATCHMETA
Definition: walletdb.cpp:49
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:142
bool EraseName(const CTxDestination &address)
Definition: walletdb.cpp:67
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:934
const std::string WALLETDESCRIPTORKEY
Definition: walletdb.cpp:48
const std::string DESTDATA
Definition: walletdb.cpp:30
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:4848
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:72
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:181
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:4773
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:98
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
Descriptor with some wallet metadata.
Definition: walletutil.h:99
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< uint8_t > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:127
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:280
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
Definition: walletdb.cpp:104
std::map< uint256, DescriptorCache > m_descriptor_caches
Definition: walletdb.cpp:276
const std::string WALLETDESCRIPTORCACHE
Definition: walletdb.cpp:46
int flags
Definition: bitcoin-tx.cpp:529
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:193
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:189
bool ErasePurpose(const CTxDestination &address)
Definition: walletdb.cpp:88
256-bit opaque blob.
Definition: uint256.h:120
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
Definition: walletdb.cpp:961
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< uint8_t > &secret)
Definition: walletdb.cpp:223
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
const std::string ACENTRY
Definition: walletdb.cpp:22
int64_t nLastWalletUpdate
Definition: bdb.h:176
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:44
std::map< std::pair< uint256, CKeyID >, CKey > m_descriptor_keys
Definition: walletdb.cpp:277
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition: walletdb.cpp:201
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet) ...
Definition: wallet.h:1284
const CChainParams & Params()
Return the currently selected parameters.
Cache for single descriptor&#39;s derived extended pubkeys.
Definition: descriptor.h:18
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:429
A TxId is the identifier of a transaction.
Definition: txid.h:14
unsigned int nLastFlushed
Definition: bdb.h:175
const std::string MINVERSION
Definition: walletdb.cpp:36
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
const std::string ACTIVEEXTERNALSPK
Definition: walletdb.cpp:23
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:679
ArgsManager gArgs
Definition: system.cpp:76
160-bit opaque blob.
Definition: uint256.h:108
std::atomic< unsigned int > nUpdateCounter
Definition: bdb.h:173
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:185
RecursiveMutex cs_wallet
Definition: wallet.h:823
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.h:991
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:110
const std::string WATCHS
Definition: walletdb.cpp:50
An encapsulated secp256k1 private key.
Definition: key.h:25
const uint8_t * end() const
Definition: pubkey.h:101
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut)
Definition: walletdb.cpp:874
const std::string BESTBLOCK
Definition: walletdb.cpp:26
const std::string CSCRIPT
Definition: walletdb.cpp:28
std::vector< TxId > vWalletUpgrade
Definition: walletdb.cpp:273
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:100
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:27
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:314
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &params)
Definition: key_io.cpp:191
const std::string BESTBLOCK_NOMERKLE
Definition: walletdb.cpp:25
const std::string TX
Definition: walletdb.cpp:43
const std::string KEY
Definition: walletdb.cpp:34
TxId GetId() const
Definition: wallet.h:593
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:87
bool IsWalletLoaded(const fs::path &wallet_path)
Return whether a wallet database is currently loaded.
Definition: walletdb.cpp:1004
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:340
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
Definition: walletdb.cpp:208
A key from a CWallet&#39;s keypool.
const std::string PURPOSE
Definition: walletdb.cpp:41