Bitcoin Core 28.99.0
P2P Digital Currency
scriptpubkeyman.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <hash.h>
6#include <key_io.h>
7#include <logging.h>
8#include <node/types.h>
9#include <outputtype.h>
10#include <script/descriptor.h>
11#include <script/script.h>
12#include <script/sign.h>
13#include <script/solver.h>
14#include <util/bip32.h>
15#include <util/check.h>
16#include <util/strencodings.h>
17#include <util/string.h>
18#include <util/time.h>
19#include <util/translation.h>
21
22#include <optional>
23
25using util::ToString;
26
27namespace wallet {
29const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
30
32{
33 if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
34 return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
35 }
37
38 // Fill-up keypool if needed
39 TopUp();
40
42
43 // Generate a new key that is added to wallet
44 CPubKey new_key;
45 if (!GetKeyFromPool(new_key, type)) {
46 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
47 }
48 LearnRelatedScripts(new_key, type);
49 return GetDestinationForKey(new_key, type);
50}
51
52typedef std::vector<unsigned char> valtype;
53
54namespace {
55
62enum class IsMineSigVersion
63{
64 TOP = 0,
65 P2SH = 1,
66 WITNESS_V0 = 2,
67};
68
74enum class IsMineResult
75{
76 NO = 0,
77 WATCH_ONLY = 1,
78 SPENDABLE = 2,
79 INVALID = 3,
80};
81
82bool PermitsUncompressed(IsMineSigVersion sigversion)
83{
84 return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
85}
86
87bool HaveKeys(const std::vector<valtype>& pubkeys, const LegacyDataSPKM& keystore)
88{
89 for (const valtype& pubkey : pubkeys) {
90 CKeyID keyID = CPubKey(pubkey).GetID();
91 if (!keystore.HaveKey(keyID)) return false;
92 }
93 return true;
94}
95
104// NOLINTNEXTLINE(misc-no-recursion)
105IsMineResult IsMineInner(const LegacyDataSPKM& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion, bool recurse_scripthash=true)
106{
107 IsMineResult ret = IsMineResult::NO;
108
109 std::vector<valtype> vSolutions;
110 TxoutType whichType = Solver(scriptPubKey, vSolutions);
111
112 CKeyID keyID;
113 switch (whichType) {
119 break;
121 keyID = CPubKey(vSolutions[0]).GetID();
122 if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
123 return IsMineResult::INVALID;
124 }
125 if (keystore.HaveKey(keyID)) {
126 ret = std::max(ret, IsMineResult::SPENDABLE);
127 }
128 break;
130 {
131 if (sigversion == IsMineSigVersion::WITNESS_V0) {
132 // P2WPKH inside P2WSH is invalid.
133 return IsMineResult::INVALID;
134 }
135 if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
136 // We do not support bare witness outputs unless the P2SH version of it would be
137 // acceptable as well. This protects against matching before segwit activates.
138 // This also applies to the P2WSH case.
139 break;
140 }
141 ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
142 break;
143 }
145 keyID = CKeyID(uint160(vSolutions[0]));
146 if (!PermitsUncompressed(sigversion)) {
147 CPubKey pubkey;
148 if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
149 return IsMineResult::INVALID;
150 }
151 }
152 if (keystore.HaveKey(keyID)) {
153 ret = std::max(ret, IsMineResult::SPENDABLE);
154 }
155 break;
157 {
158 if (sigversion != IsMineSigVersion::TOP) {
159 // P2SH inside P2WSH or P2SH is invalid.
160 return IsMineResult::INVALID;
161 }
162 CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
163 CScript subscript;
164 if (keystore.GetCScript(scriptID, subscript)) {
165 ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::P2SH) : IsMineResult::SPENDABLE);
166 }
167 break;
168 }
170 {
171 if (sigversion == IsMineSigVersion::WITNESS_V0) {
172 // P2WSH inside P2WSH is invalid.
173 return IsMineResult::INVALID;
174 }
175 if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
176 break;
177 }
178 CScriptID scriptID{RIPEMD160(vSolutions[0])};
179 CScript subscript;
180 if (keystore.GetCScript(scriptID, subscript)) {
181 ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0) : IsMineResult::SPENDABLE);
182 }
183 break;
184 }
185
187 {
188 // Never treat bare multisig outputs as ours (they can still be made watchonly-though)
189 if (sigversion == IsMineSigVersion::TOP) {
190 break;
191 }
192
193 // Only consider transactions "mine" if we own ALL the
194 // keys involved. Multi-signature transactions that are
195 // partially owned (somebody else has a key that can spend
196 // them) enable spend-out-from-under-you attacks, especially
197 // in shared-wallet situations.
198 std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
199 if (!PermitsUncompressed(sigversion)) {
200 for (size_t i = 0; i < keys.size(); i++) {
201 if (keys[i].size() != 33) {
202 return IsMineResult::INVALID;
203 }
204 }
205 }
206 if (HaveKeys(keys, keystore)) {
207 ret = std::max(ret, IsMineResult::SPENDABLE);
208 }
209 break;
210 }
211 } // no default case, so the compiler can warn about missing cases
212
213 if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {
214 ret = std::max(ret, IsMineResult::WATCH_ONLY);
215 }
216 return ret;
217}
218
219} // namespace
220
222{
223 switch (IsMineInner(*this, script, IsMineSigVersion::TOP)) {
224 case IsMineResult::INVALID:
225 case IsMineResult::NO:
226 return ISMINE_NO;
227 case IsMineResult::WATCH_ONLY:
228 return ISMINE_WATCH_ONLY;
229 case IsMineResult::SPENDABLE:
230 return ISMINE_SPENDABLE;
231 }
232 assert(false);
233}
234
236{
237 {
239 assert(mapKeys.empty());
240
241 bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
242 bool keyFail = false;
243 CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
245 for (; mi != mapCryptedKeys.end(); ++mi)
246 {
247 const CPubKey &vchPubKey = (*mi).second.first;
248 const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
249 CKey key;
250 if (!DecryptKey(master_key, vchCryptedSecret, vchPubKey, key))
251 {
252 keyFail = true;
253 break;
254 }
255 keyPass = true;
257 break;
258 else {
259 // Rewrite these encrypted keys with checksums
260 batch.WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
261 }
262 }
263 if (keyPass && keyFail)
264 {
265 LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
266 throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
267 }
268 if (keyFail || !keyPass)
269 return false;
271 }
272 return true;
273}
274
276{
278 encrypted_batch = batch;
279 if (!mapCryptedKeys.empty()) {
280 encrypted_batch = nullptr;
281 return false;
282 }
283
284 KeyMap keys_to_encrypt;
285 keys_to_encrypt.swap(mapKeys); // Clear mapKeys so AddCryptedKeyInner will succeed.
286 for (const KeyMap::value_type& mKey : keys_to_encrypt)
287 {
288 const CKey &key = mKey.second;
289 CPubKey vchPubKey = key.GetPubKey();
290 CKeyingMaterial vchSecret{UCharCast(key.begin()), UCharCast(key.end())};
291 std::vector<unsigned char> vchCryptedSecret;
292 if (!EncryptSecret(master_key, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) {
293 encrypted_batch = nullptr;
294 return false;
295 }
296 if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) {
297 encrypted_batch = nullptr;
298 return false;
299 }
300 }
301 encrypted_batch = nullptr;
302 return true;
303}
304
306{
307 if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
308 return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
309 }
311
313 if (!CanGetAddresses(internal)) {
314 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
315 }
316
317 // Fill-up keypool if needed
318 TopUp();
319
320 if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
321 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
322 }
323 return GetDestinationForKey(keypool.vchPubKey, type);
324}
325
326bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
327{
329
330 auto it = m_inactive_hd_chains.find(seed_id);
331 if (it == m_inactive_hd_chains.end()) {
332 return false;
333 }
334
335 CHDChain& chain = it->second;
336
337 if (internal) {
338 chain.m_next_internal_index = std::max(chain.m_next_internal_index, index + 1);
339 } else {
340 chain.m_next_external_index = std::max(chain.m_next_external_index, index + 1);
341 }
342
344 TopUpChain(batch, chain, 0);
345
346 return true;
347}
348
349std::vector<WalletDestination> LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
350{
352 std::vector<WalletDestination> result;
353 // extract addresses and check if they match with an unused keypool key
354 for (const auto& keyid : GetAffectedKeys(script, *this)) {
355 std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
356 if (mi != m_pool_key_to_index.end()) {
357 WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
358 for (const auto& keypool : MarkReserveKeysAsUsed(mi->second)) {
359 // derive all possible destinations as any of them could have been used
360 for (const auto& type : LEGACY_OUTPUT_TYPES) {
361 const auto& dest = GetDestinationForKey(keypool.vchPubKey, type);
362 result.push_back({dest, keypool.fInternal});
363 }
364 }
365
366 if (!TopUp()) {
367 WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
368 }
369 }
370
371 // Find the key's metadata and check if it's seed id (if it has one) is inactive, i.e. it is not the current m_hd_chain seed id.
372 // If so, TopUp the inactive hd chain
373 auto it = mapKeyMetadata.find(keyid);
374 if (it != mapKeyMetadata.end()){
375 CKeyMetadata meta = it->second;
376 if (!meta.hd_seed_id.IsNull() && meta.hd_seed_id != m_hd_chain.seed_id) {
377 std::vector<uint32_t> path;
378 if (meta.has_key_origin) {
379 path = meta.key_origin.path;
380 } else if (!ParseHDKeypath(meta.hdKeypath, path)) {
381 WalletLogPrintf("%s: Adding inactive seed keys failed, invalid hdKeypath: %s\n",
382 __func__,
383 meta.hdKeypath);
384 }
385 if (path.size() != 3) {
386 WalletLogPrintf("%s: Adding inactive seed keys failed, invalid path size: %d, has_key_origin: %s\n",
387 __func__,
388 path.size(),
389 meta.has_key_origin);
390 } else {
391 bool internal = (path[1] & ~BIP32_HARDENED_KEY_LIMIT) != 0;
392 int64_t index = path[2] & ~BIP32_HARDENED_KEY_LIMIT;
393
394 if (!TopUpInactiveHDChain(meta.hd_seed_id, index, internal)) {
395 WalletLogPrintf("%s: Adding inactive seed keys failed\n", __func__);
396 }
397 }
398 }
399 }
400 }
401
402 return result;
403}
404
406{
409 return;
410 }
411
412 std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(m_storage.GetDatabase());
413 for (auto& meta_pair : mapKeyMetadata) {
414 CKeyMetadata& meta = meta_pair.second;
415 if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
416 CKey key;
417 GetKey(meta.hd_seed_id, key);
418 CExtKey masterKey;
419 masterKey.SetSeed(key);
420 // Add to map
421 CKeyID master_id = masterKey.key.GetPubKey().GetID();
422 std::copy(master_id.begin(), master_id.begin() + 4, meta.key_origin.fingerprint);
423 if (!ParseHDKeypath(meta.hdKeypath, meta.key_origin.path)) {
424 throw std::runtime_error("Invalid stored hdKeypath");
425 }
426 meta.has_key_origin = true;
429 }
430
431 // Write meta to wallet
432 CPubKey pubkey;
433 if (GetPubKey(meta_pair.first, pubkey)) {
434 batch->WriteKeyMetadata(meta, pubkey, true);
435 }
436 }
437 }
438}
439
441{
442 if ((CanGenerateKeys() && !force) || m_storage.IsLocked()) {
443 return false;
444 }
445
447 if (!NewKeyPool()) {
448 return false;
449 }
450 return true;
451}
452
454{
455 return !m_hd_chain.seed_id.IsNull();
456}
457
459{
461 // Check if the keypool has keys
462 bool keypool_has_keys;
464 keypool_has_keys = setInternalKeyPool.size() > 0;
465 } else {
466 keypool_has_keys = KeypoolCountExternalKeys() > 0;
467 }
468 // If the keypool doesn't have keys, check if we can generate them
469 if (!keypool_has_keys) {
470 return CanGenerateKeys();
471 }
472 return keypool_has_keys;
473}
474
475bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual_str& error)
476{
478
480 // Nothing to do here if private keys are not enabled
481 return true;
482 }
483
484 bool hd_upgrade = false;
485 bool split_upgrade = false;
486 if (IsFeatureSupported(new_version, FEATURE_HD) && !IsHDEnabled()) {
487 WalletLogPrintf("Upgrading wallet to HD\n");
489
490 // generate a new master key
491 CPubKey masterPubKey = GenerateNewSeed();
492 SetHDSeed(masterPubKey);
493 hd_upgrade = true;
494 }
495 // Upgrade to HD chain split if necessary
496 if (!IsFeatureSupported(prev_version, FEATURE_HD_SPLIT) && IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) {
497 WalletLogPrintf("Upgrading wallet to use HD chain split\n");
499 split_upgrade = FEATURE_HD_SPLIT > prev_version;
500 // Upgrade the HDChain
504 throw std::runtime_error(std::string(__func__) + ": writing chain failed");
505 }
506 }
507 }
508 // Mark all keys currently in the keypool as pre-split
509 if (split_upgrade) {
511 }
512 // Regenerate the keypool if upgraded to HD
513 if (hd_upgrade) {
514 if (!NewKeyPool()) {
515 error = _("Unable to generate keys");
516 return false;
517 }
518 }
519 return true;
520}
521
523{
525 return !mapKeys.empty() || !mapCryptedKeys.empty();
526}
527
529{
531 setInternalKeyPool.clear();
532 setExternalKeyPool.clear();
533 m_pool_key_to_index.clear();
534 // Note: can't top-up keypool here, because wallet is locked.
535 // User will be prompted to unlock wallet the next operation
536 // that requires a new key.
537}
538
539static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
540 if (setKeyPool.empty()) {
541 return GetTime();
542 }
543
544 CKeyPool keypool;
545 int64_t nIndex = *(setKeyPool.begin());
546 if (!batch.ReadPool(nIndex, keypool)) {
547 throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed");
548 }
549 assert(keypool.vchPubKey.IsValid());
550 return keypool.nTime;
551}
552
554{
556
558
559 // load oldest key from keypool, get time and return
560 int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch);
562 oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), oldestKey);
563 if (!set_pre_split_keypool.empty()) {
564 oldestKey = std::max(GetOldestKeyTimeInPool(set_pre_split_keypool, batch), oldestKey);
565 }
566 }
567
568 return oldestKey;
569}
570
572{
574 return setExternalKeyPool.size() + set_pre_split_keypool.size();
575}
576
578{
580 return setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size();
581}
582
584{
586 return nTimeFirstKey;
587}
588
589std::unique_ptr<SigningProvider> LegacyDataSPKM::GetSolvingProvider(const CScript& script) const
590{
591 return std::make_unique<LegacySigningProvider>(*this);
592}
593
595{
596 IsMineResult ismine = IsMineInner(*this, script, IsMineSigVersion::TOP, /* recurse_scripthash= */ false);
597 if (ismine == IsMineResult::SPENDABLE || ismine == IsMineResult::WATCH_ONLY) {
598 // If ismine, it means we recognize keys or script ids in the script, or
599 // are watching the script itself, and we can at least provide metadata
600 // or solving information, even if not able to sign fully.
601 return true;
602 } else {
603 // If, given the stuff in sigdata, we could make a valid signature, then we can provide for this script
605 if (!sigdata.signatures.empty()) {
606 // If we could make signatures, make sure we have a private key to actually make a signature
607 bool has_privkeys = false;
608 for (const auto& key_sig_pair : sigdata.signatures) {
609 has_privkeys |= HaveKey(key_sig_pair.first);
610 }
611 return has_privkeys;
612 }
613 return false;
614 }
615}
616
617bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
618{
619 return ::SignTransaction(tx, this, coins, sighash, input_errors);
620}
621
622SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
623{
624 CKey key;
625 if (!GetKey(ToKeyID(pkhash), key)) {
627 }
628
629 if (MessageSign(key, message, str_sig)) {
630 return SigningResult::OK;
631 }
633}
634
635std::optional<PSBTError> LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed, bool finalize) const
636{
637 if (n_signed) {
638 *n_signed = 0;
639 }
640 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
641 const CTxIn& txin = psbtx.tx->vin[i];
642 PSBTInput& input = psbtx.inputs.at(i);
643
644 if (PSBTInputSigned(input)) {
645 continue;
646 }
647
648 // Get the Sighash type
649 if (sign && input.sighash_type != std::nullopt && *input.sighash_type != sighash_type) {
650 return PSBTError::SIGHASH_MISMATCH;
651 }
652
653 // Check non_witness_utxo has specified prevout
654 if (input.non_witness_utxo) {
655 if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
656 return PSBTError::MISSING_INPUTS;
657 }
658 } else if (input.witness_utxo.IsNull()) {
659 // There's no UTXO so we can just skip this now
660 continue;
661 }
662 SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, &txdata, sighash_type, nullptr, finalize);
663
664 bool signed_one = PSBTInputSigned(input);
665 if (n_signed && (signed_one || !sign)) {
666 // If sign is false, we assume that we _could_ sign if we get here. This
667 // will never have false negatives; it is hard to tell under what i
668 // circumstances it could have false positives.
669 (*n_signed)++;
670 }
671 }
672
673 // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
674 for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
675 UpdatePSBTOutput(HidingSigningProvider(this, true, !bip32derivs), psbtx, i);
676 }
677
678 return {};
679}
680
681std::unique_ptr<CKeyMetadata> LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
682{
684
685 CKeyID key_id = GetKeyForDestination(*this, dest);
686 if (!key_id.IsNull()) {
687 auto it = mapKeyMetadata.find(key_id);
688 if (it != mapKeyMetadata.end()) {
689 return std::make_unique<CKeyMetadata>(it->second);
690 }
691 }
692
693 CScript scriptPubKey = GetScriptForDestination(dest);
694 auto it = m_script_metadata.find(CScriptID(scriptPubKey));
695 if (it != m_script_metadata.end()) {
696 return std::make_unique<CKeyMetadata>(it->second);
697 }
698
699 return nullptr;
700}
701
703{
704 return uint256::ONE;
705}
706
712{
714 if (nCreateTime <= 1) {
715 // Cannot determine birthday information, so set the wallet birthday to
716 // the beginning of time.
717 nTimeFirstKey = 1;
718 } else if (nTimeFirstKey == UNKNOWN_TIME || nCreateTime < nTimeFirstKey) {
719 nTimeFirstKey = nCreateTime;
720 }
721
722 NotifyFirstKeyTimeChanged(this, nTimeFirstKey);
723}
724
725bool LegacyDataSPKM::LoadKey(const CKey& key, const CPubKey &pubkey)
726{
727 return AddKeyPubKeyInner(key, pubkey);
728}
729
730bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
731{
734 return LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(batch, secret, pubkey);
735}
736
737bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const CPubKey& pubkey)
738{
740
741 // Make sure we aren't adding private keys to private key disabled wallets
743
744 // FillableSigningProvider has no concept of wallet databases, but calls AddCryptedKey
745 // which is overridden below. To avoid flushes, the database handle is
746 // tunneled through to it.
747 bool needsDB = !encrypted_batch;
748 if (needsDB) {
749 encrypted_batch = &batch;
750 }
751 if (!AddKeyPubKeyInner(secret, pubkey)) {
752 if (needsDB) encrypted_batch = nullptr;
753 return false;
754 }
755 if (needsDB) encrypted_batch = nullptr;
756
757 // check if we need to remove from watch-only
760 if (HaveWatchOnly(script)) {
762 }
764 if (HaveWatchOnly(script)) {
766 }
767
770 return batch.WriteKey(pubkey,
771 secret.GetPrivKey(),
772 mapKeyMetadata[pubkey.GetID()]);
773 }
774 return true;
775}
776
777bool LegacyDataSPKM::LoadCScript(const CScript& redeemScript)
778{
779 /* A sanity check was added in pull #3843 to avoid adding redeemScripts
780 * that never can be redeemed. However, old wallets may still contain
781 * these. Do not add them to the wallet and warn. */
782 if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
783 {
784 std::string strAddr = EncodeDestination(ScriptHash(redeemScript));
785 WalletLogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
786 return true;
787 }
788
789 return FillableSigningProvider::AddCScript(redeemScript);
790}
791
793{
795 mapKeyMetadata[keyID] = meta;
796}
797
799{
803}
804
806{
808 m_script_metadata[script_id] = meta;
809}
810
812{
814 LegacyDataSPKM::LoadScriptMetadata(script_id, meta);
816}
817
818bool LegacyDataSPKM::AddKeyPubKeyInner(const CKey& key, const CPubKey& pubkey)
819{
821 return FillableSigningProvider::AddKeyPubKey(key, pubkey);
822}
823
825{
828 return FillableSigningProvider::AddKeyPubKey(key, pubkey);
829 }
830
831 if (m_storage.IsLocked()) {
832 return false;
833 }
834
835 std::vector<unsigned char> vchCryptedSecret;
836 CKeyingMaterial vchSecret{UCharCast(key.begin()), UCharCast(key.end())};
837 if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
838 return EncryptSecret(encryption_key, vchSecret, pubkey.GetHash(), vchCryptedSecret);
839 })) {
840 return false;
841 }
842
843 if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
844 return false;
845 }
846 return true;
847}
848
849bool LegacyDataSPKM::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret, bool checksum_valid)
850{
851 // Set fDecryptionThoroughlyChecked to false when the checksum is invalid
852 if (!checksum_valid) {
854 }
855
856 return AddCryptedKeyInner(vchPubKey, vchCryptedSecret);
857}
858
859bool LegacyDataSPKM::AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
860{
862 assert(mapKeys.empty());
863
864 mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
866 return true;
867}
868
870 const std::vector<unsigned char> &vchCryptedSecret)
871{
872 if (!AddCryptedKeyInner(vchPubKey, vchCryptedSecret))
873 return false;
874 {
876 if (encrypted_batch)
877 return encrypted_batch->WriteCryptedKey(vchPubKey,
878 vchCryptedSecret,
879 mapKeyMetadata[vchPubKey.GetID()]);
880 else
882 vchCryptedSecret,
883 mapKeyMetadata[vchPubKey.GetID()]);
884 }
885}
886
888{
890 return setWatchOnly.count(dest) > 0;
891}
892
894{
896 return (!setWatchOnly.empty());
897}
898
899static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
900{
901 std::vector<std::vector<unsigned char>> solutions;
902 return Solver(dest, solutions) == TxoutType::PUBKEY &&
903 (pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
904}
905
907{
908 {
910 setWatchOnly.erase(dest);
911 CPubKey pubKey;
912 if (ExtractPubKey(dest, pubKey)) {
913 mapWatchKeys.erase(pubKey.GetID());
914 }
915 // Related CScripts are not removed; having superfluous scripts around is
916 // harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
917 }
918
919 if (!HaveWatchOnly())
922 return false;
923
924 return true;
925}
926
928{
929 return AddWatchOnlyInMem(dest);
930}
931
933{
935 setWatchOnly.insert(dest);
936 CPubKey pubKey;
937 if (ExtractPubKey(dest, pubKey)) {
938 mapWatchKeys[pubKey.GetID()] = pubKey;
940 }
941 return true;
942}
943
945{
946 if (!AddWatchOnlyInMem(dest))
947 return false;
948 const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
951 if (batch.WriteWatchOnly(dest, meta)) {
953 return true;
954 }
955 return false;
956}
957
958bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time)
959{
960 m_script_metadata[CScriptID(dest)].nCreateTime = create_time;
961 return AddWatchOnlyWithDB(batch, dest);
962}
963
965{
967 return AddWatchOnlyWithDB(batch, dest);
968}
969
970bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
971{
972 m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime;
973 return AddWatchOnly(dest);
974}
975
977{
979 m_hd_chain = chain;
980}
981
983{
985 // Store the new chain
987 throw std::runtime_error(std::string(__func__) + ": writing chain failed");
988 }
989 // When there's an old chain, add it as an inactive chain as we are now rotating hd chains
990 if (!m_hd_chain.seed_id.IsNull()) {
992 }
993
994 m_hd_chain = chain;
995}
996
998{
1000 assert(!chain.seed_id.IsNull());
1001 m_inactive_hd_chains[chain.seed_id] = chain;
1002}
1003
1004bool LegacyDataSPKM::HaveKey(const CKeyID &address) const
1005{
1008 return FillableSigningProvider::HaveKey(address);
1009 }
1010 return mapCryptedKeys.count(address) > 0;
1011}
1012
1013bool LegacyDataSPKM::GetKey(const CKeyID &address, CKey& keyOut) const
1014{
1017 return FillableSigningProvider::GetKey(address, keyOut);
1018 }
1019
1020 CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
1021 if (mi != mapCryptedKeys.end())
1022 {
1023 const CPubKey &vchPubKey = (*mi).second.first;
1024 const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
1025 return m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
1026 return DecryptKey(encryption_key, vchCryptedSecret, vchPubKey, keyOut);
1027 });
1028 }
1029 return false;
1030}
1031
1033{
1034 CKeyMetadata meta;
1035 {
1037 auto it = mapKeyMetadata.find(keyID);
1038 if (it == mapKeyMetadata.end()) {
1039 return false;
1040 }
1041 meta = it->second;
1042 }
1043 if (meta.has_key_origin) {
1044 std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, info.fingerprint);
1045 info.path = meta.key_origin.path;
1046 } else { // Single pubkeys get the master fingerprint of themselves
1047 std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
1048 }
1049 return true;
1050}
1051
1052bool LegacyDataSPKM::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
1053{
1055 WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
1056 if (it != mapWatchKeys.end()) {
1057 pubkey_out = it->second;
1058 return true;
1059 }
1060 return false;
1061}
1062
1063bool LegacyDataSPKM::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
1064{
1067 if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
1068 return GetWatchPubKey(address, vchPubKeyOut);
1069 }
1070 return true;
1071 }
1072
1073 CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
1074 if (mi != mapCryptedKeys.end())
1075 {
1076 vchPubKeyOut = (*mi).second.first;
1077 return true;
1078 }
1079 // Check for watch-only pubkeys
1080 return GetWatchPubKey(address, vchPubKeyOut);
1081}
1082
1084{
1088 bool fCompressed = m_storage.CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
1089
1090 CKey secret;
1091
1092 // Create new metadata
1093 int64_t nCreationTime = GetTime();
1094 CKeyMetadata metadata(nCreationTime);
1095
1096 // use HD key derivation if HD was enabled during wallet creation and a seed is present
1097 if (IsHDEnabled()) {
1098 DeriveNewChildKey(batch, metadata, secret, hd_chain, (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
1099 } else {
1100 secret.MakeNewKey(fCompressed);
1101 }
1102
1103 // Compressed public keys were introduced in version 0.6.0
1104 if (fCompressed) {
1106 }
1107
1108 CPubKey pubkey = secret.GetPubKey();
1109 assert(secret.VerifyPubKey(pubkey));
1110
1111 mapKeyMetadata[pubkey.GetID()] = metadata;
1112 UpdateTimeFirstKey(nCreationTime);
1113
1114 if (!AddKeyPubKeyWithDB(batch, secret, pubkey)) {
1115 throw std::runtime_error(std::string(__func__) + ": AddKey failed");
1116 }
1117 return pubkey;
1118}
1119
1121static void DeriveExtKey(CExtKey& key_in, unsigned int index, CExtKey& key_out) {
1122 if (!key_in.Derive(key_out, index)) {
1123 throw std::runtime_error("Could not derive extended key");
1124 }
1125}
1126
1127void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal)
1128{
1129 // for now we use a fixed keypath scheme of m/0'/0'/k
1130 CKey seed; //seed (256bit)
1131 CExtKey masterKey; //hd master key
1132 CExtKey accountKey; //key at m/0'
1133 CExtKey chainChildKey; //key at m/0'/0' (external) or m/0'/1' (internal)
1134 CExtKey childKey; //key at m/0'/0'/<n>'
1135
1136 // try to get the seed
1137 if (!GetKey(hd_chain.seed_id, seed))
1138 throw std::runtime_error(std::string(__func__) + ": seed not found");
1139
1140 masterKey.SetSeed(seed);
1141
1142 // derive m/0'
1143 // use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
1144 DeriveExtKey(masterKey, BIP32_HARDENED_KEY_LIMIT, accountKey);
1145
1146 // derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
1148 DeriveExtKey(accountKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0), chainChildKey);
1149
1150 // derive child key at next index, skip keys already known to the wallet
1151 do {
1152 // always derive hardened keys
1153 // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
1154 // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
1155 if (internal) {
1156 DeriveExtKey(chainChildKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
1157 metadata.hdKeypath = "m/0'/1'/" + ToString(hd_chain.nInternalChainCounter) + "'";
1158 metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
1159 metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
1160 metadata.key_origin.path.push_back(hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
1161 hd_chain.nInternalChainCounter++;
1162 }
1163 else {
1164 DeriveExtKey(chainChildKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
1165 metadata.hdKeypath = "m/0'/0'/" + ToString(hd_chain.nExternalChainCounter) + "'";
1166 metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
1167 metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
1168 metadata.key_origin.path.push_back(hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
1169 hd_chain.nExternalChainCounter++;
1170 }
1171 } while (HaveKey(childKey.key.GetPubKey().GetID()));
1172 secret = childKey.key;
1173 metadata.hd_seed_id = hd_chain.seed_id;
1174 CKeyID master_id = masterKey.key.GetPubKey().GetID();
1175 std::copy(master_id.begin(), master_id.begin() + 4, metadata.key_origin.fingerprint);
1176 metadata.has_key_origin = true;
1177 // update the chain model in the database
1178 if (hd_chain.seed_id == m_hd_chain.seed_id && !batch.WriteHDChain(hd_chain))
1179 throw std::runtime_error(std::string(__func__) + ": writing HD chain model failed");
1180}
1181
1182void LegacyDataSPKM::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
1183{
1185 if (keypool.m_pre_split) {
1186 set_pre_split_keypool.insert(nIndex);
1187 } else if (keypool.fInternal) {
1188 setInternalKeyPool.insert(nIndex);
1189 } else {
1190 setExternalKeyPool.insert(nIndex);
1191 }
1192 m_max_keypool_index = std::max(m_max_keypool_index, nIndex);
1193 m_pool_key_to_index[keypool.vchPubKey.GetID()] = nIndex;
1194
1195 // If no metadata exists yet, create a default with the pool key's
1196 // creation time. Note that this may be overwritten by actually
1197 // stored metadata for that key later, which is fine.
1198 CKeyID keyid = keypool.vchPubKey.GetID();
1199 if (mapKeyMetadata.count(keyid) == 0)
1200 mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
1201}
1202
1204{
1205 // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
1208}
1209
1211{
1213 CKey key = GenerateRandomKey();
1214 return DeriveNewSeed(key);
1215}
1216
1218{
1219 int64_t nCreationTime = GetTime();
1220 CKeyMetadata metadata(nCreationTime);
1221
1222 // calculate the seed
1223 CPubKey seed = key.GetPubKey();
1224 assert(key.VerifyPubKey(seed));
1225
1226 // set the hd keypath to "s" -> Seed, refers the seed to itself
1227 metadata.hdKeypath = "s";
1228 metadata.has_key_origin = false;
1229 metadata.hd_seed_id = seed.GetID();
1230
1231 {
1233
1234 // mem store the metadata
1235 mapKeyMetadata[seed.GetID()] = metadata;
1236
1237 // write the key&metadata to the database
1238 if (!AddKeyPubKey(key, seed))
1239 throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed");
1240 }
1241
1242 return seed;
1243}
1244
1246{
1248 // store the keyid (hash160) together with
1249 // the child index counter in the database
1250 // as a hdchain object
1251 CHDChain newHdChain;
1253 newHdChain.seed_id = seed.GetID();
1254 AddHDChain(newHdChain);
1258}
1259
1265{
1267 return false;
1268 }
1269 {
1272
1273 for (const int64_t nIndex : setInternalKeyPool) {
1274 batch.ErasePool(nIndex);
1275 }
1276 setInternalKeyPool.clear();
1277
1278 for (const int64_t nIndex : setExternalKeyPool) {
1279 batch.ErasePool(nIndex);
1280 }
1281 setExternalKeyPool.clear();
1282
1283 for (const int64_t nIndex : set_pre_split_keypool) {
1284 batch.ErasePool(nIndex);
1285 }
1286 set_pre_split_keypool.clear();
1287
1288 m_pool_key_to_index.clear();
1289
1290 if (!TopUp()) {
1291 return false;
1292 }
1293 WalletLogPrintf("LegacyScriptPubKeyMan::NewKeyPool rewrote keypool\n");
1294 }
1295 return true;
1296}
1297
1298bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
1299{
1300 if (!CanGenerateKeys()) {
1301 return false;
1302 }
1303
1305 if (!batch.TxnBegin()) return false;
1306 if (!TopUpChain(batch, m_hd_chain, kpSize)) {
1307 return false;
1308 }
1309 for (auto& [chain_id, chain] : m_inactive_hd_chains) {
1310 if (!TopUpChain(batch, chain, kpSize)) {
1311 return false;
1312 }
1313 }
1314 if (!batch.TxnCommit()) throw std::runtime_error(strprintf("Error during keypool top up. Cannot commit changes for wallet %s", m_storage.GetDisplayName()));
1316 // Note: Unlike with DescriptorSPKM, LegacySPKM does not need to call
1317 // m_storage.TopUpCallback() as we do not know what new scripts the LegacySPKM is
1318 // watching for. CWallet's scriptPubKey cache is not used for LegacySPKMs.
1319 return true;
1320}
1321
1322bool LegacyScriptPubKeyMan::TopUpChain(WalletBatch& batch, CHDChain& chain, unsigned int kpSize)
1323{
1325
1326 if (m_storage.IsLocked()) return false;
1327
1328 // Top up key pool
1329 unsigned int nTargetSize;
1330 if (kpSize > 0) {
1331 nTargetSize = kpSize;
1332 } else {
1333 nTargetSize = m_keypool_size;
1334 }
1335 int64_t target = std::max((int64_t) nTargetSize, int64_t{1});
1336
1337 // count amount of available keys (internal, external)
1338 // make sure the keypool of external and internal keys fits the user selected target (-keypool)
1339 int64_t missingExternal;
1340 int64_t missingInternal;
1341 if (chain == m_hd_chain) {
1342 missingExternal = std::max(target - (int64_t)setExternalKeyPool.size(), int64_t{0});
1343 missingInternal = std::max(target - (int64_t)setInternalKeyPool.size(), int64_t{0});
1344 } else {
1345 missingExternal = std::max(target - (chain.nExternalChainCounter - chain.m_next_external_index), int64_t{0});
1346 missingInternal = std::max(target - (chain.nInternalChainCounter - chain.m_next_internal_index), int64_t{0});
1347 }
1348
1350 // don't create extra internal keys
1351 missingInternal = 0;
1352 }
1353 bool internal = false;
1354 for (int64_t i = missingInternal + missingExternal; i--;) {
1355 if (i < missingInternal) {
1356 internal = true;
1357 }
1358
1359 CPubKey pubkey(GenerateNewKey(batch, chain, internal));
1360 if (chain == m_hd_chain) {
1361 AddKeypoolPubkeyWithDB(pubkey, internal, batch);
1362 }
1363 }
1364 if (missingInternal + missingExternal > 0) {
1365 if (chain == m_hd_chain) {
1366 WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
1367 } else {
1368 WalletLogPrintf("inactive seed with id %s added %d external keys, %d internal keys\n", HexStr(chain.seed_id), missingExternal, missingInternal);
1369 }
1370 }
1371 return true;
1372}
1373
1374void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
1375{
1377 assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
1378 int64_t index = ++m_max_keypool_index;
1379 if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
1380 throw std::runtime_error(std::string(__func__) + ": writing imported pubkey failed");
1381 }
1382 if (internal) {
1383 setInternalKeyPool.insert(index);
1384 } else {
1385 setExternalKeyPool.insert(index);
1386 }
1387 m_pool_key_to_index[pubkey.GetID()] = index;
1388}
1389
1391{
1392 assert(type != OutputType::BECH32M);
1393 // Remove from key pool
1395 batch.ErasePool(nIndex);
1396 CPubKey pubkey;
1397 bool have_pk = GetPubKey(m_index_to_reserved_key.at(nIndex), pubkey);
1398 assert(have_pk);
1399 LearnRelatedScripts(pubkey, type);
1400 m_index_to_reserved_key.erase(nIndex);
1401 WalletLogPrintf("keypool keep %d\n", nIndex);
1402}
1403
1404void LegacyScriptPubKeyMan::ReturnDestination(int64_t nIndex, bool fInternal, const CTxDestination&)
1405{
1406 // Return to key pool
1407 {
1409 if (fInternal) {
1410 setInternalKeyPool.insert(nIndex);
1411 } else if (!set_pre_split_keypool.empty()) {
1412 set_pre_split_keypool.insert(nIndex);
1413 } else {
1414 setExternalKeyPool.insert(nIndex);
1415 }
1416 CKeyID& pubkey_id = m_index_to_reserved_key.at(nIndex);
1417 m_pool_key_to_index[pubkey_id] = nIndex;
1418 m_index_to_reserved_key.erase(nIndex);
1420 }
1421 WalletLogPrintf("keypool return %d\n", nIndex);
1422}
1423
1425{
1426 assert(type != OutputType::BECH32M);
1427 if (!CanGetAddresses(/*internal=*/ false)) {
1428 return false;
1429 }
1430
1431 CKeyPool keypool;
1432 {
1434 int64_t nIndex;
1435 if (!ReserveKeyFromKeyPool(nIndex, keypool, /*fRequestedInternal=*/ false) && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1436 if (m_storage.IsLocked()) return false;
1438 result = GenerateNewKey(batch, m_hd_chain, /*internal=*/ false);
1439 return true;
1440 }
1441 KeepDestination(nIndex, type);
1442 result = keypool.vchPubKey;
1443 }
1444 return true;
1445}
1446
1447bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
1448{
1449 nIndex = -1;
1450 keypool.vchPubKey = CPubKey();
1451 {
1453
1454 bool fReturningInternal = fRequestedInternal;
1456 bool use_split_keypool = set_pre_split_keypool.empty();
1457 std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
1458
1459 // Get the oldest key
1460 if (setKeyPool.empty()) {
1461 return false;
1462 }
1463
1465
1466 auto it = setKeyPool.begin();
1467 nIndex = *it;
1468 setKeyPool.erase(it);
1469 if (!batch.ReadPool(nIndex, keypool)) {
1470 throw std::runtime_error(std::string(__func__) + ": read failed");
1471 }
1472 CPubKey pk;
1473 if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
1474 throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
1475 }
1476 // If the key was pre-split keypool, we don't care about what type it is
1477 if (use_split_keypool && keypool.fInternal != fReturningInternal) {
1478 throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
1479 }
1480 if (!keypool.vchPubKey.IsValid()) {
1481 throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
1482 }
1483
1484 assert(m_index_to_reserved_key.count(nIndex) == 0);
1485 m_index_to_reserved_key[nIndex] = keypool.vchPubKey.GetID();
1486 m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
1487 WalletLogPrintf("keypool reserve %d\n", nIndex);
1488 }
1490 return true;
1491}
1492
1494{
1495 assert(type != OutputType::BECH32M);
1496 if (key.IsCompressed() && (type == OutputType::P2SH_SEGWIT || type == OutputType::BECH32)) {
1497 CTxDestination witdest = WitnessV0KeyHash(key.GetID());
1498 CScript witprog = GetScriptForDestination(witdest);
1499 // Make sure the resulting program is solvable.
1500 const auto desc = InferDescriptor(witprog, *this);
1501 assert(desc && desc->IsSolvable());
1502 AddCScript(witprog);
1503 }
1504}
1505
1507{
1508 // OutputType::P2SH_SEGWIT always adds all necessary scripts for all types.
1510}
1511
1512std::vector<CKeyPool> LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
1513{
1515 bool internal = setInternalKeyPool.count(keypool_id);
1516 if (!internal) assert(setExternalKeyPool.count(keypool_id) || set_pre_split_keypool.count(keypool_id));
1517 std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : (set_pre_split_keypool.empty() ? &setExternalKeyPool : &set_pre_split_keypool);
1518 auto it = setKeyPool->begin();
1519
1520 std::vector<CKeyPool> result;
1522 while (it != std::end(*setKeyPool)) {
1523 const int64_t& index = *(it);
1524 if (index > keypool_id) break; // set*KeyPool is ordered
1525
1526 CKeyPool keypool;
1527 if (batch.ReadPool(index, keypool)) { //TODO: This should be unnecessary
1528 m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
1529 }
1531 batch.ErasePool(index);
1532 WalletLogPrintf("keypool index %d removed\n", index);
1533 it = setKeyPool->erase(it);
1534 result.push_back(std::move(keypool));
1535 }
1536
1537 return result;
1538}
1539
1540std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
1541{
1542 std::vector<CScript> dummy;
1544 InferDescriptor(spk, provider)->Expand(0, DUMMY_SIGNING_PROVIDER, dummy, out);
1545 std::vector<CKeyID> ret;
1546 ret.reserve(out.pubkeys.size());
1547 for (const auto& entry : out.pubkeys) {
1548 ret.push_back(entry.first);
1549 }
1550 return ret;
1551}
1552
1554{
1556 for (auto it = setExternalKeyPool.begin(); it != setExternalKeyPool.end();) {
1557 int64_t index = *it;
1558 CKeyPool keypool;
1559 if (!batch.ReadPool(index, keypool)) {
1560 throw std::runtime_error(std::string(__func__) + ": read keypool entry failed");
1561 }
1562 keypool.m_pre_split = true;
1563 if (!batch.WritePool(index, keypool)) {
1564 throw std::runtime_error(std::string(__func__) + ": writing modified keypool entry failed");
1565 }
1566 set_pre_split_keypool.insert(index);
1567 it = setExternalKeyPool.erase(it);
1568 }
1569}
1570
1572{
1574 return AddCScriptWithDB(batch, redeemScript);
1575}
1576
1578{
1579 if (!FillableSigningProvider::AddCScript(redeemScript))
1580 return false;
1581 if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
1583 return true;
1584 }
1585 return false;
1586}
1587
1589{
1591 std::copy(info.fingerprint, info.fingerprint + 4, mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint);
1592 mapKeyMetadata[pubkey.GetID()].key_origin.path = info.path;
1593 mapKeyMetadata[pubkey.GetID()].has_key_origin = true;
1594 mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path, /*apostrophe=*/true);
1595 return batch.WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
1596}
1597
1598bool LegacyScriptPubKeyMan::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1599{
1601 for (const auto& entry : scripts) {
1602 CScriptID id(entry);
1603 if (HaveCScript(id)) {
1604 WalletLogPrintf("Already have script %s, skipping\n", HexStr(entry));
1605 continue;
1606 }
1607 if (!AddCScriptWithDB(batch, entry)) {
1608 return false;
1609 }
1610
1611 if (timestamp > 0) {
1612 m_script_metadata[CScriptID(entry)].nCreateTime = timestamp;
1613 }
1614 }
1615 if (timestamp > 0) {
1616 UpdateTimeFirstKey(timestamp);
1617 }
1618
1619 return true;
1620}
1621
1622bool LegacyScriptPubKeyMan::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1623{
1625 for (const auto& entry : privkey_map) {
1626 const CKey& key = entry.second;
1627 CPubKey pubkey = key.GetPubKey();
1628 const CKeyID& id = entry.first;
1629 assert(key.VerifyPubKey(pubkey));
1630 // Skip if we already have the key
1631 if (HaveKey(id)) {
1632 WalletLogPrintf("Already have key with pubkey %s, skipping\n", HexStr(pubkey));
1633 continue;
1634 }
1635 mapKeyMetadata[id].nCreateTime = timestamp;
1636 // If the private key is not present in the wallet, insert it.
1637 if (!AddKeyPubKeyWithDB(batch, key, pubkey)) {
1638 return false;
1639 }
1640 UpdateTimeFirstKey(timestamp);
1641 }
1642 return true;
1643}
1644
1645bool LegacyScriptPubKeyMan::ImportPubKeys(const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const int64_t timestamp)
1646{
1648 for (const auto& entry : key_origins) {
1649 AddKeyOriginWithDB(batch, entry.second.first, entry.second.second);
1650 }
1651 for (const auto& [id, internal] : ordered_pubkeys) {
1652 auto entry = pubkey_map.find(id);
1653 if (entry == pubkey_map.end()) {
1654 continue;
1655 }
1656 const CPubKey& pubkey = entry->second;
1657 CPubKey temp;
1658 if (GetPubKey(id, temp)) {
1659 // Already have pubkey, skipping
1660 WalletLogPrintf("Already have pubkey %s, skipping\n", HexStr(temp));
1661 continue;
1662 }
1663 if (!AddWatchOnlyWithDB(batch, GetScriptForRawPubKey(pubkey), timestamp)) {
1664 return false;
1665 }
1666 mapKeyMetadata[id].nCreateTime = timestamp;
1667
1668 // Add to keypool only works with pubkeys
1669 if (add_keypool) {
1670 AddKeypoolPubkeyWithDB(pubkey, internal, batch);
1672 }
1673 }
1674 return true;
1675}
1676
1677bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp)
1678{
1680 for (const CScript& script : script_pub_keys) {
1681 if (!have_solving_data || !IsMine(script)) { // Always call AddWatchOnly for non-solvable watch-only, so that watch timestamp gets updated
1682 if (!AddWatchOnlyWithDB(batch, script, timestamp)) {
1683 return false;
1684 }
1685 }
1686 }
1687 return true;
1688}
1689
1690std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
1691{
1695 }
1696 std::set<CKeyID> set_address;
1697 for (const auto& mi : mapCryptedKeys) {
1698 set_address.insert(mi.first);
1699 }
1700 return set_address;
1701}
1702
1703std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetScriptPubKeys() const
1704{
1706 std::unordered_set<CScript, SaltedSipHasher> spks;
1707
1708 // All keys have at least P2PK and P2PKH
1709 for (const auto& key_pair : mapKeys) {
1710 const CPubKey& pub = key_pair.second.GetPubKey();
1711 spks.insert(GetScriptForRawPubKey(pub));
1712 spks.insert(GetScriptForDestination(PKHash(pub)));
1713 }
1714 for (const auto& key_pair : mapCryptedKeys) {
1715 const CPubKey& pub = key_pair.second.first;
1716 spks.insert(GetScriptForRawPubKey(pub));
1717 spks.insert(GetScriptForDestination(PKHash(pub)));
1718 }
1719
1720 // For every script in mapScript, only the ISMINE_SPENDABLE ones are being tracked.
1721 // The watchonly ones will be in setWatchOnly which we deal with later
1722 // For all keys, if they have segwit scripts, those scripts will end up in mapScripts
1723 for (const auto& script_pair : mapScripts) {
1724 const CScript& script = script_pair.second;
1725 if (IsMine(script) == ISMINE_SPENDABLE) {
1726 // Add ScriptHash for scripts that are not already P2SH
1727 if (!script.IsPayToScriptHash()) {
1729 }
1730 // For segwit scripts, we only consider them spendable if we have the segwit spk
1731 int wit_ver = -1;
1732 std::vector<unsigned char> witprog;
1733 if (script.IsWitnessProgram(wit_ver, witprog) && wit_ver == 0) {
1734 spks.insert(script);
1735 }
1736 } else {
1737 // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
1738 // So check the P2SH of a multisig to see if we should insert it
1739 std::vector<std::vector<unsigned char>> sols;
1740 TxoutType type = Solver(script, sols);
1741 if (type == TxoutType::MULTISIG) {
1743 if (IsMine(ms_spk) != ISMINE_NO) {
1744 spks.insert(ms_spk);
1745 }
1746 }
1747 }
1748 }
1749
1750 // All watchonly scripts are raw
1751 for (const CScript& script : setWatchOnly) {
1752 // As the legacy wallet allowed to import any script, we need to verify the validity here.
1753 // LegacyScriptPubKeyMan::IsMine() return 'ISMINE_NO' for invalid or not watched scripts (IsMineResult::INVALID or IsMineResult::NO).
1754 // e.g. a "sh(sh(pkh()))" which legacy wallets allowed to import!.
1755 if (IsMine(script) != ISMINE_NO) spks.insert(script);
1756 }
1757
1758 return spks;
1759}
1760
1761std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetNotMineScriptPubKeys() const
1762{
1764 std::unordered_set<CScript, SaltedSipHasher> spks;
1765 for (const CScript& script : setWatchOnly) {
1766 if (IsMine(script) == ISMINE_NO) spks.insert(script);
1767 }
1768 return spks;
1769}
1770
1771std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
1772{
1774 if (m_storage.IsLocked()) {
1775 return std::nullopt;
1776 }
1777
1779
1780 std::unordered_set<CScript, SaltedSipHasher> spks{GetScriptPubKeys()};
1781
1782 // Get all key ids
1783 std::set<CKeyID> keyids;
1784 for (const auto& key_pair : mapKeys) {
1785 keyids.insert(key_pair.first);
1786 }
1787 for (const auto& key_pair : mapCryptedKeys) {
1788 keyids.insert(key_pair.first);
1789 }
1790
1791 // Get key metadata and figure out which keys don't have a seed
1792 // Note that we do not ignore the seeds themselves because they are considered IsMine!
1793 for (auto keyid_it = keyids.begin(); keyid_it != keyids.end();) {
1794 const CKeyID& keyid = *keyid_it;
1795 const auto& it = mapKeyMetadata.find(keyid);
1796 if (it != mapKeyMetadata.end()) {
1797 const CKeyMetadata& meta = it->second;
1798 if (meta.hdKeypath == "s" || meta.hdKeypath == "m") {
1799 keyid_it++;
1800 continue;
1801 }
1802 if (!meta.hd_seed_id.IsNull() && (m_hd_chain.seed_id == meta.hd_seed_id || m_inactive_hd_chains.count(meta.hd_seed_id) > 0)) {
1803 keyid_it = keyids.erase(keyid_it);
1804 continue;
1805 }
1806 }
1807 keyid_it++;
1808 }
1809
1811 if (!batch.TxnBegin()) {
1812 LogPrintf("Error generating descriptors for migration, cannot initialize db transaction\n");
1813 return std::nullopt;
1814 }
1815
1816 // keyids is now all non-HD keys. Each key will have its own combo descriptor
1817 for (const CKeyID& keyid : keyids) {
1818 CKey key;
1819 if (!GetKey(keyid, key)) {
1820 assert(false);
1821 }
1822
1823 // Get birthdate from key meta
1824 uint64_t creation_time = 0;
1825 const auto& it = mapKeyMetadata.find(keyid);
1826 if (it != mapKeyMetadata.end()) {
1827 creation_time = it->second.nCreateTime;
1828 }
1829
1830 // Get the key origin
1831 // Maybe this doesn't matter because floating keys here shouldn't have origins
1832 KeyOriginInfo info;
1833 bool has_info = GetKeyOrigin(keyid, info);
1834 std::string origin_str = has_info ? "[" + HexStr(info.fingerprint) + FormatHDKeypath(info.path) + "]" : "";
1835
1836 // Construct the combo descriptor
1837 std::string desc_str = "combo(" + origin_str + HexStr(key.GetPubKey()) + ")";
1839 std::string error;
1840 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, error, false);
1841 CHECK_NONFATAL(descs.size() == 1); // It shouldn't be possible to have an invalid or multipath descriptor
1842 WalletDescriptor w_desc(std::move(descs.at(0)), creation_time, 0, 0, 0);
1843
1844 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1845 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1846 WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, key, key.GetPubKey()));
1847 desc_spk_man->TopUpWithDB(batch);
1848 auto desc_spks = desc_spk_man->GetScriptPubKeys();
1849
1850 // Remove the scriptPubKeys from our current set
1851 for (const CScript& spk : desc_spks) {
1852 size_t erased = spks.erase(spk);
1853 assert(erased == 1);
1855 }
1856
1857 out.desc_spkms.push_back(std::move(desc_spk_man));
1858 }
1859
1860 // Handle HD keys by using the CHDChains
1861 std::vector<CHDChain> chains;
1862 chains.push_back(m_hd_chain);
1863 for (const auto& chain_pair : m_inactive_hd_chains) {
1864 chains.push_back(chain_pair.second);
1865 }
1866 for (const CHDChain& chain : chains) {
1867 for (int i = 0; i < 2; ++i) {
1868 // Skip if doing internal chain and split chain is not supported
1869 if (chain.seed_id.IsNull() || (i == 1 && !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))) {
1870 continue;
1871 }
1872 // Get the master xprv
1873 CKey seed_key;
1874 if (!GetKey(chain.seed_id, seed_key)) {
1875 assert(false);
1876 }
1877 CExtKey master_key;
1878 master_key.SetSeed(seed_key);
1879
1880 // Make the combo descriptor
1881 std::string xpub = EncodeExtPubKey(master_key.Neuter());
1882 std::string desc_str = "combo(" + xpub + "/0h/" + ToString(i) + "h/*h)";
1884 std::string error;
1885 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, error, false);
1886 CHECK_NONFATAL(descs.size() == 1); // It shouldn't be possible to have an invalid or multipath descriptor
1887 uint32_t chain_counter = std::max((i == 1 ? chain.nInternalChainCounter : chain.nExternalChainCounter), (uint32_t)0);
1888 WalletDescriptor w_desc(std::move(descs.at(0)), 0, 0, chain_counter, 0);
1889
1890 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1891 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1892 WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey()));
1893 desc_spk_man->TopUpWithDB(batch);
1894 auto desc_spks = desc_spk_man->GetScriptPubKeys();
1895
1896 // Remove the scriptPubKeys from our current set
1897 for (const CScript& spk : desc_spks) {
1898 size_t erased = spks.erase(spk);
1899 assert(erased == 1);
1901 }
1902
1903 out.desc_spkms.push_back(std::move(desc_spk_man));
1904 }
1905 }
1906 // Add the current master seed to the migration data
1907 if (!m_hd_chain.seed_id.IsNull()) {
1908 CKey seed_key;
1909 if (!GetKey(m_hd_chain.seed_id, seed_key)) {
1910 assert(false);
1911 }
1912 out.master_key.SetSeed(seed_key);
1913 }
1914
1915 // Handle the rest of the scriptPubKeys which must be imports and may not have all info
1916 for (auto it = spks.begin(); it != spks.end();) {
1917 const CScript& spk = *it;
1918
1919 // Get birthdate from script meta
1920 uint64_t creation_time = 0;
1921 const auto& mit = m_script_metadata.find(CScriptID(spk));
1922 if (mit != m_script_metadata.end()) {
1923 creation_time = mit->second.nCreateTime;
1924 }
1925
1926 // InferDescriptor as that will get us all the solving info if it is there
1927 std::unique_ptr<Descriptor> desc = InferDescriptor(spk, *GetSolvingProvider(spk));
1928 // Get the private keys for this descriptor
1929 std::vector<CScript> scripts;
1931 if (!desc->Expand(0, DUMMY_SIGNING_PROVIDER, scripts, keys)) {
1932 assert(false);
1933 }
1934 std::set<CKeyID> privkeyids;
1935 for (const auto& key_orig_pair : keys.origins) {
1936 privkeyids.insert(key_orig_pair.first);
1937 }
1938
1939 std::vector<CScript> desc_spks;
1940
1941 // Make the descriptor string with private keys
1942 std::string desc_str;
1943 bool watchonly = !desc->ToPrivateString(*this, desc_str);
1945 out.watch_descs.emplace_back(desc->ToString(), creation_time);
1946
1947 // Get the scriptPubKeys without writing this to the wallet
1948 FlatSigningProvider provider;
1949 desc->Expand(0, provider, desc_spks, provider);
1950 } else {
1951 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1952 WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
1953 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1954 for (const auto& keyid : privkeyids) {
1955 CKey key;
1956 if (!GetKey(keyid, key)) {
1957 continue;
1958 }
1959 WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, key, key.GetPubKey()));
1960 }
1961 desc_spk_man->TopUpWithDB(batch);
1962 auto desc_spks_set = desc_spk_man->GetScriptPubKeys();
1963 desc_spks.insert(desc_spks.end(), desc_spks_set.begin(), desc_spks_set.end());
1964
1965 out.desc_spkms.push_back(std::move(desc_spk_man));
1966 }
1967
1968 // Remove the scriptPubKeys from our current set
1969 for (const CScript& desc_spk : desc_spks) {
1970 auto del_it = spks.find(desc_spk);
1971 assert(del_it != spks.end());
1972 assert(IsMine(desc_spk) != ISMINE_NO);
1973 it = spks.erase(del_it);
1974 }
1975 }
1976
1977 // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
1978 // So we have to check if any of our scripts are a multisig and if so, add the P2SH
1979 for (const auto& script_pair : mapScripts) {
1980 const CScript script = script_pair.second;
1981
1982 // Get birthdate from script meta
1983 uint64_t creation_time = 0;
1984 const auto& it = m_script_metadata.find(CScriptID(script));
1985 if (it != m_script_metadata.end()) {
1986 creation_time = it->second.nCreateTime;
1987 }
1988
1989 std::vector<std::vector<unsigned char>> sols;
1990 TxoutType type = Solver(script, sols);
1991 if (type == TxoutType::MULTISIG) {
1994 CScript witprog = GetScriptForDestination(witdest);
1995 CScript sh_wsh_spk = GetScriptForDestination(ScriptHash(witprog));
1996
1997 // We only want the multisigs that we have not already seen, i.e. they are not watchonly and not spendable
1998 // For P2SH, a multisig is not ISMINE_NO when:
1999 // * All keys are in the wallet
2000 // * The multisig itself is watch only
2001 // * The P2SH is watch only
2002 // For P2SH-P2WSH, if the script is in the wallet, then it will have the same conditions as P2SH.
2003 // For P2WSH, a multisig is not ISMINE_NO when, other than the P2SH conditions:
2004 // * The P2WSH script is in the wallet and it is being watched
2005 std::vector<std::vector<unsigned char>> keys(sols.begin() + 1, sols.begin() + sols.size() - 1);
2006 if (HaveWatchOnly(sh_spk) || HaveWatchOnly(script) || HaveKeys(keys, *this) || (HaveCScript(CScriptID(witprog)) && HaveWatchOnly(witprog))) {
2007 // The above emulates IsMine for these 3 scriptPubKeys, so double check that by running IsMine
2008 assert(IsMine(sh_spk) != ISMINE_NO || IsMine(witprog) != ISMINE_NO || IsMine(sh_wsh_spk) != ISMINE_NO);
2009 continue;
2010 }
2011 assert(IsMine(sh_spk) == ISMINE_NO && IsMine(witprog) == ISMINE_NO && IsMine(sh_wsh_spk) == ISMINE_NO);
2012
2013 std::unique_ptr<Descriptor> sh_desc = InferDescriptor(sh_spk, *GetSolvingProvider(sh_spk));
2014 out.solvable_descs.emplace_back(sh_desc->ToString(), creation_time);
2015
2016 const auto desc = InferDescriptor(witprog, *this);
2017 if (desc->IsSolvable()) {
2018 std::unique_ptr<Descriptor> wsh_desc = InferDescriptor(witprog, *GetSolvingProvider(witprog));
2019 out.solvable_descs.emplace_back(wsh_desc->ToString(), creation_time);
2020 std::unique_ptr<Descriptor> sh_wsh_desc = InferDescriptor(sh_wsh_spk, *GetSolvingProvider(sh_wsh_spk));
2021 out.solvable_descs.emplace_back(sh_wsh_desc->ToString(), creation_time);
2022 }
2023 }
2024 }
2025
2026 // Make sure that we have accounted for all scriptPubKeys
2027 assert(spks.size() == 0);
2028
2029 // Finalize transaction
2030 if (!batch.TxnCommit()) {
2031 LogPrintf("Error generating descriptors for migration, cannot commit db transaction\n");
2032 return std::nullopt;
2033 }
2034
2035 return out;
2036}
2037
2039{
2040 return RunWithinTxn(m_storage.GetDatabase(), /*process_desc=*/"delete legacy records", [&](WalletBatch& batch){
2041 return DeleteRecordsWithDB(batch);
2042 });
2043}
2044
2046{
2048 return batch.EraseRecords(DBKeys::LEGACY_TYPES);
2049}
2050
2052{
2053 // Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
2054 if (!CanGetAddresses()) {
2055 return util::Error{_("No addresses available")};
2056 }
2057 {
2059 assert(m_wallet_descriptor.descriptor->IsSingleType()); // This is a combo descriptor which should not be an active descriptor
2060 std::optional<OutputType> desc_addr_type = m_wallet_descriptor.descriptor->GetOutputType();
2061 assert(desc_addr_type);
2062 if (type != *desc_addr_type) {
2063 throw std::runtime_error(std::string(__func__) + ": Types are inconsistent. Stored type does not match type of newly generated address");
2064 }
2065
2066 TopUp();
2067
2068 // Get the scriptPubKey from the descriptor
2069 FlatSigningProvider out_keys;
2070 std::vector<CScript> scripts_temp;
2071 if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
2072 // We can't generate anymore keys
2073 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
2074 }
2075 if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2076 // We can't generate anymore keys
2077 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
2078 }
2079
2080 CTxDestination dest;
2081 if (!ExtractDestination(scripts_temp[0], dest)) {
2082 return util::Error{_("Error: Cannot extract destination from the generated scriptpubkey")}; // shouldn't happen
2083 }
2084 m_wallet_descriptor.next_index++;
2085 WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
2086 return dest;
2087 }
2088}
2089
2091{
2093 if (m_map_script_pub_keys.count(script) > 0) {
2094 return ISMINE_SPENDABLE;
2095 }
2096 return ISMINE_NO;
2097}
2098
2100{
2102 if (!m_map_keys.empty()) {
2103 return false;
2104 }
2105
2106 bool keyPass = m_map_crypted_keys.empty(); // Always pass when there are no encrypted keys
2107 bool keyFail = false;
2108 for (const auto& mi : m_map_crypted_keys) {
2109 const CPubKey &pubkey = mi.second.first;
2110 const std::vector<unsigned char> &crypted_secret = mi.second.second;
2111 CKey key;
2112 if (!DecryptKey(master_key, crypted_secret, pubkey, key)) {
2113 keyFail = true;
2114 break;
2115 }
2116 keyPass = true;
2118 break;
2119 }
2120 if (keyPass && keyFail) {
2121 LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
2122 throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
2123 }
2124 if (keyFail || !keyPass) {
2125 return false;
2126 }
2128 return true;
2129}
2130
2132{
2134 if (!m_map_crypted_keys.empty()) {
2135 return false;
2136 }
2137
2138 for (const KeyMap::value_type& key_in : m_map_keys)
2139 {
2140 const CKey &key = key_in.second;
2141 CPubKey pubkey = key.GetPubKey();
2142 CKeyingMaterial secret{UCharCast(key.begin()), UCharCast(key.end())};
2143 std::vector<unsigned char> crypted_secret;
2144 if (!EncryptSecret(master_key, secret, pubkey.GetHash(), crypted_secret)) {
2145 return false;
2146 }
2147 m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
2148 batch->WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
2149 }
2150 m_map_keys.clear();
2151 return true;
2152}
2153
2155{
2157 auto op_dest = GetNewDestination(type);
2158 index = m_wallet_descriptor.next_index - 1;
2159 return op_dest;
2160}
2161
2162void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
2163{
2165 // Only return when the index was the most recent
2166 if (m_wallet_descriptor.next_index - 1 == index) {
2167 m_wallet_descriptor.next_index--;
2168 }
2169 WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
2171}
2172
2173std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const
2174{
2177 KeyMap keys;
2178 for (const auto& key_pair : m_map_crypted_keys) {
2179 const CPubKey& pubkey = key_pair.second.first;
2180 const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
2181 CKey key;
2182 m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2183 return DecryptKey(encryption_key, crypted_secret, pubkey, key);
2184 });
2185 keys[pubkey.GetID()] = key;
2186 }
2187 return keys;
2188 }
2189 return m_map_keys;
2190}
2191
2193{
2195 return m_map_keys.contains(keyid) || m_map_crypted_keys.contains(keyid);
2196}
2197
2198std::optional<CKey> DescriptorScriptPubKeyMan::GetKey(const CKeyID& keyid) const
2199{
2202 const auto& it = m_map_crypted_keys.find(keyid);
2203 if (it == m_map_crypted_keys.end()) {
2204 return std::nullopt;
2205 }
2206 const std::vector<unsigned char>& crypted_secret = it->second.second;
2207 CKey key;
2208 if (!Assume(m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2209 return DecryptKey(encryption_key, crypted_secret, it->second.first, key);
2210 }))) {
2211 return std::nullopt;
2212 }
2213 return key;
2214 }
2215 const auto& it = m_map_keys.find(keyid);
2216 if (it == m_map_keys.end()) {
2217 return std::nullopt;
2218 }
2219 return it->second;
2220}
2221
2223{
2225 if (!batch.TxnBegin()) return false;
2226 bool res = TopUpWithDB(batch, size);
2227 if (!batch.TxnCommit()) throw std::runtime_error(strprintf("Error during descriptors keypool top up. Cannot commit changes for wallet %s", m_storage.GetDisplayName()));
2228 return res;
2229}
2230
2232{
2234 std::set<CScript> new_spks;
2235 unsigned int target_size;
2236 if (size > 0) {
2237 target_size = size;
2238 } else {
2239 target_size = m_keypool_size;
2240 }
2241
2242 // Calculate the new range_end
2243 int32_t new_range_end = std::max(m_wallet_descriptor.next_index + (int32_t)target_size, m_wallet_descriptor.range_end);
2244
2245 // If the descriptor is not ranged, we actually just want to fill the first cache item
2246 if (!m_wallet_descriptor.descriptor->IsRange()) {
2247 new_range_end = 1;
2248 m_wallet_descriptor.range_end = 1;
2249 m_wallet_descriptor.range_start = 0;
2250 }
2251
2252 FlatSigningProvider provider;
2253 provider.keys = GetKeys();
2254
2255 uint256 id = GetID();
2256 for (int32_t i = m_max_cached_index + 1; i < new_range_end; ++i) {
2257 FlatSigningProvider out_keys;
2258 std::vector<CScript> scripts_temp;
2259 DescriptorCache temp_cache;
2260 // Maybe we have a cached xpub and we can expand from the cache first
2261 if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2262 if (!m_wallet_descriptor.descriptor->Expand(i, provider, scripts_temp, out_keys, &temp_cache)) return false;
2263 }
2264 // Add all of the scriptPubKeys to the scriptPubKey set
2265 new_spks.insert(scripts_temp.begin(), scripts_temp.end());
2266 for (const CScript& script : scripts_temp) {
2267 m_map_script_pub_keys[script] = i;
2268 }
2269 for (const auto& pk_pair : out_keys.pubkeys) {
2270 const CPubKey& pubkey = pk_pair.second;
2271 if (m_map_pubkeys.count(pubkey) != 0) {
2272 // We don't need to give an error here.
2273 // It doesn't matter which of many valid indexes the pubkey has, we just need an index where we can derive it and it's private key
2274 continue;
2275 }
2276 m_map_pubkeys[pubkey] = i;
2277 }
2278 // Merge and write the cache
2279 DescriptorCache new_items = m_wallet_descriptor.cache.MergeAndDiff(temp_cache);
2280 if (!batch.WriteDescriptorCacheItems(id, new_items)) {
2281 throw std::runtime_error(std::string(__func__) + ": writing cache items failed");
2282 }
2284 }
2285 m_wallet_descriptor.range_end = new_range_end;
2286 batch.WriteDescriptor(GetID(), m_wallet_descriptor);
2287
2288 // By this point, the cache size should be the size of the entire range
2289 assert(m_wallet_descriptor.range_end - 1 == m_max_cached_index);
2290
2291 m_storage.TopUpCallback(new_spks, this);
2293 return true;
2294}
2295
2297{
2299 std::vector<WalletDestination> result;
2300 if (IsMine(script)) {
2301 int32_t index = m_map_script_pub_keys[script];
2302 if (index >= m_wallet_descriptor.next_index) {
2303 WalletLogPrintf("%s: Detected a used keypool item at index %d, mark all keypool items up to this item as used\n", __func__, index);
2304 auto out_keys = std::make_unique<FlatSigningProvider>();
2305 std::vector<CScript> scripts_temp;
2306 while (index >= m_wallet_descriptor.next_index) {
2307 if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) {
2308 throw std::runtime_error(std::string(__func__) + ": Unable to expand descriptor from cache");
2309 }
2310 CTxDestination dest;
2311 ExtractDestination(scripts_temp[0], dest);
2312 result.push_back({dest, std::nullopt});
2313 m_wallet_descriptor.next_index++;
2314 }
2315 }
2316 if (!TopUp()) {
2317 WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
2318 }
2319 }
2320
2321 return result;
2322}
2323
2325{
2328 if (!AddDescriptorKeyWithDB(batch, key, pubkey)) {
2329 throw std::runtime_error(std::string(__func__) + ": writing descriptor private key failed");
2330 }
2331}
2332
2334{
2337
2338 // Check if provided key already exists
2339 if (m_map_keys.find(pubkey.GetID()) != m_map_keys.end() ||
2340 m_map_crypted_keys.find(pubkey.GetID()) != m_map_crypted_keys.end()) {
2341 return true;
2342 }
2343
2345 if (m_storage.IsLocked()) {
2346 return false;
2347 }
2348
2349 std::vector<unsigned char> crypted_secret;
2350 CKeyingMaterial secret{UCharCast(key.begin()), UCharCast(key.end())};
2351 if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2352 return EncryptSecret(encryption_key, secret, pubkey.GetHash(), crypted_secret);
2353 })) {
2354 return false;
2355 }
2356
2357 m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
2358 return batch.WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
2359 } else {
2360 m_map_keys[pubkey.GetID()] = key;
2361 return batch.WriteDescriptorKey(GetID(), pubkey, key.GetPrivKey());
2362 }
2363}
2364
2365bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal)
2366{
2369
2370 // Ignore when there is already a descriptor
2371 if (m_wallet_descriptor.descriptor) {
2372 return false;
2373 }
2374
2375 m_wallet_descriptor = GenerateWalletDescriptor(master_key.Neuter(), addr_type, internal);
2376
2377 // Store the master private key, and descriptor
2378 if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {
2379 throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");
2380 }
2381 if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
2382 throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
2383 }
2384
2385 // TopUp
2386 TopUpWithDB(batch);
2387
2389 return true;
2390}
2391
2393{
2395 return m_wallet_descriptor.descriptor->IsRange();
2396}
2397
2399{
2400 // We can only give out addresses from descriptors that are single type (not combo), ranged,
2401 // and either have cached keys or can generate more keys (ignoring encryption)
2403 return m_wallet_descriptor.descriptor->IsSingleType() &&
2404 m_wallet_descriptor.descriptor->IsRange() &&
2405 (HavePrivateKeys() || m_wallet_descriptor.next_index < m_wallet_descriptor.range_end);
2406}
2407
2409{
2411 return m_map_keys.size() > 0 || m_map_crypted_keys.size() > 0;
2412}
2413
2415{
2416 // This is only used for getwalletinfo output and isn't relevant to descriptor wallets.
2417 return std::nullopt;
2418}
2419
2420
2422{
2424 return m_wallet_descriptor.range_end - m_wallet_descriptor.next_index;
2425}
2426
2428{
2430 return m_wallet_descriptor.creation_time;
2431}
2432
2433std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CScript& script, bool include_private) const
2434{
2436
2437 // Find the index of the script
2438 auto it = m_map_script_pub_keys.find(script);
2439 if (it == m_map_script_pub_keys.end()) {
2440 return nullptr;
2441 }
2442 int32_t index = it->second;
2443
2444 return GetSigningProvider(index, include_private);
2445}
2446
2447std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CPubKey& pubkey) const
2448{
2450
2451 // Find index of the pubkey
2452 auto it = m_map_pubkeys.find(pubkey);
2453 if (it == m_map_pubkeys.end()) {
2454 return nullptr;
2455 }
2456 int32_t index = it->second;
2457
2458 // Always try to get the signing provider with private keys. This function should only be called during signing anyways
2459 return GetSigningProvider(index, true);
2460}
2461
2462std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
2463{
2465
2466 std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
2467
2468 // Fetch SigningProvider from cache to avoid re-deriving
2469 auto it = m_map_signing_providers.find(index);
2470 if (it != m_map_signing_providers.end()) {
2471 out_keys->Merge(FlatSigningProvider{it->second});
2472 } else {
2473 // Get the scripts, keys, and key origins for this script
2474 std::vector<CScript> scripts_temp;
2475 if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
2476
2477 // Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
2478 m_map_signing_providers[index] = *out_keys;
2479 }
2480
2481 if (HavePrivateKeys() && include_private) {
2482 FlatSigningProvider master_provider;
2483 master_provider.keys = GetKeys();
2484 m_wallet_descriptor.descriptor->ExpandPrivate(index, master_provider, *out_keys);
2485 }
2486
2487 return out_keys;
2488}
2489
2490std::unique_ptr<SigningProvider> DescriptorScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
2491{
2492 return GetSigningProvider(script, false);
2493}
2494
2496{
2497 return IsMine(script);
2498}
2499
2500bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
2501{
2502 std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
2503 for (const auto& coin_pair : coins) {
2504 std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(coin_pair.second.out.scriptPubKey, true);
2505 if (!coin_keys) {
2506 continue;
2507 }
2508 keys->Merge(std::move(*coin_keys));
2509 }
2510
2511 return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
2512}
2513
2514SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2515{
2516 std::unique_ptr<FlatSigningProvider> keys = GetSigningProvider(GetScriptForDestination(pkhash), true);
2517 if (!keys) {
2519 }
2520
2521 CKey key;
2522 if (!keys->GetKey(ToKeyID(pkhash), key)) {
2524 }
2525
2526 if (!MessageSign(key, message, str_sig)) {
2528 }
2529 return SigningResult::OK;
2530}
2531
2532std::optional<PSBTError> DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed, bool finalize) const
2533{
2534 if (n_signed) {
2535 *n_signed = 0;
2536 }
2537 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2538 const CTxIn& txin = psbtx.tx->vin[i];
2539 PSBTInput& input = psbtx.inputs.at(i);
2540
2541 if (PSBTInputSigned(input)) {
2542 continue;
2543 }
2544
2545 // Get the Sighash type
2546 if (sign && input.sighash_type != std::nullopt && *input.sighash_type != sighash_type) {
2547 return PSBTError::SIGHASH_MISMATCH;
2548 }
2549
2550 // Get the scriptPubKey to know which SigningProvider to use
2552 if (!input.witness_utxo.IsNull()) {
2554 } else if (input.non_witness_utxo) {
2555 if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
2556 return PSBTError::MISSING_INPUTS;
2557 }
2558 script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
2559 } else {
2560 // There's no UTXO so we can just skip this now
2561 continue;
2562 }
2563
2564 std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
2565 std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, /*include_private=*/sign);
2566 if (script_keys) {
2567 keys->Merge(std::move(*script_keys));
2568 } else {
2569 // Maybe there are pubkeys listed that we can sign for
2570 std::vector<CPubKey> pubkeys;
2571 pubkeys.reserve(input.hd_keypaths.size() + 2);
2572
2573 // ECDSA Pubkeys
2574 for (const auto& [pk, _] : input.hd_keypaths) {
2575 pubkeys.push_back(pk);
2576 }
2577
2578 // Taproot output pubkey
2579 std::vector<std::vector<unsigned char>> sols;
2581 sols[0].insert(sols[0].begin(), 0x02);
2582 pubkeys.emplace_back(sols[0]);
2583 sols[0][0] = 0x03;
2584 pubkeys.emplace_back(sols[0]);
2585 }
2586
2587 // Taproot pubkeys
2588 for (const auto& pk_pair : input.m_tap_bip32_paths) {
2589 const XOnlyPubKey& pubkey = pk_pair.first;
2590 for (unsigned char prefix : {0x02, 0x03}) {
2591 unsigned char b[33] = {prefix};
2592 std::copy(pubkey.begin(), pubkey.end(), b + 1);
2593 CPubKey fullpubkey;
2594 fullpubkey.Set(b, b + 33);
2595 pubkeys.push_back(fullpubkey);
2596 }
2597 }
2598
2599 for (const auto& pubkey : pubkeys) {
2600 std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
2601 if (pk_keys) {
2602 keys->Merge(std::move(*pk_keys));
2603 }
2604 }
2605 }
2606
2607 SignPSBTInput(HidingSigningProvider(keys.get(), /*hide_secret=*/!sign, /*hide_origin=*/!bip32derivs), psbtx, i, &txdata, sighash_type, nullptr, finalize);
2608
2609 bool signed_one = PSBTInputSigned(input);
2610 if (n_signed && (signed_one || !sign)) {
2611 // If sign is false, we assume that we _could_ sign if we get here. This
2612 // will never have false negatives; it is hard to tell under what i
2613 // circumstances it could have false positives.
2614 (*n_signed)++;
2615 }
2616 }
2617
2618 // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
2619 for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
2620 std::unique_ptr<SigningProvider> keys = GetSolvingProvider(psbtx.tx->vout.at(i).scriptPubKey);
2621 if (!keys) {
2622 continue;
2623 }
2624 UpdatePSBTOutput(HidingSigningProvider(keys.get(), /*hide_secret=*/true, /*hide_origin=*/!bip32derivs), psbtx, i);
2625 }
2626
2627 return {};
2628}
2629
2630std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
2631{
2632 std::unique_ptr<SigningProvider> provider = GetSigningProvider(GetScriptForDestination(dest));
2633 if (provider) {
2634 KeyOriginInfo orig;
2635 CKeyID key_id = GetKeyForDestination(*provider, dest);
2636 if (provider->GetKeyOrigin(key_id, orig)) {
2638 std::unique_ptr<CKeyMetadata> meta = std::make_unique<CKeyMetadata>();
2639 meta->key_origin = orig;
2640 meta->has_key_origin = true;
2641 meta->nCreateTime = m_wallet_descriptor.creation_time;
2642 return meta;
2643 }
2644 }
2645 return nullptr;
2646}
2647
2649{
2651 return m_wallet_descriptor.id;
2652}
2653
2655{
2657 std::set<CScript> new_spks;
2658 m_wallet_descriptor.cache = cache;
2659 for (int32_t i = m_wallet_descriptor.range_start; i < m_wallet_descriptor.range_end; ++i) {
2660 FlatSigningProvider out_keys;
2661 std::vector<CScript> scripts_temp;
2662 if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2663 throw std::runtime_error("Error: Unable to expand wallet descriptor from cache");
2664 }
2665 // Add all of the scriptPubKeys to the scriptPubKey set
2666 new_spks.insert(scripts_temp.begin(), scripts_temp.end());
2667 for (const CScript& script : scripts_temp) {
2668 if (m_map_script_pub_keys.count(script) != 0) {
2669 throw std::runtime_error(strprintf("Error: Already loaded script at index %d as being at index %d", i, m_map_script_pub_keys[script]));
2670 }
2671 m_map_script_pub_keys[script] = i;
2672 }
2673 for (const auto& pk_pair : out_keys.pubkeys) {
2674 const CPubKey& pubkey = pk_pair.second;
2675 if (m_map_pubkeys.count(pubkey) != 0) {
2676 // We don't need to give an error here.
2677 // It doesn't matter which of many valid indexes the pubkey has, we just need an index where we can derive it and it's private key
2678 continue;
2679 }
2680 m_map_pubkeys[pubkey] = i;
2681 }
2683 }
2684 // Make sure the wallet knows about our new spks
2685 m_storage.TopUpCallback(new_spks, this);
2686}
2687
2688bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key)
2689{
2691 m_map_keys[key_id] = key;
2692 return true;
2693}
2694
2695bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key)
2696{
2698 if (!m_map_keys.empty()) {
2699 return false;
2700 }
2701
2702 m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key);
2703 return true;
2704}
2705
2707{
2709 return !m_wallet_descriptor.id.IsNull() && !desc.id.IsNull() && m_wallet_descriptor.id == desc.id;
2710}
2711
2713{
2716 if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
2717 throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
2718 }
2719}
2720
2722{
2723 return m_wallet_descriptor;
2724}
2725
2726std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
2727{
2728 return GetScriptPubKeys(0);
2729}
2730
2731std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys(int32_t minimum_index) const
2732{
2734 std::unordered_set<CScript, SaltedSipHasher> script_pub_keys;
2735 script_pub_keys.reserve(m_map_script_pub_keys.size());
2736
2737 for (auto const& [script_pub_key, index] : m_map_script_pub_keys) {
2738 if (index >= minimum_index) script_pub_keys.insert(script_pub_key);
2739 }
2740 return script_pub_keys;
2741}
2742
2744{
2745 return m_max_cached_index + 1;
2746}
2747
2748bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, const bool priv) const
2749{
2751
2752 FlatSigningProvider provider;
2753 provider.keys = GetKeys();
2754
2755 if (priv) {
2756 // For the private version, always return the master key to avoid
2757 // exposing child private keys. The risk implications of exposing child
2758 // private keys together with the parent xpub may be non-obvious for users.
2759 return m_wallet_descriptor.descriptor->ToPrivateString(provider, out);
2760 }
2761
2762 return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, &m_wallet_descriptor.cache);
2763}
2764
2766{
2769 return;
2770 }
2771
2772 // Skip if we have the last hardened xpub cache
2773 if (m_wallet_descriptor.cache.GetCachedLastHardenedExtPubKeys().size() > 0) {
2774 return;
2775 }
2776
2777 // Expand the descriptor
2778 FlatSigningProvider provider;
2779 provider.keys = GetKeys();
2780 FlatSigningProvider out_keys;
2781 std::vector<CScript> scripts_temp;
2782 DescriptorCache temp_cache;
2783 if (!m_wallet_descriptor.descriptor->Expand(0, provider, scripts_temp, out_keys, &temp_cache)){
2784 throw std::runtime_error("Unable to expand descriptor");
2785 }
2786
2787 // Cache the last hardened xpubs
2788 DescriptorCache diff = m_wallet_descriptor.cache.MergeAndDiff(temp_cache);
2790 throw std::runtime_error(std::string(__func__) + ": writing cache items failed");
2791 }
2792}
2793
2795{
2797 std::string error;
2798 if (!CanUpdateToWalletDescriptor(descriptor, error)) {
2799 throw std::runtime_error(std::string(__func__) + ": " + error);
2800 }
2801
2802 m_map_pubkeys.clear();
2803 m_map_script_pub_keys.clear();
2804 m_max_cached_index = -1;
2805 m_wallet_descriptor = descriptor;
2806
2807 NotifyFirstKeyTimeChanged(this, m_wallet_descriptor.creation_time);
2808}
2809
2811{
2813 if (!HasWalletDescriptor(descriptor)) {
2814 error = "can only update matching descriptor";
2815 return false;
2816 }
2817
2818 if (descriptor.range_start > m_wallet_descriptor.range_start ||
2819 descriptor.range_end < m_wallet_descriptor.range_end) {
2820 // Use inclusive range for error
2821 error = strprintf("new range must include current range = [%d,%d]",
2822 m_wallet_descriptor.range_start,
2823 m_wallet_descriptor.range_end - 1);
2824 return false;
2825 }
2826
2827 return true;
2828}
2829} // namespace wallet
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
CKeyID ToKeyID(const PKHash &key_hash)
Definition: addresstype.cpp:29
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:140
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
std::string FormatHDKeypath(const std::vector< uint32_t > &path, bool apostrophe)
Definition: bip32.cpp:54
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath, bool apostrophe)
Write HD keypaths as strings.
Definition: bip32.cpp:64
int ret
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:81
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
An encapsulated private key.
Definition: key.h:35
const std::byte * begin() const
Definition: key.h:119
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized OpenSSL private key data).
Definition: key.cpp:169
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:161
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
const std::byte * end() const
Definition: key.h:120
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:236
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
uint32_t n
Definition: transaction.h:32
An encapsulated public key.
Definition: pubkey.h:34
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:204
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool IsValid() const
Definition: pubkey.h:189
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:170
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:89
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:415
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:602
An input of a transaction.
Definition: transaction.h:67
COutPoint prevout
Definition: transaction.h:69
CScript scriptPubKey
Definition: transaction.h:153
bool IsNull() const
Definition: transaction.h:170
Cache for single descriptor's derived extended pubkeys.
Definition: descriptor.h:19
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override
virtual bool AddCScript(const CScript &redeemScript)
void ImplicitlyLearnRelatedKeyScripts(const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
virtual std::set< CKeyID > GetKeys() const
std::map< CKeyID, CKey > KeyMap
virtual bool HaveCScript(const CScriptID &hash) const override
RecursiveMutex cs_KeyStore
virtual bool HaveKey(const CKeyID &address) const override
An interface to be implemented by keystores that support signing.
const unsigned char * end() const
Definition: pubkey.h:296
const unsigned char * begin() const
Definition: pubkey.h:295
constexpr bool IsNull() const
Definition: uint256.h:48
constexpr unsigned char * begin()
Definition: uint256.h:104
size_type size() const
Definition: prevector.h:294
160-bit opaque blob.
Definition: uint256.h:178
256-bit opaque blob.
Definition: uint256.h:190
static const uint256 ONE
Definition: uint256.h:199
uint32_t nInternalChainCounter
Definition: walletdb.h:101
static const int VERSION_HD_BASE
Definition: walletdb.h:106
uint32_t nExternalChainCounter
Definition: walletdb.h:100
int64_t m_next_external_index
Definition: walletdb.h:103
static const int VERSION_HD_CHAIN_SPLIT
Definition: walletdb.h:107
CKeyID seed_id
seed hash160
Definition: walletdb.h:102
int64_t m_next_internal_index
Definition: walletdb.h:104
static const int VERSION_WITH_KEY_ORIGIN
Definition: walletdb.h:140
std::string hdKeypath
Definition: walletdb.h:144
bool has_key_origin
Whether the key_origin is useful.
Definition: walletdb.h:147
KeyOriginInfo key_origin
Definition: walletdb.h:146
A key from a CWallet's keypool.
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
CPubKey vchPubKey
The public key.
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbt, const PrecomputedTransactionData &txdata, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=false, int *n_signed=nullptr, bool finalize=true) const override
Adds script and derivation path information to a PSBT, and optionally signs it.
void SetCache(const DescriptorCache &cache)
std::map< int32_t, FlatSigningProvider > m_map_signing_providers
bool CanProvide(const CScript &script, SignatureData &sigdata) override
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that,...
bool SignTransaction(CMutableTransaction &tx, const std::map< COutPoint, Coin > &coins, int sighash, std::map< int, bilingual_str > &input_errors) const override
Creates new signatures and adds them to the transaction.
std::unordered_set< CScript, SaltedSipHasher > GetScriptPubKeys() const override
Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches.
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
std::optional< CKey > GetKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet,...
bool AddCryptedKey(const CKeyID &key_id, const CPubKey &pubkey, const std::vector< unsigned char > &crypted_key)
bool SetupDescriptorGeneration(WalletBatch &batch, const CExtKey &master_key, OutputType addr_type, bool internal)
Setup descriptors based on the given CExtkey.
bool TopUp(unsigned int size=0) override
Fills internal address pool.
bool m_decryption_thoroughly_checked
keeps track of whether Unlock has run a thorough check before
std::map< CKeyID, CKey > KeyMap
unsigned int GetKeyPoolSize() const override
int64_t GetTimeFirstKey() const override
std::unique_ptr< FlatSigningProvider > GetSigningProvider(const CScript &script, bool include_private=false) const
bool CheckDecryptionKey(const CKeyingMaterial &master_key) override
Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the ke...
bool CanGetAddresses(bool internal=false) const override
bool CanUpdateToWalletDescriptor(const WalletDescriptor &descriptor, std::string &error)
bool GetDescriptorString(std::string &out, const bool priv) const
std::unique_ptr< CKeyMetadata > GetMetadata(const CTxDestination &dest) const override
util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool) override
void AddDescriptorKey(const CKey &key, const CPubKey &pubkey)
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
bool AddKey(const CKeyID &key_id, const CKey &key)
bool TopUpWithDB(WalletBatch &batch, unsigned int size=0)
Same as 'TopUp' but designed for use within a batch transaction context.
void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr) override
std::vector< WalletDestination > MarkUnusedAddresses(const CScript &script) override
Mark unused addresses as being used Affects all keys up to and including the one determined by provid...
bool AddDescriptorKeyWithDB(WalletBatch &batch, const CKey &key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
bool HasWalletDescriptor(const WalletDescriptor &desc) const
void UpdateWalletDescriptor(WalletDescriptor &descriptor)
std::optional< int64_t > GetOldestKeyPoolTime() const override
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const override
Sign a message with the given script.
util::Result< CTxDestination > GetNewDestination(const OutputType type) override
isminetype IsMine(const CScript &script) const override
bool HasPrivKey(const CKeyID &keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
bool Encrypt(const CKeyingMaterial &master_key, WalletBatch *batch) override
bool DeleteRecordsWithDB(WalletBatch &batch)
isminetype IsMine(const CScript &script) const override
std::optional< MigrationData > MigrateToDescriptor()
Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this Legac...
virtual bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey)
bool DeleteRecords()
Delete all the records of this LegacyScriptPubKeyMan from disk.
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
Load a keypool entry.
virtual void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
Load metadata (used by LoadWallet)
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)
void AddInactiveHDChain(const CHDChain &chain)
bool HaveWatchOnly(const CScript &dest) const
Returns whether the watch-only script is in the wallet.
bool HaveWatchOnly() const
Returns whether there are any watch-only things in the wallet.
bool fDecryptionThoroughlyChecked
keeps track of whether Unlock has run a thorough check before
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
std::map< CKeyID, int64_t > m_pool_key_to_index
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
std::unordered_set< CScript, SaltedSipHasher > GetScriptPubKeys() const override
Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches.
std::unordered_set< CScript, SaltedSipHasher > GetNotMineScriptPubKeys() const
Retrieves scripts that were imported by bugs into the legacy spkm and are simply invalid,...
bool LoadKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, without saving it to disk (used by LoadWallet)
bool AddWatchOnlyInMem(const CScript &dest)
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
Fetches a pubkey from mapWatchKeys if it exists there.
bool CheckDecryptionKey(const CKeyingMaterial &master_key) override
Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the ke...
bool GetKey(const CKeyID &address, CKey &keyOut) const override
bool LoadCScript(const CScript &redeemScript)
Adds a CScript to the store.
virtual void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata)
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const override
std::unordered_map< CKeyID, CHDChain, SaltedSipHasher > m_inactive_hd_chains
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool HaveKey(const CKeyID &address) const override
void LoadHDChain(const CHDChain &chain)
Load a HD chain model (used by LoadWallet)
std::vector< CKeyPool > MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
Marks all keys in the keypool up to and including the provided key as used.
void LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &metadata) override
bool CanGetAddresses(bool internal=false) const override
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
Adds a key to the store, and saves it to disk.
util::Result< CTxDestination > GetNewDestination(const OutputType type) override
bool GetKeyFromPool(CPubKey &key, const OutputType type)
Fetches a key from the keypool.
util::Result< CTxDestination > GetReservedDestination(const OutputType type, bool internal, int64_t &index, CKeyPool &keypool) override
bool Encrypt(const CKeyingMaterial &master_key, WalletBatch *batch) override
void AddHDChain(const CHDChain &chain)
bool AddCScriptWithDB(WalletBatch &batch, const CScript &script)
Adds a script to the store and saves it to disk.
bool AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey, const KeyOriginInfo &info)
Add a KeyOriginInfo to the wallet.
void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
SigningResult SignMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig) const override
Sign a message with the given script.
uint256 GetID() const override
bool SignTransaction(CMutableTransaction &tx, const std::map< COutPoint, Coin > &coins, int sighash, std::map< int, bilingual_str > &input_errors) const override
Creates new signatures and adds them to the transaction.
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
Adds an encrypted key to the store, and saves it to disk.
bool ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, bool fRequestedInternal)
Reserves a key from the keypool and sets nIndex to its index.
void AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal, WalletBatch &batch)
std::map< int64_t, CKeyID > m_index_to_reserved_key
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
void UpgradeKeyMetadata()
Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo.
bool AddWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
Private version of AddWatchOnly method which does not accept a timestamp, and which will reset the wa...
bool HavePrivateKeys() const override
std::vector< WalletDestination > MarkUnusedAddresses(const CScript &script) override
Mark unused addresses as being used Affects all keys up to and including the one determined by provid...
void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata) override
Load metadata (used by LoadWallet)
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
Update wallet first key creation time.
bool TopUp(unsigned int size=0) override
Fills internal address pool.
unsigned int GetKeyPoolSize() const override
bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey) override
bool ImportPubKeys(const std::vector< std::pair< CKeyID, bool > > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > &key_origins, const bool add_keypool, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
bool TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
Like TopUp() but adds keys for inactive HD chains.
bool CanProvide(const CScript &script, SignatureData &sigdata) override
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that,...
std::set< CKeyID > GetKeys() const override
bool IsHDEnabled() const override
bool TopUpChain(WalletBatch &batch, CHDChain &chain, unsigned int size)
bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
Adds a key to the store, and saves it to disk.
bool AddCScript(const CScript &redeemScript) override
int64_t GetTimeFirstKey() const override
std::optional< common::PSBTError > FillPSBT(PartiallySignedTransaction &psbt, const PrecomputedTransactionData &txdata, int sighash_type=SIGHASH_DEFAULT, bool sign=true, bool bip32derivs=false, int *n_signed=nullptr, bool finalize=true) const override
Adds script and derivation path information to a PSBT, and optionally signs it.
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
bool SetupGeneration(bool force=false) override
Sets up the key generation stuff, i.e.
void LearnRelatedScripts(const CPubKey &key, OutputType)
Explicitly make the wallet learn the related scripts for outputs to the given key.
void LearnAllRelatedScripts(const CPubKey &key)
Same as LearnRelatedScripts, but when the OutputType is not known (and could be anything).
CPubKey DeriveNewSeed(const CKey &key)
void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata, CKey &secret, CHDChain &hd_chain, bool internal=false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
void ReturnDestination(int64_t index, bool internal, const CTxDestination &) override
CPubKey GenerateNewKey(WalletBatch &batch, CHDChain &hd_chain, bool internal=false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
Generate a new key.
void SetHDSeed(const CPubKey &key)
bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
std::unique_ptr< CKeyMetadata > GetMetadata(const CTxDestination &dest) const override
bool Upgrade(int prev_version, int new_version, bilingual_str &error) override
Upgrades the wallet to the specified version.
void KeepDestination(int64_t index, const OutputType &type) override
void RewriteDB() override
The action to do when the DB needs rewrite.
std::optional< int64_t > GetOldestKeyPoolTime() const override
bool RemoveWatchOnly(const CScript &dest)
Remove a watch only script from the keystore.
bool ImportScriptPubKeys(const std::set< CScript > &script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
boost::signals2::signal< void(const ScriptPubKeyMan *spkm, int64_t new_birth_time)> NotifyFirstKeyTimeChanged
Birth time changed.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
void WalletLogPrintf(util::ConstevalFormatString< sizeof...(Params)> wallet_fmt, const Params &... params) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
WalletStorage & m_storage
Access to the wallet database.
Definition: walletdb.h:196
bool WriteDescriptor(const uint256 &desc_id, const WalletDescriptor &descriptor)
Definition: walletdb.cpp:258
bool WriteDescriptorCacheItems(const uint256 &desc_id, const DescriptorCache &cache)
Definition: walletdb.cpp:284
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external chain child index counter)
Definition: walletdb.cpp:1326
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition: walletdb.cpp:162
bool TxnBegin()
Begin a new transaction.
Definition: walletdb.cpp:1343
bool TxnCommit()
Commit current transaction.
Definition: walletdb.cpp:1348
bool EraseRecords(const std::unordered_set< std::string > &types)
Delete records of the given types.
Definition: walletdb.cpp:1336
bool WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, const bool overwrite)
Definition: walletdb.cpp:106
bool WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:111
bool ReadPool(int64_t nPool, CKeyPool &keypool)
Definition: walletdb.cpp:206
bool WriteCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:126
bool WriteCryptedDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const std::vector< unsigned char > &secret)
Definition: walletdb.cpp:249
bool WritePool(int64_t nPool, const CKeyPool &keypool)
Definition: walletdb.cpp:211
bool WriteDescriptorKey(const uint256 &desc_id, const CPubKey &pubkey, const CPrivKey &privkey)
Definition: walletdb.cpp:238
bool WriteCScript(const uint160 &hash, const CScript &redeemScript)
Definition: walletdb.cpp:157
bool ErasePool(int64_t nPool)
Definition: walletdb.cpp:216
bool EraseWatchOnly(const CScript &script)
Definition: walletdb.cpp:170
Descriptor with some wallet metadata.
Definition: walletutil.h:85
virtual bool IsWalletFlagSet(uint64_t) const =0
virtual void TopUpCallback(const std::set< CScript > &, ScriptPubKeyMan *)=0
Callback function for after TopUp completes containing any scripts that were added by a SPKMan.
virtual void SetMinVersion(enum WalletFeature, WalletBatch *=nullptr)=0
virtual bool CanSupportFeature(enum WalletFeature) const =0
virtual std::string GetDisplayName() const =0
virtual WalletDatabase & GetDatabase() const =0
virtual void UnsetBlankWalletFlag(WalletBatch &)=0
virtual bool IsLocked() const =0
virtual bool HasEncryptionKeys() const =0
virtual bool WithEncryptionKey(std::function< bool(const CKeyingMaterial &)> cb) const =0
Pass the encryption key to cb().
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:327
bool MessageSign(const CKey &privkey, const std::string &message, std::string &signature)
Sign a message.
Definition: signmessage.cpp:57
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition: hash.h:92
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition: hash.h:222
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:29
@ WITNESS_V0
Witness v0 (P2WPKH and P2WSH); see BIP 141.
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:352
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
#define LogPrintf(...)
Definition: logging.h:266
static int sign(const secp256k1_context *ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64)
Definition: musig.c:105
PSBTError
Definition: types.h:17
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:233
const std::unordered_set< std::string > LEGACY_TYPES
Definition: walletdb.cpp:67
static int64_t GetOldestKeyTimeInPool(const std::set< int64_t > &setKeyPool, WalletBatch &batch)
std::vector< unsigned char > valtype
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
Definition: walletdb.cpp:1247
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:62
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
static const std::unordered_set< OutputType > LEGACY_OUTPUT_TYPES
OutputTypes supported by the LegacyScriptPubKeyMan.
const uint32_t BIP32_HARDENED_KEY_LIMIT
Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value....
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
static void DeriveExtKey(CExtKey &key_in, unsigned int index, CExtKey &key_out)
Try to derive an extended key, throw if it fails.
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:41
@ ISMINE_NO
Definition: types.h:42
@ ISMINE_SPENDABLE
Definition: types.h:44
@ ISMINE_WATCH_ONLY
Definition: types.h:43
bool DecryptKey(const CKeyingMaterial &master_key, const std::span< const unsigned char > crypted_secret, const CPubKey &pub_key, CKey &key)
Definition: crypter.cpp:132
static bool ExtractPubKey(const CScript &dest, CPubKey &pubKeyOut)
@ FEATURE_COMPRPUBKEY
Definition: walletutil.h:20
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_HD
Definition: walletutil.h:22
@ FEATURE_PRE_SPLIT_KEYPOOL
Definition: walletutil.h:28
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< unsigned char > &vchCiphertext)
Definition: crypter.cpp:111
bool IsFeatureSupported(int wallet_version, int feature_version)
Definition: walletutil.cpp:35
@ WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
Definition: walletutil.h:48
@ WALLET_FLAG_KEY_ORIGIN_METADATA
Definition: walletutil.h:45
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:71
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
Definition: walletutil.cpp:49
is a home for public enum and struct type definitions that are used by internally by node code,...
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
Definition: outputtype.cpp:50
OutputType
Definition: outputtype.h:17
void UpdatePSBTOutput(const SigningProvider &provider, PartiallySignedTransaction &psbt, int index)
Updates a PSBTOutput with information from provider.
Definition: psbt.cpp:338
bool SignPSBTInput(const SigningProvider &provider, PartiallySignedTransaction &psbt, int index, const PrecomputedTransactionData *txdata, int sighash, SignatureData *out_sigdata, bool finalize)
Signs a PSBTInput, verifying that all provided data matches what is being signed.
Definition: psbt.cpp:375
bool PSBTInputSigned(const PSBTInput &input)
Checks whether a PSBTInput is already signed by checking for non-null finalized fields.
Definition: psbt.cpp:293
void SignTransaction(CMutableTransaction &mtx, const SigningProvider *keystore, const std::map< COutPoint, Coin > &coins, const UniValue &hashType, UniValue &result)
Sign a transaction with the given keystore and previous transactions.
const char * prefix
Definition: rest.cpp:1009
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:28
@ OP_0
Definition: script.h:76
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:502
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
Definition: sign.cpp:744
const SigningProvider & DUMMY_SIGNING_PROVIDER
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
SigningResult
Definition: signmessage.h:43
@ PRIVATE_KEY_NOT_AVAILABLE
@ OK
No error.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: solver.cpp:141
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:213
TxoutType
Definition: solver.h:22
@ WITNESS_V1_TAPROOT
@ WITNESS_UNKNOWN
Only for Witness versions not already defined above.
@ ANCHOR
anyone can spend script
@ WITNESS_V0_SCRIPTHASH
@ NULL_DATA
unspendable OP_RETURN script that carries data
@ WITNESS_V0_KEYHASH
unsigned char * UCharCast(char *c)
Definition: span.h:281
Definition: key.h:227
CExtPubKey Neuter() const
Definition: key.cpp:380
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:359
CKey key
Definition: key.h:232
void SetSeed(Span< const std::byte > seed)
Definition: key.cpp:368
A mutable version of CTransaction.
Definition: transaction.h:378
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
std::vector< uint32_t > path
Definition: keyorigin.h:14
A structure for PSBTs which contain per-input information.
Definition: psbt.h:198
std::map< CPubKey, KeyOriginInfo > hd_keypaths
Definition: psbt.h:205
CTransactionRef non_witness_utxo
Definition: psbt.h:199
std::optional< int > sighash_type
Definition: psbt.h:222
std::map< XOnlyPubKey, std::pair< std::set< uint256 >, KeyOriginInfo > > m_tap_bip32_paths
Definition: psbt.h:216
CTxOut witness_utxo
Definition: psbt.h:200
A version of CTransaction with the PSBT format.
Definition: psbt.h:951
std::vector< PSBTInput > inputs
Definition: psbt.h:956
std::optional< CMutableTransaction > tx
Definition: psbt.h:952
std::map< CKeyID, SigPair > signatures
BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a ...
Definition: sign.h:77
Bilingual messages:
Definition: translation.h:21
struct containing information needed for migrating legacy wallets to descriptor wallets
#define LOCK(cs)
Definition: sync.h:257
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:47
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1165
bilingual_str _(ConstevalStringLiteral str)
Translation function.
Definition: translation.h:80
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())