fuzz coverage

Coverage Report

Created: 2025-08-28 15:26

/Users/eugenesiegel/btc/bitcoin/src/wallet/scriptpubkeyman.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
6
#define BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
7
8
#include <addresstype.h>
9
#include <common/messages.h>
10
#include <common/signmessage.h>
11
#include <common/types.h>
12
#include <logging.h>
13
#include <node/types.h>
14
#include <psbt.h>
15
#include <script/descriptor.h>
16
#include <script/script.h>
17
#include <script/signingprovider.h>
18
#include <util/result.h>
19
#include <util/time.h>
20
#include <wallet/crypter.h>
21
#include <wallet/types.h>
22
#include <wallet/walletdb.h>
23
#include <wallet/walletutil.h>
24
25
#include <boost/signals2/signal.hpp>
26
27
#include <functional>
28
#include <optional>
29
#include <unordered_map>
30
31
enum class OutputType;
32
33
namespace wallet {
34
struct MigrationData;
35
class ScriptPubKeyMan;
36
37
// Wallet storage things that ScriptPubKeyMans need in order to be able to store things to the wallet database.
38
// It provides access to things that are part of the entire wallet and not specific to a ScriptPubKeyMan such as
39
// wallet flags, wallet version, encryption keys, encryption status, and the database itself. This allows a
40
// ScriptPubKeyMan to have callbacks into CWallet without causing a circular dependency.
41
// WalletStorage should be the same for all ScriptPubKeyMans of a wallet.
42
class WalletStorage
43
{
44
public:
45
0
    virtual ~WalletStorage() = default;
46
    virtual std::string GetDisplayName() const = 0;
47
    virtual WalletDatabase& GetDatabase() const = 0;
48
    virtual bool IsWalletFlagSet(uint64_t) const = 0;
49
    virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
50
    virtual bool CanSupportFeature(enum WalletFeature) const = 0;
51
    virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0;
52
    //! Pass the encryption key to cb().
53
    virtual bool WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const = 0;
54
    virtual bool HasEncryptionKeys() const = 0;
55
    virtual bool IsLocked() const = 0;
56
    //! Callback function for after TopUp completes containing any scripts that were added by a SPKMan
57
    virtual void TopUpCallback(const std::set<CScript>&, ScriptPubKeyMan*) = 0;
58
};
59
60
//! Constant representing an unknown spkm creation time
61
static constexpr int64_t UNKNOWN_TIME = std::numeric_limits<int64_t>::max();
62
63
//! Default for -keypool
64
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
65
66
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
67
68
/** A key from a CWallet's keypool
69
 *
70
 * The wallet holds one (for pre HD-split wallets) or several keypools. These
71
 * are sets of keys that have not yet been used to provide addresses or receive
72
 * change.
73
 *
74
 * The Bitcoin Core wallet was originally a collection of unrelated private
75
 * keys with their associated addresses. If a non-HD wallet generated a
76
 * key/address, gave that address out and then restored a backup from before
77
 * that key's generation, then any funds sent to that address would be
78
 * lost definitively.
79
 *
80
 * The keypool was implemented to avoid this scenario (commit: 10384941). The
81
 * wallet would generate a set of keys (100 by default). When a new public key
82
 * was required, either to give out as an address or to use in a change output,
83
 * it would be drawn from the keypool. The keypool would then be topped up to
84
 * maintain 100 keys. This ensured that as long as the wallet hadn't used more
85
 * than 100 keys since the previous backup, all funds would be safe, since a
86
 * restored wallet would be able to scan for all owned addresses.
87
 *
88
 * A keypool also allowed encrypted wallets to give out addresses without
89
 * having to be decrypted to generate a new private key.
90
 *
91
 * With the introduction of HD wallets (commit: f1902510), the keypool
92
 * essentially became an address look-ahead pool. Restoring old backups can no
93
 * longer definitively lose funds as long as the addresses used were from the
94
 * wallet's HD seed (since all private keys can be rederived from the seed).
95
 * However, if many addresses were used since the backup, then the wallet may
96
 * not know how far ahead in the HD chain to look for its addresses. The
97
 * keypool is used to implement a 'gap limit'. The keypool maintains a set of
98
 * keys (by default 1000) ahead of the last used key and scans for the
99
 * addresses of those keys.  This avoids the risk of not seeing transactions
100
 * involving the wallet's addresses, or of re-using the same address.
101
 * In the unlikely case where none of the addresses in the `gap limit` are
102
 * used on-chain, the look-ahead will not be incremented to keep
103
 * a constant size and addresses beyond this range will not be detected by an
104
 * old backup. For this reason, it is not recommended to decrease keypool size
105
 * lower than default value.
106
 *
107
 * The HD-split wallet feature added a second keypool (commit: 02592f4c). There
108
 * is an external keypool (for addresses to hand out) and an internal keypool
109
 * (for change addresses).
110
 *
111
 * Keypool keys are stored in the wallet/keystore's keymap. The keypool data is
112
 * stored as sets of indexes in the wallet (setInternalKeyPool,
113
 * setExternalKeyPool and set_pre_split_keypool), and a map from the key to the
114
 * index (m_pool_key_to_index). The CKeyPool object is used to
115
 * serialize/deserialize the pool data to/from the database.
116
 */
117
class CKeyPool
118
{
119
public:
120
    //! The time at which the key was generated. Set in AddKeypoolPubKeyWithDB
121
    int64_t nTime;
122
    //! The public key
123
    CPubKey vchPubKey;
124
    //! Whether this keypool entry is in the internal keypool (for change outputs)
125
    bool fInternal;
126
    //! Whether this key was generated for a keypool before the wallet was upgraded to HD-split
127
    bool m_pre_split;
128
129
    CKeyPool();
130
    CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn);
131
132
    template<typename Stream>
133
    void Serialize(Stream& s) const
134
0
    {
135
0
        s << int{259900}; // Unused field, writes the highest client version ever written
136
0
        s << nTime << vchPubKey << fInternal << m_pre_split;
137
0
    }
138
139
    template<typename Stream>
140
    void Unserialize(Stream& s)
141
0
    {
142
0
        s >> int{}; // Discard unused field
143
0
        s >> nTime >> vchPubKey;
144
0
        try {
145
0
            s >> fInternal;
146
0
        } catch (std::ios_base::failure&) {
147
            /* flag as external address if we can't read the internal boolean
148
               (this will be the case for any wallet before the HD chain split version) */
149
0
            fInternal = false;
150
0
        }
151
0
        try {
152
0
            s >> m_pre_split;
153
0
        } catch (std::ios_base::failure&) {
154
            /* flag as postsplit address if we can't read the m_pre_split boolean
155
               (this will be the case for any wallet that upgrades to HD chain split) */
156
0
            m_pre_split = false;
157
0
        }
158
0
    }
159
};
160
161
struct WalletDestination
162
{
163
    CTxDestination dest;
164
    std::optional<bool> internal;
165
};
166
167
/*
168
 * A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
169
 * It contains the scripts and keys related to the scriptPubKeys it manages.
170
 * A ScriptPubKeyMan will be able to give out scriptPubKeys to be used, as well as marking
171
 * when a scriptPubKey has been used. It also handles when and how to store a scriptPubKey
172
 * and its related scripts and keys, including encryption.
173
 */
