Bitcoin Core  26.1.0
P2P Digital Currency
walletdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <wallet/walletdb.h>
7 
8 #include <common/system.h>
9 #include <key_io.h>
10 #include <protocol.h>
11 #include <script/script.h>
12 #include <serialize.h>
13 #include <sync.h>
14 #include <util/bip32.h>
15 #include <util/check.h>
16 #include <util/fs.h>
17 #include <util/time.h>
18 #include <util/translation.h>
19 #ifdef USE_BDB
20 #include <wallet/bdb.h>
21 #endif
22 #ifdef USE_SQLITE
23 #include <wallet/sqlite.h>
24 #endif
25 #include <wallet/wallet.h>
26 
27 #include <atomic>
28 #include <optional>
29 #include <string>
30 
31 namespace wallet {
32 namespace DBKeys {
33 const std::string ACENTRY{"acentry"};
34 const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};
35 const std::string ACTIVEINTERNALSPK{"activeinternalspk"};
36 const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
37 const std::string BESTBLOCK{"bestblock"};
38 const std::string CRYPTED_KEY{"ckey"};
39 const std::string CSCRIPT{"cscript"};
40 const std::string DEFAULTKEY{"defaultkey"};
41 const std::string DESTDATA{"destdata"};
42 const std::string FLAGS{"flags"};
43 const std::string HDCHAIN{"hdchain"};
44 const std::string KEYMETA{"keymeta"};
45 const std::string KEY{"key"};
46 const std::string LOCKED_UTXO{"lockedutxo"};
47 const std::string MASTER_KEY{"mkey"};
48 const std::string MINVERSION{"minversion"};
49 const std::string NAME{"name"};
50 const std::string OLD_KEY{"wkey"};
51 const std::string ORDERPOSNEXT{"orderposnext"};
52 const std::string POOL{"pool"};
53 const std::string PURPOSE{"purpose"};
54 const std::string SETTINGS{"settings"};
55 const std::string TX{"tx"};
56 const std::string VERSION{"version"};
57 const std::string WALLETDESCRIPTOR{"walletdescriptor"};
58 const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
59 const std::string WALLETDESCRIPTORLHCACHE{"walletdescriptorlhcache"};
60 const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
61 const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
62 const std::string WATCHMETA{"watchmeta"};
63 const std::string WATCHS{"watchs"};
64 const std::unordered_set<std::string> LEGACY_TYPES{CRYPTED_KEY, CSCRIPT, DEFAULTKEY, HDCHAIN, KEYMETA, KEY, OLD_KEY, POOL, WATCHMETA, WATCHS};
65 } // namespace DBKeys
66 
67 //
68 // WalletBatch
69 //
70 
71 bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName)
72 {
73  return WriteIC(std::make_pair(DBKeys::NAME, strAddress), strName);
74 }
75 
76 bool WalletBatch::EraseName(const std::string& strAddress)
77 {
78  // This should only be used for sending addresses, never for receiving addresses,
79  // receiving addresses must always have an address book entry if they're not change return.
80  return EraseIC(std::make_pair(DBKeys::NAME, strAddress));
81 }
82 
83 bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
84 {
85  return WriteIC(std::make_pair(DBKeys::PURPOSE, strAddress), strPurpose);
86 }
87 
88 bool WalletBatch::ErasePurpose(const std::string& strAddress)
89 {
90  return EraseIC(std::make_pair(DBKeys::PURPOSE, strAddress));
91 }
92 
94 {
95  return WriteIC(std::make_pair(DBKeys::TX, wtx.GetHash()), wtx);
96 }
97 
99 {
100  return EraseIC(std::make_pair(DBKeys::TX, hash));
101 }
102 
103 bool WalletBatch::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite)
104 {
105  return WriteIC(std::make_pair(DBKeys::KEYMETA, pubkey), meta, overwrite);
106 }
107 
108 bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
109 {
110  if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {
111  return false;
112  }
113 
114  // hash pubkey/privkey to accelerate wallet load
115  std::vector<unsigned char> vchKey;
116  vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
117  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
118  vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
119 
120  return WriteIC(std::make_pair(DBKeys::KEY, vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey)), false);
121 }
122 
123 bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,
124  const std::vector<unsigned char>& vchCryptedSecret,
125  const CKeyMetadata &keyMeta)
126 {
127  if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {
128  return false;
129  }
130 
131  // Compute a checksum of the encrypted key
132  uint256 checksum = Hash(vchCryptedSecret);
133 
134  const auto key = std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey);
135  if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) {
136  // It may already exist, so try writing just the checksum
137  std::vector<unsigned char> val;
138  if (!m_batch->Read(key, val)) {
139  return false;
140  }
141  if (!WriteIC(key, std::make_pair(val, checksum), true)) {
142  return false;
143  }
144  }
145  EraseIC(std::make_pair(DBKeys::KEY, vchPubKey));
146  return true;
147 }
148 
149 bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
150 {
151  return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);
152 }
153 
154 bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
155 {
156  return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
157 }
158 
159 bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
160 {
161  if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {
162  return false;
163  }
164  return WriteIC(std::make_pair(DBKeys::WATCHS, dest), uint8_t{'1'});
165 }
166 
168 {
169  if (!EraseIC(std::make_pair(DBKeys::WATCHMETA, dest))) {
170  return false;
171  }
172  return EraseIC(std::make_pair(DBKeys::WATCHS, dest));
173 }
174 
176 {
177  WriteIC(DBKeys::BESTBLOCK, CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
178  return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator);
179 }
180 
182 {
183  if (m_batch->Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) return true;
184  return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
185 }
186 
187 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
188 {
189  return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);
190 }
191 
192 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool)
193 {
194  return m_batch->Read(std::make_pair(DBKeys::POOL, nPool), keypool);
195 }
196 
197 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool)
198 {
199  return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool);
200 }
201 
202 bool WalletBatch::ErasePool(int64_t nPool)
203 {
204  return EraseIC(std::make_pair(DBKeys::POOL, nPool));
205 }
206 
208 {
209  return WriteIC(DBKeys::MINVERSION, nVersion);
210 }
211 
212 bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal)
213 {
214  std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK;
215  return WriteIC(make_pair(key, type), id);
216 }
217 
218 bool WalletBatch::EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
219 {
220  const std::string key{internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK};
221  return EraseIC(make_pair(key, type));
222 }
223 
224 bool WalletBatch::WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey)
225 {
226  // hash pubkey/privkey to accelerate wallet load
227  std::vector<unsigned char> key;
228  key.reserve(pubkey.size() + privkey.size());
229  key.insert(key.end(), pubkey.begin(), pubkey.end());
230  key.insert(key.end(), privkey.begin(), privkey.end());
231 
232  return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)), std::make_pair(privkey, Hash(key)), false);
233 }
234 
235 bool WalletBatch::WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret)
236 {
237  if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY, std::make_pair(desc_id, pubkey)), secret, false)) {
238  return false;
239  }
240  EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)));
241  return true;
242 }
243 
244 bool WalletBatch::WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor)
245 {
246  return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor);
247 }
248 
249 bool WalletBatch::WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index)
250 {
251  std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
252  xpub.Encode(ser_xpub.data());
253  return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), std::make_pair(key_exp_index, der_index)), ser_xpub);
254 }
255 
256 bool WalletBatch::WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index)
257 {
258  std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
259  xpub.Encode(ser_xpub.data());
260  return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), key_exp_index), ser_xpub);
261 }
262 
263 bool WalletBatch::WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index)
264 {
265  std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
266  xpub.Encode(ser_xpub.data());
267  return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORLHCACHE, desc_id), key_exp_index), ser_xpub);
268 }
269 
271 {
272  for (const auto& parent_xpub_pair : cache.GetCachedParentExtPubKeys()) {
273  if (!WriteDescriptorParentCache(parent_xpub_pair.second, desc_id, parent_xpub_pair.first)) {
274  return false;
275  }
276  }
277  for (const auto& derived_xpub_map_pair : cache.GetCachedDerivedExtPubKeys()) {
278  for (const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
279  if (!WriteDescriptorDerivedCache(derived_xpub_pair.second, desc_id, derived_xpub_map_pair.first, derived_xpub_pair.first)) {
280  return false;
281  }
282  }
283  }
284  for (const auto& lh_xpub_pair : cache.GetCachedLastHardenedExtPubKeys()) {
285  if (!WriteDescriptorLastHardenedCache(lh_xpub_pair.second, desc_id, lh_xpub_pair.first)) {
286  return false;
287  }
288  }
289  return true;
290 }
291 
293 {
294  return WriteIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n)), uint8_t{'1'});
295 }
296 
298 {
299  return EraseIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n)));
300 }
301 
302 bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr)
303 {
304  LOCK(pwallet->cs_wallet);
305  try {
306  CPubKey vchPubKey;
307  ssKey >> vchPubKey;
308  if (!vchPubKey.IsValid())
309  {
310  strErr = "Error reading wallet database: CPubKey corrupt";
311  return false;
312  }
313  CKey key;
314  CPrivKey pkey;
315  uint256 hash;
316 
317  ssValue >> pkey;
318 
319  // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey]
320  // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
321  // using EC operations as a checksum.
322  // Newer wallets store keys as DBKeys::KEY [pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
323  // remaining backwards-compatible.
324  try
325  {
326  ssValue >> hash;
327  }
328  catch (const std::ios_base::failure&) {}
329 
330  bool fSkipCheck = false;
331 
332  if (!hash.IsNull())
333  {
334  // hash pubkey/privkey to accelerate wallet load
335  std::vector<unsigned char> vchKey;
336  vchKey.reserve(vchPubKey.size() + pkey.size());
337  vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
338  vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
339 
340  if (Hash(vchKey) != hash)
341  {
342  strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
343  return false;
344  }
345 
346  fSkipCheck = true;
347  }
348 
349  if (!key.Load(pkey, vchPubKey, fSkipCheck))
350  {
351  strErr = "Error reading wallet database: CPrivKey corrupt";
352  return false;
353  }
354  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey))
355  {
356  strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed";
357  return false;
358  }
359  } catch (const std::exception& e) {
360  if (strErr.empty()) {
361  strErr = e.what();
362  }
363  return false;
364  }
365  return true;
366 }
367 
368 bool LoadCryptedKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr)
369 {
370  LOCK(pwallet->cs_wallet);
371  try {
372  CPubKey vchPubKey;
373  ssKey >> vchPubKey;
374  if (!vchPubKey.IsValid())
375  {
376  strErr = "Error reading wallet database: CPubKey corrupt";
377  return false;
378  }
379  std::vector<unsigned char> vchPrivKey;
380  ssValue >> vchPrivKey;
381 
382  // Get the checksum and check it
383  bool checksum_valid = false;
384  if (!ssValue.eof()) {
385  uint256 checksum;
386  ssValue >> checksum;
387  if (!(checksum_valid = Hash(vchPrivKey) == checksum)) {
388  strErr = "Error reading wallet database: Encrypted key corrupt";
389  return false;
390  }
391  }
392 
393  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey(vchPubKey, vchPrivKey, checksum_valid))
394  {
395  strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCryptedKey failed";
396  return false;
397  }
398  } catch (const std::exception& e) {
399  if (strErr.empty()) {
400  strErr = e.what();
401  }
402  return false;
403  }
404  return true;
405 }
406 
407 bool LoadEncryptionKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr)
408 {
409  LOCK(pwallet->cs_wallet);
410  try {
411  // Master encryption key is loaded into only the wallet and not any of the ScriptPubKeyMans.
412  unsigned int nID;
413  ssKey >> nID;
414  CMasterKey kMasterKey;
415  ssValue >> kMasterKey;
416  if(pwallet->mapMasterKeys.count(nID) != 0)
417  {
418  strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
419  return false;
420  }
421  pwallet->mapMasterKeys[nID] = kMasterKey;
422  if (pwallet->nMasterKeyMaxID < nID)
423  pwallet->nMasterKeyMaxID = nID;
424 
425  } catch (const std::exception& e) {
426  if (strErr.empty()) {
427  strErr = e.what();
428  }
429  return false;
430  }
431  return true;
432 }
433 
434 bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr)
435 {
436  LOCK(pwallet->cs_wallet);
437  try {
438  CHDChain chain;
439  ssValue >> chain;
441  } catch (const std::exception& e) {
442  if (strErr.empty()) {
443  strErr = e.what();
444  }
445  return false;
446  }
447  return true;
448 }
449 
450 static DBErrors LoadMinVersion(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
451 {
452  AssertLockHeld(pwallet->cs_wallet);
453  int nMinVersion = 0;
454  if (batch.Read(DBKeys::MINVERSION, nMinVersion)) {
455  if (nMinVersion > FEATURE_LATEST)
456  return DBErrors::TOO_NEW;
457  pwallet->LoadMinVersion(nMinVersion);
458  }
459  return DBErrors::LOAD_OK;
460 }
461 
462 static DBErrors LoadWalletFlags(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
463 {
464  AssertLockHeld(pwallet->cs_wallet);
465  uint64_t flags;
466  if (batch.Read(DBKeys::FLAGS, flags)) {
467  if (!pwallet->LoadWalletFlags(flags)) {
468  pwallet->WalletLogPrintf("Error reading wallet database: Unknown non-tolerable wallet flags found\n");
469  return DBErrors::TOO_NEW;
470  }
471  }
472  return DBErrors::LOAD_OK;
473 }
474 
476 {
478  int m_records{0};
479 };
480 
481 using LoadFunc = std::function<DBErrors(CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err)>;
482 static LoadResult LoadRecords(CWallet* pwallet, DatabaseBatch& batch, const std::string& key, DataStream& prefix, LoadFunc load_func)
483 {
484  LoadResult result;
485  DataStream ssKey;
487 
488  Assume(!prefix.empty());
489  std::unique_ptr<DatabaseCursor> cursor = batch.GetNewPrefixCursor(prefix);
490  if (!cursor) {
491  pwallet->WalletLogPrintf("Error getting database cursor for '%s' records\n", key);
492  result.m_result = DBErrors::CORRUPT;
493  return result;
494  }
495 
496  while (true) {
497  DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
498  if (status == DatabaseCursor::Status::DONE) {
499  break;
500  } else if (status == DatabaseCursor::Status::FAIL) {
501  pwallet->WalletLogPrintf("Error reading next '%s' record for wallet database\n", key);
502  result.m_result = DBErrors::CORRUPT;
503  return result;
504  }
505  std::string type;
506  ssKey >> type;
507  assert(type == key);
508  std::string error;
509  DBErrors record_res = load_func(pwallet, ssKey, ssValue, error);
510  if (record_res != DBErrors::LOAD_OK) {
511  pwallet->WalletLogPrintf("%s\n", error);
512  }
513  result.m_result = std::max(result.m_result, record_res);
514  ++result.m_records;
515  }
516  return result;
517 }
518 
519 static LoadResult LoadRecords(CWallet* pwallet, DatabaseBatch& batch, const std::string& key, LoadFunc load_func)
520 {
522  prefix << key;
523  return LoadRecords(pwallet, batch, key, prefix, load_func);
524 }
525 
526 static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
527 {
528  AssertLockHeld(pwallet->cs_wallet);
529  DBErrors result = DBErrors::LOAD_OK;
530 
531  // Make sure descriptor wallets don't have any legacy records
532  if (pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
533  for (const auto& type : DBKeys::LEGACY_TYPES) {
534  DataStream key;
536 
538  prefix << type;
539  std::unique_ptr<DatabaseCursor> cursor = batch.GetNewPrefixCursor(prefix);
540  if (!cursor) {
541  pwallet->WalletLogPrintf("Error getting database cursor for '%s' records\n", type);
542  return DBErrors::CORRUPT;
543  }
544 
545  DatabaseCursor::Status status = cursor->Next(key, value);
546  if (status != DatabaseCursor::Status::DONE) {
547  pwallet->WalletLogPrintf("Error: Unexpected legacy entry found in descriptor wallet %s. The wallet might have been tampered with or created with malicious intent.\n", pwallet->GetName());
549  }
550  }
551 
552  return DBErrors::LOAD_OK;
553  }
554 
555  // Load HD Chain
556  // Note: There should only be one HDCHAIN record with no data following the type
557  LoadResult hd_chain_res = LoadRecords(pwallet, batch, DBKeys::HDCHAIN,
558  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
559  return LoadHDChain(pwallet, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
560  });
561  result = std::max(result, hd_chain_res.m_result);
562 
563  // Load unencrypted keys
564  LoadResult key_res = LoadRecords(pwallet, batch, DBKeys::KEY,
565  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
566  return LoadKey(pwallet, key, value, err) ? DBErrors::LOAD_OK : DBErrors::CORRUPT;
567  });
568  result = std::max(result, key_res.m_result);
569 
570  // Load encrypted keys
571  LoadResult ckey_res = LoadRecords(pwallet, batch, DBKeys::CRYPTED_KEY,
572  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
573  return LoadCryptedKey(pwallet, key, value, err) ? DBErrors::LOAD_OK : DBErrors::CORRUPT;
574  });
575  result = std::max(result, ckey_res.m_result);
576 
577  // Load scripts
578  LoadResult script_res = LoadRecords(pwallet, batch, DBKeys::CSCRIPT,
579  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& strErr) {
580  uint160 hash;
581  key >> hash;
582  CScript script;
583  value >> script;
584  if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript(script))
585  {
586  strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCScript failed";
588  }
589  return DBErrors::LOAD_OK;
590  });
591  result = std::max(result, script_res.m_result);
592 
593  // Check whether rewrite is needed
594  if (ckey_res.m_records > 0) {
595  // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
596  if (last_client == 40000 || last_client == 50000) result = std::max(result, DBErrors::NEED_REWRITE);
597  }
598 
599  // Load keymeta
600  std::map<uint160, CHDChain> hd_chains;
601  LoadResult keymeta_res = LoadRecords(pwallet, batch, DBKeys::KEYMETA,
602  [&hd_chains] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& strErr) {
603  CPubKey vchPubKey;
604  key >> vchPubKey;
605  CKeyMetadata keyMeta;
606  value >> keyMeta;
607  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
608 
609  // Extract some CHDChain info from this metadata if it has any
610  if (keyMeta.nVersion >= CKeyMetadata::VERSION_WITH_HDDATA && !keyMeta.hd_seed_id.IsNull() && keyMeta.hdKeypath.size() > 0) {
611  // Get the path from the key origin or from the path string
612  // Not applicable when path is "s" or "m" as those indicate a seed
613  // See https://github.com/bitcoin/bitcoin/pull/12924
614  bool internal = false;
615  uint32_t index = 0;
616  if (keyMeta.hdKeypath != "s" && keyMeta.hdKeypath != "m") {
617  std::vector<uint32_t> path;
618  if (keyMeta.has_key_origin) {
619  // We have a key origin, so pull it from its path vector
620  path = keyMeta.key_origin.path;
621  } else {
622  // No key origin, have to parse the string
623  if (!ParseHDKeypath(keyMeta.hdKeypath, path)) {
624  strErr = "Error reading wallet database: keymeta with invalid HD keypath";
626  }
627  }
628 
629  // Extract the index and internal from the path
630  // Path string is m/0'/k'/i'
631  // Path vector is [0', k', i'] (but as ints OR'd with the hardened bit
632  // k == 0 for external, 1 for internal. i is the index
633  if (path.size() != 3) {
634  strErr = "Error reading wallet database: keymeta found with unexpected path";
636  }
637  if (path[0] != 0x80000000) {
638  strErr = strprintf("Unexpected path index of 0x%08x (expected 0x80000000) for the element at index 0", path[0]);
640  }
641  if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) {
642  strErr = strprintf("Unexpected path index of 0x%08x (expected 0x80000000 or 0x80000001) for the element at index 1", path[1]);
644  }
645  if ((path[2] & 0x80000000) == 0) {
646  strErr = strprintf("Unexpected path index of 0x%08x (expected to be greater than or equal to 0x80000000)", path[2]);
648  }
649  internal = path[1] == (1 | 0x80000000);
650  index = path[2] & ~0x80000000;
651  }
652 
653  // Insert a new CHDChain, or get the one that already exists
654  auto [ins, inserted] = hd_chains.emplace(keyMeta.hd_seed_id, CHDChain());
655  CHDChain& chain = ins->second;
656  if (inserted) {
657  // For new chains, we want to default to VERSION_HD_BASE until we see an internal
659  chain.seed_id = keyMeta.hd_seed_id;
660  }
661  if (internal) {
663  chain.nInternalChainCounter = std::max(chain.nInternalChainCounter, index + 1);
664  } else {
665  chain.nExternalChainCounter = std::max(chain.nExternalChainCounter, index + 1);
666  }
667  }
668  return DBErrors::LOAD_OK;
669  });
670  result = std::max(result, keymeta_res.m_result);
671 
672  // Set inactive chains
673  if (!hd_chains.empty()) {
674  LegacyScriptPubKeyMan* legacy_spkm = pwallet->GetLegacyScriptPubKeyMan();
675  if (legacy_spkm) {
676  for (const auto& [hd_seed_id, chain] : hd_chains) {
677  if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) {
678  legacy_spkm->AddInactiveHDChain(chain);
679  }
680  }
681  } else {
682  pwallet->WalletLogPrintf("Inactive HD Chains found but no Legacy ScriptPubKeyMan\n");
683  result = DBErrors::CORRUPT;
684  }
685  }
686 
687  // Load watchonly scripts
688  LoadResult watch_script_res = LoadRecords(pwallet, batch, DBKeys::WATCHS,
689  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
690  CScript script;
691  key >> script;
692  uint8_t fYes;
693  value >> fYes;
694  if (fYes == '1') {
696  }
697  return DBErrors::LOAD_OK;
698  });
699  result = std::max(result, watch_script_res.m_result);
700 
701  // Load watchonly meta
702  LoadResult watch_meta_res = LoadRecords(pwallet, batch, DBKeys::WATCHMETA,
703  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
704  CScript script;
705  key >> script;
706  CKeyMetadata keyMeta;
707  value >> keyMeta;
708  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata(CScriptID(script), keyMeta);
709  return DBErrors::LOAD_OK;
710  });
711  result = std::max(result, watch_meta_res.m_result);
712 
713  // Load keypool
714  LoadResult pool_res = LoadRecords(pwallet, batch, DBKeys::POOL,
715  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
716  int64_t nIndex;
717  key >> nIndex;
718  CKeyPool keypool;
719  value >> keypool;
720  pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool);
721  return DBErrors::LOAD_OK;
722  });
723  result = std::max(result, pool_res.m_result);
724 
725  // Deal with old "wkey" and "defaultkey" records.
726  // These are not actually loaded, but we need to check for them
727 
728  // We don't want or need the default key, but if there is one set,
729  // we want to make sure that it is valid so that we can detect corruption
730  // Note: There should only be one DEFAULTKEY with nothing trailing the type
731  LoadResult default_key_res = LoadRecords(pwallet, batch, DBKeys::DEFAULTKEY,
732  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
733  CPubKey default_pubkey;
734  try {
735  value >> default_pubkey;
736  } catch (const std::exception& e) {
737  err = e.what();
738  return DBErrors::CORRUPT;
739  }
740  if (!default_pubkey.IsValid()) {
741  err = "Error reading wallet database: Default Key corrupt";
742  return DBErrors::CORRUPT;
743  }
744  return DBErrors::LOAD_OK;
745  });
746  result = std::max(result, default_key_res.m_result);
747 
748  // "wkey" records are unsupported, if we see any, throw an error
749  LoadResult wkey_res = LoadRecords(pwallet, batch, DBKeys::OLD_KEY,
750  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
751  err = "Found unsupported 'wkey' record, try loading with version 0.18";
752  return DBErrors::LOAD_FAIL;
753  });
754  result = std::max(result, wkey_res.m_result);
755 
756  if (result <= DBErrors::NONCRITICAL_ERROR) {
757  // Only do logging and time first key update if there were no critical errors
758  pwallet->WalletLogPrintf("Legacy Wallet Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total.\n",
759  key_res.m_records, ckey_res.m_records, keymeta_res.m_records, key_res.m_records + ckey_res.m_records);
760 
761  // nTimeFirstKey is only reliable if all keys have metadata
762  if (pwallet->IsLegacy() && (key_res.m_records + ckey_res.m_records + watch_script_res.m_records) != (keymeta_res.m_records + watch_meta_res.m_records)) {
763  auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan();
764  if (spk_man) {
765  LOCK(spk_man->cs_KeyStore);
766  spk_man->UpdateTimeFirstKey(1);
767  }
768  }
769  }
770 
771  return result;
772 }
773 
774 template<typename... Args>
775 static DataStream PrefixStream(const Args&... args)
776 {
779  return prefix;
780 }
781 
782 static DBErrors LoadDescriptorWalletRecords(CWallet* pwallet, DatabaseBatch& batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
783 {
784  AssertLockHeld(pwallet->cs_wallet);
785 
786  // Load descriptor record
787  int num_keys = 0;
788  int num_ckeys= 0;
789  LoadResult desc_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTOR,
790  [&batch, &num_keys, &num_ckeys, &last_client] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& strErr) {
791  DBErrors result = DBErrors::LOAD_OK;
792 
793  uint256 id;
794  key >> id;
795  WalletDescriptor desc;
796  try {
797  value >> desc;
798  } catch (const std::ios_base::failure& e) {
799  strErr = strprintf("Error: Unrecognized descriptor found in wallet %s. ", pwallet->GetName());
800  strErr += (last_client > CLIENT_VERSION) ? "The wallet might had been created on a newer version. " :
801  "The database might be corrupted or the software version is not compatible with one of your wallet descriptors. ";
802  strErr += "Please try running the latest software version";
803  // Also include error details
804  strErr = strprintf("%s\nDetails: %s", strErr, e.what());
806  }
807  pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
808 
809  // Prior to doing anything with this spkm, verify ID compatibility
810  if (id != pwallet->GetDescriptorScriptPubKeyMan(desc)->GetID()) {
811  strErr = "The descriptor ID calculated by the wallet differs from the one in DB";
812  return DBErrors::CORRUPT;
813  }
814 
815  DescriptorCache cache;
816 
817  // Get key cache for this descriptor
819  LoadResult key_cache_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORCACHE, prefix,
820  [&id, &cache] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
821  bool parent = true;
822  uint256 desc_id;
823  uint32_t key_exp_index;
824  uint32_t der_index;
825  key >> desc_id;
826  assert(desc_id == id);
827  key >> key_exp_index;
828 
829  // if the der_index exists, it's a derived xpub
830  try
831  {
832  key >> der_index;
833  parent = false;
834  }
835  catch (...) {}
836 
837  std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
838  value >> ser_xpub;
839  CExtPubKey xpub;
840  xpub.Decode(ser_xpub.data());
841  if (parent) {
842  cache.CacheParentExtPubKey(key_exp_index, xpub);
843  } else {
844  cache.CacheDerivedExtPubKey(key_exp_index, der_index, xpub);
845  }
846  return DBErrors::LOAD_OK;
847  });
848  result = std::max(result, key_cache_res.m_result);
849 
850  // Get last hardened cache for this descriptor
852  LoadResult lh_cache_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORLHCACHE, prefix,
853  [&id, &cache] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
854  uint256 desc_id;
855  uint32_t key_exp_index;
856  key >> desc_id;
857  assert(desc_id == id);
858  key >> key_exp_index;
859 
860  std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE);
861  value >> ser_xpub;
862  CExtPubKey xpub;
863  xpub.Decode(ser_xpub.data());
864  cache.CacheLastHardenedExtPubKey(key_exp_index, xpub);
865  return DBErrors::LOAD_OK;
866  });
867  result = std::max(result, lh_cache_res.m_result);
868 
869  // Set the cache for this descriptor
870  auto spk_man = (DescriptorScriptPubKeyMan*)pwallet->GetScriptPubKeyMan(id);
871  assert(spk_man);
872  spk_man->SetCache(cache);
873 
874  // Get unencrypted keys
876  LoadResult key_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORKEY, prefix,
877  [&id, &spk_man] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& strErr) {
878  uint256 desc_id;
879  CPubKey pubkey;
880  key >> desc_id;
881  assert(desc_id == id);
882  key >> pubkey;
883  if (!pubkey.IsValid())
884  {
885  strErr = "Error reading wallet database: descriptor unencrypted key CPubKey corrupt";
886  return DBErrors::CORRUPT;
887  }
888  CKey privkey;
889  CPrivKey pkey;
890  uint256 hash;
891 
892  value >> pkey;
893  value >> hash;
894 
895  // hash pubkey/privkey to accelerate wallet load
896  std::vector<unsigned char> to_hash;
897  to_hash.reserve(pubkey.size() + pkey.size());
898  to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
899  to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
900 
901  if (Hash(to_hash) != hash)
902  {
903  strErr = "Error reading wallet database: descriptor unencrypted key CPubKey/CPrivKey corrupt";
904  return DBErrors::CORRUPT;
905  }
906 
907  if (!privkey.Load(pkey, pubkey, true))
908  {
909  strErr = "Error reading wallet database: descriptor unencrypted key CPrivKey corrupt";
910  return DBErrors::CORRUPT;
911  }
912  spk_man->AddKey(pubkey.GetID(), privkey);
913  return DBErrors::LOAD_OK;
914  });
915  result = std::max(result, key_res.m_result);
916  num_keys = key_res.m_records;
917 
918  // Get encrypted keys
920  LoadResult ckey_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORCKEY, prefix,
921  [&id, &spk_man] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
922  uint256 desc_id;
923  CPubKey pubkey;
924  key >> desc_id;
925  assert(desc_id == id);
926  key >> pubkey;
927  if (!pubkey.IsValid())
928  {
929  err = "Error reading wallet database: descriptor encrypted key CPubKey corrupt";
930  return DBErrors::CORRUPT;
931  }
932  std::vector<unsigned char> privkey;
933  value >> privkey;
934 
935  spk_man->AddCryptedKey(pubkey.GetID(), pubkey, privkey);
936  return DBErrors::LOAD_OK;
937  });
938  result = std::max(result, ckey_res.m_result);
939  num_ckeys = ckey_res.m_records;
940 
941  return result;
942  });
943 
944  if (desc_res.m_result <= DBErrors::NONCRITICAL_ERROR) {
945  // Only log if there are no critical errors
946  pwallet->WalletLogPrintf("Descriptors: %u, Descriptor Keys: %u plaintext, %u encrypted, %u total.\n",
947  desc_res.m_records, num_keys, num_ckeys, num_keys + num_ckeys);
948  }
949 
950  return desc_res.m_result;
951 }
952 
954 {
955  AssertLockHeld(pwallet->cs_wallet);
956  DBErrors result = DBErrors::LOAD_OK;
957 
958  // Load name record
959  LoadResult name_res = LoadRecords(pwallet, batch, DBKeys::NAME,
960  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
961  std::string strAddress;
962  key >> strAddress;
963  std::string label;
964  value >> label;
965  pwallet->m_address_book[DecodeDestination(strAddress)].SetLabel(label);
966  return DBErrors::LOAD_OK;
967  });
968  result = std::max(result, name_res.m_result);
969 
970  // Load purpose record
971  LoadResult purpose_res = LoadRecords(pwallet, batch, DBKeys::PURPOSE,
972  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
973  std::string strAddress;
974  key >> strAddress;
975  std::string purpose_str;
976  value >> purpose_str;
977  std::optional<AddressPurpose> purpose{PurposeFromString(purpose_str)};
978  if (!purpose) {
979  pwallet->WalletLogPrintf("Warning: nonstandard purpose string '%s' for address '%s'\n", purpose_str, strAddress);
980  }
981  pwallet->m_address_book[DecodeDestination(strAddress)].purpose = purpose;
982  return DBErrors::LOAD_OK;
983  });
984  result = std::max(result, purpose_res.m_result);
985 
986  // Load destination data record
987  LoadResult dest_res = LoadRecords(pwallet, batch, DBKeys::DESTDATA,
988  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
989  std::string strAddress, strKey, strValue;
990  key >> strAddress;
991  key >> strKey;
992  value >> strValue;
993  const CTxDestination& dest{DecodeDestination(strAddress)};
994  if (strKey.compare("used") == 0) {
995  // Load "used" key indicating if an IsMine address has
996  // previously been spent from with avoid_reuse option enabled.
997  // The strValue is not used for anything currently, but could
998  // hold more information in the future. Current values are just
999  // "1" or "p" for present (which was written prior to
1000  // f5ba424cd44619d9b9be88b8593d69a7ba96db26).
1001  pwallet->LoadAddressPreviouslySpent(dest);
1002  } else if (strKey.compare(0, 2, "rr") == 0) {
1003  // Load "rr##" keys where ## is a decimal number, and strValue
1004  // is a serialized RecentRequestEntry object.
1005  pwallet->LoadAddressReceiveRequest(dest, strKey.substr(2), strValue);
1006  }
1007  return DBErrors::LOAD_OK;
1008  });
1009  result = std::max(result, dest_res.m_result);
1010 
1011  return result;
1012 }
1013 
1014 static DBErrors LoadTxRecords(CWallet* pwallet, DatabaseBatch& batch, std::vector<uint256>& upgraded_txs, bool& any_unordered) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1015 {
1016  AssertLockHeld(pwallet->cs_wallet);
1017  DBErrors result = DBErrors::LOAD_OK;
1018 
1019  // Load tx record
1020  any_unordered = false;
1021  LoadResult tx_res = LoadRecords(pwallet, batch, DBKeys::TX,
1022  [&any_unordered, &upgraded_txs] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
1023  DBErrors result = DBErrors::LOAD_OK;
1024  uint256 hash;
1025  key >> hash;
1026  // LoadToWallet call below creates a new CWalletTx that fill_wtx
1027  // callback fills with transaction metadata.
1028  auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) {
1029  if(!new_tx) {
1030  // There's some corruption here since the tx we just tried to load was already in the wallet.
1031  err = "Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning.";
1032  result = DBErrors::CORRUPT;
1033  return false;
1034  }
1035  value >> wtx;
1036  if (wtx.GetHash() != hash)
1037  return false;
1038 
1039  // Undo serialize changes in 31600
1040  if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
1041  {
1042  if (!value.empty())
1043  {
1044  uint8_t fTmp;
1045  uint8_t fUnused;
1046  std::string unused_string;
1047  value >> fTmp >> fUnused >> unused_string;
1048  pwallet->WalletLogPrintf("LoadWallet() upgrading tx ver=%d %d %s\n",
1049  wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
1050  wtx.fTimeReceivedIsTxTime = fTmp;
1051  }
1052  else
1053  {
1054  pwallet->WalletLogPrintf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString());
1055  wtx.fTimeReceivedIsTxTime = 0;
1056  }
1057  upgraded_txs.push_back(hash);
1058  }
1059 
1060  if (wtx.nOrderPos == -1)
1061  any_unordered = true;
1062 
1063  return true;
1064  };
1065  if (!pwallet->LoadToWallet(hash, fill_wtx)) {
1066  // Use std::max as fill_wtx may have already set result to CORRUPT
1067  result = std::max(result, DBErrors::NEED_RESCAN);
1068  }
1069  return result;
1070  });
1071  result = std::max(result, tx_res.m_result);
1072 
1073  // Load locked utxo record
1074  LoadResult locked_utxo_res = LoadRecords(pwallet, batch, DBKeys::LOCKED_UTXO,
1075  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
1076  uint256 hash;
1077  uint32_t n;
1078  key >> hash;
1079  key >> n;
1080  pwallet->LockCoin(COutPoint(hash, n));
1081  return DBErrors::LOAD_OK;
1082  });
1083  result = std::max(result, locked_utxo_res.m_result);
1084 
1085  // Load orderposnext record
1086  // Note: There should only be one ORDERPOSNEXT record with nothing trailing the type
1087  LoadResult order_pos_res = LoadRecords(pwallet, batch, DBKeys::ORDERPOSNEXT,
1088  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
1089  try {
1090  value >> pwallet->nOrderPosNext;
1091  } catch (const std::exception& e) {
1092  err = e.what();
1093  return DBErrors::NONCRITICAL_ERROR;
1094  }
1095  return DBErrors::LOAD_OK;
1096  });
1097  result = std::max(result, order_pos_res.m_result);
1098 
1099  return result;
1100 }
1101 
1102 static DBErrors LoadActiveSPKMs(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1103 {
1104  AssertLockHeld(pwallet->cs_wallet);
1105  DBErrors result = DBErrors::LOAD_OK;
1106 
1107  // Load spk records
1108  std::set<std::pair<OutputType, bool>> seen_spks;
1109  for (const auto& spk_key : {DBKeys::ACTIVEEXTERNALSPK, DBKeys::ACTIVEINTERNALSPK}) {
1110  LoadResult spkm_res = LoadRecords(pwallet, batch, spk_key,
1111  [&seen_spks, &spk_key] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& strErr) {
1112  uint8_t output_type;
1113  key >> output_type;
1114  uint256 id;
1115  value >> id;
1116 
1117  bool internal = spk_key == DBKeys::ACTIVEINTERNALSPK;
1118  auto [it, insert] = seen_spks.emplace(static_cast<OutputType>(output_type), internal);
1119  if (!insert) {
1120  strErr = "Multiple ScriptpubKeyMans specified for a single type";
1121  return DBErrors::CORRUPT;
1122  }
1123  pwallet->LoadActiveScriptPubKeyMan(id, static_cast<OutputType>(output_type), /*internal=*/internal);
1124  return DBErrors::LOAD_OK;
1125  });
1126  result = std::max(result, spkm_res.m_result);
1127  }
1128  return result;
1129 }
1130 
1131 static DBErrors LoadDecryptionKeys(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1132 {
1133  AssertLockHeld(pwallet->cs_wallet);
1134 
1135  // Load decryption key (mkey) records
1136  LoadResult mkey_res = LoadRecords(pwallet, batch, DBKeys::MASTER_KEY,
1137  [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
1138  if (!LoadEncryptionKey(pwallet, key, value, err)) {
1139  return DBErrors::CORRUPT;
1140  }
1141  return DBErrors::LOAD_OK;
1142  });
1143  return mkey_res.m_result;
1144 }
1145 
1147 {
1148  DBErrors result = DBErrors::LOAD_OK;
1149  bool any_unordered = false;
1150  std::vector<uint256> upgraded_txs;
1151 
1152  LOCK(pwallet->cs_wallet);
1153 
1154  // Last client version to open this wallet
1155  int last_client = CLIENT_VERSION;
1156  bool has_last_client = m_batch->Read(DBKeys::VERSION, last_client);
1157  pwallet->WalletLogPrintf("Wallet file version = %d, last client version = %d\n", pwallet->GetVersion(), last_client);
1158 
1159  try {
1160  if ((result = LoadMinVersion(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result;
1161 
1162  // Load wallet flags, so they are known when processing other records.
1163  // The FLAGS key is absent during wallet creation.
1164  if ((result = LoadWalletFlags(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result;
1165 
1166 #ifndef ENABLE_EXTERNAL_SIGNER
1168  pwallet->WalletLogPrintf("Error: External signer wallet being loaded without external signer support compiled\n");
1169  return DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED;
1170  }
1171 #endif
1172 
1173  // Load legacy wallet keys
1174  result = std::max(LoadLegacyWalletRecords(pwallet, *m_batch, last_client), result);
1175 
1176  // Load descriptors
1177  result = std::max(LoadDescriptorWalletRecords(pwallet, *m_batch, last_client), result);
1178  // Early return if there are unknown descriptors. Later loading of ACTIVEINTERNALSPK and ACTIVEEXTERNALEXPK
1179  // may reference the unknown descriptor's ID which can result in a misleading corruption error
1180  // when in reality the wallet is simply too new.
1181  if (result == DBErrors::UNKNOWN_DESCRIPTOR) return result;
1182 
1183  // Load address book
1184  result = std::max(LoadAddressBookRecords(pwallet, *m_batch), result);
1185 
1186  // Load tx records
1187  result = std::max(LoadTxRecords(pwallet, *m_batch, upgraded_txs, any_unordered), result);
1188 
1189  // Load SPKMs
1190  result = std::max(LoadActiveSPKMs(pwallet, *m_batch), result);
1191 
1192  // Load decryption keys
1193  result = std::max(LoadDecryptionKeys(pwallet, *m_batch), result);
1194  } catch (...) {
1195  // Exceptions that can be ignored or treated as non-critical are handled by the individual loading functions.
1196  // Any uncaught exceptions will be caught here and treated as critical.
1197  result = DBErrors::CORRUPT;
1198  }
1199 
1200  // Any wallet corruption at all: skip any rewriting or
1201  // upgrading, we don't want to make it worse.
1202  if (result != DBErrors::LOAD_OK)
1203  return result;
1204 
1205  for (const uint256& hash : upgraded_txs)
1206  WriteTx(pwallet->mapWallet.at(hash));
1207 
1208  if (!has_last_client || last_client != CLIENT_VERSION) // Update
1209  m_batch->Write(DBKeys::VERSION, CLIENT_VERSION);
1210 
1211  if (any_unordered)
1212  result = pwallet->ReorderTransactions();
1213 
1214  // Upgrade all of the wallet keymetadata to have the hd master key id
1215  // This operation is not atomic, but if it fails, updated entries are still backwards compatible with older software
1216  try {
1217  pwallet->UpgradeKeyMetadata();
1218  } catch (...) {
1219  result = DBErrors::CORRUPT;
1220  }
1221 
1222  // Upgrade all of the descriptor caches to cache the last hardened xpub
1223  // This operation is not atomic, but if it fails, only new entries are added so it is backwards compatible
1224  try {
1225  pwallet->UpgradeDescriptorCache();
1226  } catch (...) {
1227  result = DBErrors::CORRUPT;
1228  }
1229 
1230  return result;
1231 }
1232 
1233 DBErrors WalletBatch::FindWalletTxHashes(std::vector<uint256>& tx_hashes)
1234 {
1235  DBErrors result = DBErrors::LOAD_OK;
1236 
1237  try {
1238  int nMinVersion = 0;
1239  if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
1240  if (nMinVersion > FEATURE_LATEST)
1241  return DBErrors::TOO_NEW;
1242  }
1243 
1244  // Get cursor
1245  std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
1246  if (!cursor)
1247  {
1248  LogPrintf("Error getting wallet database cursor\n");
1249  return DBErrors::CORRUPT;
1250  }
1251 
1252  while (true)
1253  {
1254  // Read next record
1255  DataStream ssKey{};
1256  DataStream ssValue{};
1257  DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
1258  if (status == DatabaseCursor::Status::DONE) {
1259  break;
1260  } else if (status == DatabaseCursor::Status::FAIL) {
1261  LogPrintf("Error reading next record from wallet database\n");
1262  return DBErrors::CORRUPT;
1263  }
1264 
1265  std::string strType;
1266  ssKey >> strType;
1267  if (strType == DBKeys::TX) {
1268  uint256 hash;
1269  ssKey >> hash;
1270  tx_hashes.push_back(hash);
1271  }
1272  }
1273  } catch (...) {
1274  result = DBErrors::CORRUPT;
1275  }
1276 
1277  return result;
1278 }
1279 
1280 DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
1281 {
1282  // build list of wallet TX hashes
1283  std::vector<uint256> vTxHash;
1284  DBErrors err = FindWalletTxHashes(vTxHash);
1285  if (err != DBErrors::LOAD_OK) {
1286  return err;
1287  }
1288 
1289  std::sort(vTxHash.begin(), vTxHash.end());
1290  std::sort(vTxHashIn.begin(), vTxHashIn.end());
1291 
1292  // erase each matching wallet TX
1293  bool delerror = false;
1294  std::vector<uint256>::iterator it = vTxHashIn.begin();
1295  for (const uint256& hash : vTxHash) {
1296  while (it < vTxHashIn.end() && (*it) < hash) {
1297  it++;
1298  }
1299  if (it == vTxHashIn.end()) {
1300  break;
1301  }
1302  else if ((*it) == hash) {
1303  if(!EraseTx(hash)) {
1304  LogPrint(BCLog::WALLETDB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
1305  delerror = true;
1306  }
1307  vTxHashOut.push_back(hash);
1308  }
1309  }
1310 
1311  if (delerror) {
1312  return DBErrors::CORRUPT;
1313  }
1314  return DBErrors::LOAD_OK;
1315 }
1316 
1318 {
1319  static std::atomic<bool> fOneThread(false);
1320  if (fOneThread.exchange(true)) {
1321  return;
1322  }
1323 
1324  for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
1325  WalletDatabase& dbh = pwallet->GetDatabase();
1326 
1327  unsigned int nUpdateCounter = dbh.nUpdateCounter;
1328 
1329  if (dbh.nLastSeen != nUpdateCounter) {
1330  dbh.nLastSeen = nUpdateCounter;
1331  dbh.nLastWalletUpdate = GetTime();
1332  }
1333 
1334  if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
1335  if (dbh.PeriodicFlush()) {
1336  dbh.nLastFlushed = nUpdateCounter;
1337  }
1338  }
1339  }
1340 
1341  fOneThread = false;
1342 }
1343 
1344 bool WalletBatch::WriteAddressPreviouslySpent(const CTxDestination& dest, bool previously_spent)
1345 {
1346  auto key{std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), std::string("used")))};
1347  return previously_spent ? WriteIC(key, std::string("1")) : EraseIC(key);
1348 }
1349 
1350 bool WalletBatch::WriteAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& receive_request)
1351 {
1352  return WriteIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id)), receive_request);
1353 }
1354 
1355 bool WalletBatch::EraseAddressReceiveRequest(const CTxDestination& dest, const std::string& id)
1356 {
1357  return EraseIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id)));
1358 }
1359 
1360 bool WalletBatch::EraseAddressData(const CTxDestination& dest)
1361 {
1364  return m_batch->ErasePrefix(prefix);
1365 }
1366 
1367 bool WalletBatch::WriteHDChain(const CHDChain& chain)
1368 {
1369  return WriteIC(DBKeys::HDCHAIN, chain);
1370 }
1371 
1372 bool WalletBatch::WriteWalletFlags(const uint64_t flags)
1373 {
1374  return WriteIC(DBKeys::FLAGS, flags);
1375 }
1376 
1377 bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
1378 {
1379  // Begin db txn
1380  if (!m_batch->TxnBegin()) return false;
1381 
1382  // Get cursor
1383  std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
1384  if (!cursor)
1385  {
1386  return false;
1387  }
1388 
1389  // Iterate the DB and look for any records that have the type prefixes
1390  while (true) {
1391  // Read next record
1392  DataStream key{};
1393  DataStream value{};
1394  DatabaseCursor::Status status = cursor->Next(key, value);
1395  if (status == DatabaseCursor::Status::DONE) {
1396  break;
1397  } else if (status == DatabaseCursor::Status::FAIL) {
1398  cursor.reset(nullptr);
1399  m_batch->TxnAbort(); // abort db txn
1400  return false;
1401  }
1402 
1403  // Make a copy of key to avoid data being deleted by the following read of the type
1404  const SerializeData key_data{key.begin(), key.end()};
1405 
1406  std::string type;
1407  key >> type;
1408 
1409  if (types.count(type) > 0) {
1410  if (!m_batch->Erase(Span{key_data})) {
1411  cursor.reset(nullptr);
1412  m_batch->TxnAbort();
1413  return false; // erase failed
1414  }
1415  }
1416  }
1417  // Finish db txn
1418  cursor.reset(nullptr);
1419  return m_batch->TxnCommit();
1420 }
1421 
1422 bool WalletBatch::TxnBegin()
1423 {
1424  return m_batch->TxnBegin();
1425 }
1426 
1427 bool WalletBatch::TxnCommit()
1428 {
1429  return m_batch->TxnCommit();
1430 }
1431 
1432 bool WalletBatch::TxnAbort()
1433 {
1434  return m_batch->TxnAbort();
1435 }
1436 
1437 std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
1438 {
1439  bool exists;
1440  try {
1441  exists = fs::symlink_status(path).type() != fs::file_type::not_found;
1442  } catch (const fs::filesystem_error& e) {
1443  error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e)));
1444  status = DatabaseStatus::FAILED_BAD_PATH;
1445  return nullptr;
1446  }
1447 
1448  std::optional<DatabaseFormat> format;
1449  if (exists) {
1450  if (IsBDBFile(BDBDataFile(path))) {
1451  format = DatabaseFormat::BERKELEY;
1452  }
1453  if (IsSQLiteFile(SQLiteDataFile(path))) {
1454  if (format) {
1455  error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", fs::PathToString(path)));
1456  status = DatabaseStatus::FAILED_BAD_FORMAT;
1457  return nullptr;
1458  }
1459  format = DatabaseFormat::SQLITE;
1460  }
1461  } else if (options.require_existing) {
1462  error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", fs::PathToString(path)));
1463  status = DatabaseStatus::FAILED_NOT_FOUND;
1464  return nullptr;
1465  }
1466 
1467  if (!format && options.require_existing) {
1468  error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in recognized format.", fs::PathToString(path)));
1469  status = DatabaseStatus::FAILED_BAD_FORMAT;
1470  return nullptr;
1471  }
1472 
1473  if (format && options.require_create) {
1474  error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(path)));
1475  status = DatabaseStatus::FAILED_ALREADY_EXISTS;
1476  return nullptr;
1477  }
1478 
1479  // A db already exists so format is set, but options also specifies the format, so make sure they agree
1480  if (format && options.require_format && format != options.require_format) {
1481  error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in required format.", fs::PathToString(path)));
1482  status = DatabaseStatus::FAILED_BAD_FORMAT;
1483  return nullptr;
1484  }
1485 
1486  // Format is not set when a db doesn't already exist, so use the format specified by the options if it is set.
1487  if (!format && options.require_format) format = options.require_format;
1488 
1489  // If the format is not specified or detected, choose the default format based on what is available. We prefer BDB over SQLite for now.
1490  if (!format) {
1491 #ifdef USE_SQLITE
1492  format = DatabaseFormat::SQLITE;
1493 #endif
1494 #ifdef USE_BDB
1495  format = DatabaseFormat::BERKELEY;
1496 #endif
1497  }
1498 
1499  if (format == DatabaseFormat::SQLITE) {
1500 #ifdef USE_SQLITE
1501  return MakeSQLiteDatabase(path, options, status, error);
1502 #endif
1503  error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", fs::PathToString(path)));
1504  status = DatabaseStatus::FAILED_BAD_FORMAT;
1505  return nullptr;
1506  }
1507 
1508 #ifdef USE_BDB
1509  return MakeBerkeleyDatabase(path, options, status, error);
1510 #endif
1511  error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", fs::PathToString(path)));
1512  status = DatabaseStatus::FAILED_BAD_FORMAT;
1513  return nullptr;
1514 }
1515 } // namespace wallet
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1437
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
const std::string MASTER_KEY
Definition: walletdb.cpp:47
bool eof() const
Definition: streams.h:261
Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key...
Definition: crypter.h:34
std::optional< DatabaseFormat > require_format
Definition: db.h:186
const std::string BESTBLOCK_NOMERKLE
Definition: walletdb.cpp:36
const std::string SETTINGS
Definition: walletdb.cpp:54
const std::string CRYPTED_KEY
Definition: walletdb.cpp:38
static DBErrors LoadDescriptorWalletRecords(CWallet *pwallet, DatabaseBatch &batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:782
static const auto FLAGS
AssertLockHeld(pool.cs)
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::string NAME
Definition: walletdb.cpp:49
const std::string HDCHAIN
Definition: walletdb.cpp:43
const CHDChain & GetHDChain() const
#define LogPrint(category,...)
Definition: logging.h:246
assert(!tx.IsCoinBase())
const std::string ACENTRY
Definition: walletdb.cpp:33
Describes a place in the block chain to another node such that if the other node doesn&#39;t have the sam...
Definition: block.h:123
const std::string VERSION
Definition: walletdb.cpp:56
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade DescriptorCaches.
Definition: wallet.cpp:545
bool LoadToWallet(const uint256 &hash, const UpdateWalletTxFn &fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1180
const std::string DESTDATA
Definition: walletdb.cpp:41
Bilingual messages:
Definition: translation.h:18
static DBErrors LoadAddressBookRecords(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:953
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: sqlite.cpp:637
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:47
const std::string WALLETDESCRIPTORCKEY
Definition: walletdb.cpp:60
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
bool WriteDescriptorCacheItems(const uint256 &desc_id, const DescriptorCache &cache)
Definition: walletdb.cpp:270
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:48
const std::string BESTBLOCK
Definition: walletdb.cpp:37
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:446
const char * prefix
Definition: rest.cpp:1004
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< unsigned char > &secret)
Definition: walletdb.cpp:235
uint32_t nExternalChainCounter
Definition: walletdb.h:100
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:360
static DataStream PrefixStream(const Args &... args)
Definition: walletdb.cpp:775
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:3677
const std::string WALLETDESCRIPTOR
Definition: walletdb.cpp:57
bool WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey)
Definition: walletdb.cpp:149
virtual std::unique_ptr< DatabaseCursor > GetNewPrefixCursor(Span< const std::byte > prefix)=0
MasterKeyMap mapMasterKeys
Definition: wallet.h:449
static DBErrors LoadLegacyWalletRecords(CWallet *pwallet, DatabaseBatch &batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:526
bool LoadHDChain(CWallet *pwallet, DataStream &ssValue, std::string &strErr)
Definition: walletdb.cpp:434
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:436
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
const std::string KEY
Definition: walletdb.cpp:45
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:167
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
Definition: insert.h:14
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:123
std::function< DBErrors(CWallet *pwallet, DataStream &key, CDataStream &value, std::string &err)> LoadFunc
Definition: walletdb.cpp:481
bool WriteLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:292
bool WriteMinVersion(int nVersion)
Definition: walletdb.cpp:207
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:197
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:3428
A key from a CWallet&#39;s keypool.
const std::string CSCRIPT
Definition: walletdb.cpp:39
static DBErrors LoadActiveSPKMs(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:1102
bool WriteOrderPosNext(int64_t nOrderPosNext)
Definition: walletdb.cpp:187
bool ReadBestBlock(CBlockLocator &locator)
Definition: walletdb.cpp:181
const std::string PURPOSE
Definition: walletdb.cpp:53
std::atomic< unsigned int > nUpdateCounter
Definition: db.h:169
const std::string MINVERSION
Definition: walletdb.cpp:48
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:3486
std::unique_ptr< DatabaseBatch > m_batch
Definition: walletdb.h:295
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
Definition: walletdb.cpp:244
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
Definition: walletdb.cpp:224
const std::string WALLETDESCRIPTORKEY
Definition: walletdb.cpp:61
RAII class that provides access to a WalletDatabase.
Definition: db.h:45
const unsigned char * begin() const
Definition: pubkey.h:114
const std::unordered_set< std::string > LEGACY_TYPES
Definition: walletdb.cpp:64
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
Definition: walletdb.cpp:103
fs::path SQLiteDataFile(const fs::path &path)
Definition: db.cpp:78
void MaybeCompactWalletDB(WalletContext &context)
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:1317
static DBErrors LoadTxRecords(CWallet *pwallet, DatabaseBatch &batch, std::vector< uint256 > &upgraded_txs, bool &any_unordered) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:1014
bool WriteBestBlock(const CBlockLocator &locator)
Definition: walletdb.cpp:175
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:929
int64_t nLastWalletUpdate
Definition: db.h:172
static DBErrors LoadWalletFlags(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:462
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
CPrivKey is a serialized private key, with all parameters included (SIZE bytes)
Definition: key.h:23
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor &desc)
Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it.
Definition: wallet.cpp:3548
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:171
const std::string WATCHMETA
Definition: walletdb.cpp:62
bool EraseName(const std::string &strAddress)
Definition: walletdb.cpp:76
DescriptorScriptPubKeyMan * GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const
Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet...
Definition: wallet.cpp:3686
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
bool LoadEncryptionKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
Definition: walletdb.cpp:407
const_iterator end() const
Definition: streams.h:225
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:366
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition: walletdb.cpp:159
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:375
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:150
ArgsManager & args
Definition: bitcoind.cpp:269
bool IsBDBFile(const fs::path &path)
Definition: db.cpp:83
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256 &id, bool internal)
Definition: walletdb.cpp:212
const unsigned char * end() const
Definition: pubkey.h:115
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:192
static const int VERSION_WITH_HDDATA
Definition: walletdb.h:139
bool WriteDescriptorDerivedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index, uint32_t der_index)
Definition: walletdb.cpp:249
bool LoadCryptedKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
Definition: walletdb.cpp:368
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
#define LOCK(cs)
Definition: sync.h:258
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:192
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.
Definition: zeroafterfree.h:49
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:93
unsigned int nLastFlushed
Definition: db.h:171
bool IsValid() const
Definition: pubkey.h:189
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:1060
An encapsulated public key.
Definition: pubkey.h:33
const std::string POOL
Definition: walletdb.cpp:52
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
uint32_t n
Definition: transaction.h:39
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
WalletContext context
uint32_t nInternalChainCounter
Definition: walletdb.h:101
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:154
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:112
std::vector< uint256 > vHave
Definition: block.h:134
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1687
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:35
static DBErrors LoadMinVersion(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:450
constexpr bool IsNull() const
Definition: uint256.h:42
virtual bool PeriodicFlush()=0
const std::string FLAGS
Definition: walletdb.cpp:42
#define Assume(val)
Assume is the identity function.
Definition: check.h:85
bool ErasePurpose(const std::string &strAddress)
Definition: walletdb.cpp:88
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:202
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, bool checksum_valid)
Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) ...
Descriptor with some wallet metadata.
Definition: walletutil.h:84
const std::string ACTIVEINTERNALSPK
Definition: walletdb.cpp:35
const std::string KEYMETA
Definition: walletdb.cpp:44
bool WriteDescriptorParentCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
Definition: walletdb.cpp:256
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
const_iterator begin() const
Definition: streams.h:223
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:129
if(!SetupNetworking())
int flags
Definition: bitcoin-tx.cpp:528
DatabaseStatus
Definition: db.h:197
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:117
256-bit opaque blob.
Definition: uint256.h:106
bool LoadKey(CWallet *pwallet, DataStream &ssKey, DataStream &ssValue, std::string &strErr)
Definition: walletdb.cpp:302
catch(const std::exception &e)
const std::string WALLETDESCRIPTORCACHE
Definition: walletdb.cpp:58
bool EraseIC(const K &key)
Definition: walletdb.h:207
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:919
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:178
const std::string ACTIVEEXTERNALSPK
Definition: walletdb.cpp:34
bool ParseHDKeypath(const std::string &keypath_str, std::vector< uint32_t > &keypath)
Parse an HD keypaths like "m/7/0&#39;/2000".
Definition: bip32.cpp:13
bool error(const char *fmt, const Args &... args)
Definition: logging.h:262
Cache for single descriptor&#39;s derived extended pubkeys.
Definition: descriptor.h:19
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:412
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
Loads an active ScriptPubKeyMan for the specified type and internal.
Definition: wallet.cpp:3640
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
fs::path BDBDataFile(const fs::path &wallet_path)
Definition: db.cpp:64
static LoadResult LoadRecords(CWallet *pwallet, DatabaseBatch &batch, const std::string &key, DataStream &prefix, LoadFunc load_func)
Definition: walletdb.cpp:482
const uint256 & GetHash() const
Definition: transaction.h:333
bool EraseTx(uint256 hash)
Definition: walletdb.cpp:98
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:108
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
Definition: context.h:35
DBErrors ReorderTransactions()
Definition: wallet.cpp:892
const std::string LOCKED_UTXO
Definition: walletdb.cpp:46
160-bit opaque blob.
Definition: uint256.h:95
bool IsSQLiteFile(const fs::path &path)
Definition: db.cpp:108
bool require_existing
Definition: db.h:184
static const int VERSION_HD_BASE
Definition: walletdb.h:106
void AddInactiveHDChain(const CHDChain &chain)
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:581
const std::string WALLETDESCRIPTORLHCACHE
Definition: walletdb.cpp:59
bool WriteName(const std::string &strAddress, const std::string &strName)
Definition: walletdb.cpp:71
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:287
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
Definition: serialize.h:1015
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
Definition: wallet.cpp:530
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet) ...
Definition: wallet.h:802
bool WriteIC(const K &key, const T &value, bool fOverwrite=true)
Definition: walletdb.h:194
const std::string DEFAULTKEY
Definition: walletdb.cpp:40
An encapsulated private key.
Definition: key.h:32
A Span is an object that can refer to a contiguous sequence of objects.
Definition: solver.h:20
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:76
bool EraseLockedUTXO(const COutPoint &output)
Definition: walletdb.cpp:297
static bool exists(const path &p)
Definition: fs.h:88
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:292
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
Definition: walletdb.cpp:218
const std::string ORDERPOSNEXT
Definition: walletdb.cpp:51
#define LogPrintf(...)
Definition: logging.h:237
unsigned int nMasterKeyMaxID
Definition: wallet.h:450
int64_t GetTime()
DEPRECATED, see GetTime.
Definition: time.cpp:97
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:33
const std::string WATCHS
Definition: walletdb.cpp:63
bool WritePurpose(const std::string &strAddress, const std::string &purpose)
Definition: walletdb.cpp:83
CKeyID seed_id
seed hash160
Definition: walletdb.h:102
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
unsigned int nLastSeen
Definition: db.h:170
An instance of this class represents one database.
Definition: db.h:124
const std::string OLD_KEY
Definition: walletdb.cpp:50
const std::string TX
Definition: walletdb.cpp:55
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
Load a keypool entry.
static LoadResult LoadRecords(CWallet *pwallet, DatabaseBatch &batch, const std::string &key, LoadFunc load_func)
Definition: walletdb.cpp:519
static DBErrors LoadDecryptionKeys(CWallet *pwallet, DatabaseBatch &batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: walletdb.cpp:1131
bool WriteDescriptorLastHardenedCache(const CExtPubKey &xpub, const uint256 &desc_id, uint32_t key_exp_index)
Definition: walletdb.cpp:263
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:303
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:3498
uint256 hash
Definition: transaction.h:38
static const int VERSION_HD_CHAIN_SPLIT
Definition: walletdb.h:107