Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
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
479 if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
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
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
742 assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
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
804
806{
808 m_script_metadata[script_id] = meta;
809}
810
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{
1085 assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
1086 assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
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{
1212 assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
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{
1266 if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
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;
1455 fReturningInternal &= (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) || m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
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<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, 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 CKeyID& id : 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
1778 MigrationData out;
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 (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
1810 // keyids is now all non-HD keys. Each key will have its own combo descriptor
1811 for (const CKeyID& keyid : keyids) {
1812 CKey key;
1813 if (!GetKey(keyid, key)) {
1814 assert(false);
1815 }
1816
1817 // Get birthdate from key meta
1818 uint64_t creation_time = 0;
1819 const auto& it = mapKeyMetadata.find(keyid);
1820 if (it != mapKeyMetadata.end()) {
1821 creation_time = it->second.nCreateTime;
1822 }
1823
1824 // Get the key origin
1825 // Maybe this doesn't matter because floating keys here shouldn't have origins
1826 KeyOriginInfo info;
1827 bool has_info = GetKeyOrigin(keyid, info);
1828 std::string origin_str = has_info ? "[" + HexStr(info.fingerprint) + FormatHDKeypath(info.path) + "]" : "";
1829
1830 // Construct the combo descriptor
1831 std::string desc_str = "combo(" + origin_str + HexStr(key.GetPubKey()) + ")";
1833 std::string error;
1834 std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
1835 WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
1836
1837 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1838 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1839 desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
1840 desc_spk_man->TopUp();
1841 auto desc_spks = desc_spk_man->GetScriptPubKeys();
1842
1843 // Remove the scriptPubKeys from our current set
1844 for (const CScript& spk : desc_spks) {
1845 size_t erased = spks.erase(spk);
1846 assert(erased == 1);
1847 assert(IsMine(spk) == ISMINE_SPENDABLE);
1848 }
1849
1850 out.desc_spkms.push_back(std::move(desc_spk_man));
1851 }
1852
1853 // Handle HD keys by using the CHDChains
1854 std::vector<CHDChain> chains;
1855 chains.push_back(m_hd_chain);
1856 for (const auto& chain_pair : m_inactive_hd_chains) {
1857 chains.push_back(chain_pair.second);
1858 }
1859 for (const CHDChain& chain : chains) {
1860 for (int i = 0; i < 2; ++i) {
1861 // Skip if doing internal chain and split chain is not supported
1862 if (chain.seed_id.IsNull() || (i == 1 && !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))) {
1863 continue;
1864 }
1865 // Get the master xprv
1866 CKey seed_key;
1867 if (!GetKey(chain.seed_id, seed_key)) {
1868 assert(false);
1869 }
1870 CExtKey master_key;
1871 master_key.SetSeed(seed_key);
1872
1873 // Make the combo descriptor
1874 std::string xpub = EncodeExtPubKey(master_key.Neuter());
1875 std::string desc_str = "combo(" + xpub + "/0h/" + ToString(i) + "h/*h)";
1877 std::string error;
1878 std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
1879 uint32_t chain_counter = std::max((i == 1 ? chain.nInternalChainCounter : chain.nExternalChainCounter), (uint32_t)0);
1880 WalletDescriptor w_desc(std::move(desc), 0, 0, chain_counter, 0);
1881
1882 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1883 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1884 desc_spk_man->AddDescriptorKey(master_key.key, master_key.key.GetPubKey());
1885 desc_spk_man->TopUp();
1886 auto desc_spks = desc_spk_man->GetScriptPubKeys();
1887
1888 // Remove the scriptPubKeys from our current set
1889 for (const CScript& spk : desc_spks) {
1890 size_t erased = spks.erase(spk);
1891 assert(erased == 1);
1892 assert(IsMine(spk) == ISMINE_SPENDABLE);
1893 }
1894
1895 out.desc_spkms.push_back(std::move(desc_spk_man));
1896 }
1897 }
1898 // Add the current master seed to the migration data
1899 if (!m_hd_chain.seed_id.IsNull()) {
1900 CKey seed_key;
1901 if (!GetKey(m_hd_chain.seed_id, seed_key)) {
1902 assert(false);
1903 }
1904 out.master_key.SetSeed(seed_key);
1905 }
1906
1907 // Handle the rest of the scriptPubKeys which must be imports and may not have all info
1908 for (auto it = spks.begin(); it != spks.end();) {
1909 const CScript& spk = *it;
1910
1911 // Get birthdate from script meta
1912 uint64_t creation_time = 0;
1913 const auto& mit = m_script_metadata.find(CScriptID(spk));
1914 if (mit != m_script_metadata.end()) {
1915 creation_time = mit->second.nCreateTime;
1916 }
1917
1918 // InferDescriptor as that will get us all the solving info if it is there
1919 std::unique_ptr<Descriptor> desc = InferDescriptor(spk, *GetSolvingProvider(spk));
1920 // Get the private keys for this descriptor
1921 std::vector<CScript> scripts;
1923 if (!desc->Expand(0, DUMMY_SIGNING_PROVIDER, scripts, keys)) {
1924 assert(false);
1925 }
1926 std::set<CKeyID> privkeyids;
1927 for (const auto& key_orig_pair : keys.origins) {
1928 privkeyids.insert(key_orig_pair.first);
1929 }
1930
1931 std::vector<CScript> desc_spks;
1932
1933 // Make the descriptor string with private keys
1934 std::string desc_str;
1935 bool watchonly = !desc->ToPrivateString(*this, desc_str);
1936 if (watchonly && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1937 out.watch_descs.emplace_back(desc->ToString(), creation_time);
1938
1939 // Get the scriptPubKeys without writing this to the wallet
1940 FlatSigningProvider provider;
1941 desc->Expand(0, provider, desc_spks, provider);
1942 } else {
1943 // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
1944 WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
1945 auto desc_spk_man = std::make_unique<DescriptorScriptPubKeyMan>(m_storage, w_desc, /*keypool_size=*/0);
1946 for (const auto& keyid : privkeyids) {
1947 CKey key;
1948 if (!GetKey(keyid, key)) {
1949 continue;
1950 }
1951 desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
1952 }
1953 desc_spk_man->TopUp();
1954 auto desc_spks_set = desc_spk_man->GetScriptPubKeys();
1955 desc_spks.insert(desc_spks.end(), desc_spks_set.begin(), desc_spks_set.end());
1956
1957 out.desc_spkms.push_back(std::move(desc_spk_man));
1958 }
1959
1960 // Remove the scriptPubKeys from our current set
1961 for (const CScript& desc_spk : desc_spks) {
1962 auto del_it = spks.find(desc_spk);
1963 assert(del_it != spks.end());
1964 assert(IsMine(desc_spk) != ISMINE_NO);
1965 it = spks.erase(del_it);
1966 }
1967 }
1968
1969 // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
1970 // So we have to check if any of our scripts are a multisig and if so, add the P2SH
1971 for (const auto& script_pair : mapScripts) {
1972 const CScript script = script_pair.second;
1973
1974 // Get birthdate from script meta
1975 uint64_t creation_time = 0;
1976 const auto& it = m_script_metadata.find(CScriptID(script));
1977 if (it != m_script_metadata.end()) {
1978 creation_time = it->second.nCreateTime;
1979 }
1980
1981 std::vector<std::vector<unsigned char>> sols;
1982 TxoutType type = Solver(script, sols);
1983 if (type == TxoutType::MULTISIG) {
1986 CScript witprog = GetScriptForDestination(witdest);
1987 CScript sh_wsh_spk = GetScriptForDestination(ScriptHash(witprog));
1988
1989 // We only want the multisigs that we have not already seen, i.e. they are not watchonly and not spendable
1990 // For P2SH, a multisig is not ISMINE_NO when:
1991 // * All keys are in the wallet
1992 // * The multisig itself is watch only
1993 // * The P2SH is watch only
1994 // For P2SH-P2WSH, if the script is in the wallet, then it will have the same conditions as P2SH.
1995 // For P2WSH, a multisig is not ISMINE_NO when, other than the P2SH conditions:
1996 // * The P2WSH script is in the wallet and it is being watched
1997 std::vector<std::vector<unsigned char>> keys(sols.begin() + 1, sols.begin() + sols.size() - 1);
1998 if (HaveWatchOnly(sh_spk) || HaveWatchOnly(script) || HaveKeys(keys, *this) || (HaveCScript(CScriptID(witprog)) && HaveWatchOnly(witprog))) {
1999 // The above emulates IsMine for these 3 scriptPubKeys, so double check that by running IsMine
2000 assert(IsMine(sh_spk) != ISMINE_NO || IsMine(witprog) != ISMINE_NO || IsMine(sh_wsh_spk) != ISMINE_NO);
2001 continue;
2002 }
2003 assert(IsMine(sh_spk) == ISMINE_NO && IsMine(witprog) == ISMINE_NO && IsMine(sh_wsh_spk) == ISMINE_NO);
2004
2005 std::unique_ptr<Descriptor> sh_desc = InferDescriptor(sh_spk, *GetSolvingProvider(sh_spk));
2006 out.solvable_descs.emplace_back(sh_desc->ToString(), creation_time);
2007
2008 const auto desc = InferDescriptor(witprog, *this);
2009 if (desc->IsSolvable()) {
2010 std::unique_ptr<Descriptor> wsh_desc = InferDescriptor(witprog, *GetSolvingProvider(witprog));
2011 out.solvable_descs.emplace_back(wsh_desc->ToString(), creation_time);
2012 std::unique_ptr<Descriptor> sh_wsh_desc = InferDescriptor(sh_wsh_spk, *GetSolvingProvider(sh_wsh_spk));
2013 out.solvable_descs.emplace_back(sh_wsh_desc->ToString(), creation_time);
2014 }
2015 }
2016 }
2017
2018 // Make sure that we have accounted for all scriptPubKeys
2019 assert(spks.size() == 0);
2020 return out;
2021}
2022
2029
2031{
2032 // Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
2033 if (!CanGetAddresses()) {
2034 return util::Error{_("No addresses available")};
2035 }
2036 {
2038 assert(m_wallet_descriptor.descriptor->IsSingleType()); // This is a combo descriptor which should not be an active descriptor
2039 std::optional<OutputType> desc_addr_type = m_wallet_descriptor.descriptor->GetOutputType();
2040 assert(desc_addr_type);
2041 if (type != *desc_addr_type) {
2042 throw std::runtime_error(std::string(__func__) + ": Types are inconsistent. Stored type does not match type of newly generated address");
2043 }
2044
2045 TopUp();
2046
2047 // Get the scriptPubKey from the descriptor
2048 FlatSigningProvider out_keys;
2049 std::vector<CScript> scripts_temp;
2050 if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
2051 // We can't generate anymore keys
2052 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
2053 }
2054 if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2055 // We can't generate anymore keys
2056 return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
2057 }
2058
2059 CTxDestination dest;
2060 if (!ExtractDestination(scripts_temp[0], dest)) {
2061 return util::Error{_("Error: Cannot extract destination from the generated scriptpubkey")}; // shouldn't happen
2062 }
2063 m_wallet_descriptor.next_index++;
2064 WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
2065 return dest;
2066 }
2067}
2068
2070{
2072 if (m_map_script_pub_keys.count(script) > 0) {
2073 return ISMINE_SPENDABLE;
2074 }
2075 return ISMINE_NO;
2076}
2077
2079{
2081 if (!m_map_keys.empty()) {
2082 return false;
2083 }
2084
2085 bool keyPass = m_map_crypted_keys.empty(); // Always pass when there are no encrypted keys
2086 bool keyFail = false;
2087 for (const auto& mi : m_map_crypted_keys) {
2088 const CPubKey &pubkey = mi.second.first;
2089 const std::vector<unsigned char> &crypted_secret = mi.second.second;
2090 CKey key;
2091 if (!DecryptKey(master_key, crypted_secret, pubkey, key)) {
2092 keyFail = true;
2093 break;
2094 }
2095 keyPass = true;
2097 break;
2098 }
2099 if (keyPass && keyFail) {
2100 LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
2101 throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
2102 }
2103 if (keyFail || !keyPass) {
2104 return false;
2105 }
2107 return true;
2108}
2109
2111{
2113 if (!m_map_crypted_keys.empty()) {
2114 return false;
2115 }
2116
2117 for (const KeyMap::value_type& key_in : m_map_keys)
2118 {
2119 const CKey &key = key_in.second;
2120 CPubKey pubkey = key.GetPubKey();
2121 CKeyingMaterial secret{UCharCast(key.begin()), UCharCast(key.end())};
2122 std::vector<unsigned char> crypted_secret;
2123 if (!EncryptSecret(master_key, secret, pubkey.GetHash(), crypted_secret)) {
2124 return false;
2125 }
2126 m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
2127 batch->WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
2128 }
2129 m_map_keys.clear();
2130 return true;
2131}
2132
2134{
2136 auto op_dest = GetNewDestination(type);
2137 index = m_wallet_descriptor.next_index - 1;
2138 return op_dest;
2139}
2140
2141void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
2142{
2144 // Only return when the index was the most recent
2145 if (m_wallet_descriptor.next_index - 1 == index) {
2146 m_wallet_descriptor.next_index--;
2147 }
2148 WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
2150}
2151
2152std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const
2153{
2156 KeyMap keys;
2157 for (const auto& key_pair : m_map_crypted_keys) {
2158 const CPubKey& pubkey = key_pair.second.first;
2159 const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
2160 CKey key;
2161 m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2162 return DecryptKey(encryption_key, crypted_secret, pubkey, key);
2163 });
2164 keys[pubkey.GetID()] = key;
2165 }
2166 return keys;
2167 }
2168 return m_map_keys;
2169}
2170
2172{
2174 return m_map_keys.contains(keyid) || m_map_crypted_keys.contains(keyid);
2175}
2176
2177std::optional<CKey> DescriptorScriptPubKeyMan::GetKey(const CKeyID& keyid) const
2178{
2181 const auto& it = m_map_crypted_keys.find(keyid);
2182 if (it == m_map_crypted_keys.end()) {
2183 return std::nullopt;
2184 }
2185 const std::vector<unsigned char>& crypted_secret = it->second.second;
2186 CKey key;
2187 if (!Assume(m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2188 return DecryptKey(encryption_key, crypted_secret, it->second.first, key);
2189 }))) {
2190 return std::nullopt;
2191 }
2192 return key;
2193 }
2194 const auto& it = m_map_keys.find(keyid);
2195 if (it == m_map_keys.end()) {
2196 return std::nullopt;
2197 }
2198 return it->second;
2199}
2200
2202{
2204 if (!batch.TxnBegin()) return false;
2205 bool res = TopUpWithDB(batch, size);
2206 if (!batch.TxnCommit()) throw std::runtime_error(strprintf("Error during descriptors keypool top up. Cannot commit changes for wallet %s", m_storage.GetDisplayName()));
2207 return res;
2208}
2209
2211{
2213 std::set<CScript> new_spks;
2214 unsigned int target_size;
2215 if (size > 0) {
2216 target_size = size;
2217 } else {
2218 target_size = m_keypool_size;
2219 }
2220
2221 // Calculate the new range_end
2222 int32_t new_range_end = std::max(m_wallet_descriptor.next_index + (int32_t)target_size, m_wallet_descriptor.range_end);
2223
2224 // If the descriptor is not ranged, we actually just want to fill the first cache item
2225 if (!m_wallet_descriptor.descriptor->IsRange()) {
2226 new_range_end = 1;
2227 m_wallet_descriptor.range_end = 1;
2228 m_wallet_descriptor.range_start = 0;
2229 }
2230
2231 FlatSigningProvider provider;
2232 provider.keys = GetKeys();
2233
2234 uint256 id = GetID();
2235 for (int32_t i = m_max_cached_index + 1; i < new_range_end; ++i) {
2236 FlatSigningProvider out_keys;
2237 std::vector<CScript> scripts_temp;
2238 DescriptorCache temp_cache;
2239 // Maybe we have a cached xpub and we can expand from the cache first
2240 if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2241 if (!m_wallet_descriptor.descriptor->Expand(i, provider, scripts_temp, out_keys, &temp_cache)) return false;
2242 }
2243 // Add all of the scriptPubKeys to the scriptPubKey set
2244 new_spks.insert(scripts_temp.begin(), scripts_temp.end());
2245 for (const CScript& script : scripts_temp) {
2246 m_map_script_pub_keys[script] = i;
2247 }
2248 for (const auto& pk_pair : out_keys.pubkeys) {
2249 const CPubKey& pubkey = pk_pair.second;
2250 if (m_map_pubkeys.count(pubkey) != 0) {
2251 // We don't need to give an error here.
2252 // 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
2253 continue;
2254 }
2255 m_map_pubkeys[pubkey] = i;
2256 }
2257 // Merge and write the cache
2258 DescriptorCache new_items = m_wallet_descriptor.cache.MergeAndDiff(temp_cache);
2259 if (!batch.WriteDescriptorCacheItems(id, new_items)) {
2260 throw std::runtime_error(std::string(__func__) + ": writing cache items failed");
2261 }
2263 }
2264 m_wallet_descriptor.range_end = new_range_end;
2265 batch.WriteDescriptor(GetID(), m_wallet_descriptor);
2266
2267 // By this point, the cache size should be the size of the entire range
2268 assert(m_wallet_descriptor.range_end - 1 == m_max_cached_index);
2269
2270 m_storage.TopUpCallback(new_spks, this);
2272 return true;
2273}
2274
2276{
2278 std::vector<WalletDestination> result;
2279 if (IsMine(script)) {
2280 int32_t index = m_map_script_pub_keys[script];
2281 if (index >= m_wallet_descriptor.next_index) {
2282 WalletLogPrintf("%s: Detected a used keypool item at index %d, mark all keypool items up to this item as used\n", __func__, index);
2283 auto out_keys = std::make_unique<FlatSigningProvider>();
2284 std::vector<CScript> scripts_temp;
2285 while (index >= m_wallet_descriptor.next_index) {
2286 if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) {
2287 throw std::runtime_error(std::string(__func__) + ": Unable to expand descriptor from cache");
2288 }
2289 CTxDestination dest;
2290 ExtractDestination(scripts_temp[0], dest);
2291 result.push_back({dest, std::nullopt});
2292 m_wallet_descriptor.next_index++;
2293 }
2294 }
2295 if (!TopUp()) {
2296 WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
2297 }
2298 }
2299
2300 return result;
2301}
2302
2304{
2307 if (!AddDescriptorKeyWithDB(batch, key, pubkey)) {
2308 throw std::runtime_error(std::string(__func__) + ": writing descriptor private key failed");
2309 }
2310}
2311
2313{
2315 assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
2316
2317 // Check if provided key already exists
2318 if (m_map_keys.find(pubkey.GetID()) != m_map_keys.end() ||
2319 m_map_crypted_keys.find(pubkey.GetID()) != m_map_crypted_keys.end()) {
2320 return true;
2321 }
2322
2324 if (m_storage.IsLocked()) {
2325 return false;
2326 }
2327
2328 std::vector<unsigned char> crypted_secret;
2329 CKeyingMaterial secret{UCharCast(key.begin()), UCharCast(key.end())};
2330 if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2331 return EncryptSecret(encryption_key, secret, pubkey.GetHash(), crypted_secret);
2332 })) {
2333 return false;
2334 }
2335
2336 m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
2337 return batch.WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
2338 } else {
2339 m_map_keys[pubkey.GetID()] = key;
2340 return batch.WriteDescriptorKey(GetID(), pubkey, key.GetPrivKey());
2341 }
2342}
2343
2344bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal)
2345{
2347 assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
2348
2349 // Ignore when there is already a descriptor
2350 if (m_wallet_descriptor.descriptor) {
2351 return false;
2352 }
2353
2354 m_wallet_descriptor = GenerateWalletDescriptor(master_key.Neuter(), addr_type, internal);
2355
2356 // Store the master private key, and descriptor
2357 if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {
2358 throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");
2359 }
2360 if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
2361 throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
2362 }
2363
2364 // TopUp
2365 TopUpWithDB(batch);
2366
2368 return true;
2369}
2370
2372{
2374 return m_wallet_descriptor.descriptor->IsRange();
2375}
2376
2378{
2379 // We can only give out addresses from descriptors that are single type (not combo), ranged,
2380 // and either have cached keys or can generate more keys (ignoring encryption)
2382 return m_wallet_descriptor.descriptor->IsSingleType() &&
2383 m_wallet_descriptor.descriptor->IsRange() &&
2384 (HavePrivateKeys() || m_wallet_descriptor.next_index < m_wallet_descriptor.range_end);
2385}
2386
2388{
2390 return m_map_keys.size() > 0 || m_map_crypted_keys.size() > 0;
2391}
2392
2394{
2395 // This is only used for getwalletinfo output and isn't relevant to descriptor wallets.
2396 return std::nullopt;
2397}
2398
2399
2401{
2403 return m_wallet_descriptor.range_end - m_wallet_descriptor.next_index;
2404}
2405
2407{
2409 return m_wallet_descriptor.creation_time;
2410}
2411
2412std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CScript& script, bool include_private) const
2413{
2415
2416 // Find the index of the script
2417 auto it = m_map_script_pub_keys.find(script);
2418 if (it == m_map_script_pub_keys.end()) {
2419 return nullptr;
2420 }
2421 int32_t index = it->second;
2422
2423 return GetSigningProvider(index, include_private);
2424}
2425
2426std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CPubKey& pubkey) const
2427{
2429
2430 // Find index of the pubkey
2431 auto it = m_map_pubkeys.find(pubkey);
2432 if (it == m_map_pubkeys.end()) {
2433 return nullptr;
2434 }
2435 int32_t index = it->second;
2436
2437 // Always try to get the signing provider with private keys. This function should only be called during signing anyways
2438 return GetSigningProvider(index, true);
2439}
2440
2441std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
2442{
2444
2445 std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
2446
2447 // Fetch SigningProvider from cache to avoid re-deriving
2448 auto it = m_map_signing_providers.find(index);
2449 if (it != m_map_signing_providers.end()) {
2450 out_keys->Merge(FlatSigningProvider{it->second});
2451 } else {
2452 // Get the scripts, keys, and key origins for this script
2453 std::vector<CScript> scripts_temp;
2454 if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
2455
2456 // Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
2457 m_map_signing_providers[index] = *out_keys;
2458 }
2459
2460 if (HavePrivateKeys() && include_private) {
2461 FlatSigningProvider master_provider;
2462 master_provider.keys = GetKeys();
2463 m_wallet_descriptor.descriptor->ExpandPrivate(index, master_provider, *out_keys);
2464 }
2465
2466 return out_keys;
2467}
2468
2469std::unique_ptr<SigningProvider> DescriptorScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
2470{
2471 return GetSigningProvider(script, false);
2472}
2473
2475{
2476 return IsMine(script);
2477}
2478
2479bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
2480{
2481 std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
2482 for (const auto& coin_pair : coins) {
2483 std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(coin_pair.second.out.scriptPubKey, true);
2484 if (!coin_keys) {
2485 continue;
2486 }
2487 keys->Merge(std::move(*coin_keys));
2488 }
2489
2490 return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
2491}
2492
2493SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2494{
2495 std::unique_ptr<FlatSigningProvider> keys = GetSigningProvider(GetScriptForDestination(pkhash), true);
2496 if (!keys) {
2498 }
2499
2500 CKey key;
2501 if (!keys->GetKey(ToKeyID(pkhash), key)) {
2503 }
2504
2505 if (!MessageSign(key, message, str_sig)) {
2507 }
2508 return SigningResult::OK;
2509}
2510
2511std::optional<PSBTError> DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed, bool finalize) const
2512{
2513 if (n_signed) {
2514 *n_signed = 0;
2515 }
2516 for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2517 const CTxIn& txin = psbtx.tx->vin[i];
2518 PSBTInput& input = psbtx.inputs.at(i);
2519
2520 if (PSBTInputSigned(input)) {
2521 continue;
2522 }
2523
2524 // Get the Sighash type
2525 if (sign && input.sighash_type != std::nullopt && *input.sighash_type != sighash_type) {
2526 return PSBTError::SIGHASH_MISMATCH;
2527 }
2528
2529 // Get the scriptPubKey to know which SigningProvider to use
2531 if (!input.witness_utxo.IsNull()) {
2533 } else if (input.non_witness_utxo) {
2534 if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
2535 return PSBTError::MISSING_INPUTS;
2536 }
2537 script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
2538 } else {
2539 // There's no UTXO so we can just skip this now
2540 continue;
2541 }
2542
2543 std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
2544 std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, /*include_private=*/sign);
2545 if (script_keys) {
2546 keys->Merge(std::move(*script_keys));
2547 } else {
2548 // Maybe there are pubkeys listed that we can sign for
2549 std::vector<CPubKey> pubkeys;
2550 pubkeys.reserve(input.hd_keypaths.size() + 2);
2551
2552 // ECDSA Pubkeys
2553 for (const auto& [pk, _] : input.hd_keypaths) {
2554 pubkeys.push_back(pk);
2555 }
2556
2557 // Taproot output pubkey
2558 std::vector<std::vector<unsigned char>> sols;
2560 sols[0].insert(sols[0].begin(), 0x02);
2561 pubkeys.emplace_back(sols[0]);
2562 sols[0][0] = 0x03;
2563 pubkeys.emplace_back(sols[0]);
2564 }
2565
2566 // Taproot pubkeys
2567 for (const auto& pk_pair : input.m_tap_bip32_paths) {
2568 const XOnlyPubKey& pubkey = pk_pair.first;
2569 for (unsigned char prefix : {0x02, 0x03}) {
2570 unsigned char b[33] = {prefix};
2571 std::copy(pubkey.begin(), pubkey.end(), b + 1);
2572 CPubKey fullpubkey;
2573 fullpubkey.Set(b, b + 33);
2574 pubkeys.push_back(fullpubkey);
2575 }
2576 }
2577
2578 for (const auto& pubkey : pubkeys) {
2579 std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
2580 if (pk_keys) {
2581 keys->Merge(std::move(*pk_keys));
2582 }
2583 }
2584 }
2585
2586 SignPSBTInput(HidingSigningProvider(keys.get(), /*hide_secret=*/!sign, /*hide_origin=*/!bip32derivs), psbtx, i, &txdata, sighash_type, nullptr, finalize);
2587
2588 bool signed_one = PSBTInputSigned(input);
2589 if (n_signed && (signed_one || !sign)) {
2590 // If sign is false, we assume that we _could_ sign if we get here. This
2591 // will never have false negatives; it is hard to tell under what i
2592 // circumstances it could have false positives.
2593 (*n_signed)++;
2594 }
2595 }
2596
2597 // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
2598 for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
2599 std::unique_ptr<SigningProvider> keys = GetSolvingProvider(psbtx.tx->vout.at(i).scriptPubKey);
2600 if (!keys) {
2601 continue;
2602 }
2603 UpdatePSBTOutput(HidingSigningProvider(keys.get(), /*hide_secret=*/true, /*hide_origin=*/!bip32derivs), psbtx, i);
2604 }
2605
2606 return {};
2607}
2608
2609std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
2610{
2611 std::unique_ptr<SigningProvider> provider = GetSigningProvider(GetScriptForDestination(dest));
2612 if (provider) {
2613 KeyOriginInfo orig;
2614 CKeyID key_id = GetKeyForDestination(*provider, dest);
2615 if (provider->GetKeyOrigin(key_id, orig)) {
2617 std::unique_ptr<CKeyMetadata> meta = std::make_unique<CKeyMetadata>();
2618 meta->key_origin = orig;
2619 meta->has_key_origin = true;
2620 meta->nCreateTime = m_wallet_descriptor.creation_time;
2621 return meta;
2622 }
2623 }
2624 return nullptr;
2625}
2626
2628{
2630 return m_wallet_descriptor.id;
2631}
2632
2634{
2636 std::set<CScript> new_spks;
2637 m_wallet_descriptor.cache = cache;
2638 for (int32_t i = m_wallet_descriptor.range_start; i < m_wallet_descriptor.range_end; ++i) {
2639 FlatSigningProvider out_keys;
2640 std::vector<CScript> scripts_temp;
2641 if (!m_wallet_descriptor.descriptor->ExpandFromCache(i, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
2642 throw std::runtime_error("Error: Unable to expand wallet descriptor from cache");
2643 }
2644 // Add all of the scriptPubKeys to the scriptPubKey set
2645 new_spks.insert(scripts_temp.begin(), scripts_temp.end());
2646 for (const CScript& script : scripts_temp) {
2647 if (m_map_script_pub_keys.count(script) != 0) {
2648 throw std::runtime_error(strprintf("Error: Already loaded script at index %d as being at index %d", i, m_map_script_pub_keys[script]));
2649 }
2650 m_map_script_pub_keys[script] = i;
2651 }
2652 for (const auto& pk_pair : out_keys.pubkeys) {
2653 const CPubKey& pubkey = pk_pair.second;
2654 if (m_map_pubkeys.count(pubkey) != 0) {
2655 // We don't need to give an error here.
2656 // 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
2657 continue;
2658 }
2659 m_map_pubkeys[pubkey] = i;
2660 }
2662 }
2663 // Make sure the wallet knows about our new spks
2664 m_storage.TopUpCallback(new_spks, this);
2665}
2666
2667bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key)
2668{
2670 m_map_keys[key_id] = key;
2671 return true;
2672}
2673
2674bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key)
2675{
2677 if (!m_map_keys.empty()) {
2678 return false;
2679 }
2680
2681 m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key);
2682 return true;
2683}
2684
2686{
2688 return !m_wallet_descriptor.id.IsNull() && !desc.id.IsNull() && m_wallet_descriptor.id == desc.id;
2689}
2690
2692{
2695 if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
2696 throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
2697 }
2698}
2699
2701{
2702 return m_wallet_descriptor;
2703}
2704
2705std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
2706{
2707 return GetScriptPubKeys(0);
2708}
2709
2710std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys(int32_t minimum_index) const
2711{
2713 std::unordered_set<CScript, SaltedSipHasher> script_pub_keys;
2714 script_pub_keys.reserve(m_map_script_pub_keys.size());
2715
2716 for (auto const& [script_pub_key, index] : m_map_script_pub_keys) {
2717 if (index >= minimum_index) script_pub_keys.insert(script_pub_key);
2718 }
2719 return script_pub_keys;
2720}
2721
2723{
2724 return m_max_cached_index + 1;
2725}
2726
2727bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, const bool priv) const
2728{
2730
2731 FlatSigningProvider provider;
2732 provider.keys = GetKeys();
2733
2734 if (priv) {
2735 // For the private version, always return the master key to avoid
2736 // exposing child private keys. The risk implications of exposing child
2737 // private keys together with the parent xpub may be non-obvious for users.
2738 return m_wallet_descriptor.descriptor->ToPrivateString(provider, out);
2739 }
2740
2741 return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, &m_wallet_descriptor.cache);
2742}
2743
2745{
2748 return;
2749 }
2750
2751 // Skip if we have the last hardened xpub cache
2752 if (m_wallet_descriptor.cache.GetCachedLastHardenedExtPubKeys().size() > 0) {
2753 return;
2754 }
2755
2756 // Expand the descriptor
2757 FlatSigningProvider provider;
2758 provider.keys = GetKeys();
2759 FlatSigningProvider out_keys;
2760 std::vector<CScript> scripts_temp;
2761 DescriptorCache temp_cache;
2762 if (!m_wallet_descriptor.descriptor->Expand(0, provider, scripts_temp, out_keys, &temp_cache)){
2763 throw std::runtime_error("Unable to expand descriptor");
2764 }
2765
2766 // Cache the last hardened xpubs
2767 DescriptorCache diff = m_wallet_descriptor.cache.MergeAndDiff(temp_cache);
2769 throw std::runtime_error(std::string(__func__) + ": writing cache items failed");
2770 }
2771}
2772
2774{
2776 std::string error;
2777 if (!CanUpdateToWalletDescriptor(descriptor, error)) {
2778 throw std::runtime_error(std::string(__func__) + ": " + error);
2779 }
2780
2781 m_map_pubkeys.clear();
2782 m_map_script_pub_keys.clear();
2783 m_max_cached_index = -1;
2784 m_wallet_descriptor = descriptor;
2785
2786 NotifyFirstKeyTimeChanged(this, m_wallet_descriptor.creation_time);
2787}
2788
2790{
2792 if (!HasWalletDescriptor(descriptor)) {
2793 error = "can only update matching descriptor";
2794 return false;
2795 }
2796
2797 if (descriptor.range_start > m_wallet_descriptor.range_start ||
2798 descriptor.range_end < m_wallet_descriptor.range_end) {
2799 // Use inclusive range for error
2800 error = strprintf("new range must include current range = [%d,%d]",
2801 m_wallet_descriptor.range_start,
2802 m_wallet_descriptor.range_end - 1);
2803 return false;
2804 }
2805
2806 return true;
2807}
2808} // namespace wallet
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
CKeyID ToKeyID(const PKHash &key_hash)
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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 Assume(val)
Assume is the identity function.
Definition check.h:89
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:414
A reference to a CScript: the Hash160 of its serialization.
Definition script.h:591
An input of a transaction.
Definition transaction.h:67
COutPoint prevout
Definition transaction.h:69
CScript scriptPubKey
bool IsNull() const
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
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:46
constexpr unsigned char * begin()
Definition uint256.h:102
size_type size() const
Definition prevector.h:296
160-bit opaque blob.
Definition uint256.h:166
256-bit opaque blob.
Definition uint256.h:178
static const uint256 ONE
Definition uint256.h:186
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
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 ofthis 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
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore)
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 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.
void WalletLogPrintf(const char *fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
Access to the wallet database.
Definition walletdb.h:191
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)
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta)
Definition walletdb.cpp:162
bool TxnBegin()
Begin a new transaction.
bool TxnCommit()
Commit current transaction.
bool EraseRecords(const std::unordered_set< std::string > &types)
Delete records of the given types.
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:321
bool MessageSign(const CKey &privkey, const std::string &message, std::string &signature)
Sign a message.
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
CKey GenerateRandomKey(bool compressed) noexcept
Definition key.cpp:352
std::string EncodeDestination(const CTxDestination &dest)
Definition key_io.cpp:291
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition key_io.cpp:257
#define LogPrintf(...)
Definition logging.h:274
PSBTError
Definition types.h:17
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition string.h:156
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
@ P2SH
P2SH redeemScript.
@ TOP
Top-level scriptPubKey.
@ WITNESS_V0
P2WSH witnessScript.
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition crypter.h:62
bool DecryptKey(const CKeyingMaterial &vMasterKey, const std::vector< unsigned char > &vchCryptedSecret, const CPubKey &vchPubKey, CKey &key)
Definition crypter.cpp:128
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
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:108
bool IsFeatureSupported(int wallet_version, int feature_version)
@ WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
Definition walletutil.h:48
@ WALLET_FLAG_KEY_ORIGIN_METADATA
Definition walletutil.h:45
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
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.
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
const char * prefix
Definition rest.cpp:1007
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:27
@ OP_0
Definition script.h:75
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:765
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:288
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.
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:18
struct containing information needed for migrating legacy wallets to descriptor wallets
#define LOCK(cs)
Definition sync.h:257
#define AssertLockHeld(cs)
Definition sync.h:142
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition time.cpp:44
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
bilingual_str _(ConstevalStringLiteral str)
Translation function.
Definition translation.h:80
assert(!tx.IsCoinBase())