174
class ScriptPubKeyMan
175
{
176
protected:
177
    WalletStorage& m_storage;
178
179
public:
180
0
    explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
181
0
    virtual ~ScriptPubKeyMan() = default;
182
0
    virtual util::Result<CTxDestination> GetNewDestination(const OutputType type) { return util::Error{Untranslated("Not supported")}; }
183
0
    virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
184
185
    //! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
186
0
    virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key) { return false; }
187
0
    virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
188
189
0
    virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; }
190
0
    virtual void KeepDestination(int64_t index, const OutputType& type) {}
191
0
    virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
192
193
    /** Fills internal address pool. Use within ScriptPubKeyMan implementations should be used sparingly and only
194
      * when something from the address pool is removed, excluding GetNewDestination and GetReservedDestination.
195
      * External wallet code is primarily responsible for topping up prior to fetching new addresses
196
      */
197
0
    virtual bool TopUp(unsigned int size = 0) { return false; }
198
199
    /** Mark unused addresses as being used
200
     * Affects all keys up to and including the one determined by provided script.
201
     *
202
     * @param script determines the last key to mark as used
203
     *
204
     * @return All of the addresses affected
205
     */
206
0
    virtual std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) { return {}; }
207
208
    /** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active.
209
      * Returns false if already setup or setup fails, true if setup is successful
210
      * Set force=true to make it re-setup if already setup, used for upgrades
211
      */
