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