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