212
0
    virtual bool SetupGeneration(bool force = false) { return false; }
213
214
    /* Returns true if HD is enabled */
215
0
    virtual bool IsHDEnabled() const { return false; }
216
217
    /* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
218
0
    virtual bool CanGetAddresses(bool internal = false) const { return false; }
219
220
    /** Upgrades the wallet to the specified version */
221
0
    virtual bool Upgrade(int prev_version, int new_version, bilingual_str& error) { return true; }
222
223
0
    virtual bool HavePrivateKeys() const { return false; }
224
0
    virtual bool HaveCryptedKeys() const { return false; }
225
226
    //! The action to do when the DB needs rewrite
227
0
    virtual void RewriteDB() {}
228
229
0
    virtual std::optional<int64_t> GetOldestKeyPoolTime() const { return GetTime(); }
230
231
0
    virtual unsigned int GetKeyPoolSize() const { return 0; }
232
233
0
    virtual int64_t GetTimeFirstKey() const { return 0; }
234
235
0
    virtual std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const { return nullptr; }
236
237
0
    virtual std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const { return nullptr; }
238
239
    /** Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that, combined with
240
      * sigdata, can produce solving data.
241
      */
242
0
    virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
243
244
    /** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
245
0
    virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const { return false; }
246
    /** Sign a message with the given script */
247
0
    virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
248
    /** Adds script and derivation path information to a PSBT, and optionally signs it. */
249
0
    virtual 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 { return common::PSBTError::UNSUPPORTED; }
250
251
0
    virtual uint256 GetID() const { return uint256(); }
252
253
    /** Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches */
254
0
    virtual std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const { return {}; };
255
256
    /** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
257
    template <typename... Params>
258
    void WalletLogPrintf(util::ConstevalFormatString<sizeof...(Params)> wallet_fmt, const Params&... params) const
259
0
    {
260
0
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
Line
Count
Source
261
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, __VA_ARGS__)
Line
Count
Source
255
0
#define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__)
261
0
    };
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cmbEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA12_cjjNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJxxmmEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExxEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJxEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_ciEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
262
263
    /** Watch-only address added */
264
    boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
265
266
    /** Keypool has new keys */
267
    boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
268
269
    /** Birth time changed */
270
    boost::signals2::signal<void (const ScriptPubKeyMan* spkm, int64_t new_birth_time)> NotifyFirstKeyTimeChanged;
271
};
272
273
/** OutputTypes supported by the LegacyScriptPubKeyMan */
274
static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
275
    OutputType::LEGACY,
276
    OutputType::P2SH_SEGWIT,
277
    OutputType::BECH32,
278
};
279
280
class DescriptorScriptPubKeyMan;
281
282
// Manages the data for a LegacyScriptPubKeyMan.
283
// This is the minimum necessary to load a legacy wallet so that it can be migrated.
284
class LegacyDataSPKM : public ScriptPubKeyMan, public FillableSigningProvider
285
{
286
protected:
287
    using WatchOnlySet = std::set<CScript>;
288
    using WatchKeyMap = std::map<CKeyID, CPubKey>;
289
    using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
290
291
    CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
292
    WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
293
    WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
294
295
    /* the HD chain data model (external chain counters) */
296
    CHDChain m_hd_chain;
297
    std::unordered_map<CKeyID, CHDChain, SaltedSipHasher> m_inactive_hd_chains;
298
299
    //! keeps track of whether Unlock has run a thorough check before
300
    bool fDecryptionThoroughlyChecked = true;
301
302
    bool AddWatchOnlyInMem(const CScript &dest);
303
    virtual bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
304
    bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
305
306
    // Helper function to retrieve a conservative superset of all output scripts that may be relevant to this LegacyDataSPKM.
307
    // It may include scripts that are invalid or not actually watched by this LegacyDataSPKM.
308
    // Used only in migration.
309
    std::unordered_set<CScript, SaltedSipHasher> GetCandidateScriptPubKeys() const;
310
public:
311
    using ScriptPubKeyMan::ScriptPubKeyMan;
312
313
    // Map from Key ID to key metadata.
314
    std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
315
316
    // Map from Script ID to key metadata (for watch-only keys).
317
    std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_KeyStore);
