Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ipa.fuzzer.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
9#define IPA_FUZZ_TEST
10#include "./mock_transcript.hpp"
13#include "ipa.hpp"
14
15namespace bb {
16
17// We actually only use 4, because fuzzing is very slow
18constexpr size_t COMMITMENT_TEST_NUM_POINTS = 32;
27 public:
28 template <typename Transcript>
30 const ProverOpeningClaim<Curve>& opening_claim,
31 const std::shared_ptr<Transcript>& transcript,
32 size_t poly_log_size)
33 {
34 if (poly_log_size == 1) {
35 IPA<Curve, 1>::compute_opening_proof_internal(ck, opening_claim, transcript);
36 }
37 if (poly_log_size == 2) {
38 IPA<Curve, 2>::compute_opening_proof_internal(ck, opening_claim, transcript);
39 }
40 }
41 template <typename Transcript>
43 const OpeningClaim<Curve>& opening_claim,
44 const std::shared_ptr<Transcript>& transcript,
45 size_t poly_log_size)
46 {
47 if (poly_log_size == 1) {
48 return IPA<Curve, 1>::reduce_verify_internal_native(vk, opening_claim, transcript);
49 }
50 if (poly_log_size == 2) {
51 return IPA<Curve, 2>::reduce_verify_internal_native(vk, opening_claim, transcript);
52 }
53 return false;
54 }
55};
56} // namespace bb
57
58using namespace bb;
59
70
71// This define is needed to make ProxyClass a friend of IPA
72#define IPA_FUZZ_TEST
73#include "ipa.hpp"
74
75// Read uint256_t from raw bytes.
76// Don't use dereference casts, since the data may be not aligned and it causes segfault
77uint256_t read_uint256(const uint8_t* data, size_t buffer_size = 32)
78{
79 BB_ASSERT_LTE(buffer_size, 32U);
80
81 uint64_t parts[4] = { 0, 0, 0, 0 };
82
83 for (size_t i = 0; i < (buffer_size + 7) / 8; i++) {
84 size_t to_read = (buffer_size - i * 8) < 8 ? buffer_size - i * 8 : 8;
85 std::memcpy(&parts[i], data + i * 8, to_read);
86 }
87 return uint256_t(parts[0], parts[1], parts[2], parts[3]);
88}
89
96extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size)
97{
98 using Fr = grumpkin::fr;
100 // We need data
101 if (size == 0) {
102 return 0;
103 }
104 // Get the logarighmic size of polynomial
105 const auto log_size = static_cast<size_t>(data[0]);
106 // More than 4 is so bad
107 if (log_size == 0 || log_size > 2) {
108 return 0;
109 }
110 const auto* offset = data + 1;
111 const auto num_challenges = log_size + 1;
112 // How much data do we need?
113 // Challenges: sizeof(uint256_t) * num_challenges + 1 for montgomery switch
114 // Polynomial: sizeof(uint256_t) * size + 1 per size/8
115 // Eval x: sizeof(uint256_t) + 1
116 const size_t polynomial_size = (1 << log_size);
117 // Bytes controlling montgomery switching for polynomial coefficients
118 const size_t polynomial_control_bytes = (polynomial_size < 8 ? 1 : polynomial_size / 8);
119 const size_t expected_size =
120 1 /* log_size */ + 1 /* control_byte */ + num_challenges * sizeof(uint256_t) /* challenges */
121 + polynomial_size * sizeof(uint256_t) /* polynomial coefficients */ + sizeof(uint256_t) /* evaluation */ +
122 1 /* eval montgomery switch */ + polynomial_control_bytes;
123 if (size < expected_size) {
124 return 0;
125 }
126
127 // Initialize transcript
128 auto transcript = std::make_shared<MockTranscript>();
129
130 std::vector<uint256_t> challenges(num_challenges);
131 // Get the byte, where bits control if we parse challenges in montgomery form or not
132 const auto control_byte = offset[0];
133 offset++;
134 // Get challenges one by one
135 for (size_t i = 0; i < num_challenges; i++) {
136 auto challenge = read_uint256(offset);
137
138 if (((control_byte >> i) & 1) == 1) {
139 // If control byte says so, parse the value from input as if it's internal state of the field (already
140 // converted to montgomery). This allows modifying the state directly
141 auto field_challenge = Fr(challenge);
142
143 challenge = field_challenge.from_montgomery_form();
144 }
145 // Challenges can't be zero
146 if (Fr(challenge).is_zero()) {
147 return 0;
148 }
149 challenges[i] = challenge;
150 offset += sizeof(uint256_t);
151 }
152
153 // Put challenges into the transcript
154 transcript->initialize(challenges);
155
156 // Parse polynomial
157 std::vector<uint256_t> polynomial_coefficients(polynomial_size);
158 for (size_t i = 0; i < polynomial_size; i++) {
159 polynomial_coefficients[i] = read_uint256(offset);
160 offset += sizeof(uint256_t);
161 }
162 Polynomial poly(polynomial_size);
163
164 // Convert from montgomery if the appropriate bit is set
165 for (size_t i = 0; i < polynomial_size; i++) {
166 auto b = offset[i / 8];
167
168 poly.at(i) = polynomial_coefficients[i];
169 if (((b >> (i % 8)) & 1) == 1) {
171 }
172 }
173
174 offset += polynomial_control_bytes;
175 // Parse the x we are evaluating on
176 auto x = Fr(read_uint256(offset));
177 offset += sizeof(uint256_t);
178 if ((offset[0] & 1) != 0) {
179 x.self_from_montgomery_form();
180 }
181 auto const opening_pair = OpeningPair<Curve>{ x, poly.evaluate(x) };
182 auto const opening_claim = OpeningClaim<Curve>{ opening_pair, ck.commit(poly) };
183 ProxyCaller::compute_opening_proof_internal(ck, { poly, opening_pair }, transcript, log_size);
184
185 // Reset challenge indices
186 transcript->reset_indices();
187
188 // Should verify
189 if (!ProxyCaller::verify_internal(vk, opening_claim, transcript, log_size)) {
190 return 1;
191 }
192 return 0;
193}
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
CommitmentKey object over a pairing group 𝔾₁.
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:95
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:53
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Definition claim.hpp:19
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Fr evaluate(const Fr &z, size_t target_size) const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:34
Class that allows us to call internal IPA methods, because it's friendly.
static void compute_opening_proof_internal(const CommitmentKey< Curve > &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &transcript, size_t poly_log_size)
static bool verify_internal(const VerifierCommitmentKey< Curve > &vk, const OpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &transcript, size_t poly_log_size)
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
const std::vector< FF > data
FF b
ssize_t offset
Definition engine.cpp:36
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
A fuzzer for the IPA primitive.
uint256_t read_uint256(const uint8_t *data, size_t buffer_size=32)
void LLVMFuzzerInitialize(int *, char ***)
Initialize SRS, commitment key, verification key.
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
constexpr size_t COMMITMENT_TEST_NUM_POINTS
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
BB_INLINE constexpr void self_from_montgomery_form() &noexcept