Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
acir_integration.test.cpp
Go to the documentation of this file.
4#ifndef __wasm__
11
12#include <filesystem>
13#include <gtest/gtest.h>
14
15// #define LOG_SIZES
16
17using namespace bb;
18class AcirIntegrationTest : public ::testing::Test {
19 public:
20 // Function to check if a file exists
21 static bool file_exists(const std::string& path)
22 {
23 std::ifstream file(path);
24 return file.good();
25 }
26
27 static acir_format::AcirProgram get_program_data_from_test_file(const std::string& test_program_name)
28 {
29 std::string base_path = "../../acir_tests/acir_tests/" + test_program_name + "/target";
30 std::string bytecode_path = base_path + "/program.json";
31 std::string witness_path = base_path + "/witness.gz";
32
33 std::vector<uint8_t> bytecode = get_bytecode(bytecode_path);
34 std::vector<uint8_t> witness = get_bytecode(witness_path);
37
38 return { program, witness_vector };
39 }
40
42 {
43 using Prover = UltraProver_<Flavor>;
45 using Verifier = UltraVerifier_<Flavor, IO>;
47
49 auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
50 Prover prover{ prover_instance, verification_key };
51#ifdef LOG_SIZES
52 builder.blocks.summarize();
53 info("num gates = ", builder.get_num_finalized_gates_inefficient());
54 info("total circuit size = ", builder.get_estimated_total_circuit_size());
55 info("circuit size = ", prover.prover_instance->dyadic_size());
56 info("log circuit size = ", prover.prover_instance->log_dyadic_size());
57#endif
58 auto proof = prover.construct_proof();
59
60 // Verify Honk proof
61 auto vk_and_hash = std::make_shared<typename Flavor::VKAndHash>(verification_key);
62 Verifier verifier{ vk_and_hash };
63 bool result = verifier.verify_proof(proof).result;
64
65 return result;
66 }
67
68 void add_some_simple_RAM_gates(auto& circuit)
69 {
70 std::array<uint32_t, 3> ram_values{ circuit.add_variable(bb::fr(5)),
71 circuit.add_variable(bb::fr(10)),
72 circuit.add_variable(bb::fr(20)) };
73
74 size_t ram_id = circuit.create_RAM_array(3);
75
76 for (size_t i = 0; i < 3; ++i) {
77 circuit.init_RAM_element(ram_id, i, ram_values[i]);
78 }
79
80 auto val_idx_1 = circuit.read_RAM_array(ram_id, circuit.add_variable(bb::fr(1)));
81 auto val_idx_2 = circuit.read_RAM_array(ram_id, circuit.add_variable(bb::fr(2)));
82 auto val_idx_3 = circuit.read_RAM_array(ram_id, circuit.add_variable(bb::fr(0)));
83
84 circuit.create_big_add_gate({
85 val_idx_1,
86 val_idx_2,
87 val_idx_3,
88 circuit.zero_idx(),
89 1,
90 1,
91 1,
92 0,
93 -35,
94 });
95 }
96
97 protected:
99};
100
101class AcirIntegrationSingleTest : public AcirIntegrationTest, public testing::WithParamInterface<std::string> {};
102
103TEST_P(AcirIntegrationSingleTest, DISABLED_ProveAndVerifyProgram)
104{
105 using Flavor = UltraFlavor;
107
108 std::string test_name = GetParam();
109 info("Test: ", test_name);
110 acir_format::AcirProgram acir_program = get_program_data_from_test_file(test_name);
111
112 // Construct a bberg circuit from the acir representation
113 Builder builder = acir_format::create_circuit<Builder>(acir_program);
114
115 // Construct and verify Honk proof
116 EXPECT_TRUE(prove_and_verify_honk<Flavor>(builder));
117}
118
119// TODO(https://github.com/AztecProtocol/barretenberg/issues/994): Run all tests
122 testing::Values("a_1327_concrete_in_generic",
123 "a_1_mul",
124 "a_2_div",
125 "a_3_add",
126 "a_4_sub",
127 "a_5_over",
128 "a_6",
129 "a_6_array",
130 "a_7",
131 "a_7_function",
132 "aes128_encrypt",
133 "arithmetic_binary_operations",
134 "array_dynamic",
135 "array_dynamic_blackbox_input",
136 "array_dynamic_main_output",
137 "array_dynamic_nested_blackbox_input",
138 "array_eq",
139 "array_if_cond_simple",
140 "array_len",
141 "array_neq",
142 "array_sort",
143 "array_to_slice",
144 "array_to_slice_constant_length",
145 "assert",
146 "assert_statement",
147 "assign_ex",
148 "bigint",
149 "bit_and",
150 "bit_not",
151 "bit_shifts_comptime",
152 "bit_shifts_runtime",
153 "blake3",
154 "bool_not",
155 "bool_or",
156 "break_and_continue",
157 "brillig_acir_as_brillig",
158 "brillig_array_eq",
159 "brillig_array_to_slice",
160 "brillig_arrays",
161 "brillig_assert",
162 "brillig_bit_shifts_runtime",
163 "brillig_blake2s",
164 "brillig_blake3",
165 "brillig_calls",
166 "brillig_calls_array",
167 "brillig_calls_conditionals",
168 "brillig_conditional",
169 "brillig_cow",
170 "brillig_cow_assign",
171 "brillig_cow_regression",
172 "brillig_ecdsa_secp256k1",
173 "brillig_ecdsa_secp256r1",
174 "brillig_embedded_curve",
175 "brillig_fns_as_values",
176 "brillig_hash_to_field",
177 "brillig_identity_function",
178 "brillig_keccak",
179 "brillig_loop",
180 "brillig_nested_arrays",
181 "brillig_not",
182 "brillig_oracle",
183 "brillig_pedersen",
184 "brillig_recursion",
185 "brillig_references",
186 "brillig_schnorr",
187 "brillig_sha256",
188 "brillig_signed_cmp",
189 "brillig_signed_div",
190 "brillig_slices",
191 "brillig_to_be_bytes",
192 "brillig_to_bits",
193 "brillig_to_bytes_integration",
194 "brillig_to_le_bytes",
195 "brillig_top_level",
196 "brillig_uninitialized_arrays",
197 "brillig_wrapping",
198 "cast_bool",
199 "closures_mut_ref",
200 "conditional_1",
201 "conditional_2",
202 "conditional_regression_421",
203 "conditional_regression_547",
204 "conditional_regression_661",
205 "conditional_regression_short_circuit",
206 "conditional_regression_underflow",
207 "custom_entry",
208 "databus",
209 "debug_logs",
210 "diamond_deps_0",
211 "double_verify_nested_proof",
212 "double_verify_proof",
213 "ecdsa_secp256k1",
214 "ecdsa_secp256r1",
215 "ecdsa_secp256r1_3x",
216 "eddsa",
217 "embedded_curve_ops",
218 "field_attribute",
219 "generics",
220 "global_consts",
221 "hash_to_field",
222 "hashmap",
223 "higher_order_functions",
224 "if_else_chain",
225 "import",
226 "inline_never_basic",
227 "integer_array_indexing",
228 "keccak256",
229 "main_bool_arg",
230 "main_return",
231 "merkle_insert",
232 "missing_closure_env",
233 "modules",
234 "modules_more",
235 "modulus",
236 "nested_array_dynamic",
237 "nested_array_dynamic_simple",
238 "nested_array_in_slice",
239 "nested_arrays_from_brillig",
240 "no_predicates_basic",
241 "no_predicates_brillig",
242 "no_predicates_numeric_generic_poseidon",
243 "operator_overloading",
244 "pedersen_check",
245 "pedersen_commitment",
246 "pedersen_hash",
247 "poseidon_bn254_hash",
248 "poseidonsponge_x5_254",
249 "pred_eq",
250 "prelude",
251 "references",
252 "regression",
253 "regression_2660",
254 "regression_3051",
255 "regression_3394",
256 "regression_3607",
257 "regression_3889",
258 "regression_4088",
259 "regression_4124",
260 "regression_4202",
261 "regression_4449",
262 "regression_4709",
263 "regression_5045",
264 "regression_capacity_tracker",
265 "regression_mem_op_predicate",
266 "regression_method_cannot_be_found",
267 "regression_struct_array_conditional",
268 "schnorr",
269 "sha256",
270 "sha2_byte",
271 "side_effects_constrain_array",
272 "signed_arithmetic",
273 "signed_comparison",
274 "signed_division",
275 "simple_2d_array",
276 "simple_add_and_ret_arr",
277 "simple_array_param",
278 "simple_bitwise",
279 "simple_comparison",
280 "simple_mut",
281 "simple_not",
282 "simple_print",
283 "simple_program_addition",
284 "simple_radix",
285 "simple_shield",
286 "simple_shift_left_right",
287 "slice_coercion",
288 "slice_dynamic_index",
289 "slice_loop",
290 "slices",
291 "strings",
292 "struct",
293 "struct_array_inputs",
294 "struct_fields_ordering",
295 "struct_inputs",
296 "submodules",
297 "to_be_bytes",
298 "to_bytes_consistent",
299 "to_bytes_integration",
300 "to_le_bytes",
301 "trait_as_return_type",
302 "trait_impl_base_type",
303 "traits_in_crates_1",
304 "traits_in_crates_2",
305 "tuple_inputs",
306 "tuples",
307 "type_aliases",
308 "u128",
309 "u16_support",
310 "unconstrained_empty",
311 "unit_value",
312 "unsafe_range_constraint",
313 "witness_compression",
314 // "workspace",
315 // "workspace_default_member",
316 "xor"));
317
322TEST_F(AcirIntegrationTest, DISABLED_Databus)
323{
324 using Flavor = MegaFlavor;
326
327 std::string test_name = "databus";
328 info("Test: ", test_name);
329 acir_format::AcirProgram acir_program = get_program_data_from_test_file(test_name);
330
331 // Construct a bberg circuit from the acir representation
332 Builder builder = acir_format::create_circuit<Builder>(acir_program);
333
334 // This prints a summary of the types of gates in the circuit
335 builder.blocks.summarize();
336
337 // Construct and verify Honk proof
338 EXPECT_TRUE(prove_and_verify_honk<Flavor>(builder));
339}
340
346TEST_F(AcirIntegrationTest, DISABLED_DatabusTwoCalldata)
347{
348 using Flavor = MegaFlavor;
350
351 std::string test_name = "databus_two_calldata";
352 info("Test: ", test_name);
353 acir_format::AcirProgram acir_program = get_program_data_from_test_file(test_name);
354
355 // Construct a bberg circuit from the acir representation
356 Builder builder = acir_format::create_circuit<Builder>(acir_program);
357
358 // Check that the databus columns in the builder have been populated as expected
359 const auto& calldata = builder.get_calldata();
360 const auto& secondary_calldata = builder.get_secondary_calldata();
361 const auto& return_data = builder.get_return_data();
362
363 ASSERT_EQ(calldata.size(), static_cast<size_t>(4));
364 ASSERT_EQ(secondary_calldata.size(), static_cast<size_t>(3));
365 ASSERT_EQ(return_data.size(), static_cast<size_t>(4));
366
367 // Check that return data was computed from the two calldata inputs as expected
368 ASSERT_EQ(builder.get_variable(calldata[0]) + builder.get_variable(secondary_calldata[0]),
369 builder.get_variable(return_data[0]));
370 ASSERT_EQ(builder.get_variable(calldata[1]) + builder.get_variable(secondary_calldata[1]),
371 builder.get_variable(return_data[1]));
372 ASSERT_EQ(builder.get_variable(calldata[2]) + builder.get_variable(secondary_calldata[2]),
373 builder.get_variable(return_data[2]));
374 ASSERT_EQ(builder.get_variable(calldata[3]), builder.get_variable(return_data[3]));
375
376 // Ensure that every index of each bus column was read once as expected
377 for (size_t idx = 0; idx < calldata.size(); ++idx) {
378 ASSERT_EQ(calldata.get_read_count(idx), 1);
379 }
380 for (size_t idx = 0; idx < secondary_calldata.size(); ++idx) {
381 ASSERT_EQ(secondary_calldata.get_read_count(idx), 1);
382 }
383 for (size_t idx = 0; idx < return_data.size(); ++idx) {
384 ASSERT_EQ(return_data.get_read_count(idx), 1);
385 }
386
387 // This prints a summary of the types of gates in the circuit
388 builder.blocks.summarize();
389
390 // Construct and verify Honk proof
391 EXPECT_TRUE(prove_and_verify_honk<Flavor>(builder));
392}
393
399TEST_F(AcirIntegrationTest, DISABLED_UpdateAcirCircuit)
400{
401 using Flavor = MegaFlavor;
403
404 std::string test_name = "6_array"; // arbitrary program with RAM gates
405 auto acir_program = get_program_data_from_test_file(test_name);
406
407 // Construct a bberg circuit from the acir representation
408 Builder circuit = acir_format::create_circuit<Builder>(acir_program);
409
410 EXPECT_TRUE(CircuitChecker::check(circuit));
411
412 // Now append some RAM gates onto the circuit generated from acir and confirm that its still valid. (First, check
413 // that the RAM operations constitute a valid independent circuit).
414 {
415 Builder circuit;
416 add_some_simple_RAM_gates(circuit);
417 EXPECT_TRUE(CircuitChecker::check(circuit));
418 EXPECT_TRUE(prove_and_verify_honk<Flavor>(circuit));
419 }
420
421 // Now manually append the simple RAM circuit to the circuit generated from acir
422 add_some_simple_RAM_gates(circuit);
423
424 // Confirm that the result is still valid
425 EXPECT_TRUE(CircuitChecker::check(circuit));
426 EXPECT_TRUE(prove_and_verify_honk<Flavor>(circuit));
427}
428
433TEST_F(AcirIntegrationTest, DISABLED_HonkRecursion)
434{
435 using Flavor = UltraFlavor;
437
438 std::string test_name = "verify_honk_proof"; // program that recursively verifies a honk proof
439 auto acir_program = get_program_data_from_test_file(test_name);
440
441 // Construct a bberg circuit from the acir representation
442 Builder circuit = acir_format::create_circuit<Builder>(acir_program);
443
444 EXPECT_TRUE(CircuitChecker::check(circuit));
445 EXPECT_TRUE(prove_and_verify_honk<Flavor>(circuit));
446}
447
452TEST_F(AcirIntegrationTest, DISABLED_ChonkMsgpackInputs)
453{
454 // NOTE: to populate the test inputs at this location, run the following commands:
455 // export AZTEC_CACHE_COMMIT=origin/master~3
456 // export FORCE_CACHE_DOWNLOAD=1
457 // yarn-project/end-to-end/bootstrap.sh build_bench
458 std::string input_path = "../../../yarn-project/end-to-end/example-app-ivc-inputs-out/"
459 "ecdsar1+transfer_0_recursions+sponsored_fpc/ivc-inputs.msgpack";
460
463
465 ChonkProof proof = ivc->prove();
466 ChonkNativeVerifier chonk_verifier(ivc->get_hiding_kernel_vk_and_hash());
467 EXPECT_TRUE(chonk_verifier.verify(proof));
468}
469
474TEST_F(AcirIntegrationTest, DISABLED_DummyWitnessVkConsistency)
475{
476 std::string input_path = "../../../yarn-project/end-to-end/example-app-ivc-inputs-out/"
477 "ecdsar1+transfer_0_recursions+sponsored_fpc/ivc-inputs.msgpack";
478
481
482 uint256_t recomputed_vk_hash{ 0 };
483 uint256_t computed_vk_hash{ 0 };
484
485 for (auto [program_in, precomputed_vk, function_name] :
487
488 // Compute the VK using the program constraints but no witness (i.e. mimic the "dummy witness" case)
489 {
490 auto program = program_in;
491 program.witness = {}; // erase the witness to mimmic the "dummy witness" case
492 auto& ivc_constraints = program.constraints.hn_recursion_constraints;
493 const acir_format::ProgramMetadata metadata{
494 .ivc =
495 ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints)
496 };
497
498 auto circuit = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
499 recomputed_vk_hash = prover_instance_inspector::compute_vk_hash<MegaFlavor>(circuit);
500 }
501
502 // Compute the verification key using the genuine witness
503 {
504 auto program = program_in;
505 auto& ivc_constraints = program.constraints.hn_recursion_constraints;
506 const acir_format::ProgramMetadata metadata{
507 .ivc =
508 ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints)
509 };
510
511 auto circuit = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
512 computed_vk_hash = prover_instance_inspector::compute_vk_hash<MegaFlavor>(circuit);
513 }
514
515 // Check that the hashes computed from the dummy witness VK and the genuine witness VK are equal
516 EXPECT_EQ(recomputed_vk_hash, computed_vk_hash);
517 // Check that the VK hashes match the hash of the precomputed VK contained in the msgpack inputs
518 EXPECT_EQ(computed_vk_hash, precomputed_vk->hash());
519 }
520}
521#endif
INSTANTIATE_TEST_SUITE_P(AcirTests, AcirIntegrationSingleTest, testing::Values("a_1327_concrete_in_generic", "a_1_mul", "a_2_div", "a_3_add", "a_4_sub", "a_5_over", "a_6", "a_6_array", "a_7", "a_7_function", "aes128_encrypt", "arithmetic_binary_operations", "array_dynamic", "array_dynamic_blackbox_input", "array_dynamic_main_output", "array_dynamic_nested_blackbox_input", "array_eq", "array_if_cond_simple", "array_len", "array_neq", "array_sort", "array_to_slice", "array_to_slice_constant_length", "assert", "assert_statement", "assign_ex", "bigint", "bit_and", "bit_not", "bit_shifts_comptime", "bit_shifts_runtime", "blake3", "bool_not", "bool_or", "break_and_continue", "brillig_acir_as_brillig", "brillig_array_eq", "brillig_array_to_slice", "brillig_arrays", "brillig_assert", "brillig_bit_shifts_runtime", "brillig_blake2s", "brillig_blake3", "brillig_calls", "brillig_calls_array", "brillig_calls_conditionals", "brillig_conditional", "brillig_cow", "brillig_cow_assign", "brillig_cow_regression", "brillig_ecdsa_secp256k1", "brillig_ecdsa_secp256r1", "brillig_embedded_curve", "brillig_fns_as_values", "brillig_hash_to_field", "brillig_identity_function", "brillig_keccak", "brillig_loop", "brillig_nested_arrays", "brillig_not", "brillig_oracle", "brillig_pedersen", "brillig_recursion", "brillig_references", "brillig_schnorr", "brillig_sha256", "brillig_signed_cmp", "brillig_signed_div", "brillig_slices", "brillig_to_be_bytes", "brillig_to_bits", "brillig_to_bytes_integration", "brillig_to_le_bytes", "brillig_top_level", "brillig_uninitialized_arrays", "brillig_wrapping", "cast_bool", "closures_mut_ref", "conditional_1", "conditional_2", "conditional_regression_421", "conditional_regression_547", "conditional_regression_661", "conditional_regression_short_circuit", "conditional_regression_underflow", "custom_entry", "databus", "debug_logs", "diamond_deps_0", "double_verify_nested_proof", "double_verify_proof", "ecdsa_secp256k1", "ecdsa_secp256r1", "ecdsa_secp256r1_3x", "eddsa", "embedded_curve_ops", "field_attribute", "generics", "global_consts", "hash_to_field", "hashmap", "higher_order_functions", "if_else_chain", "import", "inline_never_basic", "integer_array_indexing", "keccak256", "main_bool_arg", "main_return", "merkle_insert", "missing_closure_env", "modules", "modules_more", "modulus", "nested_array_dynamic", "nested_array_dynamic_simple", "nested_array_in_slice", "nested_arrays_from_brillig", "no_predicates_basic", "no_predicates_brillig", "no_predicates_numeric_generic_poseidon", "operator_overloading", "pedersen_check", "pedersen_commitment", "pedersen_hash", "poseidon_bn254_hash", "poseidonsponge_x5_254", "pred_eq", "prelude", "references", "regression", "regression_2660", "regression_3051", "regression_3394", "regression_3607", "regression_3889", "regression_4088", "regression_4124", "regression_4202", "regression_4449", "regression_4709", "regression_5045", "regression_capacity_tracker", "regression_mem_op_predicate", "regression_method_cannot_be_found", "regression_struct_array_conditional", "schnorr", "sha256", "sha2_byte", "side_effects_constrain_array", "signed_arithmetic", "signed_comparison", "signed_division", "simple_2d_array", "simple_add_and_ret_arr", "simple_array_param", "simple_bitwise", "simple_comparison", "simple_mut", "simple_not", "simple_print", "simple_program_addition", "simple_radix", "simple_shield", "simple_shift_left_right", "slice_coercion", "slice_dynamic_index", "slice_loop", "slices", "strings", "struct", "struct_array_inputs", "struct_fields_ordering", "struct_inputs", "submodules", "to_be_bytes", "to_bytes_consistent", "to_bytes_integration", "to_le_bytes", "trait_as_return_type", "trait_impl_base_type", "traits_in_crates_1", "traits_in_crates_2", "tuple_inputs", "tuples", "type_aliases", "u128", "u16_support", "unconstrained_empty", "unit_value", "unsafe_range_constraint", "witness_compression", "xor"))
TEST_P(AcirIntegrationSingleTest, DISABLED_ProveAndVerifyProgram)
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
static bool file_exists(const std::string &path)
bool prove_and_verify_honk(Flavor::CircuitBuilder &builder)
void add_some_simple_RAM_gates(auto &circuit)
static acir_format::AcirProgram get_program_data_from_test_file(const std::string &test_program_name)
Verifier for Chonk IVC proofs (both native and recursive).
Output verify(const Proof &proof)
Verify a Chonk proof.
Manages the data that is propagated on the public inputs of an application/function circuit.
The verification key is responsible for storing the commitments to the precomputed (non-witnessk) pol...
ECCVMCircuitBuilder CircuitBuilder
Base Native verification key class.
Definition flavor.hpp:141
The data that is propagated on the public inputs of a rollup circuit.
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
void info(Args... args)
Definition log.hpp:89
AluTraceBuilder builder
Definition alu.test.cpp:124
std::vector< uint8_t > get_bytecode(const std::string &bytecodePath)
WitnessVector witness_buf_to_witness_vector(std::vector< uint8_t > &&buf)
Convert a buffer representing a witness vector into Barretenberg's internal WitnessVector format.
std::shared_ptr< Chonk > create_mock_chonk_from_constraints(const std::vector< RecursionConstraint > &constraints)
Create an IVC object with mocked state corresponding to a set of IVC recursion constraints.
std::vector< bb::fr > WitnessVector
AcirFormat circuit_buf_to_acir_format(std::vector< uint8_t > &&buf)
Convert a buffer representing a circuit into Barretenberg's internal AcirFormat representation.
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
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< MemoryValue > calldata
Barretenberg's representation of ACIR constraints.
Struct containing both the constraints to be added to the circuit and the witness vector.
Metadata required to create a circuit.
std::shared_ptr< bb::IVCBase > ivc
static std::vector< PrivateExecutionStepRaw > load_and_decompress(const std::filesystem::path &input_path)
Parsed private execution steps ready for Chonk accumulation.
std::shared_ptr< Chonk > accumulate()
Creates a Chonk instance and accumulates each circuit in the folding stack. Uses precomputed VKs when...
std::vector< std::shared_ptr< Chonk::MegaVerificationKey > > precomputed_vks
Precomputed VKs (performance)
void parse(std::vector< PrivateExecutionStepRaw > &&steps)
Converts PrivateExecutionStepRaw entries (which contain raw bytecode/witness bytes) into structured A...
std::vector< acir_format::AcirProgram > folding_stack
ACIR programs with witnesses.
std::vector< std::string > function_names
Function names for logging.