aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz/miniscript_decode.cpp
blob: 4cc0a1be8fd8ef56e56c0bc3f0ec3b6da1c026aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>
#include <hash.h>
#include <key.h>
#include <script/miniscript.h>
#include <script/script.h>
#include <span.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/strencodings.h>

#include <optional>

using miniscript::operator""_mst;


struct Converter {
    typedef CPubKey Key;

    bool ToString(const Key& key, std::string& ret) const {
        ret = HexStr(key);
        return true;
    }
    const std::vector<unsigned char> ToPKBytes(const Key& key) const {
        return {key.begin(), key.end()};
    }
    const std::vector<unsigned char> ToPKHBytes(const Key& key) const {
        const auto h = Hash160(key);
        return {h.begin(), h.end()};
    }

    template<typename I>
    bool FromString(I first, I last, Key& key) const {
        const auto bytes = ParseHex(std::string(first, last));
        key.Set(bytes.begin(), bytes.end());
        return key.IsValid();
    }
    template<typename I>
    bool FromPKBytes(I first, I last, CPubKey& key) const {
        key.Set(first, last);
        return key.IsValid();
    }
    template<typename I>
    bool FromPKHBytes(I first, I last, CPubKey& key) const {
        assert(last - first == 20);
        return false;
    }
};

const Converter CONVERTER;

FUZZ_TARGET(miniscript_decode)
{
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
    if (!script) return;

    const auto ms = miniscript::FromScript(*script, CONVERTER);
    if (!ms) return;

    // We can roundtrip it to its string representation.
    std::string ms_str;
    assert(ms->ToString(CONVERTER, ms_str));
    assert(*miniscript::FromString(ms_str, CONVERTER) == *ms);
    // The Script representation must roundtrip since we parsed it this way the first time.
    const CScript ms_script = ms->ToScript(CONVERTER);
    assert(ms_script == *script);
}