Coverage Report

Created: 2024-10-21 15:10

/root/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
225
    //! The action to do when the DB needs rewrite
226
0
    virtual void RewriteDB() {}
227
228
0
    virtual std::optional<int64_t> GetOldestKeyPoolTime() const { return GetTime(); }
229
230
0
    virtual unsigned int GetKeyPoolSize() const { return 0; }
231
232
0
    virtual int64_t GetTimeFirstKey() const { return 0; }
233
234
0
    virtual std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const { return nullptr; }
235
236
0
    virtual std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const { return nullptr; }
237
238
    /** Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSolvingProvider) that, combined with
239
      * sigdata, can produce solving data.
240
      */
241
0
    virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
242
243
    /** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
244
0
    virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const { return false; }
245
    /** Sign a message with the given script */
246
0
    virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
247
    /** Adds script and derivation path information to a PSBT, and optionally signs it. */
248
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; }
249
250
0
    virtual uint256 GetID() const { return uint256(); }
251
252
    /** Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches */
253
0
    virtual std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const { return {}; };
254
255
    /** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
256
    template <typename... Params>
257
    void WalletLogPrintf(util::ConstevalFormatString<sizeof...(Params)> wallet_fmt, const Params&... params) const
258
0
    {
259
0
        LogInfo("%s %s", m_storage.GetDisplayName(), tfm::format(wallet_fmt, params...));
260
0
    };
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_cmbEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA12_cjjNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJllmmEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEllEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJlEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
Unexecuted instantiation: _ZNK6wallet15ScriptPubKeyMan15WalletLogPrintfIJA20_ciEEEvN4util21ConstevalFormatStringIXsZT_EEEDpRKT_
261
262
    /** Watch-only address added */
263
    boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
264
265
    /** Keypool has new keys */
266
    boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
267
268
    /** Birth time changed */
269
    boost::signals2::signal<void (const ScriptPubKeyMan* spkm, int64_t new_birth_time)> NotifyFirstKeyTimeChanged;
270
};
271
272
/** OutputTypes supported by the LegacyScriptPubKeyMan */
273
static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
274
    OutputType::LEGACY,
275
    OutputType::P2SH_SEGWIT,
276
    OutputType::BECH32,
277
};
278
279
class DescriptorScriptPubKeyMan;
280
281
// Manages the data for a LegacyScriptPubKeyMan.
282
// This is the minimum necessary to load a legacy wallet so that it can be migrated.
283
class LegacyDataSPKM : public ScriptPubKeyMan, public FillableSigningProvider
284
{
285
protected:
286
    using WatchOnlySet = std::set<CScript>;
287
    using WatchKeyMap = std::map<CKeyID, CPubKey>;
288
    using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
289
290
    CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
291
    WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
292
    WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
293
294
    /* the HD chain data model (external chain counters) */
295
    CHDChain m_hd_chain;
296
    std::unordered_map<CKeyID, CHDChain, SaltedSipHasher> m_inactive_hd_chains;
297
298
    //! keeps track of whether Unlock has run a thorough check before
299
    bool fDecryptionThoroughlyChecked = true;
300
301
    bool AddWatchOnlyInMem(const CScript &dest);
302
    virtual bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
303
    bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
304
305
public:
306
    using ScriptPubKeyMan::ScriptPubKeyMan;
307
308
    // Map from Key ID to key metadata.
309
    std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
310
311
    // Map from Script ID to key metadata (for watch-only keys).
312
    std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_KeyStore);
313
314
    // ScriptPubKeyMan overrides
315
    bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
316
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
317
    std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
318
0
    uint256 GetID() const override { return uint256::ONE; }
319
    // TODO: Remove IsMine when deleting LegacyScriptPubKeyMan
320
    isminetype IsMine(const CScript& script) const override;
321
322
    // FillableSigningProvider overrides
323
    bool HaveKey(const CKeyID &address) const override;
324
    bool GetKey(const CKeyID &address, CKey& keyOut) const override;
325
    bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
326
    bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
327
328
    std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_KeyStore);
329
    std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_KeyStore);
330
    std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_KeyStore);
331
    int64_t m_max_keypool_index GUARDED_BY(cs_KeyStore) = 0;
332
    std::map<CKeyID, int64_t> m_pool_key_to_index;
333
334
    //! Load metadata (used by LoadWallet)
335
    virtual void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
336
    virtual void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
337
338
    //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
339
    bool LoadWatchOnly(const CScript &dest);
340
    //! Returns whether the watch-only script is in the wallet
341
    bool HaveWatchOnly(const CScript &dest) const;
342
    //! Returns whether there are any watch-only things in the wallet
343
    bool HaveWatchOnly() const;
344
    //! Adds a key to the store, without saving it to disk (used by LoadWallet)
