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