Bitcoin ABC  0.24.7
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/bip32.h>
16 #include <util/system.h>
17 #include <util/time.h>
18 #include <util/translation.h>
19 #include <wallet/bdb.h>
20 #include <wallet/wallet.h>
21 
22 #include <atomic>
23 
24 namespace DBKeys {
25 const std::string ACENTRY{"acentry"};
26 const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};
27 const std::string ACTIVEINTERNALSPK{"activeinternalspk"};
28 const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
29 const std::string BESTBLOCK{"bestblock"};
30 const std::string CRYPTED_KEY{"ckey"};
31 const std::string CSCRIPT{"cscript"};
32 const std::string DEFAULTKEY{"defaultkey"};
33 const std::string DESTDATA{"destdata"};
34 const std::string FLAGS{"flags"};
35 const std::string HDCHAIN{"hdchain"};
36 const std::string KEYMETA{"keymeta"};
37 const std::string KEY{"key"};
38 const std::string MASTER_KEY{"mkey"};
39 const std::string MINVERSION{"minversion"};
40 const std::string NAME{"name"};
41 const std::string OLD_KEY{"wkey"};
42 const std::string ORDERPOSNEXT{"orderposnext"};
43 const std::string POOL{"pool"};
44 const std::string PURPOSE{"purpose"};
45 const std::string SETTINGS{"settings"};
46 const std::string TX{"tx"};
47 const std::string VERSION{"version"};
48 const std::string WALLETDESCRIPTOR{"walletdescriptor"};
49 const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
50 const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
51 const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
52 const std::string WATCHMETA{"watchmeta"};
53 const std::string WATCHS{"watchs"};
54 } // namespace DBKeys
55 
56 //
57 // WalletBatch
58 //
59 
61  const std::string &strName) {
62  if (!IsValidDestination(address)) {
63  return false;
64  }
65  return WriteIC(
66  std::make_pair(DBKeys::NAME, EncodeLegacyAddr(address, Params())),
67  strName);
68 }
69 
70 bool WalletBatch::EraseName(const CTxDestination &address) {
71  // This should only be used for sending addresses, never for receiving
72  // addresses, receiving addresses must always have an address book entry if
73  // they're not change return.
74  if (!IsValidDestination(address)) {
75  return false;
76  }
77  return EraseIC(
78  std::make_pair(DBKeys::NAME, EncodeLegacyAddr(address, Params())));
79 }
80 
82  const std::string &strPurpose) {
83  if (!IsValidDestination(address)) {
84  return false;
85  }
86  return WriteIC(
87  std::make_pair(DBKeys::PURPOSE, EncodeLegacyAddr(address, Params())),
88  strPurpose);
89 }
90 
92  if (!IsValidDestination(address)) {
93  return false;
94  }
95  return EraseIC(
96  std::make_pair(DBKeys::PURPOSE, EncodeLegacyAddr(address, Params())));
97 }
98 
99 bool WalletBatch::WriteTx(const CWalletTx &wtx) {
100  return WriteIC(std::make_pair(DBKeys::TX, wtx.GetId()), wtx);
101 }
102 
104  return EraseIC(std::make_pair(DBKeys::TX, hash));
105 }
106 
108  const CPubKey &pubkey,
109  const bool overwrite) {
110  return WriteIC(std::make_pair(DBKeys::KEYMETA, pubkey), meta, overwrite);
111 }
112 
113 bool WalletBatch::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey,
114  const CKeyMetadata &keyMeta) {
115  if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {
116  return false;
117  }
118 
119  // hash pubkey/privkey to accelerate wallet load
120  std::vector<uint8_t> vchKey;
121  vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
122  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
123  vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
124 
125  return WriteIC(std::make_pair(DBKeys::KEY, vchPubKey),
126  std::make_pair(vchPrivKey, Hash(vchKey)), false);
127 }
128 
129 bool WalletBatch::WriteCryptedKey(const CPubKey &vchPubKey,
130  const std::vector<uint8_t> &vchCryptedSecret,
131  const CKeyMetadata &keyMeta) {
132  if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {
133  return false;
134  }
135 
136  // Compute a checksum of the encrypted key
137  uint256 checksum = Hash(vchCryptedSecret);
138 
139  const auto key = std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey);
140  if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) {
141  // It may already exist, so try writing just the checksum
142  std::vector<uint8_t> val;
143  if (!m_batch->Read(key, val)) {
144  return false;
145  }
146  if (!WriteIC(key, std::make_pair(val, checksum), true)) {
147  return false;
148  }
149  }
150  EraseIC(std::make_pair(DBKeys::KEY, vchPubKey));
151  return true;
152 }
153 
154 bool WalletBatch::WriteMasterKey(unsigned int nID,
155  const CMasterKey &kMasterKey) {
156  return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);
157 }
158 
160  const CScript &redeemScript) {
161  return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
162 }
163 
165  const CKeyMetadata &keyMeta) {
166  if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {
167  return false;
168  }
169  return WriteIC(std::make_pair(DBKeys::WATCHS, dest), '1');
170 }
171 
173  if (!EraseIC(std::make_pair(DBKeys::WATCHMETA, dest))) {
174  return false;
175  }
176  return EraseIC(std::make_pair(DBKeys::WATCHS, dest));
177 }
178 
180  // Write empty block locator so versions that require a merkle branch
181  // automatically rescan
183  return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator);
184 }
185 
187  if (m_batch->Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) {
188  return true;
189  }
190  return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
191 }
192 
193 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) {
194  return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);
195 }
196 
197 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool &keypool) {
198  return m_batch->Read(std::make_pair(DBKeys::POOL, nPool), keypool);
199 }
200 
201 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool &keypool) {
202  return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool);
203 }
204 
205 bool WalletBatch::ErasePool(int64_t nPool) {
206  return EraseIC(std::make_pair(DBKeys::POOL, nPool));
207 }
208 
209 bool WalletBatch::WriteMinVersion(int nVersion) {
210  return WriteIC(DBKeys::MINVERSION, nVersion);
211 }
212 
214  bool internal) {
215  std::string key =
217  return WriteIC(make_pair(key, type), id);
218 }
219 
221  const CPubKey &pubkey,
222  const CPrivKey &privkey) {
223  // hash pubkey/privkey to accelerate wallet load
224  std::vector<uint8_t> key;
225  key.reserve(pubkey.size() + privkey.size());
226  key.insert(key.end(), pubkey.begin(), pubkey.end());
227  key.insert(key.end(), privkey.begin(), privkey.end());
228 
229  return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY,
230  std::make_pair(desc_id, pubkey)),
231  std::make_pair(privkey, Hash(key)), false);
232 }
233 
235  const uint256 &desc_id, const CPubKey &pubkey,
236  const std::vector<uint8_t> &secret) {
237  if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY,
238  std::make_pair(desc_id, pubkey)),
239  secret, false)) {
240  return false;
241  }
242  EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY,
243  std::make_pair(desc_id, pubkey)));
244  return true;
245 }
246 
248  const WalletDescriptor &descriptor) {
249  return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor);
250 }
251 
253  const uint256 &desc_id,
254  uint32_t key_exp_index,
255  uint32_t der_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  std::make_pair(key_exp_index, der_index)),
261  ser_xpub);
262 }
263 
265  const uint256 &desc_id,
266  uint32_t key_exp_index) {
267  std::vector<uint8_t> ser_xpub(BIP32_EXTKEY_SIZE);
268  xpub.Encode(ser_xpub.data());
269  return WriteIC(
270  std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id),
271  key_exp_index),
272  ser_xpub);
273 }
274 
276 public:
277  unsigned int nKeys{0};
278  unsigned int nCKeys{0};
279  unsigned int nWatchKeys{0};
280  unsigned int nKeyMeta{0};
281  unsigned int m_unknown_records{0};
282  bool fIsEncrypted{false};
283  bool fAnyUnordered{false};
284  std::vector<TxId> vWalletUpgrade;
285  std::map<OutputType, uint256> m_active_external_spks;
286  std::map<OutputType, uint256> m_active_internal_spks;
287  std::map<uint256, DescriptorCache> m_descriptor_caches;
288  std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys;
289  std::map<std::pair<uint256, CKeyID>,
290  std::pair<CPubKey, std::vector<uint8_t>>>
292  std::map<uint160, CHDChain> m_hd_chains;
293 
295 };
296 
297 static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey,
298  CDataStream &ssValue, CWalletScanState &wss,
299  std::string &strType, std::string &strErr,
300  const KeyFilterFn &filter_fn = nullptr)
301  EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
302  try {
303  // Unserialize
304  // Taking advantage of the fact that pair serialization is just the two
305  // items serialized one after the other.
306  ssKey >> strType;
307  // If we have a filter, check if this matches the filter
308  if (filter_fn && !filter_fn(strType)) {
309  return true;
310  }
311  if (strType == DBKeys::NAME) {
312  std::string strAddress;
313  ssKey >> strAddress;
314  std::string label;
315  ssValue >> label;
316  pwallet
317  ->m_address_book[DecodeDestination(strAddress,
318  pwallet->GetChainParams())]
319  .SetLabel(label);
320  } else if (strType == DBKeys::PURPOSE) {
321  std::string strAddress;
322  ssKey >> strAddress;
323  ssValue >> pwallet
324  ->m_address_book[DecodeDestination(
325  strAddress, pwallet->GetChainParams())]
326  .purpose;
327  } else if (strType == DBKeys::TX) {
328  TxId txid;
329  ssKey >> txid;
330  // LoadToWallet call below creates a new CWalletTx that fill_wtx
331  // callback fills with transaction metadata.
332  auto fill_wtx = [&](CWalletTx &wtx, bool new_tx) {
333  assert(new_tx);
334  ssValue >> wtx;
335  if (wtx.GetId() != txid) {
336  return false;
337  }
338 
339  // Undo serialize changes in 31600
340  if (31404 <= wtx.fTimeReceivedIsTxTime &&
341  wtx.fTimeReceivedIsTxTime <= 31703) {
342  if (!ssValue.empty()) {
343  char fTmp;
344  char fUnused;
345  std::string unused_string;
346  ssValue >> fTmp >> fUnused >> unused_string;
347  strErr = strprintf(
348  "LoadWallet() upgrading tx ver=%d %d %s",
349  wtx.fTimeReceivedIsTxTime, fTmp, txid.ToString());
350  wtx.fTimeReceivedIsTxTime = fTmp;
351  } else {
352  strErr = strprintf(
353  "LoadWallet() repairing tx ver=%d %s",
354  wtx.fTimeReceivedIsTxTime, txid.ToString());
355  wtx.fTimeReceivedIsTxTime = 0;
356  }
357  wss.vWalletUpgrade.push_back(txid);
358  }
359 
360  if (wtx.nOrderPos == -1) {
361  wss.fAnyUnordered = true;
362  }
363 
364  return true;
365  };
366  if (!pwallet->LoadToWallet(txid, fill_wtx)) {
367  return false;
368  }
369  } else if (strType == DBKeys::WATCHS) {
370  wss.nWatchKeys++;
371  CScript script;
372  ssKey >> script;
373  char fYes;
374  ssValue >> fYes;
375  if (fYes == '1') {
377  script);
378  }
379  } else if (strType == DBKeys::KEY) {
380  CPubKey vchPubKey;
381  ssKey >> vchPubKey;
382  if (!vchPubKey.IsValid()) {
383  strErr = "Error reading wallet database: CPubKey corrupt";
384  return false;
385  }
386  CKey key;
387  CPrivKey pkey;
388  uint256 hash;
389 
390  wss.nKeys++;
391  ssValue >> pkey;
392 
393  // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey] ...
394  // which was slow for wallets with lots of keys, because the public
395  // key is re-derived from the private key using EC operations as a
396  // checksum. Newer wallets store keys as DBKeys::KEY [pubkey] =>
397  // [privkey][hash(pubkey,privkey)], which is much faster while
398  // remaining backwards-compatible.
399  try {
400  ssValue >> hash;
401  } catch (...) {
402  }
403 
404  bool fSkipCheck = false;
405 
406  if (!hash.IsNull()) {
407  // hash pubkey/privkey to accelerate wallet load
408  std::vector<uint8_t> vchKey;
409  vchKey.reserve(vchPubKey.size() + pkey.size());
410  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
411  vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
412 
413  if (Hash(vchKey) != hash) {
414  strErr = "Error reading wallet database: CPubKey/CPrivKey "
415  "corrupt";
416  return false;
417  }
418 
419  fSkipCheck = true;
420  }
421 
422  if (!key.Load(pkey, vchPubKey, fSkipCheck)) {
423  strErr = "Error reading wallet database: CPrivKey corrupt";
424  return false;
425  }
426  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(
427  key, vchPubKey)) {
428  strErr = "Error reading wallet database: "
429  "LegacyScriptPubKeyMan::LoadKey failed";
430  return false;
431  }
432  } else if (strType == DBKeys::MASTER_KEY) {
433  // Master encryption key is loaded into only the wallet and not any
434  // of the ScriptPubKeyMans.
435  unsigned int nID;
436  ssKey >> nID;
437  CMasterKey kMasterKey;
438  ssValue >> kMasterKey;
439  if (pwallet->mapMasterKeys.count(nID) != 0) {
440  strErr = strprintf(
441  "Error reading wallet database: duplicate CMasterKey id %u",
442  nID);
443  return false;
444  }
445  pwallet->mapMasterKeys[nID] = kMasterKey;
446  if (pwallet->nMasterKeyMaxID < nID) {
447  pwallet->nMasterKeyMaxID = nID;
448  }
449  } else if (strType == DBKeys::CRYPTED_KEY) {
450  CPubKey vchPubKey;
451  ssKey >> vchPubKey;
452  if (!vchPubKey.IsValid()) {
453  strErr = "Error reading wallet database: CPubKey corrupt";
454  return false;
455  }
456  std::vector<uint8_t> vchPrivKey;
457  ssValue >> vchPrivKey;
458 
459  // Get the checksum and check it
460  bool checksum_valid = false;
461  if (!ssValue.eof()) {
462  uint256 checksum;
463  ssValue >> checksum;
464  if ((checksum_valid = Hash(vchPrivKey) != checksum)) {
465  strErr =
466  "Error reading wallet database: Crypted key corrupt";
467  return false;
468  }
469  }
470 
471  wss.nCKeys++;
472 
474  vchPubKey, vchPrivKey, checksum_valid)) {
475  strErr = "Error reading wallet database: "
476  "LegacyScriptPubKeyMan::LoadCryptedKey failed";
477  return false;
478  }
479  wss.fIsEncrypted = true;
480  } else if (strType == DBKeys::KEYMETA) {
481  CPubKey vchPubKey;
482  ssKey >> vchPubKey;
483  CKeyMetadata keyMeta;
484  ssValue >> keyMeta;
485  wss.nKeyMeta++;
487  vchPubKey.GetID(), keyMeta);
488 
489  // Extract some CHDChain info from this metadata if it has any
490  if (keyMeta.nVersion >= CKeyMetadata::VERSION_WITH_HDDATA &&
491  !keyMeta.hd_seed_id.IsNull() && keyMeta.hdKeypath.size() > 0) {
492  // Get the path from the key origin or from the path string
493  // Not applicable when path is "s" or "m" as those indicate a
494  // seed.
495  // See https://reviews.bitcoinabc.org/D4175
496  bool internal = false;
497  uint32_t index = 0;
498  if (keyMeta.hdKeypath != "s" && keyMeta.hdKeypath != "m") {
499  std::vector<uint32_t> path;
500  if (keyMeta.has_key_origin) {
501  // We have a key origin, so pull it from its path vector
502  path = keyMeta.key_origin.path;
503  } else {
504  // No key origin, have to parse the string
505  if (!ParseHDKeypath(keyMeta.hdKeypath, path)) {
506  strErr = "Error reading wallet database: keymeta "
507  "with invalid HD keypath";
508  return false;
509  }
510  }
511 
512  // Extract the index and internal from the path
513  // Path string is m/0'/k'/i'
514  // Path vector is [0', k', i'] (but as ints OR'd with the
515  // hardened bit k == 0 for external, 1 for internal. i is
516  // the index
517  if (path.size() != 3) {
518  strErr = "Error reading wallet database: keymeta found "
519  "with unexpected path";
520  return false;
521  }
522  if (path[0] != 0x80000000) {
523  strErr = strprintf(
524  "Unexpected path index of 0x%08x (expected "
525  "0x80000000) for the element at index 0",
526  path[0]);
527  return false;
528  }
529  if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
530  strErr =
531  strprintf("Unexpected path index of 0x%08x "
532  "(expected 0x80000000 or 0x80000001) for "
533  "the element at index 1",
534  path[1]);
535  return false;
536  }
537  if ((path[2] & 0x80000000) == 0) {
538  strErr = strprintf(
539  "Unexpected path index of 0x%08x (expected to be "
540  "greater than or equal to 0x80000000)",
541  path[2]);
542  return false;
543  }
544  internal = path[1] == (1 | 0x80000000);
545  index = path[2] & ~0x80000000;
546  }
547 
548  // Insert a new CHDChain, or get the one that already exists
549  auto ins =
550  wss.m_hd_chains.emplace(keyMeta.hd_seed_id, CHDChain());
551  CHDChain &chain = ins.first->second;
552  if (ins.second) {
553  // For new chains, we want to default to VERSION_HD_BASE
554  // until we see an internal
556  chain.seed_id = keyMeta.hd_seed_id;
557  }
558  if (internal) {
560  chain.nInternalChainCounter =
561  std::max(chain.nInternalChainCounter, index);
562  } else {
563  chain.nExternalChainCounter =
564  std::max(chain.nExternalChainCounter, index);
565  }
566  }
567  } else if (strType == DBKeys::WATCHMETA) {
568  CScript script;
569  ssKey >> script;
570  CKeyMetadata keyMeta;
571  ssValue >> keyMeta;
572  wss.nKeyMeta++;
574  CScriptID(script), keyMeta);
575  } else if (strType == DBKeys::DEFAULTKEY) {
576  // We don't want or need the default key, but if there is one set,
577  // we want to make sure that it is valid so that we can detect
578  // corruption
579  CPubKey vchPubKey;
580  ssValue >> vchPubKey;
581  if (!vchPubKey.IsValid()) {
582  strErr = "Error reading wallet database: Default Key corrupt";
583  return false;
584  }
585  } else if (strType == DBKeys::POOL) {
586  int64_t nIndex;
587  ssKey >> nIndex;
588  CKeyPool keypool;
589  ssValue >> keypool;
590 
592  keypool);
593  } else if (strType == DBKeys::CSCRIPT) {
594  uint160 hash;
595  ssKey >> hash;
596  CScript script;
597  ssValue >> script;
599  script)) {
600  strErr = "Error reading wallet database: "
601  "LegacyScriptPubKeyMan::LoadCScript failed";
602  return false;
603  }
604  } else if (strType == DBKeys::ORDERPOSNEXT) {
605  ssValue >> pwallet->nOrderPosNext;
606  } else if (strType == DBKeys::DESTDATA) {
607  std::string strAddress, strKey, strValue;
608  ssKey >> strAddress;
609  ssKey >> strKey;
610  ssValue >> strValue;
611  pwallet->LoadDestData(
612  DecodeDestination(strAddress, pwallet->GetChainParams()),
613  strKey, strValue);
614  } else if (strType == DBKeys::HDCHAIN) {
615  CHDChain chain;
616  ssValue >> chain;
618  } else if (strType == DBKeys::FLAGS) {
619  uint64_t flags;
620  ssValue >> flags;
621  if (!pwallet->LoadWalletFlags(flags)) {
622  strErr = "Error reading wallet database: Unknown non-tolerable "
623  "wallet flags found";
624  return false;
625  }
626  } else if (strType == DBKeys::OLD_KEY) {
627  strErr = "Found unsupported 'wkey' record, try loading with "
628  "version 0.20";
629  return false;
630  } else if (strType == DBKeys::ACTIVEEXTERNALSPK ||
631  strType == DBKeys::ACTIVEINTERNALSPK) {
632  uint8_t type;
633  ssKey >> type;
634  uint256 id;
635  ssValue >> id;
636 
637  bool internal = strType == DBKeys::ACTIVEINTERNALSPK;
638  auto &spk_mans = internal ? wss.m_active_internal_spks
640  if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
641  strErr =
642  "Multiple ScriptPubKeyMans specified for a single type";
643  return false;
644  }
645  spk_mans[static_cast<OutputType>(type)] = id;
646  } else if (strType == DBKeys::WALLETDESCRIPTOR) {
647  uint256 id;
648  ssKey >> id;
649  WalletDescriptor desc;
650  ssValue >> desc;
651  if (wss.m_descriptor_caches.count(id) == 0) {
653  }
654  pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
655  } else if (strType == DBKeys::WALLETDESCRIPTORCACHE) {
656  bool parent = true;
657  uint256 desc_id;
658  uint32_t key_exp_index;
659  uint32_t der_index;
660  ssKey >> desc_id;
661  ssKey >> key_exp_index;
662 
663  // if the der_index exists, it's a derived xpub
664  try {
665  ssKey >> der_index;
666  parent = false;
667  } catch (...) {
668  }
669 
670  std::vector<uint8_t> ser_xpub(BIP32_EXTKEY_SIZE);
671  ssValue >> ser_xpub;
672  CExtPubKey xpub;
673  xpub.Decode(ser_xpub.data());
674  if (parent) {
675  wss.m_descriptor_caches[desc_id].CacheParentExtPubKey(
676  key_exp_index, xpub);
677  } else {
678  wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(
679  key_exp_index, der_index, xpub);
680  }
681  } else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
682  uint256 desc_id;
683  CPubKey pubkey;
684  ssKey >> desc_id;
685  ssKey >> pubkey;
686  if (!pubkey.IsValid()) {
687  strErr = "Error reading wallet database: CPubKey corrupt";
688  return false;
689  }
690  CKey key;
691  CPrivKey pkey;
692  uint256 hash;
693 
694  wss.nKeys++;
695  ssValue >> pkey;
696  ssValue >> hash;
697 
698  // hash pubkey/privkey to accelerate wallet load
699  std::vector<uint8_t> to_hash;
700  to_hash.reserve(pubkey.size() + pkey.size());
701  to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
702  to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
703 
704  if (Hash(to_hash) != hash) {
705  strErr =
706  "Error reading wallet database: CPubKey/CPrivKey corrupt";
707  return false;
708  }
709 
710  if (!key.Load(pkey, pubkey, true)) {
711  strErr = "Error reading wallet database: CPrivKey corrupt";
712  return false;
713  }
714  wss.m_descriptor_keys.insert(
715  std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
716  } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
717  uint256 desc_id;
718  CPubKey pubkey;
719  ssKey >> desc_id;
720  ssKey >> pubkey;
721  if (!pubkey.IsValid()) {
722  strErr = "Error reading wallet database: CPubKey corrupt";
723  return false;
724  }
725  std::vector<uint8_t> privkey;
726  ssValue >> privkey;
727  wss.nCKeys++;
728 
729  wss.m_descriptor_crypt_keys.insert(
730  std::make_pair(std::make_pair(desc_id, pubkey.GetID()),
731  std::make_pair(pubkey, privkey)));
732  wss.fIsEncrypted = true;
733  } else if (strType != DBKeys::BESTBLOCK &&
734  strType != DBKeys::BESTBLOCK_NOMERKLE &&
735  strType != DBKeys::MINVERSION &&
736  strType != DBKeys::ACENTRY && strType != DBKeys::VERSION &&
737  strType != DBKeys::SETTINGS) {
738  wss.m_unknown_records++;
739  }
740  } catch (const std::exception &e) {
741  if (strErr.empty()) {
742  strErr = e.what();
743  }
744  return false;
745  } catch (...) {
746  if (strErr.empty()) {
747  strErr = "Caught unknown exception in ReadKeyValue";
748  }
749  return false;
750  }
751  return true;
752 }
753 
754 bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue,
755  std::string &strType, std::string &strErr,
756  const KeyFilterFn &filter_fn) {
757  CWalletScanState dummy_wss;
758  LOCK(pwallet->cs_wallet);
759  return ReadKeyValue(pwallet, ssKey, ssValue, dummy_wss, strType, strErr,
760  filter_fn);
761 }
762 
763 bool WalletBatch::IsKeyType(const std::string &strType) {
764  return (strType == DBKeys::KEY || strType == DBKeys::MASTER_KEY ||
765  strType == DBKeys::CRYPTED_KEY);
766 }
767 
769  CWalletScanState wss;
770  bool fNoncriticalErrors = false;
771  DBErrors result = DBErrors::LOAD_OK;
772 
773  LOCK(pwallet->cs_wallet);
774  try {
775  int nMinVersion = 0;
776  if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
777  if (nMinVersion > FEATURE_LATEST) {
778  return DBErrors::TOO_NEW;
779  }
780  pwallet->LoadMinVersion(nMinVersion);
781  }
782 
783  // Get cursor
784  if (!m_batch->StartCursor()) {
785  pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
786  return DBErrors::CORRUPT;
787  }
788 
789  while (true) {
790  // Read next record
793  bool complete;
794  bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
795  if (complete) {
796  break;
797  }
798  if (!ret) {
799  m_batch->CloseCursor();
800  pwallet->WalletLogPrintf(
801  "Error reading next record from wallet database\n");
802  return DBErrors::CORRUPT;
803  }
804 
805  // Try to be tolerant of single corrupt records:
806  std::string strType, strErr;
807  if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) {
808  // losing keys is considered a catastrophic error, anything else
809  // we assume the user can live with:
810  if (IsKeyType(strType) || strType == DBKeys::DEFAULTKEY) {
811  result = DBErrors::CORRUPT;
812  } else if (strType == DBKeys::FLAGS) {
813  // Reading the wallet flags can only fail if unknown flags
814  // are present.
815  result = DBErrors::TOO_NEW;
816  } else {
817  // Leave other errors alone, if we try to fix them we might
818  // make things worse. But do warn the user there is
819  // something wrong.
820  fNoncriticalErrors = true;
821  if (strType == DBKeys::TX) {
822  // Rescan if there is a bad transaction record:
823  gArgs.SoftSetBoolArg("-rescan", true);
824  }
825  }
826  }
827  if (!strErr.empty()) {
828  pwallet->WalletLogPrintf("%s\n", strErr);
829  }
830  }
831  } catch (...) {
832  result = DBErrors::CORRUPT;
833  }
834  m_batch->CloseCursor();
835 
836  // Set the active ScriptPubKeyMans
837  for (auto spk_man_pair : wss.m_active_external_spks) {
838  pwallet->LoadActiveScriptPubKeyMan(
839  spk_man_pair.second, spk_man_pair.first, /* internal */ false);
840  }
841  for (auto spk_man_pair : wss.m_active_internal_spks) {
842  pwallet->LoadActiveScriptPubKeyMan(
843  spk_man_pair.second, spk_man_pair.first, /* internal */ true);
844  }
845 
846  // Set the descriptor caches
847  for (auto desc_cache_pair : wss.m_descriptor_caches) {
848  auto spk_man = pwallet->GetScriptPubKeyMan(desc_cache_pair.first);
849  assert(spk_man);
850  ((DescriptorScriptPubKeyMan *)spk_man)
851  ->SetCache(desc_cache_pair.second);
852  }
853 
854  // Set the descriptor keys
855  for (auto desc_key_pair : wss.m_descriptor_keys) {
856  auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
857  ((DescriptorScriptPubKeyMan *)spk_man)
858  ->AddKey(desc_key_pair.first.second, desc_key_pair.second);
859  }
860  for (auto desc_key_pair : wss.m_descriptor_crypt_keys) {
861  auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
862  ((DescriptorScriptPubKeyMan *)spk_man)
863  ->AddCryptedKey(desc_key_pair.first.second,
864  desc_key_pair.second.first,
865  desc_key_pair.second.second);
866  }
867 
868  if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
870  }
871 
872  // Any wallet corruption at all: skip any rewriting or upgrading, we don't
873  // want to make it worse.
874  if (result != DBErrors::LOAD_OK) {
875  return result;
876  }
877 
878  // Last client version to open this wallet, was previously the file version
879  // number
880  int last_client = CLIENT_VERSION;
881  m_batch->Read(DBKeys::VERSION, last_client);
882 
883  int wallet_version = pwallet->GetVersion();
884  pwallet->WalletLogPrintf("Wallet File Version = %d\n",
885  wallet_version > 0 ? wallet_version : last_client);
886 
887  pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ "
888  "metadata, %u total. Unknown wallet records: %u\n",
889  wss.nKeys, wss.nCKeys, wss.nKeyMeta,
890  wss.nKeys + wss.nCKeys, wss.m_unknown_records);
891 
892  // nTimeFirstKey is only reliable if all keys have metadata
893  if (pwallet->IsLegacy() &&
894  (wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) {
895  auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan();
896  if (spk_man) {
897  LOCK(spk_man->cs_KeyStore);
898  spk_man->UpdateTimeFirstKey(1);
899  }
900  }
901 
902  for (const TxId &txid : wss.vWalletUpgrade) {
903  WriteTx(pwallet->mapWallet.at(txid));
904  }
905 
906  // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
907  if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000)) {
908  return DBErrors::NEED_REWRITE;
909  }
910 
911  if (last_client < CLIENT_VERSION) {
912  // Update
914  }
915 
916  if (wss.fAnyUnordered) {
917  result = pwallet->ReorderTransactions();
918  }
919 
920  // Upgrade all of the wallet keymetadata to have the hd master key id
921  // This operation is not atomic, but if it fails, updated entries are still
922  // backwards compatible with older software
923  try {
924  pwallet->UpgradeKeyMetadata();
925  } catch (...) {
926  result = DBErrors::CORRUPT;
927  }
928 
929  // Set the inactive chain
930  if (wss.m_hd_chains.size() > 0) {
931  LegacyScriptPubKeyMan *legacy_spkm =
932  pwallet->GetLegacyScriptPubKeyMan();
933  if (!legacy_spkm) {
934  pwallet->WalletLogPrintf(
935  "Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
936  return DBErrors::CORRUPT;
937  }
938  for (const auto &chain_pair : wss.m_hd_chains) {
939  if (chain_pair.first !=
942  chain_pair.second);
943  }
944  }
945  }
946 
947  return result;
948 }
949 
950 DBErrors WalletBatch::FindWalletTx(std::vector<TxId> &txIds,
951  std::list<CWalletTx> &vWtx) {
952  DBErrors result = DBErrors::LOAD_OK;
953 
954  try {
955  int nMinVersion = 0;
956  if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
957  if (nMinVersion > FEATURE_LATEST) {
958  return DBErrors::TOO_NEW;
959  }
960  }
961 
962  // Get cursor
963  if (!m_batch->StartCursor()) {
964  LogPrintf("Error getting wallet database cursor\n");
965  return DBErrors::CORRUPT;
966  }
967 
968  while (true) {
969  // Read next record
972  bool complete;
973  bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
974  if (complete) {
975  break;
976  }
977 
978  if (!ret) {
979  m_batch->CloseCursor();
980  LogPrintf("Error reading next record from wallet database\n");
981  return DBErrors::CORRUPT;
982  }
983 
984  std::string strType;
985  ssKey >> strType;
986  if (strType == DBKeys::TX) {
987  TxId txid;
988  ssKey >> txid;
989  txIds.push_back(txid);
990  vWtx.emplace_back(nullptr /* wallet */, nullptr /* tx */);
991  ssValue >> vWtx.back();
992  }
993  }
994  } catch (...) {
995  result = DBErrors::CORRUPT;
996  }
997  m_batch->CloseCursor();
998 
999  return result;
1000 }
1001 
1002 DBErrors WalletBatch::ZapSelectTx(std::vector<TxId> &txIdsIn,
1003  std::vector<TxId> &txIdsOut) {
1004  // Build list of wallet TXs and hashes.
1005  std::vector<TxId> txIds;
1006  std::list<CWalletTx> vWtx;
1007  DBErrors err = FindWalletTx(txIds, vWtx);
1008  if (err != DBErrors::LOAD_OK) {
1009  return err;
1010  }
1011 
1012  std::sort(txIds.begin(), txIds.end());
1013  std::sort(txIdsIn.begin(), txIdsIn.end());
1014 
1015  // Erase each matching wallet TX.
1016  bool delerror = false;
1017  std::vector<TxId>::iterator it = txIdsIn.begin();
1018  for (const TxId &txid : txIds) {
1019  while (it < txIdsIn.end() && (*it) < txid) {
1020  it++;
1021  }
1022  if (it == txIdsIn.end()) {
1023  break;
1024  }
1025 
1026  if ((*it) == txid) {
1027  if (!EraseTx(txid)) {
1029  "Transaction was found for deletion but returned "
1030  "database error: %s\n",
1031  txid.GetHex());
1032  delerror = true;
1033  }
1034  txIdsOut.push_back(txid);
1035  }
1036  }
1037 
1038  if (delerror) {
1039  return DBErrors::CORRUPT;
1040  }
1041  return DBErrors::LOAD_OK;
1042 }
1043 
1045  static std::atomic<bool> fOneThread;
1046  if (fOneThread.exchange(true)) {
1047  return;
1048  }
1049 
1050  for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) {
1051  WalletDatabase &dbh = pwallet->GetDBHandle();
1052 
1053  unsigned int nUpdateCounter = dbh.nUpdateCounter;
1054 
1055  if (dbh.nLastSeen != nUpdateCounter) {
1056  dbh.nLastSeen = nUpdateCounter;
1057  dbh.nLastWalletUpdate = GetTime();
1058  }
1059 
1060  if (dbh.nLastFlushed != nUpdateCounter &&
1061  GetTime() - dbh.nLastWalletUpdate >= 2) {
1062  if (dbh.PeriodicFlush()) {
1063  dbh.nLastFlushed = nUpdateCounter;
1064  }
1065  }
1066  }
1067 
1068  fOneThread = false;
1069 }
1070 
1072  const std::string &key,
1073  const std::string &value) {
1074  if (!IsValidDestination(address)) {
1075  return false;
1076  }
1077  return WriteIC(
1078  std::make_pair(
1080  std::make_pair(EncodeLegacyAddr(address, Params()), key)),
1081  value);
1082 }
1083 
1085  const std::string &key) {
1086  if (!IsValidDestination(address)) {
1087  return false;
1088  }
1089  return EraseIC(std::make_pair(
1091  std::make_pair(EncodeLegacyAddr(address, Params()), key)));
1092 }
1093 
1095  return WriteIC(DBKeys::HDCHAIN, chain);
1096 }
1097 
1098 bool WalletBatch::WriteWalletFlags(const uint64_t flags) {
1099  return WriteIC(DBKeys::FLAGS, flags);
1100 }
1101 
1103  return m_batch->TxnBegin();
1104 }
1105 
1107  return m_batch->TxnCommit();
1108 }
1109 
1111  return m_batch->TxnAbort();
1112 }
1113 
1114 std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path &path,
1115  const DatabaseOptions &options,
1116  DatabaseStatus &status,
1117  bilingual_str &error) {
1118  bool exists;
1119  try {
1120  exists = fs::symlink_status(path).type() != fs::file_not_found;
1121  } catch (const fs::filesystem_error &e) {
1122  error = Untranslated(
1123  strprintf("Failed to access database path '%s': %s", path.string(),
1126  return nullptr;
1127  }
1128 
1129  std::optional<DatabaseFormat> format;
1130  if (exists) {
1131  if (ExistsBerkeleyDatabase(path)) {
1133  }
1134  } else if (options.require_existing) {
1135  error = Untranslated(
1136  strprintf("Failed to load database path '%s'. Path does not exist.",
1137  path.string()));
1139  return nullptr;
1140  }
1141 
1142  if (!format && options.require_existing) {
1143  error = Untranslated(strprintf("Failed to load database path '%s'. "
1144  "Data is not in recognized format.",
1145  path.string()));
1147  return nullptr;
1148  }
1149 
1150  if (format && options.require_create) {
1152  "Failed to create database path '%s'. Database already exists.",
1153  path.string()));
1155  return nullptr;
1156  }
1157 
1158  return MakeBerkeleyDatabase(path, options, status, error);
1159 }
1160 
1164 std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase() {
1165  return std::make_unique<DummyDatabase>();
1166 }
1167 
1169 std::unique_ptr<WalletDatabase> CreateMockWalletDatabase() {
1170  return std::make_unique<BerkeleyDatabase>(
1171  std::make_shared<BerkeleyEnvironment>(), "");
1172 }
WalletBatch::WritePool
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:201
DatabaseOptions::require_existing
bool require_existing
Definition: db.h:222
DatabaseOptions
Definition: db.h:221
CWallet::WalletLogPrintf
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:1464
BIP32_EXTKEY_SIZE
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
DatabaseStatus::FAILED_BAD_PATH
@ FAILED_BAD_PATH
WalletBatch::WriteDescriptor
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
Definition: walletdb.cpp:247
bip32.h
CWallet::nMasterKeyMaxID
unsigned int nMasterKeyMaxID
Definition: wallet.h:847
WalletBatch::IsKeyType
static bool IsKeyType(const std::string &strType)
Definition: walletdb.cpp:763
CHDChain::nExternalChainCounter
uint32_t nExternalChainCounter
Definition: walletdb.h:90
CWalletScanState::CWalletScanState
CWalletScanState()
Definition: walletdb.cpp:294
DBKeys::OLD_KEY
const std::string OLD_KEY
Definition: walletdb.cpp:41
WalletBatch::WriteCScript
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:159
OutputType
OutputType
Definition: outputtype.h:17
DBKeys::CSCRIPT
const std::string CSCRIPT
Definition: walletdb.cpp:31
WalletBatch::m_batch
std::unique_ptr< DatabaseBatch > m_batch
Definition: walletdb.h:286
DBKeys::FLAGS
const std::string FLAGS
Definition: walletdb.cpp:34
MaybeCompactWalletDB
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:1044
CWallet::GetChainParams
const CChainParams & GetChainParams() const override
Definition: wallet.cpp:389
tinyformat::format
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1111
CWalletTx::GetId
TxId GetId() const
Definition: wallet.h:586
CreateDummyWalletDatabase
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
Definition: walletdb.cpp:1164
wallet.h
DBKeys::BESTBLOCK
const std::string BESTBLOCK
Definition: walletdb.cpp:29
CKeyPool
A key from a CWallet's keypool.
Definition: scriptpubkeyman.h:106
LegacyScriptPubKeyMan::GetHDChain
const CHDChain & GetHDChain() const
Definition: scriptpubkeyman.h:540
fs.h
DBKeys::MASTER_KEY
const std::string MASTER_KEY
Definition: walletdb.cpp:38
DBErrors::NEED_REWRITE
@ NEED_REWRITE
WalletBatch::EraseTx
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:103
flags
int flags
Definition: bitcoin-tx.cpp:532
key_io.h
DBKeys::ORDERPOSNEXT
const std::string ORDERPOSNEXT
Definition: walletdb.cpp:42
ArgsManager::SoftSetBoolArg
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: system.cpp:534
CPubKey::end
const uint8_t * end() const
Definition: pubkey.h:101
CWalletScanState::m_descriptor_keys
std::map< std::pair< uint256, CKeyID >, CKey > m_descriptor_keys
Definition: walletdb.cpp:288
sync.h
CHDChain::nVersion
int nVersion
Definition: walletdb.h:98
WalletBatch::LoadWallet
DBErrors LoadWallet(CWallet *pwallet)
Definition: walletdb.cpp:768
DBKeys::CRYPTED_KEY
const std::string CRYPTED_KEY
Definition: walletdb.cpp:30
LegacyScriptPubKeyMan::LoadKeyPool
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
Load a keypool entry.
Definition: scriptpubkeyman.cpp:1101
fsbridge::get_filesystem_error_message
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:131
CWallet::LoadDescriptorScriptPubKeyMan
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
Definition: wallet.cpp:4922
bilingual_str
Bilingual messages:
Definition: translation.h:17
CBlockLocator::vHave
std::vector< BlockHash > vHave
Definition: block.h:101
CWalletScanState::fAnyUnordered
bool fAnyUnordered
Definition: walletdb.cpp:283
ExistsBerkeleyDatabase
bool ExistsBerkeleyDatabase(const fs::path &path)
Check if Berkeley database exists at specified path.
Definition: bdb.cpp:892
CWalletScanState
Definition: walletdb.cpp:275
LegacyScriptPubKeyMan::LoadKeyMetadata
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
Definition: scriptpubkeyman.cpp:724
DBKeys::WATCHS
const std::string WATCHS
Definition: walletdb.cpp:53
DatabaseOptions::require_create
bool require_create
Definition: db.h:223
WalletBatch::WriteMasterKey
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:154
GetTime
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:27
DBErrors::NONCRITICAL_ERROR
@ NONCRITICAL_ERROR
ReadKeyValue
static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, std::string &strType, std::string &strErr, const KeyFilterFn &filter_fn=nullptr) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:297
DBKeys::WALLETDESCRIPTORCACHE
const std::string WALLETDESCRIPTORCACHE
Definition: walletdb.cpp:49
DatabaseFormat::BERKELEY
@ BERKELEY
CMasterKey
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key.
Definition: crypter.h:31
WalletDatabase
An instance of this class represents one database.
Definition: db.h:100
CHDChain::VERSION_HD_CHAIN_SPLIT
static const int VERSION_HD_CHAIN_SPLIT
Definition: walletdb.h:96
DatabaseStatus::FAILED_BAD_FORMAT
@ FAILED_BAD_FORMAT
LegacyScriptPubKeyMan
Definition: scriptpubkeyman.h:320
bdb.h
chainparams.h
MakeDatabase
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1114
WalletBatch::WriteDestData
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
Write destination data key,value tuple to database.
Definition: walletdb.cpp:1071
LegacyScriptPubKeyMan::LoadKey
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
Definition: scriptpubkeyman.cpp:647
CWalletScanState::fIsEncrypted
bool fIsEncrypted
Definition: walletdb.cpp:282
WalletBatch::WriteCryptedDescriptorKey
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< uint8_t > &secret)
Definition: walletdb.cpp:234
DBKeys::VERSION
const std::string VERSION
Definition: walletdb.cpp:47
DBKeys::MINVERSION
const std::string MINVERSION
Definition: walletdb.cpp:39
CPrivKey
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
WalletBatch::WriteActiveScriptPubKeyMan
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition: walletdb.cpp:213
DBKeys::ACTIVEINTERNALSPK
const std::string ACTIVEINTERNALSPK
Definition: walletdb.cpp:27
CExtPubKey::Encode
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:314
WalletBatch::TxnCommit
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:1106
DBKeys::WATCHMETA
const std::string WATCHMETA
Definition: walletdb.cpp:52
CWallet::GetVersion
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition: wallet.h:1313
WalletBatch::WriteDescriptorParentCache
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
Definition: walletdb.cpp:264
DescriptorScriptPubKeyMan
Definition: scriptpubkeyman.h:657
CWallet::LoadToWallet
bool LoadToWallet(const TxId &txid, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1047
DBKeys::WALLETDESCRIPTORCKEY
const std::string WALLETDESCRIPTORCKEY
Definition: walletdb.cpp:50
CPubKey::begin
const uint8_t * begin() const
Definition: pubkey.h:100
DBKeys::PURPOSE
const std::string PURPOSE
Definition: walletdb.cpp:44
WalletDatabase::nUpdateCounter
std::atomic< unsigned int > nUpdateCounter
Definition: db.h:156
Hash
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:74
LegacyScriptPubKeyMan::LoadCScript
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
Definition: scriptpubkeyman.cpp:704
CWallet::UpgradeKeyMetadata
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition: wallet.cpp:405
CHDChain::VERSION_HD_BASE
static const int VERSION_HD_BASE
Definition: walletdb.h:95
WalletDatabase::nLastWalletUpdate
int64_t nLastWalletUpdate
Definition: db.h:159
CWalletScanState::nKeyMeta
unsigned int nKeyMeta
Definition: walletdb.cpp:280
BCLog::WALLETDB
@ WALLETDB
Definition: logging.h:44
DBKeys::KEYMETA
const std::string KEYMETA
Definition: walletdb.cpp:36
CWalletScanState::vWalletUpgrade
std::vector< TxId > vWalletUpgrade
Definition: walletdb.cpp:284
LegacyScriptPubKeyMan::LoadHDChain
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
Definition: scriptpubkeyman.cpp:880
CWallet::LoadWalletFlags
bool LoadWalletFlags(uint64_t flags)
Loads the flags into the wallet.
Definition: wallet.cpp:1633
Untranslated
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:36
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:263
WalletBatch::EraseIC
bool EraseIC(const K &key)
Definition: walletdb.h:190
WalletBatch::ReadPool
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:197
EncodeLegacyAddr
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &params)
Definition: key_io.cpp:191
WalletBatch::WriteOrderPosNext
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:193
DatabaseStatus::FAILED_NOT_FOUND
@ FAILED_NOT_FOUND
DatabaseStatus::FAILED_ALREADY_EXISTS
@ FAILED_ALREADY_EXISTS
DBKeys::POOL
const std::string POOL
Definition: walletdb.cpp:43
CWallet::LoadDestData
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:4184
DBKeys::WALLETDESCRIPTOR
const std::string WALLETDESCRIPTOR
Definition: walletdb.cpp:48
WalletBatch::WriteCryptedKey
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< uint8_t > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:129
DBKeys::BESTBLOCK_NOMERKLE
const std::string BESTBLOCK_NOMERKLE
Definition: walletdb.cpp:28
DBKeys::KEY
const std::string KEY
Definition: walletdb.cpp:37
DBKeys::SETTINGS
const std::string SETTINGS
Definition: walletdb.cpp:45
WalletBatch::EraseWatchOnly
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:172
time.h
CHDChain::nInternalChainCounter
uint32_t nInternalChainCounter
Definition: walletdb.h:91
DBKeys::DEFAULTKEY
const std::string DEFAULTKEY
Definition: walletdb.cpp:32
WalletDatabase::nLastFlushed
unsigned int nLastFlushed
Definition: db.h:158
WalletBatch::WriteBestBlock
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:179
WalletBatch::ErasePool
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:205
WalletBatch::WriteDescriptorDerivedCache
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
Definition: walletdb.cpp:252
CWallet::mapMasterKeys
MasterKeyMap mapMasterKeys
Definition: wallet.h:846
CWallet::ReorderTransactions
DBErrors ReorderTransactions()
Definition: wallet.cpp:827
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:98
uint256
256-bit opaque blob.
Definition: uint256.h:127
TxId
A TxId is the identifier of a transaction.
Definition: txid.h:14
DBKeys
Definition: walletdb.cpp:24
LogPrint
#define LogPrint(category,...)
Definition: logging.h:193
WalletBatch::EraseDestData
bool EraseDestData(const CTxDestination &address, const std::string &key)
Erase destination data tuple from wallet database.
Definition: walletdb.cpp:1084
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:430
CWalletScanState::m_active_internal_spks
std::map< OutputType, uint256 > m_active_internal_spks
Definition: walletdb.cpp:286
CWallet::GetLegacyScriptPubKeyMan
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:4872
WalletBatch::WriteHDChain
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Definition: walletdb.cpp:1094
DBErrors::LOAD_OK
@ LOAD_OK
DBKeys::ACTIVEEXTERNALSPK
const std::string ACTIVEEXTERNALSPK
Definition: walletdb.cpp:26
DescriptorCache
Cache for single descriptor's derived extended pubkeys.
Definition: descriptor.h:19
CWalletScanState::m_unknown_records
unsigned int m_unknown_records
Definition: walletdb.cpp:281
CWalletScanState::m_active_external_spks
std::map< OutputType, uint256 > m_active_external_spks
Definition: walletdb.cpp:285
WalletBatch::ReadBestBlock
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:186
WalletBatch::WriteDescriptorKey
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
Definition: walletdb.cpp:220
WalletDatabase::nLastSeen
unsigned int nLastSeen
Definition: db.h:157
system.h
CWalletScanState::nWatchKeys
unsigned int nWatchKeys
Definition: walletdb.cpp:279
CWalletScanState::nCKeys
unsigned int nCKeys
Definition: walletdb.cpp:278
CLIENT_VERSION
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:44
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
LegacyScriptPubKeyMan::LoadScriptMetadata
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
Definition: scriptpubkeyman.cpp:731
DBErrors
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:46
uint160
160-bit opaque blob.
Definition: uint256.h:115
CPubKey
An encapsulated public key.
Definition: pubkey.h:31
LegacyScriptPubKeyMan::LoadCryptedKey
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< uint8_t > &vchCryptedSecret, bool checksum_valid)
Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
Definition: scriptpubkeyman.cpp:762
FEATURE_LATEST
@ FEATURE_LATEST
Definition: walletutil.h:36
base_blob::IsNull
bool IsNull() const
Definition: uint256.h:30
CKey
An encapsulated secp256k1 private key.
Definition: key.h:28
translation.h
CWalletScanState::m_hd_chains
std::map< uint160, CHDChain > m_hd_chains
Definition: walletdb.cpp:292
CHDChain
Definition: walletdb.h:88
EXCLUSIVE_LOCKS_REQUIRED
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
WalletBatch::ErasePurpose
bool ErasePurpose(const CTxDestination &address)
Definition: walletdb.cpp:91
LOCK
#define LOCK(cs)
Definition: sync.h:241
WalletBatch::ZapSelectTx
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut)
Definition: walletdb.cpp:1002
gArgs
ArgsManager gArgs
Definition: system.cpp:75
CreateMockWalletDatabase
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
Definition: walletdb.cpp:1169
CWallet
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:678
CHDChain::seed_id
CKeyID seed_id
seed hash160
Definition: walletdb.h:93
CWalletTx
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:280
CWalletScanState::nKeys
unsigned int nKeys
Definition: walletdb.cpp:277
LegacyScriptPubKeyMan::LoadWatchOnly
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
Definition: scriptpubkeyman.cpp:832
DBErrors::CORRUPT
@ CORRUPT
WalletBatch::WriteKeyMetadata
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
Definition: walletdb.cpp:107
CKeyMetadata::VERSION_WITH_HDDATA
static const int VERSION_WITH_HDDATA
Definition: walletdb.h:124
MakeBerkeleyDatabase
std::unique_ptr< BerkeleyDatabase > MakeBerkeleyDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Return object giving access to Berkeley database at specified path.
Definition: bdb.cpp:900
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:506
DatabaseStatus
DatabaseStatus
Definition: db.h:229
CWallet::IsLegacy
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:4992
WalletBatch::WriteWatchOnly
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition: walletdb.cpp:164
SER_DISK
@ SER_DISK
Definition: serialize.h:166
CWallet::cs_wallet
RecursiveMutex cs_wallet
Definition: wallet.h:819
serialize.h
WalletDatabase::PeriodicFlush
virtual bool PeriodicFlush()=0
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:197
WalletBatch::WriteIC
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
Definition: walletdb.h:179
CWallet::GetScriptPubKeyMan
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:4811
WalletBatch::WriteMinVersion
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:209
WalletDescriptor
Descriptor with some wallet metadata.
Definition: walletutil.h:80
walletdb.h
CDataStream::empty
bool empty() const
Definition: streams.h:281
DBKeys::ACENTRY
const std::string ACENTRY
Definition: walletdb.cpp:25
DBKeys::HDCHAIN
const std::string HDCHAIN
Definition: walletdb.cpp:35
CKey::Load
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:336
WalletBatch::TxnBegin
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:1102
WalletBatch::WriteName
bool WriteName(const CTxDestination &address, const std::string &strName)
Definition: walletdb.cpp:60
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
WalletBatch::WriteTx
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:99
WalletBatch::EraseName
bool EraseName(const CTxDestination &address)
Definition: walletdb.cpp:70
GetWallets
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: wallet.cpp:147
CBlockLocator
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:100
LegacyScriptPubKeyMan::AddInactiveHDChain
void AddInactiveHDChain(const CHDChain &chain)
Definition: scriptpubkeyman.cpp:901
ParseHDKeypath
bool ParseHDKeypath(const std::string &keypath_str, std::vector< uint32_t > &keypath)
Parse an HD keypaths like "m/7/0'/2000".
Definition: bip32.cpp:13
CWallet::LoadActiveScriptPubKeyMan
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:4978
CWalletScanState::m_descriptor_crypt_keys
std::map< std::pair< uint256, CKeyID >, std::pair< CPubKey, std::vector< uint8_t > > > m_descriptor_crypt_keys
Definition: walletdb.cpp:291
WalletBatch::FindWalletTx
DBErrors FindWalletTx(std::vector< TxId > &txIds, std::list< CWalletTx > &vWtx)
Definition: walletdb.cpp:950
WalletBatch::WritePurpose
bool WritePurpose(const CTxDestination &address, const std::string &purpose)
Definition: walletdb.cpp:81
CScriptID
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:65
WalletBatch::WriteKey
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:113
DecodeDestination
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
CWalletScanState::m_descriptor_caches
std::map< uint256, DescriptorCache > m_descriptor_caches
Definition: walletdb.cpp:287
DBKeys::TX
const std::string TX
Definition: walletdb.cpp:46
DBKeys::NAME
const std::string NAME
Definition: walletdb.cpp:40
CExtPubKey
Definition: pubkey.h:198
CTxDestination
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:132
CKeyMetadata
Definition: walletdb.h:121
CDataStream::eof
bool eof() const
Definition: streams.h:380
LogPrintf
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:175
KeyFilterFn
std::function< bool(const std::string &)> KeyFilterFn
Callback for filtering key types to deserialize in ReadKeyValue.
Definition: walletdb.h:295
CWallet::GetOrCreateLegacyScriptPubKeyMan
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:4886
CWallet::LoadMinVersion
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.h:987
DBErrors::TOO_NEW
@ TOO_NEW
CExtPubKey::Decode
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:326
DBKeys::WALLETDESCRIPTORKEY
const std::string WALLETDESCRIPTORKEY
Definition: walletdb.cpp:51
WalletBatch::WriteWalletFlags
bool WriteWalletFlags(const uint64_t flags)
Definition: walletdb.cpp:1098
WalletBatch::TxnAbort
bool TxnAbort()
Abort current transaction.
Definition: walletdb.cpp:1110
DBKeys::DESTDATA
const std::string DESTDATA
Definition: walletdb.cpp:33