318
319
    // ScriptPubKeyMan overrides
320
    bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
321
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
322
    std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
323
0
    uint256 GetID() const override { return uint256::ONE; }
324
    // TODO: Remove IsMine when deleting LegacyScriptPubKeyMan
325
    isminetype IsMine(const CScript& script) const override;
326
    bool CanProvide(const CScript& script, SignatureData& sigdata) override;
327
328
    // FillableSigningProvider overrides
329
    bool HaveKey(const CKeyID &address) const override;
330
    bool GetKey(const CKeyID &address, CKey& keyOut) const override;
331
    bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
332
    bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
333
334
    std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_KeyStore);
335
    std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_KeyStore);
336
    std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_KeyStore);
337
    int64_t m_max_keypool_index GUARDED_BY(cs_KeyStore) = 0;
338
    std::map<CKeyID, int64_t> m_pool_key_to_index;
339
340
    //! Load metadata (used by LoadWallet)
341
    virtual void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
342
    virtual void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
343
344
    //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
345
    bool LoadWatchOnly(const CScript &dest);
346
    //! Returns whether the watch-only script is in the wallet
347
    bool HaveWatchOnly(const CScript &dest) const;
348
    //! Returns whether there are any watch-only things in the wallet
349
    bool HaveWatchOnly() const;
350
    //! Adds a key to the store, without saving it to disk (used by LoadWallet)
351
    bool LoadKey(const CKey& key, const CPubKey &pubkey);
352
    //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
353
    bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret, bool checksum_valid);
354
    //! Adds a CScript to the store
355
    bool LoadCScript(const CScript& redeemScript);
356
    //! Load a HD chain model (used by LoadWallet)
357
    void LoadHDChain(const CHDChain& chain);
358
    void AddInactiveHDChain(const CHDChain& chain);
359
0
    const CHDChain& GetHDChain() const { return m_hd_chain; }
360
    //! Load a keypool entry
361
    void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
362
363
    //! Fetches a pubkey from mapWatchKeys if it exists there
364
    bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
365
366
    /**
367
     * Retrieves scripts that were imported by bugs into the legacy spkm and are
368
     * simply invalid, such as a sh(sh(pkh())) script, or not watched.
369
     */
370
    std::unordered_set<CScript, SaltedSipHasher> GetNotMineScriptPubKeys() const;
371
372
    /** Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this LegacyScriptPubKeyMan.
373
     * Does not modify this ScriptPubKeyMan. */
374
    std::optional<MigrationData> MigrateToDescriptor();
375
    /** Delete all the records of this LegacyScriptPubKeyMan from disk*/
376
    bool DeleteRecords();
377
    bool DeleteRecordsWithDB(WalletBatch& batch);
378
};
379
380
// Implements the full legacy wallet behavior
381
class LegacyScriptPubKeyMan : public LegacyDataSPKM
382
{
383
private:
384
    WalletBatch *encrypted_batch GUARDED_BY(cs_KeyStore) = nullptr;
385
386
    // By default, do not scan any block until keys/scripts are generated/imported
387
    int64_t nTimeFirstKey GUARDED_BY(cs_KeyStore) = UNKNOWN_TIME;
388
389
    //! Number of pre-generated keys/scripts (part of the look-ahead process, used to detect payments)
390
    int64_t m_keypool_size GUARDED_BY(cs_KeyStore){DEFAULT_KEYPOOL_SIZE};
391
392
    bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey) override;
