Coverage Report

Created: 2025-09-19 18:31

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