LCOV - code coverage report
Current view: top level - src/script - signingprovider.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 81.4 % 43 35
Test Date: 2026-06-19 07:16:20 Functions: 66.7 % 21 14
Branches: 70.7 % 58 41

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2                 :             : // Copyright (c) 2009-present The Bitcoin Core developers
       3                 :             : // Distributed under the MIT software license, see the accompanying
       4                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5                 :             : 
       6                 :             : #ifndef BITCOIN_SCRIPT_SIGNINGPROVIDER_H
       7                 :             : #define BITCOIN_SCRIPT_SIGNINGPROVIDER_H
       8                 :             : 
       9                 :             : #include <addresstype.h>
      10                 :             : #include <attributes.h>
      11                 :             : #include <key.h>
      12                 :             : #include <pubkey.h>
      13                 :             : #include <script/keyorigin.h>
      14                 :             : #include <script/script.h>
      15                 :             : #include <sync.h>
      16                 :             : #include <uint256.h>
      17                 :             : 
      18                 :             : #include <compare>
      19                 :             : #include <cstdint>
      20                 :             : #include <functional>
      21                 :             : #include <map>
      22                 :             : #include <memory>
      23                 :             : #include <optional>
      24                 :             : #include <set>
      25                 :             : #include <span>
      26                 :             : #include <tuple>
      27                 :             : #include <utility>
      28                 :             : #include <variant>
      29                 :             : #include <vector>
      30                 :             : 
      31                 :             : class MuSig2SecNonce;
      32                 :             : 
      33                 :             : struct ShortestVectorFirstComparator
      34                 :             : {
      35                 :       38122 :     bool operator()(const std::vector<unsigned char>& a, const std::vector<unsigned char>& b) const
      36                 :             :     {
      37   [ -  +  -  +  :       38122 :         if (a.size() < b.size()) return true;
                   +  + ]
      38         [ +  + ]:       21411 :         if (a.size() > b.size()) return false;
      39                 :       19417 :         return a < b;
      40                 :             :     }
      41                 :             : };
      42                 :             : 
      43         [ +  - ]:      551108 : struct TaprootSpendData
           [ -  +  +  - ]
      44                 :             : {
      45                 :             :     /** The BIP341 internal key. */
      46                 :             :     XOnlyPubKey internal_key;
      47                 :             :     /** The Merkle root of the script tree (0 if no scripts). */
      48                 :             :     uint256 merkle_root;
      49                 :             :     /** Map from (script, leaf_version) to (sets of) control blocks.
      50                 :             :      *  More than one control block for a given script is only possible if it
      51                 :             :      *  appears in multiple branches of the tree. We keep them all so that
      52                 :             :      *  inference can reconstruct the full tree. Within each set, the control
      53                 :             :      *  blocks are sorted by size, so that the signing logic can easily
      54                 :             :      *  prefer the cheapest one. */
      55                 :             :     std::map<std::pair<std::vector<unsigned char>, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> scripts;
      56                 :             :     /** Merge other TaprootSpendData (for the same scriptPubKey) into this. */
      57                 :             :     void Merge(TaprootSpendData other);
      58                 :             : };
      59                 :             : 
      60                 :             : /** Utility class to construct Taproot outputs from internal key and script tree. */
      61         [ +  + ]:      876639 : class TaprootBuilder
      62                 :             : {
      63                 :             : private:
      64                 :             :     /** Information about a tracked leaf in the Merkle tree. */
      65                 :     1772727 :     struct LeafInfo
      66                 :             :     {
      67                 :             :         std::vector<unsigned char> script;   //!< The script.
      68                 :             :         int leaf_version;                    //!< The leaf version for that script.
      69                 :             :         std::vector<uint256> merkle_branch;  //!< The hashing partners above this leaf.
      70                 :             :     };
      71                 :             : 
      72                 :             :     /** Information associated with a node in the Merkle tree. */
      73                 :      595466 :     struct NodeInfo
      74                 :             :     {
      75                 :             :         /** Merkle hash of this node. */
      76                 :             :         uint256 hash;
      77                 :             :         /** Tracked leaves underneath this node (either from the node itself, or its children).
      78                 :             :          *  The merkle_branch field of each is the partners to get to *this* node. */
      79                 :             :         std::vector<LeafInfo> leaves;
      80                 :             :     };
      81                 :             :     /** Whether the builder is in a valid state so far. */
      82                 :             :     bool m_valid = true;
      83                 :             : 
      84                 :             :     /** The current state of the builder.
      85                 :             :      *
      86                 :             :      * For each level in the tree, one NodeInfo object may be present. m_branch[0]
      87                 :             :      * is information about the root; further values are for deeper subtrees being
      88                 :             :      * explored.
      89                 :             :      *
      90                 :             :      * For every right branch taken to reach the position we're currently
      91                 :             :      * working in, there will be a (non-nullopt) entry in m_branch corresponding
      92                 :             :      * to the left branch at that level.
      93                 :             :      *
      94                 :             :      * For example, imagine this tree:     - N0 -
      95                 :             :      *                                    /      \
      96                 :             :      *                                   N1      N2
      97                 :             :      *                                  /  \    /  \
      98                 :             :      *                                 A    B  C   N3
      99                 :             :      *                                            /  \
     100                 :             :      *                                           D    E
     101                 :             :      *
     102                 :             :      * Initially, m_branch is empty. After processing leaf A, it would become
     103                 :             :      * {nullopt, nullopt, A}. When processing leaf B, an entry at level 2 already
     104                 :             :      * exists, and it would thus be combined with it to produce a level 1 one,
     105                 :             :      * resulting in {nullopt, N1}. Adding C and D takes us to {nullopt, N1, C}
     106                 :             :      * and {nullopt, N1, C, D} respectively. When E is processed, it is combined
     107                 :             :      * with D, and then C, and then N1, to produce the root, resulting in {N0}.
     108                 :             :      *
     109                 :             :      * This structure allows processing with just O(log n) overhead if the leaves
     110                 :             :      * are computed on the fly.
     111                 :             :      *
     112                 :             :      * As an invariant, there can never be nullopt entries at the end. There can
     113                 :             :      * also not be more than 128 entries (as that would mean more than 128 levels
     114                 :             :      * in the tree). The depth of newly added entries will always be at least
     115                 :             :      * equal to the current size of m_branch (otherwise it does not correspond
     116                 :             :      * to a depth-first traversal of a tree). m_branch is only empty if no entries
     117                 :             :      * have ever be processed. m_branch having length 1 corresponds to being done.
     118                 :             :      */
     119                 :             :     std::vector<std::optional<NodeInfo>> m_branch;
     120                 :             : 
     121                 :             :     XOnlyPubKey m_internal_key;  //!< The internal key, set when finalizing.
     122                 :             :     XOnlyPubKey m_output_key;    //!< The output key, computed when finalizing.
     123                 :             :     bool m_parity;               //!< The tweak parity, computed when finalizing.
     124                 :             : 
     125                 :             :     /** Combine information about a parent Merkle tree node from its child nodes. */
     126                 :             :     static NodeInfo Combine(NodeInfo&& a, NodeInfo&& b);
     127                 :             :     /** Insert information about a node at a certain depth, and propagate information up. */
     128                 :             :     void Insert(NodeInfo&& node, int depth);
     129                 :             : 
     130                 :             : public:
     131                 :             :     /** Add a new script at a certain depth in the tree. Add() operations must be called
     132                 :             :      *  in depth-first traversal order of binary tree. If track is true, it will be included in
     133                 :             :      *  the GetSpendData() output. */
     134                 :             :     TaprootBuilder& Add(int depth, std::span<const unsigned char> script, int leaf_version, bool track = true);
     135                 :             :     /** Like Add(), but for a Merkle node with a given hash to the tree. */
     136                 :             :     TaprootBuilder& AddOmitted(int depth, const uint256& hash);
     137                 :             :     /** Finalize the construction. Can only be called when IsComplete() is true.
     138                 :             :         internal_key.IsFullyValid() must be true. */
     139                 :             :     TaprootBuilder& Finalize(const XOnlyPubKey& internal_key);
     140                 :             : 
     141                 :             :     /** Return true if so far all input was valid. */
     142   [ -  -  +  + ]:      254260 :     bool IsValid() const { return m_valid; }
     143                 :             :     /** Return whether there were either no leaves, or the leaves form a Huffman tree. */
     144   [ +  +  -  +  :      553064 :     bool IsComplete() const { return m_valid && (m_branch.size() == 0 || (m_branch.size() == 1 && m_branch[0].has_value())); }
          +  +  +  +  +  
                      - ]
     145                 :             :     /** Compute scriptPubKey (after Finalize()). */
     146                 :             :     WitnessV1Taproot GetOutput();
     147                 :             :     /** Check if a list of depths is legal (will lead to IsComplete()). */
     148                 :             :     static bool ValidDepths(const std::vector<int>& depths);
     149                 :             :     /** Compute spending data (after Finalize()). */
     150                 :             :     TaprootSpendData GetSpendData() const;
     151                 :             :     /** Returns a vector of tuples representing the depth, leaf version, and script */
     152                 :             :     std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> GetTreeTuples() const;
     153                 :             :     /** Returns true if there are any tapscripts */
     154         [ +  - ]:         216 :     bool HasScripts() const { return !m_branch.empty(); }
     155                 :             : 
     156                 :             :     bool operator==(const TaprootBuilder& other) const { return GetTreeTuples() == other.GetTreeTuples(); }
     157                 :             : };
     158                 :             : 
     159                 :             : /** Given a TaprootSpendData and the output key, reconstruct its script tree.
     160                 :             :  *
     161                 :             :  * If the output doesn't match the spenddata, or if the data in spenddata is incomplete,
     162                 :             :  * std::nullopt is returned. Otherwise, a vector of (depth, script, leaf_ver) tuples is
     163                 :             :  * returned, corresponding to a depth-first traversal of the script tree.
     164                 :             :  */
     165                 :             : std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output);
     166                 :             : 
     167                 :             : /** An interface to be implemented by keystores that support signing. */
     168                 :        9108 : class SigningProvider
     169                 :             : {
     170                 :             : public:
     171         [ +  - ]:        4192 :     virtual ~SigningProvider() = default;
     172                 :      218509 :     virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; }
     173                 :           0 :     virtual bool HaveCScript(const CScriptID &scriptid) const { return false; }
     174                 :       99134 :     virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; }
     175                 :       13745 :     virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; }
     176                 :           0 :     virtual bool HaveKey(const CKeyID &address) const { return false; }
     177                 :      254851 :     virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; }
     178                 :       25526 :     virtual bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const { return false; }
     179                 :        9844 :     virtual bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const { return false; }
     180                 :           0 :     virtual std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const { return {}; }
     181                 :        9844 :     virtual std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const {return {}; }
     182                 :           0 :     virtual void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const {}
     183                 :           0 :     virtual std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const { return std::nullopt; }
     184                 :           0 :     virtual void DeleteMuSig2Session(const uint256& session_id) const {}
     185                 :             : 
     186                 :      220543 :     bool GetKeyByXOnly(const XOnlyPubKey& pubkey, CKey& key) const
     187                 :             :     {
     188         [ +  + ]:      523405 :         for (const auto& id : pubkey.GetKeyIDs()) {
     189   [ +  -  +  + ]:      428737 :             if (GetKey(id, key)) return true;
     190                 :      125875 :         }
     191                 :       94668 :         return false;
     192                 :             :     }
     193                 :             : 
     194                 :        3141 :     bool GetPubKeyByXOnly(const XOnlyPubKey& pubkey, CPubKey& out) const
     195                 :             :     {
     196         [ +  - ]:        4842 :         for (const auto& id : pubkey.GetKeyIDs()) {
     197   [ +  -  +  + ]:        4842 :             if (GetPubKey(id, out)) return true;
     198                 :             :         }
     199                 :           0 :         return false;
     200                 :             :     }
     201                 :             : 
     202                 :      465638 :     bool GetKeyOriginByXOnly(const XOnlyPubKey& pubkey, KeyOriginInfo& info) const
     203                 :             :     {
     204         [ +  + ]:      728706 :         for (const auto& id : pubkey.GetKeyIDs()) {
     205   [ +  -  +  + ]:      691943 :             if (GetKeyOrigin(id, info)) return true;
     206                 :             :         }
     207                 :       36763 :         return false;
     208                 :             :     }
     209                 :             : };
     210                 :             : 
     211                 :             : extern const SigningProvider& DUMMY_SIGNING_PROVIDER;
     212                 :             : 
     213         [ +  + ]:        1423 : class HidingSigningProvider : public SigningProvider
     214                 :             : {
     215                 :             : private:
     216                 :             :     const bool m_hide_secret;
     217                 :             :     const bool m_hide_origin;
     218                 :             :     const SigningProvider* m_provider;
     219                 :             : 
     220                 :             : public:
     221   [ +  -  +  - ]:        1423 :     HidingSigningProvider(const SigningProvider* provider, bool hide_secret, bool hide_origin) : m_hide_secret(hide_secret), m_hide_origin(hide_origin), m_provider(provider) {}
     222                 :             :     bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
     223                 :             :     bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
     224                 :             :     bool GetKey(const CKeyID& keyid, CKey& key) const override;
     225                 :             :     bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
     226                 :             :     bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override;
     227                 :             :     bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override;
     228                 :             :     std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const override;
     229                 :             :     std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const override;
     230                 :             :     void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const override;
     231                 :             :     std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const override;
     232                 :             :     void DeleteMuSig2Session(const uint256& session_id) const override;
     233                 :             : };
     234                 :             : 
     235                 :             : struct FlatSigningProvider final : public SigningProvider
     236                 :             : {
     237                 :             :     std::map<CScriptID, CScript> scripts;
     238                 :             :     std::map<CKeyID, CPubKey> pubkeys;
     239                 :             :     std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins;
     240                 :             :     std::map<CKeyID, CKey> keys;
     241                 :             :     std::map<XOnlyPubKey, TaprootBuilder> tr_trees; /** Map from output key to Taproot tree (which can then make the TaprootSpendData */
     242                 :             :     std::map<CPubKey, std::vector<CPubKey>> aggregate_pubkeys; /** MuSig2 aggregate pubkeys */
     243                 :             :     std::map<uint256, MuSig2SecNonce>* musig2_secnonces{nullptr};
     244                 :             : 
     245                 :             :     bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
     246                 :             :     bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
     247                 :             :     bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
     248                 :             :     bool HaveKey(const CKeyID &keyid) const override;
     249                 :             :     bool GetKey(const CKeyID& keyid, CKey& key) const override;
     250                 :             :     bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override;
     251                 :             :     bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override;
     252                 :             :     std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const override;
     253                 :             :     std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const override;
     254                 :             :     void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const override;
     255                 :             :     std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const override;
     256                 :             :     void DeleteMuSig2Session(const uint256& session_id) const override;
     257                 :             : 
     258                 :             :     FlatSigningProvider& Merge(FlatSigningProvider&& b) LIFETIMEBOUND;
     259                 :             : };
     260                 :             : 
     261                 :             : /** Fillable signing provider that keeps keys in an address->secret map */
     262                 :             : class FillableSigningProvider : public SigningProvider
     263                 :             : {
     264                 :             : protected:
     265                 :             :     using KeyMap = std::map<CKeyID, CKey>;
     266                 :             :     using ScriptMap = std::map<CScriptID, CScript>;
     267                 :             : 
     268                 :             :     /**
     269                 :             :      * Map of key id to unencrypted private keys known by the signing provider.
     270                 :             :      * Map may be empty if the provider has another source of keys, like an
     271                 :             :      * encrypted store.
     272                 :             :      */
     273                 :             :     KeyMap mapKeys GUARDED_BY(cs_KeyStore);
     274                 :             : 
     275                 :             :     /**
     276                 :             :      * Map of script id to scripts known by the signing provider.
     277                 :             :      *
     278                 :             :      * This map originally just held P2SH redeemScripts, and was used by wallet
     279                 :             :      * code to look up script ids referenced in "OP_HASH160 <script id>
     280                 :             :      * OP_EQUAL" P2SH outputs. Later in 605e8473a7d it was extended to hold
     281                 :             :      * P2WSH witnessScripts as well, and used to look up nested scripts
     282                 :             :      * referenced in "OP_0 <script hash>" P2WSH outputs. Later in commits
     283                 :             :      * f4691ab3a9d and 248f3a76a82, it was extended once again to hold segwit
     284                 :             :      * "OP_0 <key or script hash>" scriptPubKeys, in order to give the wallet a
     285                 :             :      * way to distinguish between segwit outputs that it generated addresses for
     286                 :             :      * and wanted to receive payments from, and segwit outputs that it never
     287                 :             :      * generated addresses for, but it could spend just because of having keys.
     288                 :             :      * (Before segwit activation it was also important to not treat segwit
     289                 :             :      * outputs to arbitrary wallet keys as payments, because these could be
     290                 :             :      * spent by anyone without even needing to sign with the keys.)
     291                 :             :      *
     292                 :             :      * Some of the scripts stored in mapScripts are memory-only and
     293                 :             :      * intentionally not saved to disk. Specifically, scripts added by
     294                 :             :      * ImplicitlyLearnRelatedKeyScripts(pubkey) calls are not written to disk so
     295                 :             :      * future wallet code can have flexibility to be more selective about what
     296                 :             :      * transaction outputs it recognizes as payments, instead of having to treat
     297                 :             :      * all outputs spending to keys it knows as payments. By contrast,
     298                 :             :      * mapScripts entries added by AddCScript(script),
     299                 :             :      * LearnRelatedScripts(pubkey, type), and LearnAllRelatedScripts(pubkey)
     300                 :             :      * calls are saved because they are all intentionally used to receive
     301                 :             :      * payments.
     302                 :             :      *
     303                 :             :      * The FillableSigningProvider::mapScripts script map should not be confused
     304                 :             :      * with LegacyScriptPubKeyMan::setWatchOnly script set. The two collections
     305                 :             :      * can hold the same scripts, but they serve different purposes. The
     306                 :             :      * setWatchOnly script set is intended to expand the set of outputs the
     307                 :             :      * wallet considers payments. Every output with a script it contains is
     308                 :             :      * considered to belong to the wallet, regardless of whether the script is
     309                 :             :      * solvable or signable. By contrast, the scripts in mapScripts are only
     310                 :             :      * used for solving, and to restrict which outputs are considered payments
     311                 :             :      * by the wallet. An output with a script in mapScripts, unlike
     312                 :             :      * setWatchOnly, is not automatically considered to belong to the wallet if
     313                 :             :      * it can't be solved and signed for.
     314                 :             :      */
     315                 :             :     ScriptMap mapScripts GUARDED_BY(cs_KeyStore);
     316                 :             : 
     317                 :             :     void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
     318                 :             : 
     319                 :             : public:
     320                 :             :     mutable RecursiveMutex cs_KeyStore;
     321                 :             : 
     322                 :             :     virtual bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
     323                 :        6912 :     virtual bool AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); }
     324                 :             :     virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
     325                 :             :     virtual bool HaveKey(const CKeyID &address) const override;
     326                 :             :     virtual std::set<CKeyID> GetKeys() const;
     327                 :             :     virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override;
     328                 :             :     virtual bool AddCScript(const CScript& redeemScript);
     329                 :             :     virtual bool HaveCScript(const CScriptID &hash) const override;
     330                 :             :     virtual std::set<CScriptID> GetCScripts() const;
     331                 :             :     virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
     332                 :             : };
     333                 :             : 
     334                 :             : /** Return the CKeyID of the key involved in a script (if there is a unique one). */
     335                 :             : CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest);
     336                 :             : 
     337                 :             : /** A signing provider to be used to interface with multiple signing providers at once. */
     338                 :           0 : class MultiSigningProvider: public SigningProvider {
     339                 :             :     std::vector<std::unique_ptr<SigningProvider>> m_providers;
     340                 :             : 
     341                 :             : public:
     342                 :             :     void AddProvider(std::unique_ptr<SigningProvider> provider);
     343                 :             : 
     344                 :             :     bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
     345                 :             :     bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
     346                 :             :     bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
     347                 :             :     bool GetKey(const CKeyID& keyid, CKey& key) const override;
     348                 :             :     bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override;
     349                 :             :     bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override;
     350                 :             : };
     351                 :             : 
     352                 :             : #endif // BITCOIN_SCRIPT_SIGNINGPROVIDER_H
        

Generated by: LCOV version 2.0-1