Coverage Report

Created: 2025-04-09 20:14

/root/bitcoin/src/test/fuzz/muhash.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2020-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 <arith_uint256.h>
6
#include <crypto/muhash.h>
7
#include <span.h>
8
#include <uint256.h>
9
#include <test/fuzz/FuzzedDataProvider.h>
10
#include <test/fuzz/fuzz.h>
11
#include <test/fuzz/util.h>
12
13
#include <algorithm>
14
#include <array>
15
#include <vector>
16
17
namespace {
18
19
/** Class to represent 6144-bit numbers using arith_uint256 code.
20
 *
21
 * 6144 is sufficient to represent the product of two 3072-bit numbers. */
22
class arith_uint6144 : public base_uint<6144> {
23
public:
24
0
    arith_uint6144(uint64_t x) : base_uint{x} {}
25
26
    /** Construct an arith_uint6144 from any multiple of 4 bytes in LE notation,
27
     *  up to 768 bytes. */
28
0
    arith_uint6144(std::span<const uint8_t> bytes) : base_uint{}
29
0
    {
30
0
        assert(bytes.size() % 4 == 0);
31
0
        assert(bytes.size() <= 768);
32
0
        for (unsigned i = 0; i * 4 < bytes.size(); ++i) {
33
0
            pn[i] = ReadLE32(bytes.data() + 4 * i);
34
0
        }
35
0
    }
36
37
    /** Serialize an arithm_uint6144 to any multiply of 4 bytes in LE notation,
38
     *  on the condition that the represented number fits. */
39
0
    void Serialize(std::span<uint8_t> bytes) {
40
0
        assert(bytes.size() % 4 == 0);
41
0
        assert(bytes.size() <= 768);
42
0
        for (unsigned i = 0; i * 4 < bytes.size(); ++i) {
43
0
            WriteLE32(bytes.data() + 4 * i, pn[i]);
44
0
        }
45
0
        for (unsigned i = bytes.size() / 4; i * 4 < 768; ++i) {
46
0
            assert(pn[i] == 0);
47
0
        }
48
0
    };
49
};
50
51
/** The MuHash3072 modulus (2**3072 - 1103717) as 768 LE8 bytes. */
52
constexpr std::array<const uint8_t, 768> MODULUS_BYTES = {
53
    155,  40, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
60
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
61
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
63
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
64
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
76
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
77
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
89
};
90
91
const arith_uint6144 ZERO{0};
92
const arith_uint6144 ONE{1};
93
const arith_uint6144 MODULUS{MODULUS_BYTES};
94
95
/** Update value to be the modulus of the input modulo MODULUS. */
96
void Reduce(arith_uint6144& value)
97
0
{
98
0
    arith_uint6144 tmp = value;
99
0
    tmp /= MODULUS;
100
0
    tmp *= MODULUS;
101
0
    value -= tmp;
102
0
}
103
104
} // namespace
105
106
FUZZ_TARGET(num3072_mul)
107
0
{
108
    // Test multiplication
109
0
    FuzzedDataProvider provider{buffer.data(), buffer.size()};
110
111
    // Read two 3072-bit numbers from fuzz input, and construct arith_uint6144
112
    // and Num3072 objects with the read values.
113
0
    uint16_t data_a_len = provider.ConsumeIntegralInRange(0, 384);
114
0
    uint8_t data_a[384] = {0};
115
0
    provider.ConsumeData(data_a, data_a_len);
116
0
    arith_uint6144 a_uint{data_a};
117
0
    Num3072 a_num{data_a};
118
119
0
    uint8_t data_b[384] = {0};
120
0
    provider.ConsumeData(data_b, 384);
121
0
    arith_uint6144 b_uint{data_b};
122
0
    Num3072 b_num{data_b};
123
124
    // Multiply the first number with the second, in both representations.
125
0
    a_num.Multiply(b_num);
126
0
    a_uint *= b_uint;
127
0
    Reduce(a_uint);
128
129
    // Serialize both to bytes and compare.
130
0
    uint8_t buf_num[384], buf_uint[384];
131
0
    a_num.ToBytes(buf_num);
132
0
    a_uint.Serialize(buf_uint);
133
0
    assert(std::ranges::equal(buf_num, buf_uint));
134
0
}
135
136
FUZZ_TARGET(num3072_inv)
137
0
{
138
    // Test inversion
139
140
0
    FuzzedDataProvider provider{buffer.data(), buffer.size()};
141
142
    // Read a 3072-bit number from fuzz input, and construct arith_uint6144
143
    // and Num3072 objects with the read values.
144
0
    uint8_t data[384] = {0};
145
0
    provider.ConsumeData(data, 384);
146
0
    Num3072 num{data};
147
0
    arith_uint6144 uint{data};
148
149
    // Bail out if the number has no inverse.
150
0
    if ((uint == ZERO) || (uint == MODULUS)) return;
151
152
    // Compute the inverse of the Num3072 object.
153
0
    Num3072 inv;
154
0
    inv.SetToOne();
155
0
    inv.Divide(num);
156
157
    // Convert the computed inverse to arith_uint6144.
158
0
    uint8_t buf[384];
159
0
    inv.ToBytes(buf);
160
0
    arith_uint6144 uint_inv{buf};
161
162
    // Multiply the original and the inverse, and expect 1.
163
0
    uint *= uint_inv;
164
0
    Reduce(uint);
165
0
    assert(uint == ONE);
166
0
}
167
168
FUZZ_TARGET(muhash)
169
0
{
170
0
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
171
0
    std::vector<uint8_t> data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
172
0
    std::vector<uint8_t> data2{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
173
174
0
    MuHash3072 muhash;
175
176
0
    muhash.Insert(data);
177
0
    muhash.Insert(data2);
178
179
0
    constexpr uint256 initial_state_hash{"dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8"};
180
0
    uint256 out;
181
0
    uint256 out2;
182
0
    CallOneOf(
183
0
        fuzzed_data_provider,
184
0
        [&] {
185
            // Test that MuHash result is consistent independent of order of operations
186
0
            muhash.Finalize(out);
187
188
0
            muhash = MuHash3072();
189
0
            muhash.Insert(data2);
190
0
            muhash.Insert(data);
191
0
            muhash.Finalize(out2);
192
0
        },
193
0
        [&] {
194
            // Test that multiplication with the initial state never changes the finalized result
195
0
            muhash.Finalize(out);
196
0
            MuHash3072 muhash3;
197
0
            muhash3 *= muhash;
198
0
            muhash3.Finalize(out2);
199
0
        },
200
0
        [&] {
201
            // Test that dividing a MuHash by itself brings it back to it's initial state
202
203
            // See note about clang + self-assignment in test/uint256_tests.cpp
204
0
            #if defined(__clang__)
205
0
            #    pragma clang diagnostic push
206
0
            #    pragma clang diagnostic ignored "-Wself-assign-overloaded"
207
0
            #endif
208
209
0
            muhash /= muhash;
210
211
0
            #if defined(__clang__)
212
0
            #    pragma clang diagnostic pop
213
0
            #endif
214
215
0
            muhash.Finalize(out);
216
0
            out2 = initial_state_hash;
217
0
        },
218
0
        [&] {
219
            // Test that removing all added elements brings the object back to it's initial state
220
0
            muhash.Remove(data);
221
0
            muhash.Remove(data2);
222
0
            muhash.Finalize(out);
223
0
            out2 = initial_state_hash;
224
0
        });
225
0
    assert(out == out2);
226
0
}