diff --git a/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh index a0b1490c9d84..8963d723ef5b 100755 --- a/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_changed.sh @@ -21,7 +21,7 @@ script_path="$root/barretenberg/cpp/scripts/test_chonk_standalone_vks_havent_cha # - Generate a hash for versioning: sha256sum bb-chonk-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-chonk-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-chonk-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="b4b68156" +pinned_short_hash="0b4484d9" pinned_chonk_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-chonk-inputs-${pinned_short_hash}.tar.gz" function update_pinned_hash_in_script { diff --git a/barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp b/barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp index 9dcdb0f2467b..f45c55269170 100644 --- a/barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp @@ -405,7 +405,7 @@ HEAVY_TEST(ChonkKernelCapacity, MaxCapacityPassing) { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); - const size_t NUM_APP_CIRCUITS = 18; + const size_t NUM_APP_CIRCUITS = 21; auto [proof, vk] = ChonkTests::accumulate_and_prove_ivc(NUM_APP_CIRCUITS); bool verified = ChonkTests::verify_chonk(proof, vk); diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp index bab312c1670c..7208f43affbb 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp @@ -246,8 +246,9 @@ TEST(MegaCircuitBuilder, EccOpBlockIsFirstInTrace) /** * @brief Verify that an empty circuit can be finalized and passes circuit checks - * @details Finalization should add required gates to ensure all polynomials are non-zero - * @note This is a "completeness" test; unlikely to be a use-case. + * @details Mega finalization no longer adds dummy non-zero gates — the disabled head region and + * polynomial allocation handle the zero-commitment issue. Finalization still processes ROM/RAM + * arrays, range lists, and public inputs (all empty for an empty circuit). */ TEST(MegaCircuitBuilder, EmptyCircuitFinalization) { @@ -255,14 +256,28 @@ TEST(MegaCircuitBuilder, EmptyCircuitFinalization) // Completely empty circuit - no gates added EXPECT_EQ(builder.blocks.ecc_op.size(), 0); + EXPECT_FALSE(builder.circuit_finalized); builder.finalize_circuit(true); - // After finalization, ecc_op block remains empty (no dummy ops needed) + EXPECT_TRUE(builder.circuit_finalized); + + // After finalization: only zero_idx arithmetic gates and the corresponding public inputs remain. + // No dummy ecc ops, databus entries, or other gate types are added. + EXPECT_EQ(builder.blocks.arithmetic.size(), 4); // zero_idx setup + EXPECT_EQ(builder.blocks.pub_inputs.size(), 0); EXPECT_EQ(builder.blocks.ecc_op.size(), 0); - EXPECT_GT(builder.get_calldata().size(), 0) << "Finalization should add databus entries"; - EXPECT_GT(builder.get_secondary_calldata().size(), 0); - EXPECT_GT(builder.get_return_data().size(), 0); + EXPECT_EQ(builder.blocks.busread.size(), 0); + EXPECT_EQ(builder.blocks.lookup.size(), 0); + EXPECT_EQ(builder.blocks.delta_range.size(), 0); + EXPECT_EQ(builder.blocks.elliptic.size(), 0); + EXPECT_EQ(builder.blocks.memory.size(), 0); + EXPECT_EQ(builder.blocks.nnf.size(), 0); + EXPECT_EQ(builder.blocks.poseidon2_external.size(), 0); + EXPECT_EQ(builder.blocks.poseidon2_internal.size(), 0); + EXPECT_EQ(builder.get_calldata().size(), 0); + EXPECT_EQ(builder.get_secondary_calldata().size(), 0); + EXPECT_EQ(builder.get_return_data().size(), 0); EXPECT_TRUE(CircuitChecker::check(builder)); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 72f4498ece0b..ec3cafa225b4 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -629,7 +629,7 @@ class ECCVMFlavor { const size_t num_rows = std::max({ point_table_rows.size(), msm_rows.size(), transcript_rows.size() }) + TRACE_OFFSET; - vinfo("Num rows in the ECCVM: ", num_rows); + info("Num rows in the ECCVM: ", num_rows); const auto log_num_rows = static_cast(numeric::get_msb64(num_rows)); size_t dyadic_num_rows = 1UL << (log_num_rows + (1UL << log_num_rows == num_rows ? 0 : 1)); BB_ASSERT_LTE(dyadic_num_rows, diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index c6fe573c23dd..791dcdcf402a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -16,60 +16,9 @@ using namespace bb::crypto; namespace bb { -template void MegaCircuitBuilder_::finalize_circuit(const bool ensure_nonzero) +template void MegaCircuitBuilder_::finalize_circuit([[maybe_unused]] const bool ensure_nonzero) { - if (ensure_nonzero && !this->circuit_finalized) { - // do the mega part of ensuring all polynomials are nonzero; ultra part will be done inside of - // Ultra::finalize_circuit - add_mega_gates_to_ensure_all_polys_are_non_zero(); - } - // All of the gates involved in finalization are part of the Ultra arithmetization - UltraCircuitBuilder_::finalize_circuit(ensure_nonzero); -} - -/** - * @brief Ensure all polynomials have at least one non-zero coefficient to avoid commiting to the zero-polynomial. - * This only adds gates for the Goblin polynomials. Most polynomials are handled via the Ultra method, - * which should be done by a separate call to the Ultra builder's non zero polynomial gates method. - * - * @param in Structure containing variables and witness selectors - */ -template void MegaCircuitBuilder_::add_mega_gates_to_ensure_all_polys_are_non_zero() -{ - // Add a single default value to all databus columns. Note: This value must be equal across all columns in order for - // inter-circuit databus commitment checks to pass in IVC settings. - - // Create an arbitrary calldata read gate - add_public_calldata(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in calldata - auto raw_read_idx = static_cast(get_calldata().size()) - 1; // read data that was just added - auto read_idx = this->add_variable(FF(raw_read_idx)); - update_finalize_witnesses({ read_idx, read_calldata(read_idx) }); - - // Create an arbitrary secondary_calldata read gate - add_public_secondary_calldata(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in secondary_calldata - raw_read_idx = static_cast(get_secondary_calldata().size()) - 1; // read data that was just added - read_idx = this->add_variable(FF(raw_read_idx)); - update_finalize_witnesses({ read_idx, read_secondary_calldata(read_idx) }); - - // Create an arbitrary return data read gate - add_public_return_data(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in return data - raw_read_idx = static_cast(get_return_data().size()) - 1; // read data that was just added - read_idx = this->add_variable(FF(raw_read_idx)); - update_finalize_witnesses({ read_idx, read_return_data(read_idx) }); -} - -/** - * @brief Ensure all polynomials have at least one non-zero coefficient to avoid commiting to the zero-polynomial. - * This only adds gates for the Goblin polynomials. Most polynomials are handled via the Ultra method, - * which should be done by a separate call to the Ultra builder's non zero polynomial gates method. - * - * @param in Structure containing variables and witness selectors - */ -template void MegaCircuitBuilder_::add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero() -{ - // Most polynomials are handled via the conventional Ultra method - UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero(); - add_mega_gates_to_ensure_all_polys_are_non_zero(); + UltraCircuitBuilder_::finalize_circuit(ENSURE_NONZERO); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index c6ac2e726578..ad77477021fd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -119,9 +119,8 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_(circuit); auto verification_key = std::make_shared(prover_instance->get_precomputed()); @@ -75,7 +75,7 @@ TEST_F(OinkTests, OinkProverIsDeterministic) TEST_F(OinkTests, OinkProverCommitments) { Builder circuit; - circuit.add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero(); // Ensure all polys are non-zero + GoblinMockCircuits::construct_simple_circuit(circuit); auto prover_instance = std::make_shared(circuit); auto verification_key = std::make_shared(prover_instance->get_precomputed()); auto vk_and_hash = std::make_shared(verification_key); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index 76bb6933e342..18e799d922b9 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -11,6 +11,8 @@ #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/stdlib/hash/poseidon2/poseidon2.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" #include "barretenberg/stdlib/primitives/pairing_points.hpp" #include "barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" @@ -158,11 +160,12 @@ template void create_some_elliptic_curve_addition_gates(auto& circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, /*is_addition=*/false }); } -template void create_some_ecc_op_queue_gates(auto& circuit_builder) +template +void create_some_ecc_op_queue_gates(auto& circuit_builder) + requires IsMegaFlavor { using G1 = typename Flavor::Curve::Group; using FF = typename Flavor::FF; - static_assert(IsMegaFlavor); const size_t num_ecc_operations = 10; // arbitrary for (size_t i = 0; i < num_ecc_operations; ++i) { auto point = G1::affine_one * FF::random_element(); @@ -171,6 +174,43 @@ template void create_some_ecc_op_queue_gates(auto& circuit_bui } } +template +void create_some_databus_gates(auto& builder) + requires HasDataBus +{ + using FF = typename Flavor::FF; + auto val = builder.add_variable(FF::random_element()); + builder.add_public_calldata(val); + builder.read_calldata(builder.add_variable(FF(0))); + builder.add_public_secondary_calldata(val); + builder.read_secondary_calldata(builder.add_variable(FF(0))); + builder.add_public_return_data(val); + builder.read_return_data(builder.add_variable(FF(0))); +} + +template void create_some_non_native_field_gates(auto& builder) +{ + using Builder = typename Flavor::CircuitBuilder; + using fq_ct = stdlib::bigfield; + + auto a = fq_ct::from_witness(&builder, bb::fq::random_element()); + auto b = fq_ct::from_witness(&builder, bb::fq::random_element()); + [[maybe_unused]] auto c = a * b; +} + +template void create_some_poseidon2_gates(auto& builder) +{ + using field_ct = stdlib::field_t; + using witness_ct = stdlib::witness_t; + using FF = typename Flavor::FF; + + std::vector inputs; + for (size_t i = 0; i < 4; ++i) { + inputs.emplace_back(witness_ct(&builder, FF::random_element())); + } + stdlib::poseidon2::hash(inputs); +} + class UltraRelationCorrectnessTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } @@ -201,6 +241,8 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) create_some_delta_range_constraint_gates(builder); create_some_elliptic_curve_addition_gates(builder); create_some_RAM_gates(builder); + create_some_non_native_field_gates(builder); + create_some_poseidon2_gates(builder); stdlib::recursion::honk::DefaultIO::add_default(builder); // Create a prover (it will compute proving key and witness) @@ -234,7 +276,10 @@ TEST_F(UltraRelationCorrectnessTests, Mega) create_some_delta_range_constraint_gates(builder); create_some_elliptic_curve_addition_gates(builder); create_some_RAM_gates(builder); - create_some_ecc_op_queue_gates(builder); // Goblin! + create_some_ecc_op_queue_gates(builder); + create_some_databus_gates(builder); + create_some_non_native_field_gates(builder); + create_some_poseidon2_gates(builder); stdlib::recursion::honk::DefaultIO::add_default(builder); // Create a prover (it will compute proving key and witness) @@ -242,15 +287,14 @@ TEST_F(UltraRelationCorrectnessTests, Mega) complete_prover_instance_for_test(prover_inst); - // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution + // Check that selectors and databus inverses are nonzero to ensure relations are non-trivially exercised for (auto selector : prover_inst->polynomials.get_gate_selectors()) { ensure_non_zero(selector); } - - // Check the databus read counts/tags/inverses are non-zero (data columns may be zero with DEFAULT_VALUE=0) for (auto poly : prover_inst->polynomials.get_databus_inverses()) { ensure_non_zero(poly); } + auto& prover_polynomials = prover_inst->polynomials; auto params = prover_inst->relation_parameters;