Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2020-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.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>13#include <algorithm>14#include <array>15#include <vector>17namespace {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. */22class arith_uint6144 : public base_uint<6144> {23public:24arith_uint6144(uint64_t x) : base_uint{x} {}26/** Construct an arith_uint6144 from any multiple of 4 bytes in LE notation,27* up to 768 bytes. */28arith_uint6144(std::span<const uint8_t> bytes) : base_uint{}29{30assert(bytes.size() % 4 == 0);31assert(bytes.size() <= 768);32for (unsigned i = 0; i * 4 < bytes.size(); ++i) {33pn[i] = ReadLE32(bytes.data() + 4 * i);34}35}37/** Serialize an arithm_uint6144 to any multiply of 4 bytes in LE notation,38* on the condition that the represented number fits. */39void Serialize(std::span<uint8_t> bytes) {40assert(bytes.size() % 4 == 0);41assert(bytes.size() <= 768);42for (unsigned i = 0; i * 4 < bytes.size(); ++i) {43WriteLE32(bytes.data() + 4 * i, pn[i]);44}45for (unsigned i = bytes.size() / 4; i * 4 < 768; ++i) {46assert(pn[i] == 0);47}48};49};51/** The MuHash3072 modulus (2**3072 - 1103717) as 768 LE8 bytes. */52constexpr std::array<const uint8_t, 768> MODULUS_BYTES = {53155, 40, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,54255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,55255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,56255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,57255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,58255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,59255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,60255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,61255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,62255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,63255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,64255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,65255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,66255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,67255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,68255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,69255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,70255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,71255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,72255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,73255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,74255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,75255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,76255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,770, 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,780, 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,790, 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,800, 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,810, 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,820, 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,830, 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,840, 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,850, 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,860, 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,870, 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,880, 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, 089};91const arith_uint6144 ZERO{0};92const arith_uint6144 ONE{1};93const arith_uint6144 MODULUS{MODULUS_BYTES};95/** Update value to be the modulus of the input modulo MODULUS. */96void Reduce(arith_uint6144& value)97{98arith_uint6144 tmp = value;99tmp /= MODULUS;100tmp *= MODULUS;101value -= tmp;102}104} // namespace106FUZZ_TARGET(num3072_mul)107{108// Test multiplication109FuzzedDataProvider provider{buffer.data(), buffer.size()};111// Read two 3072-bit numbers from fuzz input, and construct arith_uint6144112// and Num3072 objects with the read values.113uint16_t data_a_len = provider.ConsumeIntegralInRange(0, 384);114uint8_t data_a[384] = {0};115provider.ConsumeData(data_a, data_a_len);116arith_uint6144 a_uint{data_a};117Num3072 a_num{data_a};119uint8_t data_b[384] = {0};120provider.ConsumeData(data_b, 384);121arith_uint6144 b_uint{data_b};122Num3072 b_num{data_b};124// Multiply the first number with the second, in both representations.125a_num.Multiply(b_num);126a_uint *= b_uint;127Reduce(a_uint);129// Serialize both to bytes and compare.130uint8_t buf_num[384], buf_uint[384];131a_num.ToBytes(buf_num);132a_uint.Serialize(buf_uint);133assert(std::ranges::equal(buf_num, buf_uint));134}136FUZZ_TARGET(num3072_inv)137{138// Test inversion140FuzzedDataProvider provider{buffer.data(), buffer.size()};142// Read a 3072-bit number from fuzz input, and construct arith_uint6144143// and Num3072 objects with the read values.144uint8_t data[384] = {0};145provider.ConsumeData(data, 384);146Num3072 num{data};147arith_uint6144 uint{data};149// Bail out if the number has no inverse.150if ((uint == ZERO) || (uint == MODULUS)) return;152// Compute the inverse of the Num3072 object.153Num3072 inv;154inv.SetToOne();155inv.Divide(num);157// Convert the computed inverse to arith_uint6144.158uint8_t buf[384];159inv.ToBytes(buf);160arith_uint6144 uint_inv{buf};162// Multiply the original and the inverse, and expect 1.163uint *= uint_inv;164Reduce(uint);165assert(uint == ONE);166}168FUZZ_TARGET(muhash)169{170FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};171std::vector<uint8_t> data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};172std::vector<uint8_t> data2{ConsumeRandomLengthByteVector(fuzzed_data_provider)};174MuHash3072 muhash;176muhash.Insert(data);177muhash.Insert(data2);179constexpr uint256 initial_state_hash{"dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8"};180uint256 out;181uint256 out2;182CallOneOf(183fuzzed_data_provider,184[&] {185// Test that MuHash result is consistent independent of order of operations186muhash.Finalize(out);188muhash = MuHash3072();189muhash.Insert(data2);190muhash.Insert(data);191muhash.Finalize(out2);192},193[&] {194// Test that multiplication with the initial state never changes the finalized result195muhash.Finalize(out);196MuHash3072 muhash3;197muhash3 *= muhash;198muhash3.Finalize(out2);199},200[&] {201// Test that dividing a MuHash by itself brings it back to its initial state202muhash /= muhash;203muhash.Finalize(out);204out2 = initial_state_hash;205},206[&] {207// Test that removing all added elements brings the object back to its initial state208muhash.Remove(data);209muhash.Remove(data2);210muhash.Finalize(out);211out2 = initial_state_hash;212});213assert(out == out2);214}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.