46 using IO =
typename Params::IO;
89 const size_t num_gates = (1 << log_num_gates);
90 for (
size_t i = 0; i < num_gates; ++i) {
92 uint32_t a_idx =
builder.add_variable(
a);
97 uint32_t b_idx =
builder.add_variable(
b);
98 uint32_t c_idx =
builder.add_variable(c);
99 uint32_t d_idx =
builder.add_variable(d);
101 builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
122 EXPECT_EQ(result,
true);
145 static_cast<uint64_t
>(verifier.get_verifier_instance()->vk_and_hash->vk->log_circuit_size.get_value()),
146 honk_vk->log_circuit_size);
148 static_cast<uint64_t
>(verifier.get_verifier_instance()->vk_and_hash->vk->num_public_inputs.get_value()),
149 honk_vk->num_public_inputs);
150 for (
auto [vk_poly, native_vk_poly] :
151 zip_view(verifier.get_verifier_instance()->vk_and_hash->vk->get_all(), honk_vk->get_all())) {
152 EXPECT_EQ(vk_poly.get_value(), native_vk_poly);
165 auto get_blocks = [](
size_t inner_size) -> std::tuple<
typename OuterBuilder::ExecutionTrace,
172 auto verification_key =
174 InnerProver inner_prover(inner_prover_instance, verification_key);
175 info(
"test circuit size: ", inner_prover_instance->dyadic_size());
180 auto stdlib_vk_and_hash =
190 inputs.pairing_inputs = verifier_output.points_accumulator;
191 if constexpr (IO::HasIPA) {
193 inputs.ipa_claim = verifier_output.ipa_claim;
196 outer_circuit.ipa_proof = verifier_output.ipa_proof.get_value();
201 auto outer_verification_key =
204 return { outer_circuit.blocks, outer_verification_key };
207 auto [blocks_10, verification_key_10] = get_blocks(10);
208 auto [blocks_14, verification_key_14] = get_blocks(14);
210 compare_ultra_blocks_and_verification_keys<OuterFlavor>({ blocks_10, blocks_14 },
211 { verification_key_10, verification_key_14 });
225 auto verification_key =
227 InnerProver inner_prover(prover_instance, verification_key);
232 auto stdlib_vk_and_hash =
235 recursive_transcript->enable_manifest();
239 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
244 if constexpr (IO::HasIPA) {
249 outer_circuit.ipa_proof = output.
ipa_proof.get_value();
254 EXPECT_EQ(outer_circuit.failed(),
false) << outer_circuit.err();
260 native_transcript->enable_manifest();
261 InnerVerifier native_verifier(vk_and_hash, native_transcript);
263 bool native_result = native_verifier.
verify_proof(inner_proof).result;
266 info(
"input pairing points result: ", result);
267 EXPECT_EQ(result, native_result);
271 auto recursive_manifest = verifier.get_transcript()->get_manifest();
272 auto native_manifest = native_verifier.
get_transcript()->get_manifest();
273 for (
size_t i = 0; i < recursive_manifest.size(); ++i) {
274 EXPECT_EQ(recursive_manifest[i], native_manifest[i]);
280 auto verification_key =
282 info(
"Recursive Verifier: num gates = ", outer_circuit.get_num_finalized_gates());
283 OuterProver prover(prover_instance, verification_key);
293 const auto expected_gate_count =
std::get<0>(acir_format::HONK_RECURSION_CONSTANTS<RecursiveFlavor>());
294 ASSERT_EQ(outer_circuit.get_num_finalized_gates(), expected_gate_count)
295 <<
"MegaZKHonk Recursive verifier changed in Ultra gate count! Update this value if you "
296 "are sure this is expected.";
309 typename InnerFlavor::Transcript::Proof& inner_proof,
313 static constexpr size_t FIRST_WITNESS_INDEX = InnerFlavor::NUM_PRECOMPUTED_ENTITIES;
317 const size_t log_n = InnerFlavor::USE_PADDING ? InnerFlavor::VIRTUAL_LOG_N : inner_prover.
log_dyadic_size();
318 structured_proof.deserialize(inner_prover.
get_transcript()->test_get_proof_data(), num_public_inputs, log_n);
323 structured_proof.sumcheck_univariates[0].value_at(0) += delta;
324 structured_proof.sumcheck_univariates[0].value_at(1) -= delta;
334 if constexpr (InnerFlavor::HasZK) {
342 structured_proof.serialize(inner_prover.
get_transcript()->test_get_proof_data(), log_n);
350 for (
size_t idx = 0; idx < static_cast<size_t>(
TamperType::END); idx++) {
362 auto inner_verification_key =
364 InnerProver inner_prover(prover_instance, inner_verification_key);
372 auto stdlib_vk_and_hash =
376 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
405 auto verification_key =
407 InnerProver inner_prover(prover_instance, verification_key);
412 auto stdlib_vk_and_hash =
418 verifier.get_verifier_instance()->vk_and_hash->vk->pub_inputs_offset.fix_witness();
419 verifier.get_verifier_instance()->vk_and_hash->vk->log_circuit_size.fix_witness();
422 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
431 pairing_points.fix_witness();
437 if constexpr (IO::HasIPA) {
438 output.
ipa_claim.opening_pair.challenge.fix_witness();
439 output.
ipa_claim.opening_pair.evaluation.fix_witness();
442 info(
"Recursive Verifier: num gates = ", outer_circuit.get_num_finalized_gates_inefficient());
445 EXPECT_EQ(outer_circuit.failed(),
false) << outer_circuit.err();
447 outer_circuit.finalize_circuit(
false);
453 auto graph = Analyzer(outer_circuit);
454 auto [cc, variables_in_one_gate] = graph.analyze_circuit(
true);
457 EXPECT_EQ(cc.size(), 1);
460 size_t expected_unconstrained = 0;
461 EXPECT_EQ(variables_in_one_gate.size(), expected_unconstrained);
469 TestFixture::test_inner_circuit();
474 TestFixture::test_recursive_verification_key_creation();
479 TestFixture::test_recursive_verification();
484 using RecursiveFlavor =
typename TypeParam::RecursiveFlavor;
485 if constexpr (
IsAnyOf<RecursiveFlavor,
489 TestFixture::test_independent_vk_hash();
491 GTEST_SKIP() <<
"Not built for this parameter";
497 TestFixture::test_recursive_verification_fails();
508 TestFixture::test_recursive_verification_with_graph_analysis();
511#ifdef DISABLE_HEAVY_TESTS
513TEST(RecursiveVerifierTest, DoNothingTestToEnsureATestExists) {}
The recursive counterpart to MegaZKFlavor.
Contains all the information required by a Honk prover to create a proof, constructed from a finalize...
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
size_t num_public_inputs() const
const std::shared_ptr< Transcript > & get_transcript() const
size_t log_dyadic_size() const
Proof export_proof()
Export the complete proof, including IPA proof for rollup circuits.
The recursive counterpart to the "native" Ultra flavor.
const std::shared_ptr< Instance > & get_verifier_instance() const
Get the verifier instance (for accessing VK and witness commitments in Chonk/Goblin)
typename Flavor::VerificationKey VerificationKey
std::conditional_t< IsRecursive, stdlib::recursion::honk::UltraRecursiveVerifierOutput< Builder >, UltraVerifierOutput< Flavor > > Output
const std::shared_ptr< Transcript > & get_transcript() const
Get the transcript (for accessing manifest in tests)
Output verify_proof(const Proof &proof)
Perform ultra verification.
The recursive counterpart to UltraZKFlavor.
A simple wrapper around a vector of stdlib field elements representing a proof.
Manages the data that is propagated on the public inputs of an application/function circuit.
Test suite for recursive verification of Honk proofs for both Ultra and Mega arithmetisation.
static void test_recursive_verification()
Construct a recursive verification circuit for the proof of an inner circuit then call check_circuit ...
@ MODIFY_SUMCHECK_UNIVARIATE
static void SetUpTestSuite()
static InnerBuilder create_inner_circuit(size_t log_num_gates=10)
Create a non-trivial arbitrary inner circuit, the proof of which will be recursively verified.
std::conditional_t< IO::HasIPA, bb::RollupIO, bb::DefaultIO > NativeIO
static void test_recursive_verification_fails()
std::vector< InnerFF > InnerProof
static void tamper_honk_proof(InnerProver &inner_prover, typename InnerFlavor::Transcript::Proof &inner_proof, TamperType type)
static void test_inner_circuit()
Create inner circuit and call check_circuit on it.
static void test_recursive_verification_key_creation()
Instantiate a recursive verification key from the native verification key produced by the inner cicui...
static void test_independent_vk_hash()
Ensures that the recursive verifier circuit for two inner circuits of different size is the same as t...
std::conditional_t< IO::HasIPA, RollupIO, DefaultIO< InnerBuilder > > InnerIO
std::conditional_t< IsMegaBuilder< OuterBuilder >, MegaFlavor, UltraFlavor > OuterFlavor
typename Params::RecursiveFlavor RecursiveFlavor
InnerFlavor::Commitment InnerCommitment
typename RecursiveFlavor::CircuitBuilder OuterBuilder
typename RecursiveFlavor::NativeFlavor InnerFlavor
typename InnerFlavor::CircuitBuilder InnerBuilder
static void test_recursive_verification_with_graph_analysis()
Test recursive verification with static graph analysis to detect unconstrained variables.
typename RecursiveVerifier::VerificationKey VerificationKey
The data that is propagated on the public inputs of a rollup circuit.
Base class templates shared across Honk flavors.
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
testing::Types< RecursiveVerifierTestParams< MegaRecursiveFlavor_< MegaCircuitBuilder >, DefaultIO< MegaCircuitBuilder > >, RecursiveVerifierTestParams< MegaRecursiveFlavor_< UltraCircuitBuilder >, DefaultIO< UltraCircuitBuilder > >, RecursiveVerifierTestParams< UltraRecursiveFlavor_< UltraCircuitBuilder >, DefaultIO< UltraCircuitBuilder > >, RecursiveVerifierTestParams< UltraRecursiveFlavor_< UltraCircuitBuilder >, RollupIO >, RecursiveVerifierTestParams< UltraRecursiveFlavor_< MegaCircuitBuilder >, DefaultIO< MegaCircuitBuilder > >, RecursiveVerifierTestParams< UltraZKRecursiveFlavor_< UltraCircuitBuilder >, DefaultIO< UltraCircuitBuilder > >, RecursiveVerifierTestParams< UltraZKRecursiveFlavor_< MegaCircuitBuilder >, DefaultIO< MegaCircuitBuilder > >, RecursiveVerifierTestParams< MegaZKRecursiveFlavor_< MegaCircuitBuilder >, DefaultIO< MegaCircuitBuilder > >, RecursiveVerifierTestParams< MegaZKRecursiveFlavor_< UltraCircuitBuilder >, DefaultIO< UltraCircuitBuilder > > > TestConfigs
TYPED_TEST_SUITE(RecursiveVerifierTest, TestConfigs)
field< Bn254FrParams > fr
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
StaticAnalyzer_< bb::fr, bb::MegaCircuitBuilder > MegaStaticAnalyzer
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Full Honk proof layout (used by UltraVerifier).
Test utility for deserializing/serializing proof data into typed structures.
static field random_element(numeric::RNG *engine=nullptr) noexcept
An object storing two EC points that represent the inputs to a pairing check.
RecursiveFlavor_ RecursiveFlavor
Output type for recursive ultra verification.
OpeningClaim< grumpkin< Builder > > ipa_claim
PairingPoints< Curve > points_accumulator
stdlib::Proof< Builder > ipa_proof
#define HEAVY_TYPED_TEST(x, y)