345
    bool LoadKey(const CKey& key, const CPubKey &pubkey);
346
    //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
347
    bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret, bool checksum_valid);
348
    //! Adds a CScript to the store
349
    bool LoadCScript(const CScript& redeemScript);
350
    //! Load a HD chain model (used by LoadWallet)
351
    void LoadHDChain(const CHDChain& chain);
352
    void AddInactiveHDChain(const CHDChain& chain);
353
0
    const CHDChain& GetHDChain() const { return m_hd_chain; }
354
    //! Load a keypool entry
355
    void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
356
357
    //! Fetches a pubkey from mapWatchKeys if it exists there
358
    bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
359
360
    /**
361
     * Retrieves scripts that were imported by bugs into the legacy spkm and are
362
     * simply invalid, such as a sh(sh(pkh())) script, or not watched.
363
     */
364
    std::unordered_set<CScript, SaltedSipHasher> GetNotMineScriptPubKeys() const;
365
366
    /** Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this LegacyScriptPubKeyMan.
367
     * Does not modify this ScriptPubKeyMan. */
368
    std::optional<MigrationData> MigrateToDescriptor();
369
    /** Delete all the records ofthis LegacyScriptPubKeyMan from disk*/
370
    bool DeleteRecords();
371
};
372
373
// Implements the full legacy wallet behavior
374
class LegacyScriptPubKeyMan : public LegacyDataSPKM
375
{
376
private:
377
    WalletBatch *encrypted_batch GUARDED_BY(cs_KeyStore) = nullptr;
378
379
    // By default, do not scan any block until keys/scripts are generated/imported
380
    int64_t nTimeFirstKey GUARDED_BY(cs_KeyStore) = UNKNOWN_TIME;
381
382
    //! Number of pre-generated keys/scripts (part of the look-ahead process, used to detect payments)
383
    int64_t m_keypool_size GUARDED_BY(cs_KeyStore){DEFAULT_KEYPOOL_SIZE};
384
385
    bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey) override;
386
387
    /**
388
     * Private version of AddWatchOnly method which does not accept a
389
     * timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
390
     * the watch key did not previously have a timestamp associated with it.
391
     * Because this is an inherited virtual method, it is accessible despite
392
     * being marked private, but it is marked private anyway to encourage use
393
     * of the other AddWatchOnly which accepts a timestamp and sets
394
     * nTimeFirstKey more intelligently for more efficient rescans.
395
     */
396
    bool AddWatchOnly(const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
397
    bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
398
    //! Adds a watch-only address to the store, and saves it to disk.
399
    bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
400
401
    //! Adds a key to the store, and saves it to disk.
402
    bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
403
404
    void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
405
406
    //! Adds a script to the store and saves it to disk
407
    bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
408
409
    /** Add a KeyOriginInfo to the wallet */
410
    bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
411
412
    /* HD derive new child key (on internal or external chain) */
413
    void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
414
415
    // Tracks keypool indexes to CKeyIDs of keys that have been taken out of the keypool but may be returned to it
416
    std::map<int64_t, CKeyID> m_index_to_reserved_key;
417
418
    //! Fetches a key from the keypool
419
    bool GetKeyFromPool(CPubKey &key, const OutputType type);
420
421
    /**
422
     * Reserves a key from the keypool and sets nIndex to its index
423
     *
424
     * @param[out] nIndex the index of the key in keypool
425
     * @param[out] keypool the keypool the key was drawn from, which could be the
426
     *     the pre-split pool if present, or the internal or external pool
427
     * @param fRequestedInternal true if the caller would like the key drawn
428
     *     from the internal keypool, false if external is preferred
429
     *
430
     * @return true if succeeded, false if failed due to empty keypool
431
     * @throws std::runtime_error if keypool read failed, key was invalid,
432
     *     was not found in the wallet, or was misclassified in the internal
433
     *     or external keypool
434
     */
435
    bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
436
437
    /**
438
     * Like TopUp() but adds keys for inactive HD chains.
439
     * Ensures that there are at least -keypool number of keys derived after the given index.
440
     *
441
     * @param seed_id the CKeyID for the HD seed.
442
     * @param index the index to start generating keys from
443
     * @param internal whether the internal chain should be used. true for internal chain, false for external chain.
444
     *
445
     * @return true if seed was found and keys were derived. false if unable to derive seeds
446
     */
447
    bool TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal);
448
449
    bool TopUpChain(WalletBatch& batch, CHDChain& chain, unsigned int size);
450
public:
451
0
    LegacyScriptPubKeyMan(WalletStorage& storage, int64_t keypool_size) : LegacyDataSPKM(storage), m_keypool_size(keypool_size) {}
452
453
    util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
