LCOV - code coverage report
Current view: top level - src/test/fuzz - miniscript.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 99.1 % 753 746
Test Date: 2026-01-28 04:17:28 Functions: 100.0 % 54 54
Branches: 70.8 % 1122 794

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <core_io.h>
       6                 :             : #include <hash.h>
       7                 :             : #include <key.h>
       8                 :             : #include <script/miniscript.h>
       9                 :             : #include <script/script.h>
      10                 :             : #include <script/signingprovider.h>
      11                 :             : #include <test/fuzz/FuzzedDataProvider.h>
      12                 :             : #include <test/fuzz/fuzz.h>
      13                 :             : #include <test/fuzz/util.h>
      14                 :             : #include <test/fuzz/util/descriptor.h>
      15                 :             : #include <util/strencodings.h>
      16                 :             : 
      17                 :             : #include <algorithm>
      18                 :             : 
      19                 :             : namespace {
      20                 :             : 
      21                 :             : using Fragment = miniscript::Fragment;
      22                 :             : using NodeRef = miniscript::NodeRef<CPubKey>;
      23                 :             : using Node = miniscript::Node<CPubKey>;
      24                 :             : using Type = miniscript::Type;
      25                 :             : using MsCtx = miniscript::MiniscriptContext;
      26                 :             : using miniscript::operator""_mst;
      27                 :             : 
      28                 :             : //! Some pre-computed data for more efficient string roundtrips and to simulate challenges.
      29                 :             : struct TestData {
      30                 :             :     typedef CPubKey Key;
      31                 :             : 
      32                 :             :     // Precomputed public keys, and a dummy signature for each of them.
      33                 :             :     std::vector<Key> dummy_keys;
      34                 :             :     std::map<Key, int> dummy_key_idx_map;
      35                 :             :     std::map<CKeyID, Key> dummy_keys_map;
      36                 :             :     std::map<Key, std::pair<std::vector<unsigned char>, bool>> dummy_sigs;
      37                 :             :     std::map<XOnlyPubKey, std::pair<std::vector<unsigned char>, bool>> schnorr_sigs;
      38                 :             : 
      39                 :             :     // Precomputed hashes of each kind.
      40                 :             :     std::vector<std::vector<unsigned char>> sha256;
      41                 :             :     std::vector<std::vector<unsigned char>> ripemd160;
      42                 :             :     std::vector<std::vector<unsigned char>> hash256;
      43                 :             :     std::vector<std::vector<unsigned char>> hash160;
      44                 :             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> sha256_preimages;
      45                 :             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> ripemd160_preimages;
      46                 :             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash256_preimages;
      47                 :             :     std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash160_preimages;
      48                 :             : 
      49                 :             :     //! Set the precomputed data.
      50                 :           3 :     void Init() {
      51                 :           3 :         unsigned char keydata[32] = {1};
      52                 :             :         // All our signatures sign (and are required to sign) this constant message.
      53                 :           3 :         constexpr uint256 MESSAGE_HASH{"0000000000000000f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065"};
      54                 :             :         // We don't pass additional randomness when creating a schnorr signature.
      55                 :           3 :         const auto EMPTY_AUX{uint256::ZERO};
      56                 :             : 
      57         [ +  + ]:         771 :         for (size_t i = 0; i < 256; i++) {
      58                 :         768 :             keydata[31] = i;
      59                 :         768 :             CKey privkey;
      60         [ +  - ]:         768 :             privkey.Set(keydata, keydata + 32, true);
      61         [ +  - ]:         768 :             const Key pubkey = privkey.GetPubKey();
      62                 :             : 
      63         [ +  - ]:         768 :             dummy_keys.push_back(pubkey);
      64         [ +  - ]:         768 :             dummy_key_idx_map.emplace(pubkey, i);
      65   [ +  -  +  - ]:         768 :             dummy_keys_map.insert({pubkey.GetID(), pubkey});
      66                 :         768 :             XOnlyPubKey xonly_pubkey{pubkey};
      67         [ +  - ]:         768 :             dummy_key_idx_map.emplace(xonly_pubkey, i);
      68         [ +  - ]:         768 :             uint160 xonly_hash{Hash160(xonly_pubkey)};
      69         [ +  - ]:         768 :             dummy_keys_map.emplace(xonly_hash, pubkey);
      70                 :             : 
      71         [ +  - ]:         768 :             std::vector<unsigned char> sig, schnorr_sig(64);
      72         [ +  - ]:         768 :             privkey.Sign(MESSAGE_HASH, sig);
      73         [ +  - ]:         768 :             sig.push_back(1); // SIGHASH_ALL
      74   [ +  -  +  - ]:        1536 :             dummy_sigs.insert({pubkey, {sig, i & 1}});
      75   [ -  +  +  -  :         768 :             assert(privkey.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
                   -  + ]
      76         [ +  - ]:         768 :             schnorr_sig.push_back(1); // Maximally-sized signature has sighash byte
      77         [ +  - ]:         768 :             schnorr_sigs.emplace(XOnlyPubKey{pubkey}, std::make_pair(std::move(schnorr_sig), i & 1));
      78                 :             : 
      79                 :         768 :             std::vector<unsigned char> hash;
      80         [ +  - ]:         768 :             hash.resize(32);
      81   [ +  -  +  -  :         768 :             CSHA256().Write(keydata, 32).Finalize(hash.data());
                   +  - ]
      82         [ +  - ]:         768 :             sha256.push_back(hash);
      83   [ +  +  +  -  :         768 :             if (i & 1) sha256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
                   +  - ]
      84   [ +  -  +  -  :         768 :             CHash256().Write(keydata).Finalize(hash);
             -  +  +  - ]
      85         [ +  - ]:         768 :             hash256.push_back(hash);
      86   [ +  +  +  -  :         768 :             if (i & 1) hash256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
                   +  - ]
      87         [ +  - ]:         768 :             hash.resize(20);
      88   [ +  -  +  -  :         768 :             CRIPEMD160().Write(keydata, 32).Finalize(hash.data());
                   +  - ]
      89   [ -  +  -  + ]:         768 :             assert(hash.size() == 20);
      90         [ +  - ]:         768 :             ripemd160.push_back(hash);
      91   [ +  +  +  -  :         768 :             if (i & 1) ripemd160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
                   +  - ]
      92   [ +  -  +  -  :         768 :             CHash160().Write(keydata).Finalize(hash);
             -  +  +  - ]
      93         [ +  - ]:         768 :             hash160.push_back(hash);
      94   [ +  +  +  -  :         768 :             if (i & 1) hash160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
                   +  - ]
      95                 :         768 :         }
      96                 :           3 :     }
      97                 :             : 
      98                 :             :     //! Get the (Schnorr or ECDSA, depending on context) signature for this pubkey.
      99                 :      300054 :     const std::pair<std::vector<unsigned char>, bool>* GetSig(const MsCtx script_ctx, const Key& key) const {
     100         [ +  + ]:      300054 :         if (!miniscript::IsTapscript(script_ctx)) {
     101                 :      179880 :             const auto it = dummy_sigs.find(key);
     102         [ +  - ]:      179880 :             if (it == dummy_sigs.end()) return nullptr;
     103                 :      179880 :             return &it->second;
     104                 :             :         } else {
     105                 :      120174 :             const auto it = schnorr_sigs.find(XOnlyPubKey{key});
     106         [ +  - ]:      120174 :             if (it == schnorr_sigs.end()) return nullptr;
     107                 :      120174 :             return &it->second;
     108                 :             :         }
     109                 :             :     }
     110                 :             : } TEST_DATA;
     111                 :             : 
     112                 :             : /**
     113                 :             :  * Context to parse a Miniscript node to and from Script or text representation.
     114                 :             :  * Uses an integer (an index in the dummy keys array from the test data) as keys in order
     115                 :             :  * to focus on fuzzing the Miniscript nodes' test representation, not the key representation.
     116                 :             :  */
     117                 :             : struct ParserContext {
     118                 :             :     typedef CPubKey Key;
     119                 :             : 
     120                 :             :     const MsCtx script_ctx;
     121                 :             : 
     122                 :       11643 :     constexpr ParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
     123                 :             : 
     124                 :      819906 :     bool KeyCompare(const Key& a, const Key& b) const {
     125   [ +  +  +  +  :      819906 :         return a < b;
          -  -  -  -  -  
          -  -  -  +  +  
             +  +  +  + ]
     126                 :             :     }
     127                 :             : 
     128                 :      145043 :     std::optional<std::string> ToString(const Key& key, bool& has_priv_key) const
     129                 :             :     {
     130                 :      145043 :         has_priv_key = false;
     131                 :      145043 :         auto it = TEST_DATA.dummy_key_idx_map.find(key);
     132         [ -  + ]:      145043 :         if (it == TEST_DATA.dummy_key_idx_map.end()) {
     133                 :           0 :             return HexStr(key);
     134                 :             :         }
     135                 :      145043 :         has_priv_key = true;
     136                 :      145043 :         uint8_t idx = it->second;
     137                 :      145043 :         return HexStr(std::span{&idx, 1});
     138                 :             :     }
     139                 :             : 
     140                 :      203512 :     std::vector<unsigned char> ToPKBytes(const Key& key) const {
     141         [ +  + ]:      203512 :         if (!miniscript::IsTapscript(script_ctx)) {
     142                 :      122242 :             return {key.begin(), key.end()};
     143                 :             :         }
     144                 :       81270 :         const XOnlyPubKey xonly_pubkey{key};
     145                 :       81270 :         return {xonly_pubkey.begin(), xonly_pubkey.end()};
     146                 :             :     }
     147                 :             : 
     148                 :       19513 :     std::vector<unsigned char> ToPKHBytes(const Key& key) const {
     149         [ +  + ]:       19513 :         if (!miniscript::IsTapscript(script_ctx)) {
     150                 :       10621 :             const auto h = Hash160(key);
     151                 :       10621 :             return {h.begin(), h.end()};
     152                 :             :         }
     153                 :        8892 :         const auto h = Hash160(XOnlyPubKey{key});
     154                 :        8892 :         return {h.begin(), h.end()};
     155                 :             :     }
     156                 :             : 
     157                 :             :     template<typename I>
     158         [ +  + ]:      154355 :     std::optional<Key> FromString(I first, I last) const {
     159         [ +  + ]:      154355 :         if (last - first != 2) return {};
     160   [ -  +  +  -  :      308696 :         auto idx = ParseHex(std::string(first, last));
                   -  + ]
     161         [ +  + ]:      154348 :         if (idx.size() != 1) return {};
     162                 :      154327 :         return TEST_DATA.dummy_keys[idx[0]];
     163                 :      154348 :     }
     164                 :             : 
     165                 :             :     template<typename I>
     166                 :       90454 :     std::optional<Key> FromPKBytes(I first, I last) const {
     167         [ +  + ]:       90454 :         if (!miniscript::IsTapscript(script_ctx)) {
     168         [ +  - ]:       54773 :             Key key{first, last};
     169         [ +  - ]:       54773 :             if (key.IsValid()) return key;
     170                 :           0 :             return {};
     171                 :             :         }
     172         [ -  + ]:       35681 :         if (last - first != 32) return {};
     173                 :       35681 :         XOnlyPubKey xonly_pubkey;
     174                 :       35681 :         std::copy(first, last, xonly_pubkey.begin());
     175                 :       35681 :         return xonly_pubkey.GetEvenCorrespondingCPubKey();
     176                 :             :     }
     177                 :             : 
     178                 :             :     template<typename I>
     179         [ -  + ]:        9564 :     std::optional<Key> FromPKHBytes(I first, I last) const {
     180         [ -  + ]:        9564 :         assert(last - first == 20);
     181                 :        9564 :         CKeyID keyid;
     182                 :        9564 :         std::copy(first, last, keyid.begin());
     183         [ -  + ]:        9564 :         const auto it = TEST_DATA.dummy_keys_map.find(keyid);
     184         [ -  + ]:        9564 :         if (it == TEST_DATA.dummy_keys_map.end()) return {};
     185                 :        9564 :         return it->second;
     186                 :             :     }
     187                 :             : 
     188                 :     1978158 :     MsCtx MsContext() const {
     189   [ +  -  +  -  :     1978158 :         return script_ctx;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  +  +  
                -  +  - ]
     190                 :             :     }
     191                 :             : };
     192                 :             : 
     193                 :             : //! Context that implements naive conversion from/to script only, for roundtrip testing.
     194                 :             : struct ScriptParserContext {
     195                 :             :     const MsCtx script_ctx;
     196                 :             : 
     197                 :        1204 :     constexpr ScriptParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
     198                 :             : 
     199                 :             :     //! For Script roundtrip we never need the key from a key hash.
     200         [ +  - ]:       56987 :     struct Key {
     201                 :             :         bool is_hash;
     202                 :             :         std::vector<unsigned char> data;
     203                 :             :     };
     204                 :             : 
     205                 :       24498 :     bool KeyCompare(const Key& a, const Key& b) const {
     206   [ +  +  +  +  :       24498 :         return a.data < b.data;
          -  -  -  -  -  
          -  -  -  +  +  
             +  +  +  + ]
     207                 :             :     }
     208                 :             : 
     209                 :        1301 :     const std::vector<unsigned char>& ToPKBytes(const Key& key) const
     210                 :             :     {
     211         [ -  + ]:        1301 :         assert(!key.is_hash);
     212                 :        1301 :         return key.data;
     213                 :             :     }
     214                 :             : 
     215                 :         693 :     std::vector<unsigned char> ToPKHBytes(const Key& key) const
     216                 :             :     {
     217         [ +  - ]:         693 :         if (key.is_hash) return key.data;
     218                 :           0 :         const auto h = Hash160(key.data);
     219                 :           0 :         return {h.begin(), h.end()};
     220                 :             :     }
     221                 :             : 
     222                 :             :     template<typename I>
     223         [ +  - ]:        6057 :     std::optional<Key> FromPKBytes(I first, I last) const
     224                 :             :     {
     225         [ +  - ]:        6057 :         Key key;
     226                 :        6057 :         key.data.assign(first, last);
     227                 :        6057 :         key.is_hash = false;
     228                 :        6057 :         return key;
     229                 :        6057 :     }
     230                 :             : 
     231                 :             :     template<typename I>
     232         [ +  - ]:        5416 :     std::optional<Key> FromPKHBytes(I first, I last) const
     233                 :             :     {
     234         [ +  - ]:        5416 :         Key key;
     235                 :        5416 :         key.data.assign(first, last);
     236                 :        5416 :         key.is_hash = true;
     237                 :        5416 :         return key;
     238                 :        5416 :     }
     239                 :             : 
     240                 :     5682861 :     MsCtx MsContext() const {
     241   [ +  -  +  -  :     5682861 :         return script_ctx;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     242                 :             :     }
     243                 :             : };
     244                 :             : 
     245                 :             : //! Context to produce a satisfaction for a Miniscript node using the pre-computed data.
     246                 :             : struct SatisfierContext : ParserContext {
     247                 :             : 
     248                 :        5018 :     constexpr SatisfierContext(MsCtx ctx) noexcept : ParserContext(ctx) {}
     249                 :             : 
     250                 :             :     // Timelock challenges satisfaction. Make the value (deterministically) vary to explore different
     251                 :             :     // paths.
     252         [ +  + ]:        9990 :     bool CheckAfter(uint32_t value) const { return value % 2; }
     253         [ +  + ]:       11278 :     bool CheckOlder(uint32_t value) const { return value % 2; }
     254                 :             : 
     255                 :             :     // Signature challenges fulfilled with a dummy signature, if it was one of our dummy keys.
     256                 :      200036 :     miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
     257                 :      200036 :         bool sig_available{false};
     258         [ +  - ]:      200036 :         if (auto res = TEST_DATA.GetSig(script_ctx, key)) {
     259                 :      200036 :             std::tie(sig, sig_available) = *res;
     260                 :             :         }
     261         [ +  + ]:      200036 :         return sig_available ? miniscript::Availability::YES : miniscript::Availability::NO;
     262                 :             :     }
     263                 :             : 
     264                 :             :     //! Lookup generalization for all the hash satisfactions below
     265                 :       33592 :     miniscript::Availability LookupHash(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage,
     266                 :             :                                         const std::map<std::vector<unsigned char>, std::vector<unsigned char>>& map) const
     267                 :             :     {
     268                 :       33592 :         const auto it = map.find(hash);
     269         [ +  + ]:       33592 :         if (it == map.end()) return miniscript::Availability::NO;
     270                 :       20948 :         preimage = it->second;
     271                 :       20948 :         return miniscript::Availability::YES;
     272                 :             :     }
     273                 :        7982 :     miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
     274         [ +  - ]:        7982 :         return LookupHash(hash, preimage, TEST_DATA.sha256_preimages);
     275                 :             :     }
     276                 :        8370 :     miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
     277         [ +  - ]:        8370 :         return LookupHash(hash, preimage, TEST_DATA.ripemd160_preimages);
     278                 :             :     }
     279                 :        9110 :     miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
     280         [ +  - ]:        9110 :         return LookupHash(hash, preimage, TEST_DATA.hash256_preimages);
     281                 :             :     }
     282                 :        8130 :     miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
     283         [ +  - ]:        8130 :         return LookupHash(hash, preimage, TEST_DATA.hash160_preimages);
     284                 :             :     }
     285                 :             : };
     286                 :             : 
     287                 :             : //! Context to check a satisfaction against the pre-computed data.
     288                 :             : const struct CheckerContext: BaseSignatureChecker {
     289                 :             :     // Signature checker methods. Checks the right dummy signature is used.
     290                 :       34760 :     bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& vchPubKey,
     291                 :             :                              const CScript& scriptCode, SigVersion sigversion) const override
     292                 :             :     {
     293         [ -  + ]:       34760 :         const CPubKey key{vchPubKey};
     294                 :       34760 :         const auto it = TEST_DATA.dummy_sigs.find(key);
     295         [ +  - ]:       34760 :         if (it == TEST_DATA.dummy_sigs.end()) return false;
     296                 :       34760 :         return it->second.first == sig;
     297                 :             :     }
     298                 :       12019 :     bool CheckSchnorrSignature(std::span<const unsigned char> sig, std::span<const unsigned char> pubkey, SigVersion,
     299                 :             :                                ScriptExecutionData&, ScriptError*) const override {
     300                 :       12019 :         XOnlyPubKey pk{pubkey};
     301                 :       12019 :         auto it = TEST_DATA.schnorr_sigs.find(pk);
     302         [ +  - ]:       12019 :         if (it == TEST_DATA.schnorr_sigs.end()) return false;
     303                 :       12019 :         return std::ranges::equal(it->second.first, sig);
     304                 :             :     }
     305                 :        1749 :     bool CheckLockTime(const CScriptNum& nLockTime) const override { return nLockTime.GetInt64() & 1; }
     306                 :        2683 :     bool CheckSequence(const CScriptNum& nSequence) const override { return nSequence.GetInt64() & 1; }
     307                 :             : } CHECKER_CTX;
     308                 :             : 
     309                 :             : //! Context to check for duplicates when instancing a Node.
     310                 :             : const struct KeyComparator {
     311                 :      325568 :     bool KeyCompare(const CPubKey& a, const CPubKey& b) const {
     312   [ +  +  +  +  :      325568 :         return a < b;
          -  -  -  -  -  
          -  -  -  +  +  
             +  +  +  + ]
     313                 :             :     }
     314                 :             : } KEY_COMP;
     315                 :             : 
     316                 :             : // A dummy scriptsig to pass to VerifyScript (we always use Segwit v0).
     317                 :             : const CScript DUMMY_SCRIPTSIG;
     318                 :             : 
     319                 :             : //! Construct a miniscript node as a shared_ptr.
     320                 :      434366 : template<typename... Args> NodeRef MakeNodeRef(Args&&... args) {
     321                 :      434366 :     return miniscript::MakeNodeRef<CPubKey>(miniscript::internal::NoDupCheck{}, std::forward<Args>(args)...);
     322                 :             : }
     323                 :             : 
     324                 :             : /** Information about a yet to be constructed Miniscript node. */
     325                 :             : struct NodeInfo {
     326                 :             :     //! The type of this node
     327                 :             :     Fragment fragment;
     328                 :             :     //! The timelock value for older() and after(), the threshold value for multi() and thresh()
     329                 :             :     uint32_t k;
     330                 :             :     //! Keys for this node, if it has some
     331                 :             :     std::vector<CPubKey> keys;
     332                 :             :     //! The hash value for this node, if it has one
     333                 :             :     std::vector<unsigned char> hash;
     334                 :             :     //! The type requirements for the children of this node.
     335                 :             :     std::vector<Type> subtypes;
     336                 :             : 
     337                 :       50144 :     NodeInfo(Fragment frag): fragment(frag), k(0) {}
     338                 :       29977 :     NodeInfo(Fragment frag, CPubKey key): fragment(frag), k(0), keys({key}) {}
     339                 :        8407 :     NodeInfo(Fragment frag, uint32_t _k): fragment(frag), k(_k) {}
     340                 :       18921 :     NodeInfo(Fragment frag, std::vector<unsigned char> h): fragment(frag), k(0), hash(std::move(h)) {}
     341                 :      149341 :     NodeInfo(std::vector<Type> subt, Fragment frag): fragment(frag), k(0), subtypes(std::move(subt)) {}
     342                 :       14584 :     NodeInfo(std::vector<Type> subt, Fragment frag, uint32_t _k): fragment(frag), k(_k), subtypes(std::move(subt))  {}
     343                 :       13151 :     NodeInfo(Fragment frag, uint32_t _k, std::vector<CPubKey> _keys): fragment(frag), k(_k), keys(std::move(_keys)) {}
     344                 :             : };
     345                 :             : 
     346                 :             : /** Pick an index in a collection from a single byte in the fuzzer's output. */
     347                 :             : template<typename T, typename A>
     348                 :      138301 : T ConsumeIndex(FuzzedDataProvider& provider, A& col) {
     349                 :      138301 :     const uint8_t i = provider.ConsumeIntegral<uint8_t>();
     350                 :      138301 :     return col[i];
     351                 :             : }
     352                 :             : 
     353                 :      127287 : CPubKey ConsumePubKey(FuzzedDataProvider& provider) {
     354                 :      127287 :     return ConsumeIndex<CPubKey>(provider, TEST_DATA.dummy_keys);
     355                 :             : }
     356                 :             : 
     357                 :        2443 : std::vector<unsigned char> ConsumeSha256(FuzzedDataProvider& provider) {
     358                 :        2443 :     return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.sha256);
     359                 :             : }
     360                 :             : 
     361                 :        3081 : std::vector<unsigned char> ConsumeHash256(FuzzedDataProvider& provider) {
     362                 :        3081 :     return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash256);
     363                 :             : }
     364                 :             : 
     365                 :        2807 : std::vector<unsigned char> ConsumeRipemd160(FuzzedDataProvider& provider) {
     366                 :        2807 :     return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.ripemd160);
     367                 :             : }
     368                 :             : 
     369                 :        2683 : std::vector<unsigned char> ConsumeHash160(FuzzedDataProvider& provider) {
     370                 :        2683 :     return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash160);
     371                 :             : }
     372                 :             : 
     373                 :        8445 : std::optional<uint32_t> ConsumeTimeLock(FuzzedDataProvider& provider) {
     374                 :        8445 :     const uint32_t k = provider.ConsumeIntegral<uint32_t>();
     375         [ +  + ]:        8445 :     if (k == 0 || k >= 0x80000000) return {};
     376                 :        8407 :     return k;
     377                 :             : }
     378                 :             : 
     379                 :             : /**
     380                 :             :  * Consume a Miniscript node from the fuzzer's output.
     381                 :             :  *
     382                 :             :  * This version is intended to have a fixed, stable, encoding for Miniscript nodes:
     383                 :             :  *  - The first byte sets the type of the fragment. 0, 1 and all non-leaf fragments but thresh() are a
     384                 :             :  *    single byte.
     385                 :             :  *  - For the other leaf fragments, the following bytes depend on their type.
     386                 :             :  *    - For older() and after(), the next 4 bytes define the timelock value.
     387                 :             :  *    - For pk_k(), pk_h(), and all hashes, the next byte defines the index of the value in the test data.
     388                 :             :  *    - For multi(), the next 2 bytes define respectively the threshold and the number of keys. Then as many
     389                 :             :  *      bytes as the number of keys define the index of each key in the test data.
     390                 :             :  *    - For multi_a(), same as for multi() but the threshold and the keys count are encoded on two bytes.
     391                 :             :  *    - For thresh(), the next byte defines the threshold value and the following one the number of subs.
     392                 :             :  */
     393                 :      247956 : std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx, FuzzedDataProvider& provider, Type type_needed) {
     394   [ +  +  +  + ]:      247956 :     bool allow_B = (type_needed == ""_mst) || (type_needed << "B"_mst);
     395   [ +  +  +  + ]:      247956 :     bool allow_K = (type_needed == ""_mst) || (type_needed << "K"_mst);
     396   [ +  +  +  + ]:      247956 :     bool allow_V = (type_needed == ""_mst) || (type_needed << "V"_mst);
     397   [ +  +  +  + ]:      247956 :     bool allow_W = (type_needed == ""_mst) || (type_needed << "W"_mst);
     398                 :             : 
     399   [ +  +  +  +  :      247956 :     switch (provider.ConsumeIntegral<uint8_t>()) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  + ]
     400                 :       36952 :         case 0:
     401         [ +  + ]:       36952 :             if (!allow_B) return {};
     402                 :       36866 :             return {{Fragment::JUST_0}};
     403                 :       13288 :         case 1:
     404         [ +  + ]:       13288 :             if (!allow_B) return {};
     405                 :       13278 :             return {{Fragment::JUST_1}};
     406                 :        8872 :         case 2:
     407         [ +  + ]:        8872 :             if (!allow_K) return {};
     408                 :        8865 :             return {{Fragment::PK_K, ConsumePubKey(provider)}};
     409                 :        5762 :         case 3:
     410         [ +  + ]:        5762 :             if (!allow_K) return {};
     411                 :        5750 :             return {{Fragment::PK_H, ConsumePubKey(provider)}};
     412                 :        4513 :         case 4: {
     413         [ +  + ]:        4513 :             if (!allow_B) return {};
     414                 :        4504 :             const auto k = ConsumeTimeLock(provider);
     415         [ +  + ]:        4504 :             if (!k) return {};
     416                 :        4482 :             return {{Fragment::OLDER, *k}};
     417                 :             :         }
     418                 :        3947 :         case 5: {
     419         [ +  + ]:        3947 :             if (!allow_B) return {};
     420                 :        3941 :             const auto k = ConsumeTimeLock(provider);
     421         [ +  + ]:        3941 :             if (!k) return {};
     422                 :        3925 :             return {{Fragment::AFTER, *k}};
     423                 :             :         }
     424                 :        2449 :         case 6:
     425         [ +  + ]:        2449 :             if (!allow_B) return {};
     426                 :        2443 :             return {{Fragment::SHA256, ConsumeSha256(provider)}};
     427                 :        3087 :         case 7:
     428         [ +  + ]:        3087 :             if (!allow_B) return {};
     429                 :        3081 :             return {{Fragment::HASH256, ConsumeHash256(provider)}};
     430                 :        2810 :         case 8:
     431         [ +  + ]:        2810 :             if (!allow_B) return {};
     432                 :        2807 :             return {{Fragment::RIPEMD160, ConsumeRipemd160(provider)}};
     433                 :        2686 :         case 9:
     434         [ +  + ]:        2686 :             if (!allow_B) return {};
     435                 :        2683 :             return {{Fragment::HASH160, ConsumeHash160(provider)}};
     436                 :        6022 :         case 10: {
     437   [ +  +  +  + ]:        6022 :             if (!allow_B || IsTapscript(script_ctx)) return {};
     438                 :        5099 :             const auto k = provider.ConsumeIntegral<uint8_t>();
     439                 :        5099 :             const auto n_keys = provider.ConsumeIntegral<uint8_t>();
     440   [ +  +  +  + ]:        5099 :             if (n_keys > 20 || k == 0 || k > n_keys) return {};
     441                 :        5089 :             std::vector<CPubKey> keys{n_keys};
     442         [ +  + ]:       29256 :             for (auto& key: keys) key = ConsumePubKey(provider);
     443                 :        5089 :             return {{Fragment::MULTI, k, std::move(keys)}};
     444                 :        5089 :         }
     445                 :       11537 :         case 11:
     446   [ +  +  +  + ]:       11537 :             if (!(allow_B || allow_K || allow_V)) return {};
     447                 :       11534 :             return {{{"B"_mst, type_needed, type_needed}, Fragment::ANDOR}};
     448                 :       27988 :         case 12:
     449   [ +  +  +  + ]:       27988 :             if (!(allow_B || allow_K || allow_V)) return {};
     450                 :       27983 :             return {{{"V"_mst, type_needed}, Fragment::AND_V}};
     451                 :        6559 :         case 13:
     452         [ +  + ]:        6559 :             if (!allow_B) return {};
     453                 :        6555 :             return {{{"B"_mst, "W"_mst}, Fragment::AND_B}};
     454                 :        4519 :         case 15:
     455         [ +  + ]:        4519 :             if (!allow_B) return {};
     456                 :        4514 :             return {{{"B"_mst, "W"_mst}, Fragment::OR_B}};
     457                 :        3088 :         case 16:
     458         [ +  + ]:        3088 :             if (!allow_V) return {};
     459                 :        3080 :             return {{{"B"_mst, "V"_mst}, Fragment::OR_C}};
     460                 :        8271 :         case 17:
     461         [ +  + ]:        8271 :             if (!allow_B) return {};
     462                 :        8266 :             return {{{"B"_mst, "B"_mst}, Fragment::OR_D}};
     463                 :       16437 :         case 18:
     464   [ +  +  +  + ]:       16437 :             if (!(allow_B || allow_K || allow_V)) return {};
     465                 :       16428 :             return {{{type_needed, type_needed}, Fragment::OR_I}};
     466                 :        6557 :         case 19: {
     467         [ +  + ]:        6557 :             if (!allow_B) return {};
     468                 :        6548 :             auto k = provider.ConsumeIntegral<uint8_t>();
     469                 :        6548 :             auto n_subs = provider.ConsumeIntegral<uint8_t>();
     470         [ +  + ]:        6548 :             if (k == 0 || k > n_subs) return {};
     471                 :        6524 :             std::vector<Type> subtypes;
     472         [ +  - ]:        6524 :             subtypes.reserve(n_subs);
     473         [ +  - ]:        6524 :             subtypes.emplace_back("B"_mst);
     474   [ +  -  +  + ]:       27440 :             for (size_t i = 1; i < n_subs; ++i) subtypes.emplace_back("W"_mst);
     475                 :        6524 :             return {{std::move(subtypes), Fragment::THRESH, k}};
     476                 :        6524 :         }
     477                 :       16662 :         case 20:
     478         [ +  + ]:       16662 :             if (!allow_W) return {};
     479                 :       16654 :             return {{{"B"_mst}, Fragment::WRAP_A}};
     480                 :        1578 :         case 21:
     481         [ +  + ]:        1578 :             if (!allow_W) return {};
     482                 :        1572 :             return {{{"B"_mst}, Fragment::WRAP_S}};
     483                 :       11703 :         case 22:
     484         [ +  + ]:       11703 :             if (!allow_B) return {};
     485                 :       11696 :             return {{{"K"_mst}, Fragment::WRAP_C}};
     486                 :        1196 :         case 23:
     487         [ +  + ]:        1196 :             if (!allow_B) return {};
     488                 :        1193 :             return {{{"V"_mst}, Fragment::WRAP_D}};
     489                 :       28226 :         case 24:
     490         [ +  + ]:       28226 :             if (!allow_V) return {};
     491                 :       28219 :             return {{{"B"_mst}, Fragment::WRAP_V}};
     492                 :        2650 :         case 25:
     493         [ +  + ]:        2650 :             if (!allow_B) return {};
     494                 :        2643 :             return {{{"B"_mst}, Fragment::WRAP_J}};
     495                 :        9010 :         case 26:
     496         [ +  + ]:        9010 :             if (!allow_B) return {};
     497                 :        9004 :             return {{{"B"_mst}, Fragment::WRAP_N}};
     498                 :        1563 :         case 27: {
     499   [ +  +  +  + ]:        1563 :             if (!allow_B || !IsTapscript(script_ctx)) return {};
     500                 :        1285 :             const auto k = provider.ConsumeIntegral<uint16_t>();
     501                 :        1285 :             const auto n_keys = provider.ConsumeIntegral<uint16_t>();
     502   [ +  +  +  + ]:        1285 :             if (n_keys > 999 || k == 0 || k > n_keys) return {};
     503                 :        1276 :             std::vector<CPubKey> keys{n_keys};
     504         [ +  + ]:       21471 :             for (auto& key: keys) key = ConsumePubKey(provider);
     505                 :        1276 :             return {{Fragment::MULTI_A, k, std::move(keys)}};
     506                 :        1276 :         }
     507                 :          24 :         default:
     508                 :          24 :             break;
     509                 :             :     }
     510                 :          24 :     return {};
     511                 :             : }
     512                 :             : 
     513                 :             : /* This structure contains a table which for each "target" Type a list of recipes
     514                 :             :  * to construct it, automatically inferred from the behavior of ComputeType.
     515                 :             :  * Note that the Types here are not the final types of the constructed Nodes, but
     516                 :             :  * just the subset that are required. For example, a recipe for the "Bo" type
     517                 :             :  * might construct a "Bondu" sha256() NodeInfo, but cannot construct a "Bz" older().
     518                 :             :  * Each recipe is a Fragment together with a list of required types for its subnodes.
     519                 :             :  */
     520                 :             : struct SmartInfo
     521                 :             : {
     522                 :             :     using recipe = std::pair<Fragment, std::vector<Type>>;
     523                 :             :     std::map<Type, std::vector<recipe>> wsh_table, tap_table;
     524                 :             : 
     525                 :           1 :     void Init()
     526                 :             :     {
     527                 :           1 :         Init(wsh_table, MsCtx::P2WSH);
     528                 :           1 :         Init(tap_table, MsCtx::TAPSCRIPT);
     529                 :           1 :     }
     530                 :             : 
     531                 :           2 :     void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)
     532                 :             :     {
     533                 :             :         /* Construct a set of interesting type requirements to reason with (sections of BKVWzondu). */
     534                 :           2 :         std::vector<Type> types;
     535         [ +  + ]:          10 :         for (int base = 0; base < 4; ++base) { /* select from B,K,V,W */
     536   [ +  +  +  +  :           8 :             Type type_base = base == 0 ? "B"_mst : base == 1 ? "K"_mst : base == 2 ? "V"_mst : "W"_mst;
                   +  + ]
     537         [ +  + ]:          32 :             for (int zo = 0; zo < 3; ++zo) { /* select from z,o,(none) */
     538   [ +  +  +  + ]:          24 :                 Type type_zo = zo == 0 ? "z"_mst : zo == 1 ? "o"_mst : ""_mst;
     539         [ +  + ]:          72 :                 for (int n = 0; n < 2; ++n) { /* select from (none),n */
     540         [ +  + ]:          48 :                     if (zo == 0 && n == 1) continue; /* z conflicts with n */
     541         [ +  + ]:          40 :                     if (base == 3 && n == 1) continue; /* W conflicts with n */
     542         [ +  + ]:          36 :                     Type type_n = n == 0 ? ""_mst : "n"_mst;
     543         [ +  + ]:         108 :                     for (int d = 0; d < 2; ++d) { /* select from (none),d */
     544         [ +  + ]:          72 :                         if (base == 2 && d == 1) continue; /* V conflicts with d */
     545         [ +  + ]:          62 :                         Type type_d = d == 0 ? ""_mst : "d"_mst;
     546         [ +  + ]:         186 :                         for (int u = 0; u < 2; ++u) { /* select from (none),u */
     547         [ +  + ]:         124 :                             if (base == 2 && u == 1) continue; /* V conflicts with u */
     548         [ +  + ]:         114 :                             Type type_u = u == 0 ? ""_mst : "u"_mst;
     549         [ +  - ]:         114 :                             Type type = type_base | type_zo | type_n | type_d | type_u;
     550         [ +  - ]:         114 :                             types.push_back(type);
     551                 :             :                         }
     552                 :             :                     }
     553                 :             :                 }
     554                 :             :             }
     555                 :             :         }
     556                 :             : 
     557                 :             :         /* We define a recipe a to be a super-recipe of recipe b if they use the same
     558                 :             :          * fragment, the same number of subexpressions, and each of a's subexpression
     559                 :             :          * types is a supertype of the corresponding subexpression type of b.
     560                 :             :          * Within the set of recipes for the construction of a given type requirement,
     561                 :             :          * no recipe should be a super-recipe of another (as the super-recipe is
     562                 :             :          * applicable in every place the sub-recipe is, the sub-recipe is redundant). */
     563                 :      260828 :         auto is_super_of = [](const recipe& a, const recipe& b) {
     564         [ +  + ]:      260826 :             if (a.first != b.first) return false;
     565   [ -  +  -  +  :       26260 :             if (a.second.size() != b.second.size()) return false;
                   +  + ]
     566         [ +  + ]:       91420 :             for (size_t i = 0; i < a.second.size(); ++i) {
     567         [ +  + ]:       66654 :                 if (!(b.second[i] << a.second[i])) return false;
     568                 :             :             }
     569                 :             :             return true;
     570                 :             :         };
     571                 :             : 
     572                 :             :         /* Sort the type requirements. Subtypes will always sort later (e.g. Bondu will
     573                 :             :          * sort after Bo or Bu). As we'll be constructing recipes using these types, in
     574                 :             :          * order, in what follows, we'll construct super-recipes before sub-recipes.
     575                 :             :          * That means we never need to go back and delete a sub-recipe because a
     576                 :             :          * super-recipe got added. */
     577                 :           2 :         std::sort(types.begin(), types.end());
     578                 :             : 
     579                 :             :         // Iterate over all possible fragments.
     580         [ +  + ]:          56 :         for (int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
     581                 :          54 :             int sub_count = 0; //!< The minimum number of child nodes this recipe has.
     582                 :          54 :             int sub_range = 1; //!< The maximum number of child nodes for this recipe is sub_count+sub_range-1.
     583                 :          54 :             size_t data_size = 0;
     584                 :          54 :             size_t n_keys = 0;
     585                 :          54 :             uint32_t k = 0;
     586                 :          54 :             Fragment frag{fragidx};
     587                 :             : 
     588                 :             :             // Only produce recipes valid in the given context.
     589         [ +  + ]:          81 :             if ((!miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI_A)
     590   [ +  +  +  +  :          80 :                 || (miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI)) {
                   +  + ]
     591                 :           2 :                 continue;
     592                 :             :             }
     593                 :             : 
     594                 :             :             // Based on the fragment, determine #subs/data/k/keys to pass to ComputeType. */
     595   [ +  +  +  +  :          52 :             switch (frag) {
          +  +  +  +  +  
                      + ]
     596                 :           4 :                 case Fragment::PK_K:
     597                 :           4 :                 case Fragment::PK_H:
     598                 :           4 :                     n_keys = 1;
     599                 :           4 :                     break;
     600                 :           2 :                 case Fragment::MULTI:
     601                 :           2 :                 case Fragment::MULTI_A:
     602                 :           2 :                     n_keys = 1;
     603                 :           2 :                     k = 1;
     604                 :           2 :                     break;
     605                 :           4 :                 case Fragment::OLDER:
     606                 :           4 :                 case Fragment::AFTER:
     607                 :           4 :                     k = 1;
     608                 :           4 :                     break;
     609                 :           4 :                 case Fragment::SHA256:
     610                 :           4 :                 case Fragment::HASH256:
     611                 :           4 :                     data_size = 32;
     612                 :           4 :                     break;
     613                 :           4 :                 case Fragment::RIPEMD160:
     614                 :           4 :                 case Fragment::HASH160:
     615                 :           4 :                     data_size = 20;
     616                 :           4 :                     break;
     617                 :             :                 case Fragment::JUST_0:
     618                 :             :                 case Fragment::JUST_1:
     619                 :             :                     break;
     620                 :          14 :                 case Fragment::WRAP_A:
     621                 :          14 :                 case Fragment::WRAP_S:
     622                 :          14 :                 case Fragment::WRAP_C:
     623                 :          14 :                 case Fragment::WRAP_D:
     624                 :          14 :                 case Fragment::WRAP_V:
     625                 :          14 :                 case Fragment::WRAP_J:
     626                 :          14 :                 case Fragment::WRAP_N:
     627                 :          14 :                     sub_count = 1;
     628                 :          14 :                     break;
     629                 :          12 :                 case Fragment::AND_V:
     630                 :          12 :                 case Fragment::AND_B:
     631                 :          12 :                 case Fragment::OR_B:
     632                 :          12 :                 case Fragment::OR_C:
     633                 :          12 :                 case Fragment::OR_D:
     634                 :          12 :                 case Fragment::OR_I:
     635                 :          12 :                     sub_count = 2;
     636                 :          12 :                     break;
     637                 :           2 :                 case Fragment::ANDOR:
     638                 :           2 :                     sub_count = 3;
     639                 :           2 :                     break;
     640                 :           2 :                 case Fragment::THRESH:
     641                 :             :                     // Thresh logic is executed for 1 and 2 arguments. Larger numbers use ad-hoc code to extend.
     642                 :           2 :                     sub_count = 1;
     643                 :           2 :                     sub_range = 2;
     644                 :           2 :                     k = 1;
     645                 :           2 :                     break;
     646                 :             :             }
     647                 :             : 
     648                 :             :             // Iterate over the number of subnodes (sub_count...sub_count+sub_range-1).
     649                 :          52 :             std::vector<Type> subt;
     650         [ +  + ]:         106 :             for (int subs = sub_count; subs < sub_count + sub_range; ++subs) {
     651                 :             :                 // Iterate over the possible subnode types (at most 3).
     652         [ +  + ]:        1878 :                 for (Type x : types) {
     653         [ +  + ]:       53830 :                     for (Type y : types) {
     654         [ +  + ]:     2886502 :                         for (Type z : types) {
     655                 :             :                             // Compute the resulting type of a node with the selected fragment / subnode types.
     656         [ +  + ]:     2836790 :                             subt.clear();
     657   [ +  +  +  - ]:     2836790 :                             if (subs > 0) subt.push_back(x);
     658   [ +  +  +  - ]:     2836768 :                             if (subs > 1) subt.push_back(y);
     659   [ +  +  +  - ]:     2796208 :                             if (subs > 2) subt.push_back(z);
     660         [ +  - ]:     2836790 :                             Type res = miniscript::internal::ComputeType(frag, x, y, z, subt, k, data_size, subs, n_keys, script_ctx);
     661                 :             :                             // Continue if the result is not a valid node.
     662         [ +  + ]:     2836790 :                             if ((res << "K"_mst) + (res << "V"_mst) + (res << "B"_mst) + (res << "W"_mst) != 1) continue;
     663                 :             : 
     664         [ +  - ]:       11456 :                             recipe entry{frag, subt};
     665         [ +  + ]:      260826 :                             auto super_of_entry = [&](const recipe& rec) { return is_super_of(rec, entry); };
     666                 :             :                             // Iterate over all supertypes of res (because if e.g. our selected fragment/subnodes result
     667                 :             :                             // in a Bondu, they can form a recipe that is also applicable for constructing a B, Bou, Bdu, ...).
     668         [ +  + ]:      664448 :                             for (Type s : types) {
     669         [ +  + ]:      652992 :                                 if ((res & "BKVWzondu"_mst) << s) {
     670         [ +  - ]:       25510 :                                     auto& recipes = table[s];
     671                 :             :                                     // If we don't already have a super-recipe to the new one, add it.
     672         [ +  + ]:       25510 :                                     if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {
     673         [ +  - ]:         744 :                                         recipes.push_back(entry);
     674                 :             :                                     }
     675                 :             :                                 }
     676                 :             :                             }
     677                 :             : 
     678         [ +  + ]:       11456 :                             if (subs <= 2) break;
     679                 :       11456 :                         }
     680         [ +  + ]:       52918 :                         if (subs <= 1) break;
     681                 :             :                     }
     682         [ +  + ]:        1846 :                     if (subs <= 0) break;
     683                 :             :                 }
     684                 :             :             }
     685                 :             :         }
     686                 :             : 
     687                 :             :         /* Find which types are useful. The fuzzer logic only cares about constructing
     688                 :             :          * B,V,K,W nodes, so any type that isn't needed in any recipe (directly or
     689                 :             :          * indirectly) for the construction of those is uninteresting. */
     690         [ +  - ]:           4 :         std::set<Type> useful_types{"B"_mst, "V"_mst, "K"_mst, "W"_mst};
     691                 :             :         // Find the transitive closure by adding types until the set of types does not change.
     692                 :           4 :         while (true) {
     693                 :           4 :             size_t set_size = useful_types.size();
     694         [ +  + ]:         200 :             for (const auto& [type, recipes] : table) {
     695         [ +  + ]:         196 :                 if (useful_types.contains(type)) {
     696         [ +  + ]:        1129 :                     for (const auto& [_, subtypes] : recipes) {
     697   [ +  -  +  + ]:        2379 :                         for (auto subtype : subtypes) useful_types.insert(subtype);
     698                 :             :                     }
     699                 :             :                 }
     700                 :             :             }
     701         [ +  + ]:           4 :             if (useful_types.size() == set_size) break;
     702                 :             :         }
     703                 :             :         // Remove all rules that construct uninteresting types.
     704         [ +  + ]:         100 :         for (auto type_it = table.begin(); type_it != table.end();) {
     705         [ +  + ]:          98 :             if (!useful_types.contains(type_it->first)) {
     706                 :          34 :                 type_it = table.erase(type_it);
     707                 :             :             } else {
     708                 :          64 :                 ++type_it;
     709                 :             :             }
     710                 :             :         }
     711                 :             : 
     712                 :             :         /* Find which types are constructible. A type is constructible if there is a leaf
     713                 :             :          * node recipe for constructing it, or a recipe whose subnodes are all constructible.
     714                 :             :          * Types can be non-constructible because they have no recipes to begin with,
     715                 :             :          * because they can only be constructed using recipes that involve otherwise
     716                 :             :          * non-constructible types, or because they require infinite recursion. */
     717                 :           4 :         std::set<Type> constructible_types{};
     718                 :         812 :         auto known_constructible = [&](Type type) { return constructible_types.contains(type); };
     719                 :             :         // Find the transitive closure by adding types until the set of types does not change.
     720                 :           4 :         while (true) {
     721                 :           4 :             size_t set_size = constructible_types.size();
     722                 :             :             // Iterate over all types we have recipes for.
     723         [ +  + ]:         132 :             for (const auto& [type, recipes] : table) {
     724         [ +  + ]:         128 :                 if (!known_constructible(type)) {
     725                 :             :                     // For not (yet known to be) constructible types, iterate over their recipes.
     726         [ +  + ]:          80 :                     for (const auto& [_, subt] : recipes) {
     727                 :             :                         // If any recipe involves only (already known to be) constructible types,
     728                 :             :                         // add the recipe's type to the set.
     729         [ +  + ]:          72 :                         if (std::all_of(subt.begin(), subt.end(), known_constructible)) {
     730         [ +  - ]:          60 :                             constructible_types.insert(type);
     731                 :             :                             break;
     732                 :             :                         }
     733                 :             :                     }
     734                 :             :                 }
     735                 :             :             }
     736         [ +  + ]:           4 :             if (constructible_types.size() == set_size) break;
     737                 :             :         }
     738         [ +  + ]:          66 :         for (auto type_it = table.begin(); type_it != table.end();) {
     739                 :             :             // Remove all recipes which involve non-constructible types.
     740                 :          64 :             type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),
     741                 :         594 :                 [&](const recipe& rec) {
     742                 :         594 :                     return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);
     743                 :          64 :                 }), type_it->second.end());
     744                 :             :             // Delete types entirely which have no recipes left.
     745         [ +  + ]:          64 :             if (type_it->second.empty()) {
     746                 :           4 :                 type_it = table.erase(type_it);
     747                 :             :             } else {
     748                 :          60 :                 ++type_it;
     749                 :             :             }
     750                 :             :         }
     751                 :             : 
     752         [ +  + ]:          62 :         for (auto& [type, recipes] : table) {
     753                 :             :             // Sort recipes for determinism, and place those using fewer subnodes first.
     754                 :             :             // This avoids runaway expansion (when reaching the end of the fuzz input,
     755                 :             :             // all zeroes are read, resulting in the first available recipe being picked).
     756                 :          60 :             std::sort(recipes.begin(), recipes.end(),
     757                 :        1271 :                 [](const recipe& a, const recipe& b) {
     758   [ -  +  -  +  :        1271 :                     if (a.second.size() < b.second.size()) return true;
                   +  + ]
     759         [ +  + ]:         988 :                     if (a.second.size() > b.second.size()) return false;
     760                 :         536 :                     return a < b;
     761                 :             :                 }
     762                 :             :             );
     763                 :             :         }
     764                 :           2 :     }
     765                 :             : } SMARTINFO;
     766                 :             : 
     767                 :             : /**
     768                 :             :  * Consume a Miniscript node from the fuzzer's output.
     769                 :             :  *
     770                 :             :  * This is similar to ConsumeNodeStable, but uses a precomputed table with permitted
     771                 :             :  * fragments/subnode type for each required type. It is intended to more quickly explore
     772                 :             :  * interesting miniscripts, at the cost of higher implementation complexity (which could
     773                 :             :  * cause it miss things if incorrect), and with less regard for stability of the seeds
     774                 :             :  * (as improvements to the tables or changes to the typing rules could invalidate
     775                 :             :  * everything).
     776                 :             :  */
     777                 :      211099 : std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx, FuzzedDataProvider& provider, Type type_needed) {
     778                 :             :     /** Table entry for the requested type. */
     779         [ +  + ]:      211099 :     const auto& table{IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
     780                 :      211099 :     auto recipes_it = table.find(type_needed);
     781         [ -  + ]:      211099 :     assert(recipes_it != table.end());
     782                 :             :     /** Pick one recipe from the available ones for that type. */
     783   [ +  +  +  +  :      211099 :     const auto& [frag, subt] = PickValue(provider, recipes_it->second);
          +  +  +  +  +  
                   +  - ]
     784                 :             : 
     785                 :             :     // Based on the fragment the recipe uses, fill in other data (k, keys, data).
     786   [ +  +  +  +  :      211099 :     switch (frag) {
          +  +  +  +  +  
                   +  - ]
     787                 :       15362 :         case Fragment::PK_K:
     788                 :       15362 :         case Fragment::PK_H:
     789                 :       15362 :             return {{frag, ConsumePubKey(provider)}};
     790                 :        5274 :         case Fragment::MULTI: {
     791                 :        5274 :             const auto n_keys = provider.ConsumeIntegralInRange<uint8_t>(1, 20);
     792                 :        5274 :             const auto k = provider.ConsumeIntegralInRange<uint8_t>(1, n_keys);
     793                 :        5274 :             std::vector<CPubKey> keys{n_keys};
     794         [ +  + ]:       30204 :             for (auto& key: keys) key = ConsumePubKey(provider);
     795                 :        5274 :             return {{frag, k, std::move(keys)}};
     796                 :        5274 :         }
     797                 :        1512 :         case Fragment::MULTI_A: {
     798                 :        1512 :             const auto n_keys = provider.ConsumeIntegralInRange<uint16_t>(1, 999);
     799                 :        1512 :             const auto k = provider.ConsumeIntegralInRange<uint16_t>(1, n_keys);
     800                 :        1512 :             std::vector<CPubKey> keys{n_keys};
     801         [ +  + ]:       29530 :             for (auto& key: keys) key = ConsumePubKey(provider);
     802                 :        1512 :             return {{frag, k, std::move(keys)}};
     803                 :        1512 :         }
     804                 :        4162 :         case Fragment::OLDER:
     805                 :        4162 :         case Fragment::AFTER:
     806                 :        4162 :             return {{frag, provider.ConsumeIntegralInRange<uint32_t>(1, 0x7FFFFFF)}};
     807                 :        2036 :         case Fragment::SHA256:
     808                 :        2036 :             return {{frag, PickValue(provider, TEST_DATA.sha256)}};
     809                 :        2110 :         case Fragment::HASH256:
     810                 :        2110 :             return {{frag, PickValue(provider, TEST_DATA.hash256)}};
     811                 :        1895 :         case Fragment::RIPEMD160:
     812                 :        1895 :             return {{frag, PickValue(provider, TEST_DATA.ripemd160)}};
     813                 :        1866 :         case Fragment::HASH160:
     814                 :        1866 :             return {{frag, PickValue(provider, TEST_DATA.hash160)}};
     815                 :      168822 :         case Fragment::JUST_0:
     816                 :      168822 :         case Fragment::JUST_1:
     817                 :      168822 :         case Fragment::WRAP_A:
     818                 :      168822 :         case Fragment::WRAP_S:
     819                 :      168822 :         case Fragment::WRAP_C:
     820                 :      168822 :         case Fragment::WRAP_D:
     821                 :      168822 :         case Fragment::WRAP_V:
     822                 :      168822 :         case Fragment::WRAP_J:
     823                 :      168822 :         case Fragment::WRAP_N:
     824                 :      168822 :         case Fragment::AND_V:
     825                 :      168822 :         case Fragment::AND_B:
     826                 :      168822 :         case Fragment::OR_B:
     827                 :      168822 :         case Fragment::OR_C:
     828                 :      168822 :         case Fragment::OR_D:
     829                 :      168822 :         case Fragment::OR_I:
     830                 :      168822 :         case Fragment::ANDOR:
     831                 :      168822 :             return {{subt, frag}};
     832                 :        8060 :         case Fragment::THRESH: {
     833                 :        8060 :             uint32_t children;
     834   [ -  +  +  + ]:        8060 :             if (subt.size() < 2) {
     835                 :        6710 :                 children = subt.size();
     836                 :             :             } else {
     837                 :             :                 // If we hit a thresh with 2 subnodes, artificially extend it to any number
     838                 :             :                 // (2 or larger) by replicating the type of the last subnode.
     839                 :        1350 :                 children = provider.ConsumeIntegralInRange<uint32_t>(2, MAX_OPS_PER_SCRIPT / 2);
     840                 :             :             }
     841                 :        8060 :             auto k = provider.ConsumeIntegralInRange<uint32_t>(1, children);
     842                 :        8060 :             std::vector<Type> subs = subt;
     843   [ +  -  -  +  :       37061 :             while (subs.size() < children) subs.push_back(subs.back());
                   +  + ]
     844                 :        8060 :             return {{std::move(subs), frag, k}};
     845                 :        8060 :         }
     846                 :             :     }
     847                 :             : 
     848                 :           0 :     assert(false);
     849                 :             : }
     850                 :             : 
     851                 :             : /**
     852                 :             :  * Generate a Miniscript node based on the fuzzer's input.
     853                 :             :  *
     854                 :             :  * - ConsumeNode is a function object taking a Type, and returning an std::optional<NodeInfo>.
     855                 :             :  * - root_type is the required type properties of the constructed NodeRef.
     856                 :             :  * - strict_valid sets whether ConsumeNode is expected to guarantee a NodeInfo that results in
     857                 :             :  *   a NodeRef whose Type() matches the type fed to ConsumeNode.
     858                 :             :  */
     859                 :             : template<typename F>
     860                 :        7519 : NodeRef GenNode(MsCtx script_ctx, F ConsumeNode, Type root_type, bool strict_valid = false) {
     861                 :             :     /** A stack of miniscript Nodes being built up. */
     862                 :        7519 :     std::vector<NodeRef> stack;
     863                 :             :     /** The queue of instructions. */
     864   [ +  -  +  +  :       22557 :     std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
                   -  - ]
     865                 :             :     /** Predict the number of (static) script ops. */
     866                 :        7519 :     uint32_t ops{0};
     867                 :             :     /** Predict the total script size (every unexplored subnode is counted as one, as every leaf is
     868                 :             :      *  at least one script byte). */
     869                 :        7519 :     uint32_t scriptsize{1};
     870                 :             : 
     871         [ +  + ]:      898932 :     while (!todo.empty()) {
     872                 :             :         // The expected type we have to construct.
     873                 :      893421 :         auto type_needed = todo.back().first;
     874         [ +  + ]:      893421 :         if (!todo.back().second) {
     875                 :             :             // Fragment/children have not been decided yet. Decide them.
     876         [ +  + ]:      459055 :             auto node_info = ConsumeNode(type_needed);
     877         [ +  + ]:      459055 :             if (!node_info) return {};
     878                 :             :             // Update predicted resource limits. Since every leaf Miniscript node is at least one
     879                 :             :             // byte long, we move one byte from each child to their parent. A similar technique is
     880                 :             :             // used in the miniscript::internal::Parse function to prevent runaway string parsing.
     881   [ -  +  -  +  :      457509 :             scriptsize += miniscript::internal::ComputeScriptLen(node_info->fragment, ""_mst, node_info->subtypes.size(), node_info->k, node_info->subtypes.size(),
                   +  - ]
     882         [ -  + ]:      457509 :                                                                  node_info->keys.size(), script_ctx) - 1;
     883         [ +  + ]:      457509 :             if (scriptsize > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
     884   [ +  +  +  +  :      457465 :             switch (node_info->fragment) {
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  + ]
     885                 :             :             case Fragment::JUST_0:
     886                 :             :             case Fragment::JUST_1:
     887                 :             :                 break;
     888                 :             :             case Fragment::PK_K:
     889                 :             :                 break;
     890                 :       10419 :             case Fragment::PK_H:
     891                 :       10419 :                 ops += 3;
     892                 :       10419 :                 break;
     893                 :       12569 :             case Fragment::OLDER:
     894                 :             :             case Fragment::AFTER:
     895                 :       12569 :                 ops += 1;
     896                 :       12569 :                 break;
     897                 :       18920 :             case Fragment::RIPEMD160:
     898                 :             :             case Fragment::SHA256:
     899                 :             :             case Fragment::HASH160:
     900                 :             :             case Fragment::HASH256:
     901                 :       18920 :                 ops += 4;
     902                 :       18920 :                 break;
     903                 :       20561 :             case Fragment::ANDOR:
     904                 :       20561 :                 ops += 3;
     905                 :       20561 :                 break;
     906                 :             :             case Fragment::AND_V:
     907                 :             :                 break;
     908                 :       20788 :             case Fragment::AND_B:
     909                 :             :             case Fragment::OR_B:
     910                 :       20788 :                 ops += 1;
     911                 :       20788 :                 break;
     912                 :        6133 :             case Fragment::OR_C:
     913                 :        6133 :                 ops += 2;
     914                 :        6133 :                 break;
     915                 :       13406 :             case Fragment::OR_D:
     916                 :       13406 :                 ops += 3;
     917                 :       13406 :                 break;
     918                 :       26589 :             case Fragment::OR_I:
     919                 :       26589 :                 ops += 3;
     920                 :       26589 :                 break;
     921         [ -  + ]:       14584 :             case Fragment::THRESH:
     922         [ -  + ]:       14584 :                 ops += node_info->subtypes.size();
     923                 :       14584 :                 break;
     924                 :       10363 :             case Fragment::MULTI:
     925                 :       10363 :                 ops += 1;
     926                 :       10363 :                 break;
     927         [ -  + ]:        2757 :             case Fragment::MULTI_A:
     928         [ -  + ]:        2757 :                 ops += node_info->keys.size() + 1;
     929                 :        2757 :                 break;
     930                 :       37409 :             case Fragment::WRAP_A:
     931                 :       37409 :                 ops += 2;
     932                 :       37409 :                 break;
     933                 :        4610 :             case Fragment::WRAP_S:
     934                 :        4610 :                 ops += 1;
     935                 :        4610 :                 break;
     936                 :       20425 :             case Fragment::WRAP_C:
     937                 :       20425 :                 ops += 1;
     938                 :       20425 :                 break;
     939                 :        2089 :             case Fragment::WRAP_D:
     940                 :        2089 :                 ops += 3;
     941                 :        2089 :                 break;
     942                 :             :             case Fragment::WRAP_V:
     943                 :             :                 // We don't account for OP_VERIFY here; that will be corrected for when the actual
     944                 :             :                 // node is constructed below.
     945                 :             :                 break;
     946                 :        4226 :             case Fragment::WRAP_J:
     947                 :        4226 :                 ops += 4;
     948                 :        4226 :                 break;
     949                 :       15023 :             case Fragment::WRAP_N:
     950                 :       15023 :                 ops += 1;
     951                 :       15023 :                 break;
     952                 :             :             }
     953         [ +  + ]:      457465 :             if (ops > MAX_OPS_PER_SCRIPT) return {};
     954         [ +  - ]:      457311 :             auto subtypes = node_info->subtypes;
     955         [ -  + ]:      457311 :             todo.back().second = std::move(node_info);
     956   [ -  +  +  - ]:      457311 :             todo.reserve(todo.size() + subtypes.size());
     957                 :             :             // As elements on the todo stack are processed back to front, construct
     958                 :             :             // them in reverse order (so that the first subnode is generated first).
     959   [ -  +  +  + ]:      940336 :             for (size_t i = 0; i < subtypes.size(); ++i) {
     960         [ +  - ]:      483025 :                 todo.emplace_back(*(subtypes.rbegin() + i), std::nullopt);
     961                 :             :             }
     962                 :      459055 :         } else {
     963                 :             :             // The back of todo has fragment and number of children decided, and
     964                 :             :             // those children have been constructed at the back of stack. Pop
     965                 :             :             // that entry off todo, and use it to construct a new NodeRef on
     966                 :             :             // stack.
     967         [ -  + ]:      434366 :             NodeInfo& info = *todo.back().second;
     968                 :             :             // Gather children from the back of stack.
     969                 :      434366 :             std::vector<NodeRef> sub;
     970   [ -  +  +  - ]:      434366 :             sub.reserve(info.subtypes.size());
     971   [ -  +  +  + ]:      855349 :             for (size_t i = 0; i < info.subtypes.size(); ++i) {
     972         [ +  - ]:      420983 :                 sub.push_back(std::move(*(stack.end() - info.subtypes.size() + i)));
     973                 :             :             }
     974                 :      434366 :             stack.erase(stack.end() - info.subtypes.size(), stack.end());
     975                 :             :             // Construct new NodeRef.
     976                 :      434366 :             NodeRef node;
     977         [ +  + ]:      434366 :             if (info.keys.empty()) {
     978         [ +  - ]:      782574 :                 node = MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
     979                 :             :             } else {
     980         [ -  + ]:       43079 :                 assert(sub.empty());
     981         [ -  + ]:       43079 :                 assert(info.hash.empty());
     982         [ +  - ]:       86158 :                 node = MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
     983                 :             :             }
     984                 :             :             // Verify acceptability.
     985   [ +  -  +  + ]:      434366 :             if (!node || (node->GetType() & "KVWB"_mst) == ""_mst) {
     986         [ -  + ]:         234 :                 assert(!strict_valid);
     987                 :         234 :                 return {};
     988                 :             :             }
     989         [ +  + ]:      434132 :             if (!(type_needed == ""_mst)) {
     990         [ -  + ]:      410845 :                 assert(node->GetType() << type_needed);
     991                 :             :             }
     992         [ +  + ]:      434132 :             if (!node->IsValid()) return {};
     993                 :             :             // Update resource predictions.
     994   [ +  +  +  + ]:      434128 :             if (node->fragment == Fragment::WRAP_V && node->subs[0]->GetType() << "x"_mst) {
     995                 :       24866 :                 ops += 1;
     996                 :       24866 :                 scriptsize += 1;
     997                 :             :             }
     998   [ +  +  +  + ]:      434128 :             if (!miniscript::IsTapscript(script_ctx) && ops > MAX_OPS_PER_SCRIPT) return {};
     999   [ +  +  +  + ]:      700143 :             if (scriptsize > miniscript::internal::MaxScriptSize(script_ctx)) {
    1000                 :           3 :                 return {};
    1001                 :             :             }
    1002                 :             :             // Move it to the stack.
    1003                 :      434102 :             stack.push_back(std::move(node));
    1004                 :      434102 :             todo.pop_back();
    1005                 :      434366 :         }
    1006                 :             :     }
    1007         [ -  + ]:        5511 :     assert(stack.size() == 1);
    1008         [ -  + ]:        5511 :     assert(stack[0]->GetStaticOps() == ops);
    1009         [ -  + ]:        5511 :     assert(stack[0]->ScriptSize() == scriptsize);
    1010         [ +  - ]:        5511 :     stack[0]->DuplicateKeyCheck(KEY_COMP);
    1011                 :        5511 :     return std::move(stack[0]);
    1012         [ -  + ]:       15038 : }
    1013                 :             : 
    1014                 :             : //! The spk for this script under the given context. If it's a Taproot output also record the spend data.
    1015                 :        5018 : CScript ScriptPubKey(MsCtx ctx, const CScript& script, TaprootBuilder& builder)
    1016                 :             : {
    1017   [ +  +  +  -  :        5018 :     if (!miniscript::IsTapscript(ctx)) return CScript() << OP_0 << WitnessV0ScriptHash(script);
                   +  - ]
    1018                 :             : 
    1019                 :             :     // For Taproot outputs we always use a tree with a single script and a dummy internal key.
    1020         [ +  + ]:        4170 :     builder.Add(0, script, TAPROOT_LEAF_TAPSCRIPT);
    1021                 :        2085 :     builder.Finalize(XOnlyPubKey::NUMS_H);
    1022         [ +  - ]:        4170 :     return GetScriptForDestination(builder.GetOutput());
    1023                 :             : }
    1024                 :             : 
    1025                 :             : //! Fill the witness with the data additional to the script satisfaction.
    1026                 :        4571 : void SatisfactionToWitness(MsCtx ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
    1027                 :             :     // For P2WSH, it's only the witness script.
    1028         [ +  + ]:        9142 :     witness.stack.emplace_back(script.begin(), script.end());
    1029         [ +  + ]:        4571 :     if (!miniscript::IsTapscript(ctx)) return;
    1030                 :             :     // For Tapscript we also need the control block.
    1031         [ +  - ]:        3718 :     witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
    1032                 :             : }
    1033                 :             : 
    1034                 :             : /** Perform various applicable tests on a miniscript Node. */
    1035                 :        7519 : void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& provider)
    1036                 :             : {
    1037         [ +  + ]:        7519 :     if (!node) return;
    1038                 :             : 
    1039                 :             :     // Check that it roundtrips to text representation
    1040                 :        5511 :     const ParserContext parser_ctx{script_ctx};
    1041                 :        5511 :     std::optional<std::string> str{node->ToString(parser_ctx)};
    1042         [ -  + ]:        5511 :     assert(str);
    1043         [ -  + ]:        5511 :     auto parsed = miniscript::FromString(*str, parser_ctx);
    1044         [ -  + ]:        5511 :     assert(parsed);
    1045   [ +  -  -  + ]:        5511 :     assert(*parsed == *node);
    1046                 :             : 
    1047                 :             :     // Check consistency between script size estimation and real size.
    1048         [ +  - ]:        5511 :     auto script = node->ToScript(parser_ctx);
    1049   [ +  +  -  + ]:       10566 :     assert(node->ScriptSize() == script.size());
    1050                 :             : 
    1051                 :             :     // Check consistency of "x" property with the script (type K is excluded, because it can end
    1052                 :             :     // with a push of a key, which could match these opcodes).
    1053         [ +  + ]:        5511 :     if (!(node->GetType() << "K"_mst)) {
    1054         [ +  + ]:        5372 :         bool ends_in_verify = !(node->GetType() << "x"_mst);
    1055   [ +  +  +  +  :       25071 :         assert(ends_in_verify == (script.back() == OP_CHECKSIG || script.back() == OP_CHECKMULTISIG || script.back() == OP_EQUAL || script.back() == OP_NUMEQUAL));
          +  +  +  +  +  
                +  -  + ]
    1056                 :             :     }
    1057                 :             : 
    1058                 :             :     // The rest of the checks only apply when testing a valid top-level script.
    1059         [ +  + ]:        5511 :     if (!node->IsValidTopLevel()) return;
    1060                 :             : 
    1061                 :             :     // Check roundtrip to script
    1062         [ +  - ]:        5018 :     auto decoded = miniscript::FromScript(script, parser_ctx);
    1063         [ -  + ]:        5018 :     assert(decoded);
    1064                 :             :     // Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
    1065                 :             :     // - The script corresponding to that decoded form matches exactly
    1066                 :             :     // - The type matches exactly
    1067   [ +  -  -  + ]:        5018 :     assert(decoded->ToScript(parser_ctx) == script);
    1068         [ -  + ]:        5018 :     assert(decoded->GetType() == node->GetType());
    1069                 :             : 
    1070                 :             :     // Optionally pad the script or the witness in order to increase the sensitivity of the tests of
    1071                 :             :     // the resources limits logic.
    1072                 :        5018 :     CScriptWitness witness_mal, witness_nonmal;
    1073         [ +  + ]:        5018 :     if (provider.ConsumeBool()) {
    1074                 :             :         // Under P2WSH, optionally pad the script with OP_NOPs to max op the ops limit of the constructed script.
    1075                 :             :         // This makes the script obviously not actually miniscript-compatible anymore, but the
    1076                 :             :         // signatures constructed in this test don't commit to the script anyway, so the same
    1077                 :             :         // miniscript satisfier will work. This increases the sensitivity of the test to the ops
    1078                 :             :         // counting logic being too low, especially for simple scripts.
    1079                 :             :         // Do this optionally because we're not solely interested in cases where the number of ops is
    1080                 :             :         // maximal.
    1081                 :             :         // Do not pad more than what would cause MAX_STANDARD_P2WSH_SCRIPT_SIZE to be reached, however,
    1082                 :             :         // as that also invalidates scripts.
    1083                 :         842 :         const auto node_ops{node->GetOps()};
    1084   [ +  +  +  + ]:        1297 :         if (!IsTapscript(script_ctx) && node_ops && *node_ops < MAX_OPS_PER_SCRIPT
    1085   [ +  +  +  + ]:        1220 :             && node->ScriptSize() < MAX_STANDARD_P2WSH_SCRIPT_SIZE) {
    1086         [ +  + ]:         375 :             int add = std::min<int>(
    1087         [ +  + ]:         375 :                 MAX_OPS_PER_SCRIPT - *node_ops,
    1088         [ +  + ]:         375 :                 MAX_STANDARD_P2WSH_SCRIPT_SIZE - node->ScriptSize());
    1089         [ +  + ]:       36004 :             for (int i = 0; i < add; ++i) script.push_back(OP_NOP);
    1090                 :             :         }
    1091                 :             : 
    1092                 :             :         // Under Tapscript, optionally pad the stack up to the limit minus the calculated maximum execution stack
    1093                 :             :         // size to assert a Miniscript would never add more elements to the stack during execution than anticipated.
    1094                 :         842 :         const auto node_exec_ss{node->GetExecStackSize()};
    1095   [ +  +  +  +  :         842 :         if (miniscript::IsTapscript(script_ctx) && node_exec_ss && *node_exec_ss < MAX_STACK_SIZE) {
                   +  - ]
    1096         [ +  - ]:         353 :             unsigned add{(unsigned)MAX_STACK_SIZE - *node_exec_ss};
    1097         [ +  - ]:         353 :             witness_mal.stack.resize(add);
    1098         [ +  - ]:         353 :             witness_nonmal.stack.resize(add);
    1099                 :         353 :             script.reserve(add);
    1100         [ +  + ]:      340115 :             for (unsigned i = 0; i < add; ++i) script.push_back(OP_NIP);
    1101                 :             :         }
    1102                 :             :     }
    1103                 :             : 
    1104                 :        5018 :     const SatisfierContext satisfier_ctx{script_ctx};
    1105                 :             : 
    1106                 :             :     // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
    1107         [ +  - ]:        5018 :     TaprootBuilder builder;
    1108         [ +  - ]:        5018 :     const CScript script_pubkey{ScriptPubKey(script_ctx, script, builder)};
    1109                 :             : 
    1110                 :             :     // Run malleable satisfaction algorithm.
    1111                 :        5018 :     std::vector<std::vector<unsigned char>> stack_mal;
    1112         [ +  - ]:        5018 :     const bool mal_success = node->Satisfy(satisfier_ctx, stack_mal, false) == miniscript::Availability::YES;
    1113                 :             : 
    1114                 :             :     // Run non-malleable satisfaction algorithm.
    1115                 :        5018 :     std::vector<std::vector<unsigned char>> stack_nonmal;
    1116         [ +  - ]:        5018 :     const bool nonmal_success = node->Satisfy(satisfier_ctx, stack_nonmal, true) == miniscript::Availability::YES;
    1117                 :             : 
    1118         [ +  + ]:        5018 :     if (nonmal_success) {
    1119                 :             :         // Non-malleable satisfactions are bounded by the satisfaction size plus:
    1120                 :             :         // - For P2WSH spends, the witness script
    1121                 :             :         // - For Tapscript spends, both the witness script and the control block
    1122                 :        1400 :         const size_t max_stack_size{*node->GetStackSize() + 1 + miniscript::IsTapscript(script_ctx)};
    1123   [ -  +  -  + ]:        1400 :         assert(stack_nonmal.size() <= max_stack_size);
    1124                 :             :         // If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
    1125         [ -  + ]:        1400 :         assert(mal_success);
    1126         [ -  + ]:        1400 :         assert(stack_nonmal == stack_mal);
    1127                 :             :         // Compute witness size (excluding script push, control block, and witness count encoding).
    1128   [ -  +  -  + ]:        1400 :         const uint64_t wit_size{GetSerializeSize(stack_nonmal) - GetSizeOfCompactSize(stack_nonmal.size())};
    1129   [ -  +  -  + ]:        2800 :         assert(wit_size <= *node->GetWitnessSize());
    1130                 :             : 
    1131                 :             :         // Test non-malleable satisfaction.
    1132         [ +  - ]:        1400 :         witness_nonmal.stack.insert(witness_nonmal.stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
    1133         [ +  - ]:        1400 :         SatisfactionToWitness(script_ctx, witness_nonmal, script, builder);
    1134                 :        1400 :         ScriptError serror;
    1135         [ +  - ]:        1400 :         bool res = VerifyScript(DUMMY_SCRIPTSIG, script_pubkey, &witness_nonmal, STANDARD_SCRIPT_VERIFY_FLAGS, CHECKER_CTX, &serror);
    1136                 :             :         // Non-malleable satisfactions are guaranteed to be valid if ValidSatisfactions().
    1137   [ +  +  -  + ]:        1400 :         if (node->ValidSatisfactions()) assert(res);
    1138                 :             :         // More detailed: non-malleable satisfactions must be valid, or could fail with ops count error (if CheckOpsLimit failed),
    1139                 :             :         // or with a stack size error (if CheckStackSize check failed).
    1140   [ +  +  +  -  :         128 :         assert(res ||
          -  +  -  -  -  
                      - ]
    1141                 :             :                (!node->CheckOpsLimit() && serror == ScriptError::SCRIPT_ERR_OP_COUNT) ||
    1142                 :             :                (!node->CheckStackSize() && serror == ScriptError::SCRIPT_ERR_STACK_SIZE));
    1143                 :             :     }
    1144                 :             : 
    1145   [ +  +  +  +  :        5018 :     if (mal_success && (!nonmal_success || witness_mal.stack != witness_nonmal.stack)) {
                   +  - ]
    1146                 :             :         // Test malleable satisfaction only if it's different from the non-malleable one.
    1147         [ +  - ]:        3171 :         witness_mal.stack.insert(witness_mal.stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
    1148         [ +  - ]:        3171 :         SatisfactionToWitness(script_ctx, witness_mal, script, builder);
    1149                 :        3171 :         ScriptError serror;
    1150         [ +  - ]:        3171 :         bool res = VerifyScript(DUMMY_SCRIPTSIG, script_pubkey, &witness_mal, STANDARD_SCRIPT_VERIFY_FLAGS, CHECKER_CTX, &serror);
    1151                 :             :         // Malleable satisfactions are not guaranteed to be valid under any conditions, but they can only
    1152                 :             :         // fail due to stack or ops limits.
    1153   [ +  +  +  +  :        3171 :         assert(res || serror == ScriptError::SCRIPT_ERR_OP_COUNT || serror == ScriptError::SCRIPT_ERR_STACK_SIZE);
                   -  + ]
    1154                 :             :     }
    1155                 :             : 
    1156         [ +  + ]:        5018 :     if (node->IsSane()) {
    1157                 :             :         // For sane nodes, the two algorithms behave identically.
    1158         [ -  + ]:         654 :         assert(mal_success == nonmal_success);
    1159                 :             :     }
    1160                 :             : 
    1161                 :             :     // Verify that if a node is policy-satisfiable, the malleable satisfaction
    1162                 :             :     // algorithm succeeds. Given that under IsSane() both satisfactions
    1163                 :             :     // are identical, this implies that for such nodes, the non-malleable
    1164                 :             :     // satisfaction will also match the expected policy.
    1165                 :      105036 :     const auto is_key_satisfiable = [script_ctx](const CPubKey& pubkey) -> bool {
    1166                 :      100018 :         auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
    1167   [ +  -  +  + ]:      100018 :         return sig_ptr != nullptr && sig_ptr->second;
    1168                 :        5018 :     };
    1169         [ +  - ]:        5018 :     bool satisfiable = node->IsSatisfiable([&](const Node& node) -> bool {
    1170   [ +  +  +  +  :       66897 :         switch (node.fragment) {
             +  +  +  - ]
    1171                 :       27057 :         case Fragment::PK_K:
    1172                 :       27057 :         case Fragment::PK_H:
    1173                 :       27057 :             return is_key_satisfiable(node.keys[0]);
    1174                 :       12410 :         case Fragment::MULTI:
    1175                 :       12410 :         case Fragment::MULTI_A: {
    1176                 :       12410 :             size_t sats = std::count_if(node.keys.begin(), node.keys.end(), [&](const auto& key) {
    1177                 :       72961 :                 return size_t(is_key_satisfiable(key));
    1178                 :       12410 :             });
    1179                 :       12410 :             return sats >= node.k;
    1180                 :             :         }
    1181                 :       10634 :         case Fragment::OLDER:
    1182                 :       10634 :         case Fragment::AFTER:
    1183                 :       10634 :             return node.k & 1;
    1184                 :        3991 :         case Fragment::SHA256:
    1185                 :        3991 :             return TEST_DATA.sha256_preimages.contains(node.data);
    1186                 :        4555 :         case Fragment::HASH256:
    1187                 :        4555 :             return TEST_DATA.hash256_preimages.contains(node.data);
    1188                 :        4185 :         case Fragment::RIPEMD160:
    1189                 :        4185 :             return TEST_DATA.ripemd160_preimages.contains(node.data);
    1190                 :        4065 :         case Fragment::HASH160:
    1191                 :        4065 :             return TEST_DATA.hash160_preimages.contains(node.data);
    1192                 :           0 :         default:
    1193                 :           0 :             assert(false);
    1194                 :             :         }
    1195                 :             :         return false;
    1196                 :             :     });
    1197         [ -  + ]:        5018 :     assert(mal_success == satisfiable);
    1198                 :        5511 : }
    1199                 :             : 
    1200                 :             : } // namespace
    1201                 :             : 
    1202                 :           3 : void FuzzInit()
    1203                 :             : {
    1204   [ +  -  +  -  :           3 :     static ECC_Context ecc_context{};
                   +  - ]
    1205                 :           3 :     TEST_DATA.Init();
    1206                 :           3 : }
    1207                 :             : 
    1208                 :           1 : void FuzzInitSmart()
    1209                 :             : {
    1210                 :           1 :     FuzzInit();
    1211                 :           1 :     SMARTINFO.Init();
    1212                 :           1 : }
    1213                 :             : 
    1214                 :             : /** Fuzz target that runs TestNode on nodes generated using ConsumeNodeStable. */
    1215         [ +  - ]:        2964 : FUZZ_TARGET(miniscript_stable, .init = FuzzInit)
    1216                 :             : {
    1217                 :             :     // Run it under both P2WSH and Tapscript contexts.
    1218         [ +  + ]:        7542 :     for (const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
    1219                 :        5028 :         FuzzedDataProvider provider(buffer.data(), buffer.size());
    1220         [ +  - ]:      252984 :         TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
    1221         [ +  - ]:      247956 :             return ConsumeNodeStable(script_ctx, provider, needed_type);
    1222                 :             :         }, ""_mst), provider);
    1223                 :             :     }
    1224                 :        2514 : }
    1225                 :             : 
    1226                 :             : /** Fuzz target that runs TestNode on nodes generated using ConsumeNodeSmart. */
    1227         [ +  - ]:        2941 : FUZZ_TARGET(miniscript_smart, .init = FuzzInitSmart)
    1228                 :             : {
    1229                 :             :     /** The set of types we aim to construct nodes for. Together they cover all. */
    1230                 :        2491 :     static constexpr std::array<Type, 4> BASE_TYPES{"B"_mst, "V"_mst, "K"_mst, "W"_mst};
    1231                 :             : 
    1232                 :        2491 :     FuzzedDataProvider provider(buffer.data(), buffer.size());
    1233                 :        2491 :     const auto script_ctx{(MsCtx)provider.ConsumeBool()};
    1234         [ +  - ]:      213590 :     TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
    1235         [ +  - ]:      211099 :         return ConsumeNodeSmart(script_ctx, provider, needed_type);
    1236                 :        2491 :     }, PickValue(provider, BASE_TYPES), true), provider);
    1237                 :        2491 : }
    1238                 :             : 
    1239                 :             : /* Fuzz tests that test parsing from a string, and roundtripping via string. */
    1240         [ +  - ]:        1732 : FUZZ_TARGET(miniscript_string, .init = FuzzInit)
    1241                 :             : {
    1242   [ +  +  +  + ]:        2564 :     constexpr auto is_too_expensive{[](std::span<const uint8_t> buf) { return HasTooManySubFrag(buf) || HasTooManyWrappers(buf); }};
    1243                 :             : 
    1244         [ +  - ]:        1282 :     if (buffer.empty()) return;
    1245                 :        1282 :     FuzzedDataProvider provider(buffer.data(), buffer.size());
    1246                 :        1282 :     auto str = provider.ConsumeBytesAsString(provider.remaining_bytes() - 1);
    1247   [ +  -  +  + ]:        1282 :     if (is_too_expensive(MakeUCharSpan(str))) return;
    1248                 :        1114 :     const ParserContext parser_ctx{(MsCtx)provider.ConsumeBool()};
    1249         [ -  + ]:        1114 :     auto parsed = miniscript::FromString(str, parser_ctx);
    1250         [ +  + ]:        1114 :     if (!parsed) return;
    1251                 :             : 
    1252         [ +  - ]:         635 :     const auto str2 = parsed->ToString(parser_ctx);
    1253         [ -  + ]:         635 :     assert(str2);
    1254         [ -  + ]:         635 :     auto parsed2 = miniscript::FromString(*str2, parser_ctx);
    1255         [ -  + ]:         635 :     assert(parsed2);
    1256   [ +  -  -  + ]:         635 :     assert(*parsed == *parsed2);
    1257                 :        1761 : }
    1258                 :             : 
    1259                 :             : /* Fuzz tests that test parsing from a script, and roundtripping via script. */
    1260         [ +  - ]:        1676 : FUZZ_TARGET(miniscript_script)
    1261                 :             : {
    1262                 :        1226 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    1263                 :        1226 :     const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
    1264         [ +  + ]:        1226 :     if (!script) return;
    1265                 :             : 
    1266                 :        1204 :     const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.ConsumeBool()};
    1267         [ +  - ]:        1204 :     const auto ms = miniscript::FromScript(*script, script_parser_ctx);
    1268         [ +  + ]:        1204 :     if (!ms) return;
    1269                 :             : 
    1270   [ +  -  -  + ]:         423 :     assert(ms->ToScript(script_parser_ctx) == *script);
    1271                 :        2007 : }
        

Generated by: LCOV version 2.0-1