Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,23 +246,38 @@ 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - I try to avoid the comments that referenece an historical pattern

* 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)
{
auto builder = MegaCircuitBuilder();

// 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));
}
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentional?

const auto log_num_rows = static_cast<size_t>(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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,60 +16,9 @@ using namespace bb::crypto;

namespace bb {

template <typename FF> void MegaCircuitBuilder_<FF>::finalize_circuit(const bool ensure_nonzero)
template <typename FF> void MegaCircuitBuilder_<FF>::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_<MegaExecutionTraceBlocks>::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 <typename FF> void MegaCircuitBuilder_<FF>::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<uint32_t>(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<uint32_t>(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<uint32_t>(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 <typename FF> void MegaCircuitBuilder_<FF>::add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero()
{
// Most polynomials are handled via the conventional Ultra method
UltraCircuitBuilder_<MegaExecutionTraceBlocks>::add_gates_to_ensure_all_polys_are_non_zero();
add_mega_gates_to_ensure_all_polys_are_non_zero();
UltraCircuitBuilder_<MegaExecutionTraceBlocks>::finalize_circuit(ENSURE_NONZERO);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the reason for not doing the same for Ultra?

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,8 @@ template <typename FF> class MegaCircuitBuilder_ : public UltraCircuitBuilder_<M
return 0;
}

void finalize_circuit(const bool ensure_nonzero);
void add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero();
void add_mega_gates_to_ensure_all_polys_are_non_zero();
static constexpr bool ENSURE_NONZERO = false;
void finalize_circuit(const bool ensure_nonzero = ENSURE_NONZERO);

size_t get_num_constant_gates() const override { return 0; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class OinkTests : public ::testing::Test {
TEST_F(OinkTests, OinkProverIsDeterministic)
{
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<ProverInstance>(circuit);
auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());

Expand Down Expand Up @@ -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<ProverInstance>(circuit);
auto verification_key = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
auto vk_and_hash = std::make_shared<typename Flavor::VKAndHash>(verification_key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -158,11 +160,12 @@ template <typename Flavor> void create_some_elliptic_curve_addition_gates(auto&
circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, /*is_addition=*/false });
}

template <typename Flavor> void create_some_ecc_op_queue_gates(auto& circuit_builder)
template <typename Flavor>
void create_some_ecc_op_queue_gates(auto& circuit_builder)
requires IsMegaFlavor<Flavor>
{
using G1 = typename Flavor::Curve::Group;
using FF = typename Flavor::FF;
static_assert(IsMegaFlavor<Flavor>);
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();
Expand All @@ -171,6 +174,43 @@ template <typename Flavor> void create_some_ecc_op_queue_gates(auto& circuit_bui
}
}

template <typename Flavor>
void create_some_databus_gates(auto& builder)
requires HasDataBus<Flavor>
{
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 <typename Flavor> void create_some_non_native_field_gates(auto& builder)
{
using Builder = typename Flavor::CircuitBuilder;
using fq_ct = stdlib::bigfield<Builder, bb::Bn254FqParams>;

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 <typename Flavor> void create_some_poseidon2_gates(auto& builder)
{
using field_ct = stdlib::field_t<typename Flavor::CircuitBuilder>;
using witness_ct = stdlib::witness_t<typename Flavor::CircuitBuilder>;
using FF = typename Flavor::FF;

std::vector<field_ct> inputs;
for (size_t i = 0; i < 4; ++i) {
inputs.emplace_back(witness_ct(&builder, FF::random_element()));
}
stdlib::poseidon2<typename Flavor::CircuitBuilder>::hash(inputs);
}

class UltraRelationCorrectnessTests : public ::testing::Test {
protected:
static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); }
Expand Down Expand Up @@ -201,6 +241,8 @@ TEST_F(UltraRelationCorrectnessTests, Ultra)
create_some_delta_range_constraint_gates<Flavor>(builder);
create_some_elliptic_curve_addition_gates<Flavor>(builder);
create_some_RAM_gates<Flavor>(builder);
create_some_non_native_field_gates<Flavor>(builder);
create_some_poseidon2_gates<Flavor>(builder);
stdlib::recursion::honk::DefaultIO<UltraCircuitBuilder>::add_default(builder);

// Create a prover (it will compute proving key and witness)
Expand Down Expand Up @@ -234,23 +276,25 @@ TEST_F(UltraRelationCorrectnessTests, Mega)
create_some_delta_range_constraint_gates<Flavor>(builder);
create_some_elliptic_curve_addition_gates<Flavor>(builder);
create_some_RAM_gates<Flavor>(builder);
create_some_ecc_op_queue_gates<Flavor>(builder); // Goblin!
create_some_ecc_op_queue_gates<Flavor>(builder);
create_some_databus_gates<Flavor>(builder);
create_some_non_native_field_gates<Flavor>(builder);
create_some_poseidon2_gates<Flavor>(builder);
stdlib::recursion::honk::DefaultIO<MegaCircuitBuilder>::add_default(builder);

// Create a prover (it will compute proving key and witness)
auto prover_inst = std::make_shared<ProverInstance_<Flavor>>(builder);

complete_prover_instance_for_test<Flavor>(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;

Expand Down
Loading