454
455
    bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
456
457
    util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
458
    void KeepDestination(int64_t index, const OutputType& type) override;
459
    void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
460
461
    bool TopUp(unsigned int size = 0) override;
462
463
    std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
464
465
    //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
466
    void UpgradeKeyMetadata();
467
468
    bool IsHDEnabled() const override;
469
470
    bool SetupGeneration(bool force = false) override;
471
472
    bool Upgrade(int prev_version, int new_version, bilingual_str& error) override;
473
474
    bool HavePrivateKeys() const override;
475
476
    void RewriteDB() override;
477
478
    std::optional<int64_t> GetOldestKeyPoolTime() const override;
479
    size_t KeypoolCountExternalKeys() const;
480
    unsigned int GetKeyPoolSize() const override;
481
482
    int64_t GetTimeFirstKey() const override;
483
484
    std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
485
486
    bool CanGetAddresses(bool internal = false) const override;
487
488
    bool CanProvide(const CScript& script, SignatureData& sigdata) override;
489
490
    bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
491
    SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
492
    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;
493
494
    uint256 GetID() const override;
495
496
    //! Adds a key to the store, and saves it to disk.
497
    bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
498
    //! Adds an encrypted key to the store, and saves it to disk.
499
    bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
500
    void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
501
    //! Load metadata (used by LoadWallet)
502
    void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) override;
503
    void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) override;
504
    //! Generate a new key
505
    CPubKey GenerateNewKey(WalletBatch& batch, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
506
507
    /* Set the HD chain model (chain child index counters) and writes it to the database */
508
    void AddHDChain(const CHDChain& chain);
509
510
    //! Remove a watch only script from the keystore
511
    bool RemoveWatchOnly(const CScript &dest);
512
    bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
513
514
    /* SigningProvider overrides */
515
    bool AddCScript(const CScript& redeemScript) override;
516
517
    bool NewKeyPool();
518
    void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
519
520
    bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
521
    bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
522
    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);
523
    bool ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
524
525
    /* Returns true if the wallet can generate new keys */
526
    bool CanGenerateKeys() const;
527
528
    /* Generates a new HD seed (will not be activated) */
529
    CPubKey GenerateNewSeed();
530
531
    /* Derives a new HD seed (will not be activated) */
532
    CPubKey DeriveNewSeed(const CKey& key);
533
534
    /* Set the current HD seed (will reset the chain child index counters)
535
       Sets the seed's version based on the current wallet version (so the
536
       caller must ensure the current wallet version is correct before calling
537
       this function). */
538
    void SetHDSeed(const CPubKey& key);
539
540
    /**
541
     * Explicitly make the wallet learn the related scripts for outputs to the
542
     * given key. This is purely to make the wallet file compatible with older
543
     * software, as FillableSigningProvider automatically does this implicitly for all
544
     * keys now.
545
     */
546
    void LearnRelatedScripts(const CPubKey& key, OutputType);
547
548
    /**
549
     * Same as LearnRelatedScripts, but when the OutputType is not known (and could
550
     * be anything).
551
     */
552
    void LearnAllRelatedScripts(const CPubKey& key);
553
554
    /**
555
     * Marks all keys in the keypool up to and including the provided key as used.
556
     *
557
     * @param keypool_id determines the last key to mark as used
558
     *
559
     * @return All affected keys
560
     */
561
    std::vector<CKeyPool> MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
562
0
    const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
563
564
    std::set<CKeyID> GetKeys() const override;
565
};
566
567
/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr. Does not provide privkeys */
568
class LegacySigningProvider : public SigningProvider
569
{
570
private:
571
    const LegacyDataSPKM& m_spk_man;
572
public:
573
0
    explicit LegacySigningProvider(const LegacyDataSPKM& spk_man) : m_spk_man(spk_man) {}
574
575
0
    bool GetCScript(const CScriptID &scriptid, CScript& script) const override { return m_spk_man.GetCScript(scriptid, script); }
576
0
    bool HaveCScript(const CScriptID &scriptid) const override { return m_spk_man.HaveCScript(scriptid); }
577
0
    bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const override { return m_spk_man.GetPubKey(address, pubkey); }
578
0
    bool GetKey(const CKeyID &address, CKey& key) const override { return false; }
579
0
    bool HaveKey(const CKeyID &address) const override { return false; }
580
0
    bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override { return m_spk_man.GetKeyOrigin(keyid, info); }
581
};
582
583
class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
584
{
585
private:
586
    using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index
587
    using PubKeyMap = std::map<CPubKey, int32_t>; // Map of pubkeys involved in scripts to descriptor range index
588
    using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
589
    using KeyMap = std::map<CKeyID, CKey>;
590
591
    ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
592
    PubKeyMap m_map_pubkeys GUARDED_BY(cs_desc_man);
593
    int32_t m_max_cached_index = -1;
594
595
    KeyMap m_map_keys GUARDED_BY(cs_desc_man);
596
    CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man);
