Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
chonk.test.cpp
Go to the documentation of this file.
13#include "gtest/gtest.h"
14
15using namespace bb;
16
17static constexpr size_t SMALL_LOG_2_NUM_GATES = 5;
18
19class ChonkTests : public ::testing::Test {
20 protected:
22
24 using FF = typename Flavor::FF;
31 using CircuitProducer = PrivateFunctionExecutionMockCircuitProducer;
32
33 public:
40 static void tamper_with_proof(HonkProof& proof, size_t public_inputs_offset)
41 {
42 // Tamper with the commitment in the proof
43 Commitment commitment = FrCodec::deserialize_from_fields<Commitment>(
44 std::span{ proof }.subspan(public_inputs_offset, FrCodec::template calc_num_fields<Commitment>()));
45 commitment = commitment + Commitment::one();
46 auto commitment_frs = FrCodec::serialize_to_fields<Commitment>(commitment);
47 for (size_t idx = 0; idx < 4; ++idx) {
48 proof[public_inputs_offset + idx] = commitment_frs[idx];
49 }
50 }
51
53 TestSettings settings = {},
54 bool check_circuit_sizes = false)
55 {
56 CircuitProducer circuit_producer(num_app_circuits);
57 const size_t num_circuits = circuit_producer.total_num_circuits;
58 Chonk ivc{ num_circuits };
59
60 for (size_t j = 0; j < num_circuits; ++j) {
61 circuit_producer.construct_and_accumulate_next_circuit(ivc, settings, check_circuit_sizes);
62 }
63 return { ivc.prove(), ivc.get_vk() };
64 };
65};
66
74TEST_F(ChonkTests, TestCircuitSizes)
75{
76 const size_t NUM_APP_CIRCUITS = 2;
77
78 // Check circuit sizes when no settings are passed
79 {
80 auto [proof, vk] = accumulate_and_prove_ivc(NUM_APP_CIRCUITS, {}, true);
81 EXPECT_TRUE(Chonk::verify(proof, vk));
82 }
83
84 // Check circuit sizes when no settings are passed
85 {
86 auto [proof, vk] =
87 accumulate_and_prove_ivc(NUM_APP_CIRCUITS, { .log2_num_gates = SMALL_LOG_2_NUM_GATES }, true);
88 EXPECT_TRUE(Chonk::verify(proof, vk));
89 }
90};
91
99{
100 const size_t NUM_APP_CIRCUITS = 2;
101 auto [proof, vk] = accumulate_and_prove_ivc(NUM_APP_CIRCUITS);
102
103 EXPECT_TRUE(Chonk::verify(proof, vk));
104};
105
113TEST_F(ChonkTests, BadProofFailure)
114{
115 BB_DISABLE_ASSERTS(); // Disable assert in HN prover
116
117 const size_t NUM_APP_CIRCUITS = 2;
118 // Confirm that the IVC verifies if nothing is tampered with
119 {
120
121 CircuitProducer circuit_producer(NUM_APP_CIRCUITS);
122 const size_t NUM_CIRCUITS = circuit_producer.total_num_circuits;
123 Chonk ivc{ NUM_CIRCUITS };
124 TestSettings settings{ .log2_num_gates = SMALL_LOG_2_NUM_GATES };
125
126 // Construct and accumulate a set of mocked private function execution circuits
127 for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
128 circuit_producer.construct_and_accumulate_next_circuit(ivc, settings);
129 }
130 auto proof = ivc.prove();
131 EXPECT_TRUE(Chonk::verify(proof, ivc.get_vk()));
132 }
133
134 // The IVC throws an exception if the FIRST fold proof is tampered with
135 {
136 CircuitProducer circuit_producer(NUM_APP_CIRCUITS);
137 const size_t NUM_CIRCUITS = circuit_producer.total_num_circuits;
138 Chonk ivc{ NUM_CIRCUITS };
139
140 size_t num_public_inputs = 0;
141
142 // Construct and accumulate a set of mocked private function execution circuits
143 for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
144 auto [circuit, vk] =
145 circuit_producer.create_next_circuit_and_vk(ivc, { .log2_num_gates = SMALL_LOG_2_NUM_GATES });
146 ivc.accumulate(circuit, vk);
147
148 if (idx == 1) {
149 num_public_inputs = circuit.num_public_inputs();
150 }
151
152 if (idx == 2) {
153 EXPECT_EQ(ivc.verification_queue.size(), 2); // two proofs after 3 calls to accumulation
154 tamper_with_proof(ivc.verification_queue[0].proof,
155 num_public_inputs); // tamper with first proof
156 }
157 }
158 auto proof = ivc.prove();
159 EXPECT_FALSE(Chonk::verify(proof, ivc.get_vk()));
160 }
161
162 // The IVC fails if the SECOND fold proof is tampered with
163 {
164 CircuitProducer circuit_producer(NUM_APP_CIRCUITS);
165 const size_t NUM_CIRCUITS = circuit_producer.total_num_circuits;
166 Chonk ivc{ NUM_CIRCUITS };
167
168 // Construct and accumulate a set of mocked private function execution circuits
169 for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
170 auto [circuit, vk] =
171 circuit_producer.create_next_circuit_and_vk(ivc, { .log2_num_gates = SMALL_LOG_2_NUM_GATES });
172 ivc.accumulate(circuit, vk);
173
174 if (idx == 2) {
175 EXPECT_EQ(ivc.verification_queue.size(), 2); // two proofs after 3 calls to accumulation
176 tamper_with_proof(ivc.verification_queue[1].proof,
177 circuit.num_public_inputs()); // tamper with second proof
178 }
179 }
180 auto proof = ivc.prove();
181 EXPECT_FALSE(Chonk::verify(proof, ivc.get_vk()));
182 }
183
184 // The IVC fails if the calldata of the Hiding Kernel is different from the return data of the Tail Kernels
185 {
186 CircuitProducer circuit_producer(NUM_APP_CIRCUITS);
187 const size_t NUM_CIRCUITS = circuit_producer.total_num_circuits;
188 Chonk ivc{ NUM_CIRCUITS };
189
190 // Construct and accumulate a set of mocked private function execution circuits
191 for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
192 auto [circuit, vk] =
193 circuit_producer.create_next_circuit_and_vk(ivc, { .log2_num_gates = SMALL_LOG_2_NUM_GATES });
194 ivc.accumulate(circuit, vk);
195 }
196 auto proof = ivc.prove();
197
198 // The public input after the PairingPoints is the commitment to the return data of the Tail kernel.
199 tamper_with_proof(proof.mega_proof, PAIRING_POINTS_SIZE);
200 EXPECT_FALSE(Chonk::verify(proof, ivc.get_vk()));
201 }
202
203 EXPECT_TRUE(true);
204};
205
211TEST_F(ChonkTests, WrongProofComponentFailure)
212{
213 // Produce two valid proofs
214 auto [chonk_proof_1, chonk_vk_1] = accumulate_and_prove_ivc(/*num_app_circuits=*/1);
215 {
216 EXPECT_TRUE(Chonk::verify(chonk_proof_1, chonk_vk_1));
217 }
218
219 auto [chonk_proof_2, chonk_vk_2] = accumulate_and_prove_ivc(/*num_app_circuits=*/1);
220 {
221 EXPECT_TRUE(Chonk::verify(chonk_proof_2, chonk_vk_2));
222 }
223
224 {
225 // Replace Merge proof
226 Chonk::Proof tampered_proof = chonk_proof_1;
227
228 tampered_proof.goblin_proof.merge_proof = chonk_proof_2.goblin_proof.merge_proof;
229
230 EXPECT_THROW_OR_ABORT(Chonk::verify(tampered_proof, chonk_vk_1), ".*IPA verification fails.*");
231 }
232
233 {
234 // Replace Hiding kernel proof
235 Chonk::Proof tampered_proof = chonk_proof_1;
236
237 tampered_proof.mega_proof = chonk_proof_2.mega_proof;
238
239 EXPECT_THROW_OR_ABORT(Chonk::verify(tampered_proof, chonk_vk_1), ".*IPA verification fails.*");
240 }
241
242 {
243 // Replace ECCVM proof
244 Chonk::Proof tampered_proof = chonk_proof_1;
245
246 tampered_proof.goblin_proof.eccvm_proof = chonk_proof_2.goblin_proof.eccvm_proof;
247
248 EXPECT_THROW_OR_ABORT(Chonk::verify(tampered_proof, chonk_vk_1), ".*IPA verification fails.*");
249 }
250
251 {
252 // Replace Translator proof
253 Chonk::Proof tampered_proof = chonk_proof_1;
254
255 tampered_proof.goblin_proof.translator_proof = chonk_proof_2.goblin_proof.translator_proof;
256
257 EXPECT_FALSE(Chonk::verify(tampered_proof, chonk_vk_1));
258 }
259};
260
265TEST_F(ChonkTests, VKIndependenceFromNumberOfCircuits)
266{
267 const TestSettings settings{ .log2_num_gates = SMALL_LOG_2_NUM_GATES };
268
269 auto [unused_1, chonk_vk_1] = accumulate_and_prove_ivc(/*num_app_circuits=*/1, settings);
270 auto [unused_2, chonk_vk_2] = accumulate_and_prove_ivc(/*num_app_circuits=*/3, settings);
271
272 // Check the equality of the Mega components of the Chonk VKeys.
273 EXPECT_EQ(*chonk_vk_1.mega.get(), *chonk_vk_2.mega.get());
274
275 // Check the equality of the ECCVM components of the Chonk VKeys.
276 EXPECT_EQ(*chonk_vk_1.eccvm.get(), *chonk_vk_2.eccvm.get());
277
278 // Check the equality of the Translator components of the Chonk VKeys.
279 EXPECT_EQ(*chonk_vk_1.translator.get(), *chonk_vk_2.translator.get());
280};
281
286TEST_F(ChonkTests, VKIndependenceFromCircuitSize)
287{
288 // Run IVC for two sets of circuits
289 const size_t NUM_APP_CIRCUITS = 1;
290 const size_t log2_num_gates_small = 5;
291 const size_t log2_num_gates_big = 18;
292
293 const TestSettings settings_1{ .log2_num_gates = log2_num_gates_small };
294 const TestSettings settings_2{ .log2_num_gates = log2_num_gates_big };
295
296 auto [unused_1, chonk_vk_1] = accumulate_and_prove_ivc(NUM_APP_CIRCUITS, settings_1);
297 auto [unused_2, chonk_vk_2] = accumulate_and_prove_ivc(NUM_APP_CIRCUITS, settings_2);
298
299 // Check the equality of the Mega components of the Chonk VKeys.
300 EXPECT_EQ(*chonk_vk_1.mega.get(), *chonk_vk_2.mega.get());
301
302 // Check the equality of the ECCVM components of the Chonk VKeys.
303 EXPECT_EQ(*chonk_vk_1.eccvm.get(), *chonk_vk_2.eccvm.get());
304
305 // Check the equality of the Translator components of the Chonk VKeys.
306 EXPECT_EQ(*chonk_vk_1.translator.get(), *chonk_vk_2.translator.get());
307};
308
313HEAVY_TEST(ChonkKernelCapacity, MaxCapacityPassing)
314{
316
317 const size_t NUM_APP_CIRCUITS = 17;
318 auto [proof, vk] = ChonkTests::accumulate_and_prove_ivc(NUM_APP_CIRCUITS);
319
320 bool verified = Chonk::verify(proof, vk);
321 EXPECT_TRUE(verified);
322};
323
328TEST_F(ChonkTests, MsgpackProofFromFileOrBuffer)
329{
330 // Generate an arbitrary valid CICV proof
331 TestSettings settings{ .log2_num_gates = SMALL_LOG_2_NUM_GATES };
332 auto [proof, vk] = accumulate_and_prove_ivc(/*num_app_circuits=*/1, settings);
333
334 { // Serialize/deserialize the proof to/from a file, check that it verifies
335 const std::string filename = "proof.msgpack";
336 proof.to_file_msgpack(filename);
337 auto proof_deserialized = Chonk::Proof::from_file_msgpack(filename);
338
339 EXPECT_TRUE(Chonk::verify(proof_deserialized, vk));
340 }
341
342 { // Serialize/deserialize proof to/from a heap buffer, check that it verifies
343 uint8_t* buffer = proof.to_msgpack_heap_buffer();
344 auto uint8_buffer = from_buffer<std::vector<uint8_t>>(buffer);
345 uint8_t const* uint8_ptr = uint8_buffer.data();
346 auto proof_deserialized = Chonk::Proof::from_msgpack_buffer(uint8_ptr);
347
348 EXPECT_TRUE(Chonk::verify(proof_deserialized, vk));
349 }
350
351 { // Check that attempting to deserialize a proof from a buffer with random bytes fails gracefully
352 msgpack::sbuffer buffer = proof.to_msgpack_buffer();
353 auto proof_deserialized = Chonk::Proof::from_msgpack_buffer(buffer);
354 EXPECT_TRUE(Chonk::verify(proof_deserialized, vk));
355
356 std::vector<uint8_t> random_bytes(buffer.size());
357 std::generate(random_bytes.begin(), random_bytes.end(), []() { return static_cast<uint8_t>(rand() % 256); });
358 std::copy(random_bytes.begin(), random_bytes.end(), buffer.data());
359
360 // Expect deserialization to fail with error msgpack::v1::type_error with description "std::bad_cast"
361 EXPECT_THROW(Chonk::Proof::from_msgpack_buffer(buffer), msgpack::v1::type_error);
362 }
363};
364
374TEST_F(ChonkTests, DatabusFailure)
375{
376 BB_DISABLE_ASSERTS(); // Disable assert in HN prover
377
378 PrivateFunctionExecutionMockCircuitProducer circuit_producer{ /*num_app_circuits=*/1 };
379 const size_t NUM_CIRCUITS = circuit_producer.total_num_circuits;
380 Chonk ivc{ NUM_CIRCUITS };
381
382 // Construct and accumulate a series of mocked private function execution circuits
383 for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
384 auto [circuit, vk] = circuit_producer.create_next_circuit_and_vk(ivc);
385
386 // Tamper with the return data of the app circuit before it is processed as input to the next kernel
387 if (idx == 0) {
388 circuit_producer.tamper_with_databus();
389 }
390
391 ivc.accumulate(circuit, vk);
392 }
393
394 auto proof = ivc.prove();
395 EXPECT_FALSE(Chonk::verify(proof, ivc.get_vk()));
396};
#define EXPECT_THROW_OR_ABORT(statement, matcher)
Definition assert.hpp:174
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:32
TEST_F(ChonkTests, TestCircuitSizes)
Test sizes of the circuits generated by MockCircuitProducer.
PrivateFunctionExecutionMockCircuitProducer CircuitProducer
static void tamper_with_proof(HonkProof &proof, size_t public_inputs_offset)
Tamper with a proof.
Flavor::Commitment Commitment
static void SetUpTestSuite()
typename Flavor::FF FF
static std::pair< Chonk::Proof, Chonk::VerificationKey > accumulate_and_prove_ivc(size_t num_app_circuits, TestSettings settings={}, bool check_circuit_sizes=false)
The IVC scheme used by the aztec client for private function execution.
Definition chonk.hpp:38
HypernovaDeciderProver DeciderProver
Definition chonk.hpp:78
Proof prove()
Construct a proof for the IVC, which, if verified, fully establishes its correctness.
Definition chonk.cpp:511
ProverInstance_< Flavor > ProverInstance
Definition chonk.hpp:49
MegaFlavor Flavor
Definition chonk.hpp:42
VerifierInstance_< Flavor > VerifierInstance
Definition chonk.hpp:51
void accumulate(ClientCircuit &circuit, const std::shared_ptr< MegaVerificationKey > &precomputed_vk) override
Perform prover work for accumulation (e.g. HN folding, merge proving)
Definition chonk.cpp:361
MegaCircuitBuilder ClientCircuit
Definition chonk.hpp:52
static bool verify(const Proof &proof, const VerificationKey &vk)
Definition chonk.cpp:528
The verification key is responsible for storing the commitments to the precomputed (non-witness) poly...
Curve::ScalarField FF
Curve::AffineElement Commitment
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
The VerifierInstance encapsulates all the necessary information for a Mega Honk Verifier to verify a ...
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::vector< fr > HonkProof
Definition proof.hpp:15
::testing::Types< BN254Settings, GrumpkinSettings > TestSettings
void tamper_with_proof(InnerProver &inner_prover, ProofType &inner_proof, TamperType type)
Test method that provides several ways to tamper with a proof. TODO(https://github....
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
A full proof for the IVC scheme containing a Mega proof showing correctness of the Hiding kernel (whi...
Definition chonk.hpp:91
static Proof from_msgpack_buffer(uint8_t const *&buffer)
Definition chonk.cpp:623
static Proof from_file_msgpack(const std::string &filename)
Definition chonk.cpp:653
HonkProof mega_proof
Definition chonk.hpp:92
GoblinProof goblin_proof
Definition chonk.hpp:93
HonkProof eccvm_proof
Definition types.hpp:23
HonkProof merge_proof
Definition types.hpp:22
HonkProof translator_proof
Definition types.hpp:25
#define HEAVY_TEST(x, y)
Definition test.hpp:9