Skip to content

Commit

Permalink
feat: Checking finalized sizes + a test of two folding verifiers (#8503)
Browse files Browse the repository at this point in the history
Original goal: add a test so we can get the size of a circuit containing
two folding verifiers.

Detour: (Ultra and Mega flavors only) getting the size after adding
nonzero gates and finalizing a circuit used to require adding a printout
to the Honk proving key constructor, which would either be noise in many
tests, or which would then have to be removed. Rearranging the
ensure_nonzero function, we can accommodate the use case in tests where
we want to print out the number of gates after finalization. To do this,
just call finalize and and print the number of gates before passing the
circuit to the prover or proving key constructor. You get a warning, but
that's appropriate.

Caution: I left in a code path that finalizes but does add extra gates
because this was in use in many places. If those are all valid uses,
then we only really want the gate-adding version in one place, so I made
the default not add nonzero gates.

```
Console is in 'commands' mode, prefix expressions with '?'.
Launching: /mnt/user-data/cody/aztec-packages/barretenberg/cpp/build-debug/bin/stdlib_protogalaxy_verifier_tests --gtest_color=no --gtest_filter=ProtogalaxyRecursiveTests/0.RecursiveFoldingTwiceTest --gtest_also_run_disabled_tests --gtest_break_on_failure
Launched process 2323108
Running main() from /mnt/user-data/cody/aztec-packages/barretenberg/cpp/build-debug/_deps/gtest-src/googletest/src/gtest_main.cc
Note: Google Test filter = ProtogalaxyRecursiveTests/0.RecursiveFoldingTwiceTest
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from ProtogalaxyRecursiveTests/0, where TypeParam = bb::MegaRecursiveFlavor_<bb::MegaCircuitBuilder_<bb::field<bb::Bn254FrParams> > >
[ RUN      ] ProtogalaxyRecursiveTests/0.RecursiveFoldingTwiceTest
Folding Recursive Verifier: num gates unfinalized = 18085
Folding Recursive Verifier: num gates finalized = 20211
WARNING: Redundant call to finalize_circuit(). Is this intentional?
Dyadic size of verifier circuit: 32768
[       OK ] ProtogalaxyRecursiveTests/0.RecursiveFoldingTwiceTest (6768 ms)
[----------] 1 test from ProtogalaxyRecursiveTests/0 (6768 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (6768 ms total)
[  PASSED  ] 1 test.
Process exited with code 0.
```
```
  • Loading branch information
codygunton authored Sep 12, 2024
1 parent 986e703 commit d9e3f4d
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ MemBn254CrsFactory::MemBn254CrsFactory(std::vector<g1::affine_element> const& po
std::shared_ptr<bb::srs::factories::ProverCrs<curve::BN254>> MemBn254CrsFactory::get_prover_crs(size_t degree)
{
if (prover_crs_->get_monomial_size() < degree) {
throw_or_abort(format("prover trying to get too many points in MemGrumpkinCrsFactory! ",
throw_or_abort(format("prover trying to get too many points in MemBn254CrsFactory! ",
prover_crs_->get_monomial_size(),
" vs ",
degree));
Expand All @@ -72,7 +72,7 @@ std::shared_ptr<bb::srs::factories::VerifierCrs<curve::BN254>> MemBn254CrsFactor
{

if (prover_crs_->get_monomial_size() < degree) {
throw_or_abort(format("verifier trying to get too many points in MemGrumpkinCrsFactory! ",
throw_or_abort(format("verifier trying to get too many points in MemBn254CrsFactory! ",
prover_crs_->get_monomial_size(),
" vs ",
degree));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ template <typename RecursiveFlavor> class ProtogalaxyRecursiveTests : public tes
* @brief Tests that a valid recursive fold works as expected.
*
*/
static void test_recursive_folding()
static void test_recursive_folding(const size_t num_verifiers = 1)
{
// Create two arbitrary circuits for the first round of folding
InnerBuilder builder1;
Expand Down Expand Up @@ -204,14 +204,30 @@ template <typename RecursiveFlavor> class ProtogalaxyRecursiveTests : public tes

auto verifier =
FoldingRecursiveVerifier{ &folding_circuit, recursive_decider_vk_1, { recursive_decider_vk_2 } };
verifier.verify_folding_proof(stdlib_proof);
info("Folding Recursive Verifier: num gates = ", folding_circuit.get_num_gates());
std::shared_ptr<RecursiveDeciderVerificationKey> accumulator;
for (size_t idx = 0; idx < num_verifiers; idx++) {
accumulator = verifier.verify_folding_proof(stdlib_proof);
if (idx < num_verifiers - 1) { // else the transcript is null in the test below
verifier = FoldingRecursiveVerifier{ &folding_circuit,
accumulator,
{ std::make_shared<RecursiveVerificationKey>(
&folding_circuit, decider_vk_1->verification_key) } };
}
}
info("Folding Recursive Verifier: num gates unfinalized = ", folding_circuit.num_gates);
EXPECT_EQ(folding_circuit.failed(), false) << folding_circuit.err();

// Perform native folding verification and ensure it returns the same result (either true or false) as
// calling check_circuit on the recursive folding verifier
InnerFoldingVerifier native_folding_verifier({ decider_vk_1, decider_vk_2 });
std::shared_ptr<InnerDeciderVerificationKey> native_accumulator;
native_folding_verifier.verify_folding_proof(folding_proof.proof);
for (size_t idx = 0; idx < num_verifiers; idx++) {
native_accumulator = native_folding_verifier.verify_folding_proof(folding_proof.proof);
if (idx < num_verifiers - 1) { // else the transcript is null in the test below
native_folding_verifier = InnerFoldingVerifier{ { native_accumulator, decider_vk_1 } };
}
}

// Ensure that the underlying native and recursive folding verification algorithms agree by ensuring the
// manifestsproduced by each agree.
Expand All @@ -226,7 +242,11 @@ template <typename RecursiveFlavor> class ProtogalaxyRecursiveTests : public tes
// Check for a failure flag in the recursive verifier circuit

if constexpr (!IsSimulator<OuterBuilder>) {
// inefficiently check finalized size
folding_circuit.finalize_circuit(/* ensure_nonzero= */ true);
info("Folding Recursive Verifier: num gates finalized = ", folding_circuit.num_gates);
auto decider_pk = std::make_shared<OuterDeciderProvingKey>(folding_circuit);
info("Dyadic size of verifier circuit: ", decider_pk->proving_key.circuit_size);
OuterProver prover(decider_pk);
auto honk_vk = std::make_shared<typename OuterFlavor::VerificationKey>(decider_pk->proving_key);
OuterVerifier verifier(honk_vk);
Expand Down Expand Up @@ -405,6 +425,11 @@ TYPED_TEST(ProtogalaxyRecursiveTests, RecursiveFoldingTest)
TestFixture::test_recursive_folding();
}

TYPED_TEST(ProtogalaxyRecursiveTests, RecursiveFoldingTwiceTest)
{
TestFixture::test_recursive_folding(/* num_verifiers= */ 2);
}

TYPED_TEST(ProtogalaxyRecursiveTests, FullProtogalaxyRecursiveTest)
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ using namespace bb::crypto;

namespace bb {

template <typename FF> void MegaCircuitBuilder_<FF>::finalize_circuit()
template <typename FF> void MegaCircuitBuilder_<FF>::finalize_circuit(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_<MegaArith<FF>>::finalize_circuit();
UltraCircuitBuilder_<MegaArith<FF>>::finalize_circuit(ensure_nonzero);
}

/**
Expand All @@ -26,11 +31,8 @@ template <typename FF> void MegaCircuitBuilder_<FF>::finalize_circuit()
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1066): This function adds valid (but arbitrary) gates to
// ensure that the circuit which includes them will not result in any zero-polynomials. It also ensures that the first
// coefficient of the wire polynomials is zero, which is required for them to be shiftable.
template <typename FF> void MegaCircuitBuilder_<FF>::add_gates_to_ensure_all_polys_are_non_zero()
template <typename FF> void MegaCircuitBuilder_<FF>::add_mega_gates_to_ensure_all_polys_are_non_zero()
{
// Most polynomials are handled via the conventional Ultra method
UltraCircuitBuilder_<MegaArith<FF>>::add_gates_to_ensure_all_polys_are_non_zero();

// All that remains is to handle databus related and poseidon2 related polynomials. In what follows we populate the
// calldata with some mock data then constuct a single calldata read gate

Expand Down Expand Up @@ -62,6 +64,23 @@ template <typename FF> void MegaCircuitBuilder_<FF>::add_gates_to_ensure_all_pol
this->queue_ecc_eq();
}

/**
* @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
*/
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1066): This function adds valid (but arbitrary) gates to
// ensure that the circuit which includes them will not result in any zero-polynomials. It also ensures that the first
// coefficient of the wire polynomials is zero, which is required for them to be shiftable.
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_<MegaArith<FF>>::add_gates_to_ensure_all_polys_are_non_zero();
add_mega_gates_to_ensure_all_polys_are_non_zero();
}

/**
* @brief Add simple point addition operation to the op queue and add corresponding gates
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ template <typename FF> class MegaCircuitBuilder_ : public UltraCircuitBuilder_<M
return null_op_idx;
}

void finalize_circuit();
void add_gates_to_ensure_all_polys_are_non_zero();
void finalize_circuit(const bool ensure_nonzero = false);
void add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero();
void add_mega_gates_to_ensure_all_polys_are_non_zero();

size_t get_num_constant_gates() const override { return 0; }

Expand Down Expand Up @@ -141,7 +142,7 @@ template <typename FF> class MegaCircuitBuilder_ : public UltraCircuitBuilder_<M
MegaCircuitBuilder_<FF> builder; // instantiate new builder

size_t num_gates_prior = builder.get_num_gates();
builder.add_gates_to_ensure_all_polys_are_non_zero();
builder.add_ultra_and_mega_gates_to_ensure_all_polys_are_non_zero();
size_t num_gates_post = builder.get_num_gates(); // accounts for finalization gates

return num_gates_post - num_gates_prior;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

namespace bb {

template <typename Arithmetization> void UltraCircuitBuilder_<Arithmetization>::finalize_circuit()
template <typename Arithmetization>
void UltraCircuitBuilder_<Arithmetization>::finalize_circuit(const bool ensure_nonzero)
{
/**
* First of all, add the gates related to ROM arrays and range lists.
Expand Down Expand Up @@ -41,6 +42,9 @@ template <typename Arithmetization> void UltraCircuitBuilder_<Arithmetization>::
* our circuit is finalized, and we must not to execute these functions again.
*/
if (!circuit_finalized) {
if (ensure_nonzero) {
add_gates_to_ensure_all_polys_are_non_zero();
}
process_non_native_field_multiplications();
process_ROM_arrays();
process_RAM_arrays();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase<typename Arithmetization_
#endif // NDEBUG
}

void finalize_circuit();
void finalize_circuit(const bool ensure_nonzero = false);

void add_gates_to_ensure_all_polys_are_non_zero();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ template <class Flavor> class DeciderProvingKey_ {
std::shared_ptr<typename Flavor::CommitmentKey> commitment_key = nullptr)
{
BB_OP_COUNT_TIME_NAME("DeciderProvingKey(Circuit&)");
circuit.add_gates_to_ensure_all_polys_are_non_zero();
circuit.finalize_circuit();
circuit.finalize_circuit(/* ensure_nonzero = */ true);

// Set flag indicating whether the polynomials will be constructed with fixed block sizes for each gate type
const bool is_structured = (trace_structure != TraceStructure::NONE);
Expand Down

0 comments on commit d9e3f4d

Please sign in to comment.