393
394
    /**
395
     * Private version of AddWatchOnly method which does not accept a
396
     * timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
397
     * the watch key did not previously have a timestamp associated with it.
398
     * Because this is an inherited virtual method, it is accessible despite
399
     * being marked private, but it is marked private anyway to encourage use
400
     * of the other AddWatchOnly which accepts a timestamp and sets
401
     * nTimeFirstKey more intelligently for more efficient rescans.
402
     */
403
    bool AddWatchOnly(const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
404
    bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
405
    //! Adds a watch-only address to the store, and saves it to disk.
406
    bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
407
408
    //! Adds a key to the store, and saves it to disk.
409
    bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
410
411
    void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
412
413
    //! Adds a script to the store and saves it to disk
414
    bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
415
416
    /** Add a KeyOriginInfo to the wallet */
417
    bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
418
419
    /* HD derive new child key (on internal or external chain) */
420
    void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
421
422
    // Tracks keypool indexes to CKeyIDs of keys that have been taken out of the keypool but may be returned to it
423
    std::map<int64_t, CKeyID> m_index_to_reserved_key;
424
425
    //! Fetches a key from the keypool
426
    bool GetKeyFromPool(CPubKey &key, const OutputType type);
427
428
    /**
429
     * Reserves a key from the keypool and sets nIndex to its index
430
     *
431
     * @param[out] nIndex the index of the key in keypool
432
     * @param[out] keypool the keypool the key was drawn from, which could be the
433
     *     the pre-split pool if present, or the internal or external pool
434
     * @param fRequestedInternal true if the caller would like the key drawn
435
     *     from the internal keypool, false if external is preferred
436
     *
437
     * @return true if succeeded, false if failed due to empty keypool
438
     * @throws std::runtime_error if keypool read failed, key was invalid,
439
     *     was not found in the wallet, or was misclassified in the internal
440
     *     or external keypool
441
     */
442
    bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
443
444
    /**
445
     * Like TopUp() but adds keys for inactive HD chains.
446
     * Ensures that there are at least -keypool number of keys derived after the given index.
447
     *
448
     * @param seed_id the CKeyID for the HD seed.
449
     * @param index the index to start generating keys from
450
     * @param internal whether the internal chain should be used. true for internal chain, false for external chain.
451
     *
452
     * @return true if seed was found and keys were derived. false if unable to derive seeds
453
     */
454
    bool TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal);
455
456
    bool TopUpChain(WalletBatch& batch, CHDChain& chain, unsigned int size);
457
public:
458
0
    LegacyScriptPubKeyMan(WalletStorage& storage, int64_t keypool_size) : LegacyDataSPKM(storage), m_keypool_size(keypool_size) {}
459
460
    util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
461
462
    bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
463
464
    util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
465
    void KeepDestination(int64_t index, const OutputType& type) override;
466
    void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
467
468
    bool TopUp(unsigned int size = 0) override;
469
470
    std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
471
472
    //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
473
    void UpgradeKeyMetadata();
474
475
    bool IsHDEnabled() const override;
476
477
    bool SetupGeneration(bool force = false) override;
478
479
    bool Upgrade(int prev_version, int new_version, bilingual_str& error) override;
480
481
    bool HavePrivateKeys() const override;
482
    bool HaveCryptedKeys() const override;
483
484
    void RewriteDB() override;
485
486
    std::optional<int64_t> GetOldestKeyPoolTime() const override;
487
    size_t KeypoolCountExternalKeys() const;
488
    unsigned int GetKeyPoolSize() const override;
489
490
    int64_t GetTimeFirstKey() const override;
491
492
    std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
493
494
    bool CanGetAddresses(bool internal = false) const override;
495
496
    bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
497
    SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
498
    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;
499
500
    uint256 GetID() const override;
501
502
    //! Adds a key to the store, and saves it to disk.
503
    bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
504
    //! Adds an encrypted key to the store, and saves it to disk.
505
    bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
506
    void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
