scriptpubkeyman.h raw

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