49 using IO =
typename Params::IO;
92 const size_t num_gates = (1 << log_num_gates);
93 for (
size_t i = 0; i < num_gates; ++i) {
95 uint32_t a_idx =
builder.add_variable(
a);
100 uint32_t b_idx =
builder.add_variable(
b);
101 uint32_t c_idx =
builder.add_variable(c);
102 uint32_t d_idx =
builder.add_variable(d);
104 builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
148 static_cast<uint64_t
>(verifier.get_verifier_instance()->vk_and_hash->vk->log_circuit_size.get_value()),
149 honk_vk->log_circuit_size);
151 static_cast<uint64_t
>(verifier.get_verifier_instance()->vk_and_hash->vk->num_public_inputs.get_value()),
152 honk_vk->num_public_inputs);
153 for (
auto [vk_poly, native_vk_poly] :
154 zip_view(verifier.get_verifier_instance()->vk_and_hash->vk->get_all(), honk_vk->get_all())) {
155 EXPECT_EQ(vk_poly.get_value(), native_vk_poly);
168 auto get_blocks = [](
size_t inner_size) -> std::tuple<
typename OuterBuilder::ExecutionTrace,
175 auto verification_key =
177 InnerProver inner_prover(inner_prover_instance, verification_key);
178 info(
"test circuit size: ", inner_prover_instance->dyadic_size());
183 auto stdlib_vk_and_hash =
193 inputs.pairing_inputs = verifier_output.points_accumulator;
194 if constexpr (IO::HasIPA) {
196 inputs.ipa_claim = verifier_output.ipa_claim;
199 outer_circuit.ipa_proof = verifier_output.ipa_proof.get_value();
204 auto outer_verification_key =
207 return { outer_circuit.blocks, outer_verification_key };
210 auto [blocks_10, verification_key_10] = get_blocks(10);
211 auto [blocks_14, verification_key_14] = get_blocks(14);
213 compare_ultra_blocks_and_verification_keys<OuterFlavor>({ blocks_10, blocks_14 },
214 { verification_key_10, verification_key_14 });
228 auto verification_key =
230 InnerProver inner_prover(prover_instance, verification_key);
235 auto stdlib_vk_and_hash =
238 recursive_transcript->enable_manifest();
242 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
247 if constexpr (IO::HasIPA) {
252 outer_circuit.ipa_proof = output.
ipa_proof.get_value();
257 EXPECT_EQ(outer_circuit.failed(),
false) << outer_circuit.err();
263 native_transcript->enable_manifest();
264 InnerVerifier native_verifier(vk_and_hash, native_transcript);
266 bool native_result = native_verifier.
verify_proof(inner_proof).result;
269 info(
"input pairing points result: ",
result);
270 EXPECT_EQ(
result, native_result);
274 auto recursive_manifest = verifier.get_transcript()->get_manifest();
275 auto native_manifest = native_verifier.
get_transcript()->get_manifest();
276 for (
size_t i = 0; i < recursive_manifest.size(); ++i) {
277 EXPECT_EQ(recursive_manifest[i], native_manifest[i]);
283 auto verification_key =
285 info(
"Recursive Verifier: num gates = ", outer_circuit.get_num_finalized_gates());
286 OuterProver prover(prover_instance, verification_key);
296 const auto expected_gate_count =
std::get<0>(acir_format::HONK_RECURSION_CONSTANTS<RecursiveFlavor>());
297 ASSERT_EQ(outer_circuit.get_num_finalized_gates(), expected_gate_count)
298 <<
"MegaZKHonk Recursive verifier changed in Ultra gate count! Update this value if you "
299 "are sure this is expected.";
312 typename InnerFlavor::Transcript::Proof& inner_proof,
316 static constexpr size_t FIRST_WITNESS_INDEX = InnerFlavor::NUM_PRECOMPUTED_ENTITIES;
320 const size_t log_n = InnerFlavor::USE_PADDING ? InnerFlavor::VIRTUAL_LOG_N : inner_prover.
log_dyadic_size();
321 structured_proof.deserialize(inner_prover.
get_transcript()->test_get_proof_data(), num_public_inputs, log_n);
326 structured_proof.sumcheck_univariates[0].value_at(0) += delta;
327 structured_proof.sumcheck_univariates[0].value_at(1) -= delta;
337 if constexpr (InnerFlavor::HasZK) {
345 structured_proof.serialize(inner_prover.
get_transcript()->test_get_proof_data(), log_n);
353 for (
size_t idx = 0; idx < static_cast<size_t>(
TamperType::END); idx++) {
365 auto inner_verification_key =
367 InnerProver inner_prover(prover_instance, inner_verification_key);
375 auto stdlib_vk_and_hash =
379 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
408 auto verification_key =
410 InnerProver inner_prover(prover_instance, verification_key);
415 auto stdlib_vk_and_hash =
421 verifier.get_verifier_instance()->vk_and_hash->vk->pub_inputs_offset.fix_witness();
422 verifier.get_verifier_instance()->vk_and_hash->vk->log_circuit_size.fix_witness();
425 VerifierOutput output = verifier.verify_proof(stdlib_inner_proof);
434 pairing_points.fix_witness();
440 if constexpr (IO::HasIPA) {
441 output.
ipa_claim.opening_pair.challenge.fix_witness();
442 output.
ipa_claim.opening_pair.evaluation.fix_witness();
445 info(
"Recursive Verifier: num gates = ", outer_circuit.get_num_finalized_gates_inefficient());
448 EXPECT_EQ(outer_circuit.failed(),
false) << outer_circuit.err();
450 outer_circuit.finalize_circuit();
456 auto graph = Analyzer(outer_circuit);
457 auto [cc, variables_in_one_gate] = graph.analyze_circuit(
true);
460 EXPECT_EQ(cc.size(), 1);
463 size_t expected_unconstrained = 0;
464 EXPECT_EQ(variables_in_one_gate.size(), expected_unconstrained);
472 TestFixture::test_inner_circuit();
477 TestFixture::test_recursive_verification_key_creation();
482 TestFixture::test_recursive_verification();
487 using RecursiveFlavor =
typename TypeParam::RecursiveFlavor;
488 if constexpr (
IsAnyOf<RecursiveFlavor,
492 TestFixture::test_independent_vk_hash();
494 GTEST_SKIP() <<
"Not built for this parameter";
500 TestFixture::test_recursive_verification_fails();
511 TestFixture::test_recursive_verification_with_graph_analysis();
514#ifdef DISABLE_HEAVY_TESTS
516TEST(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)