507
    //! Load metadata (used by LoadWallet)
508
    void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) override;
509
    void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) override;
510
    //! Generate a new key
511
    CPubKey GenerateNewKey(WalletBatch& batch, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
512
513
    /* Set the HD chain model (chain child index counters) and writes it to the database */
514
    void AddHDChain(const CHDChain& chain);
515
516
    //! Remove a watch only script from the keystore
517
    bool RemoveWatchOnly(const CScript &dest);
518
    bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
519
520
    /* SigningProvider overrides */
521
    bool AddCScript(const CScript& redeemScript) override;
522
523
    bool NewKeyPool();
524
    void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
525
526
    bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
527
    bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
528
    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);
529
    bool ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
530
531
    /* Returns true if the wallet can generate new keys */
532
    bool CanGenerateKeys() const;
533
534
    /* Generates a new HD seed (will not be activated) */
535
    CPubKey GenerateNewSeed();
536
537
    /* Derives a new HD seed (will not be activated) */
538
    CPubKey DeriveNewSeed(const CKey& key);
539
540
    /* Set the current HD seed (will reset the chain child index counters)
541
       Sets the seed's version based on the current wallet version (so the
542
       caller must ensure the current wallet version is correct before calling
543
       this function). */
544
    void SetHDSeed(const CPubKey& key);
545
546
    /**
547
     * Explicitly make the wallet learn the related scripts for outputs to the
548
     * given key. This is purely to make the wallet file compatible with older
549
     * software, as FillableSigningProvider automatically does this implicitly for all
550
     * keys now.
551
     */
552
    void LearnRelatedScripts(const CPubKey& key, OutputType);
553
554
    /**
555
     * Same as LearnRelatedScripts, but when the OutputType is not known (and could
556
     * be anything).
557
     */
558
    void LearnAllRelatedScripts(const CPubKey& key);
559
560
    /**
561
     * Marks all keys in the keypool up to and including the provided key as used.
562
     *
563
     * @param keypool_id determines the last key to mark as used
564
     *
565
     * @return All affected keys
566
     */
567
    std::vector<CKeyPool> MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
568
0
    const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
569
570
    std::set<CKeyID> GetKeys() const override;
571
};
572
573
/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr. Does not provide privkeys */
574
class LegacySigningProvider : public SigningProvider
575
{
576
private:
577
    const LegacyDataSPKM& m_spk_man;
578
public:
579
0
    explicit LegacySigningProvider(const LegacyDataSPKM& spk_man) : m_spk_man(spk_man) {}
580
581
0
    bool GetCScript(const CScriptID &scriptid, CScript& script) const override { return m_spk_man.GetCScript(scriptid, script); }
582
0
    bool HaveCScript(const CScriptID &scriptid) const override { return m_spk_man.HaveCScript(scriptid); }
583
0
    bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const override { return m_spk_man.GetPubKey(address, pubkey); }
584
0
    bool GetKey(const CKeyID &address, CKey& key) const override { return false; }
585
0
    bool HaveKey(const CKeyID &address) const override { return false; }
586
0
    bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override { return m_spk_man.GetKeyOrigin(keyid, info); }
587
};
588
589
class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
590
{
591
    friend class LegacyDataSPKM;
592
private:
593
    using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index
594
    using PubKeyMap = std::map<CPubKey, int32_t>; // Map of pubkeys involved in scripts to descriptor range index
595
    using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
596
    using KeyMap = std::map<CKeyID, CKey>;
597
598
    ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
599
    PubKeyMap m_map_pubkeys GUARDED_BY(cs_desc_man);
600
    int32_t m_max_cached_index = -1;
601
602
    KeyMap m_map_keys GUARDED_BY(cs_desc_man);
603
    CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man);
604
605
    //! keeps track of whether Unlock has run a thorough check before
606
    bool m_decryption_thoroughly_checked = false;
607
608
    //! Number of pre-generated keys/scripts (part of the look-ahead process, used to detect payments)
609
    int64_t m_keypool_size GUARDED_BY(cs_desc_man){DEFAULT_KEYPOOL_SIZE};
