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