597
598
    //! keeps track of whether Unlock has run a thorough check before
599
    bool m_decryption_thoroughly_checked = false;
600
601
    //! Number of pre-generated keys/scripts (part of the look-ahead process, used to detect payments)
602
    int64_t m_keypool_size GUARDED_BY(cs_desc_man){DEFAULT_KEYPOOL_SIZE};
603
604
    bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
605
606
    KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
607
608
    // Cached FlatSigningProviders to avoid regenerating them each time they are needed.
609
    mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
610
    // Fetch the SigningProvider for the given script and optionally include private keys
611
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
612
    // Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
613
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CPubKey& pubkey) const;
614
    // Fetch the SigningProvider for a given index and optionally include private keys. Called by the above functions.
615
    std::unique_ptr<FlatSigningProvider> GetSigningProvider(int32_t index, bool include_private = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
616
617
protected:
618
    WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man);
619
620
    //! Same as 'TopUp' but designed for use within a batch transaction context
621
    bool TopUpWithDB(WalletBatch& batch, unsigned int size = 0);
622
623
public:
624
    DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor, int64_t keypool_size)
625
0
        :   ScriptPubKeyMan(storage),
626
0
            m_keypool_size(keypool_size),
627
0
            m_wallet_descriptor(descriptor)
628
0
        {}
629
    DescriptorScriptPubKeyMan(WalletStorage& storage, int64_t keypool_size)
630
0
        :   ScriptPubKeyMan(storage),
631
0
            m_keypool_size(keypool_size)
632
0
        {}
633
634
    mutable RecursiveMutex cs_desc_man;
635
636
    util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
637
    isminetype IsMine(const CScript& script) const override;
638
639
    bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
640
    bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
641
642
    util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
643
    void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
644
645
    // Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
646
    // and is used to expand the descriptor in GetNewDestination. DescriptorScriptPubKeyMan relies
647
    // more on ephemeral data than LegacyScriptPubKeyMan. For wallets using unhardened derivation
648
    // (with or without private keys), the "keypool" is a single xpub.
649
    bool TopUp(unsigned int size = 0) override;
650
651
    std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
652
653
    bool IsHDEnabled() const override;
654
655
    //! Setup descriptors based on the given CExtkey
656
    bool SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal);
657
658
    bool HavePrivateKeys() const override;
659
    bool HasPrivKey(const CKeyID& keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
660
    //! Retrieve the particular key if it is available. Returns nullopt if the key is not in the wallet, or if the wallet is locked.
661
    std::optional<CKey> GetKey(const CKeyID& keyid) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
662
663
    std::optional<int64_t> GetOldestKeyPoolTime() const override;
664
    unsigned int GetKeyPoolSize() const override;
665
666
    int64_t GetTimeFirstKey() const override;
667
668
    std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
669
670
    bool CanGetAddresses(bool internal = false) const override;
671
672
    std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const override;
673
674
    bool CanProvide(const CScript& script, SignatureData& sigdata) override;
675
676
    bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
677
    SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
678
    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;
679
680
    uint256 GetID() const override;
681
682
    void SetCache(const DescriptorCache& cache);
683
684
    bool AddKey(const CKeyID& key_id, const CKey& key);
685
    bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key);
686
687
    bool HasWalletDescriptor(const WalletDescriptor& desc) const;
688
    void UpdateWalletDescriptor(WalletDescriptor& descriptor);
689
    bool CanUpdateToWalletDescriptor(const WalletDescriptor& descriptor, std::string& error);
690
    void AddDescriptorKey(const CKey& key, const CPubKey &pubkey);
691
    void WriteDescriptor();
692
693
    WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
694
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
695
    std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys(int32_t minimum_index) const;
696
    int32_t GetEndRange() const;
697
698
    [[nodiscard]] bool GetDescriptorString(std::string& out, const bool priv) const;
699
700
    void UpgradeDescriptorCache();
701
};
702
703
/** struct containing information needed for migrating legacy wallets to descriptor wallets */
704
struct MigrationData
705
{
706
    CExtKey master_key;
707
    std::vector<std::pair<std::string, int64_t>> watch_descs;
708
    std::vector<std::pair<std::string, int64_t>> solvable_descs;
709
    std::vector<std::unique_ptr<DescriptorScriptPubKeyMan>> desc_spkms;
710
    std::shared_ptr<CWallet> watchonly_wallet{nullptr};
711
    std::shared_ptr<CWallet> solvable_wallet{nullptr};
712
};
713
714
} // namespace wallet
715
716
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H