610
611
    bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
612
613
    KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
614
615
    // Cached FlatSigningProviders to avoid regenerating them each time they are needed.
616
    mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
617
    // Fetch the SigningProvider for the given script and optionally include private keys
618
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
619
    // Fetch the SigningProvider for a given index and optionally include private keys. Called by the above functions.
620
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(int32_t index, bool include_private = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
621
622
protected:
623
    WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man);
624
625
    //! Same as 'TopUp' but designed for use within a batch transaction context
626
    bool TopUpWithDB(WalletBatch& batch, unsigned int size = 0);
627
628
public:
629
    DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor, int64_t keypool_size)
630
0
        :   ScriptPubKeyMan(storage),
631
0
            m_keypool_size(keypool_size),
632
0
            m_wallet_descriptor(descriptor)
633
0
        {}
634
    DescriptorScriptPubKeyMan(WalletStorage& storage, int64_t keypool_size)
635
0
        :   ScriptPubKeyMan(storage),
636
0
            m_keypool_size(keypool_size)
637
0
        {}
638
639
    mutable RecursiveMutex cs_desc_man;
640
641
    util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
642
    isminetype IsMine(const CScript& script) const override;
643
644
    bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
645
    bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
646
647
    util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
648
    void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
649
650
    // Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
651
    // and is used to expand the descriptor in GetNewDestination. DescriptorScriptPubKeyMan relies
652
    // more on ephemeral data than LegacyScriptPubKeyMan. For wallets using unhardened derivation
653
    // (with or without private keys), the "keypool" is a single xpub.
654
    bool TopUp(unsigned int size = 0) override;
655
656
    std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
657
658
    bool IsHDEnabled() const override;
659
660
    //! Setup descriptors based on the given CExtkey
661
    bool SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal);
662
663
    bool HavePrivateKeys() const override;
664
    bool HasPrivKey(const CKeyID& keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
665
    //! Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet, or if the wallet is locked.
666
    std::optional<CKey> GetKey(const CKeyID& keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
667
    bool HaveCryptedKeys() const override;
668
669
    std::optional<int64_t> GetOldestKeyPoolTime() const override;
670
    unsigned int GetKeyPoolSize() const override;
671
672
    int64_t GetTimeFirstKey() const override;
673
674
    std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
675
676
    bool CanGetAddresses(bool internal = false) const override;
677
678
    std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
679
680
    bool CanProvide(const CScript& script, SignatureData& sigdata) override;
681
682
    // Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
683
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CPubKey& pubkey) const;
684
685
    bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
686
    SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
687
    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;
688
689
    uint256 GetID() const override;
690
691
    void SetCache(const DescriptorCache& cache);
692
693
    bool AddKey(const CKeyID& key_id, const CKey& key);
694
    bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key);
695
696
    bool HasWalletDescriptor(const WalletDescriptor& desc) const;
697
    util::Result<void> UpdateWalletDescriptor(WalletDescriptor& descriptor);
698
    bool CanUpdateToWalletDescriptor(const WalletDescriptor& descriptor, std::string& error);
699
    void AddDescriptorKey(const CKey& key, const CPubKey &pubkey);
700
    void WriteDescriptor();
701
702
    WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
703
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
704
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys(int32_t minimum_index) const;
705
    int32_t GetEndRange() const;
706
707
    [[nodiscard]] bool GetDescriptorString(std::string& out, const bool priv) const;
708
709
    void UpgradeDescriptorCache();
710
};
711
712
/** struct containing information needed for migrating legacy wallets to descriptor wallets */
713
struct MigrationData
714
{
715
    CExtKey master_key;
716
    std::vector<std::pair<std::string, int64_t>> watch_descs;
717
    std::vector<std::pair<std::string, int64_t>> solvable_descs;
718
    std::vector<std::unique_ptr<DescriptorScriptPubKeyMan>> desc_spkms;
719
    std::shared_ptr<CWallet> watchonly_wallet{nullptr};
720
    std::shared_ptr<CWallet> solvable_wallet{nullptr};
721
};
722
723
} // namespace wallet
724
725
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H