Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
graph_description_merge_recursive_verifier.test.cpp
Go to the documentation of this file.
7
8using namespace cdg;
9
11
19template <class RecursiveBuilder> class BoomerangRecursiveMergeVerifierTest : public testing::Test {
20
21 // Types for recursive verifier circuit
25
26 // Define types relevant for inner circuit
30
31 // Define additional types for testing purposes
38
39 public:
41
42 static void analyze_circuit(RecursiveBuilder& outer_circuit)
43 {
44 auto tool = StaticAnalyzer_<bb::fr, RecursiveBuilder>(outer_circuit);
45 auto result = tool.analyze_circuit();
46 EXPECT_EQ(result.first.size(), 1);
47 EXPECT_EQ(result.second.size(), 0);
48 }
49
50 static std::shared_ptr<ECCOpQueue> construct_final_merge_op_queue(const size_t num_subtables_up_to_tail)
51 {
52 auto op_queue = std::make_shared<ECCOpQueue>();
53
54 for (size_t idx = 0; idx < num_subtables_up_to_tail; ++idx) {
55 InnerBuilder circuit{ op_queue };
57 op_queue->merge();
58 }
59
60 op_queue->construct_zk_columns();
61
62 InnerBuilder hiding_circuit{ op_queue };
64
65 // The merge protocol is only used for the hiding kernel, whose subtable has a fixed size. The prover and
66 // verifier both rely on this (the verifier hard-codes the shift size from it), so pad the final subtable to
67 // match.
68 BB_ASSERT_LTE(op_queue->get_current_subtable_size(), bb::HIDING_KERNEL_ULTRA_OPS);
69 while (op_queue->get_current_subtable_size() < bb::HIDING_KERNEL_ULTRA_OPS) {
70 op_queue->no_op_ultra_only();
71 }
72 return op_queue;
73 }
74
75 static void prove_and_verify_merge(const std::shared_ptr<ECCOpQueue>& op_queue, const bool run_analyzer = false)
76
77 {
78 RecursiveBuilder outer_circuit;
79
80 auto prover_transcript = std::make_shared<NativeTranscript>();
81 MergeProver merge_prover{ op_queue, prover_transcript };
82 auto merge_proof = merge_prover.construct_proof();
83
84 // Subtable values and commitments - needed for (Recursive)MergeVerifier
85 MergeCommitments merge_commitments;
86 RecursiveMergeCommitments recursive_merge_commitments;
87 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
88 auto T_prev = op_queue->construct_table_columns_up_to_tail();
89 for (size_t idx = 0; idx < InnerFlavor::NUM_WIRES; idx++) {
90 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
91 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
92 recursive_merge_commitments.t_commitments[idx] =
93 RecursiveMergeVerifier::Commitment::from_witness(&outer_circuit, merge_commitments.t_commitments[idx]);
94 recursive_merge_commitments.T_prev_commitments[idx] = RecursiveMergeVerifier::Commitment::from_witness(
95 &outer_circuit, merge_commitments.T_prev_commitments[idx]);
96 // Removing the free witness tag, since the merge commitments in the full scheme are supposed to
97 // be fiat-shamirred earlier
98 recursive_merge_commitments.t_commitments[idx].unset_free_witness_tag();
99 recursive_merge_commitments.T_prev_commitments[idx].unset_free_witness_tag();
100 }
101
102 // Create a recursive merge verification circuit for the merge proof
104 RecursiveMergeVerifier verifier{ merge_transcript };
105 const stdlib::Proof<RecursiveBuilder> stdlib_merge_proof(outer_circuit, merge_proof);
106 auto [pairing_points, merged_commitments, reduction_succeeded] =
107 verifier.reduce_to_pairing_check(stdlib_merge_proof, recursive_merge_commitments);
108
109 // The pairing points are public outputs from the recursive verifier that will be verified externally via a
110 // pairing check. Their output coordinate limbs (from goblin batch_mul's queue_ecc_eq) may only appear in a
111 // single ECC op gate. Calling fix_witness() adds explicit constraints on these values so the StaticAnalyzer
112 // does not flag them as under-constrained.
113 pairing_points.fix_witness();
114
115 // Check for a failure flag in the recursive verifier circuit
116 EXPECT_FALSE(outer_circuit.failed());
117 if (run_analyzer) {
118 analyze_circuit(outer_circuit);
119 }
120 }
121
123 {
124 auto op_queue = construct_final_merge_op_queue(/*num_subtables_up_to_tail=*/3);
125 prove_and_verify_merge(op_queue, /*run_analyzer=*/true);
126 }
127};
128
129using Builder = testing::Types<MegaCircuitBuilder>;
130
132
134{
135 TestFixture::test_recursive_merge_verification();
136};
137
138} // namespace bb::stdlib::recursion::goblin
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
static void construct_simple_circuit(MegaBuilder &builder)
Generate a simple test circuit with some ECC op gates and conventional arithmetic gates.
Curve::ScalarField FF
static constexpr size_t NUM_WIRES
MegaCircuitBuilder CircuitBuilder
Curve::AffineElement Commitment
Prover for the single-step Goblin ECC op queue merge protocol.
std::vector< FF > MergeProof
BB_PROFILE MergeProof construct_proof()
Prove proper construction of the aggregate Goblin ECC op queue polynomials T_j.
Verifier for the single-step Goblin ECC op queue merge protocol.
std::array< Commitment, NUM_WIRES > TableCommitments
Contains all the information required by a Honk prover to create a proof, constructed from a finalize...
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:20
static std::shared_ptr< ECCOpQueue > construct_final_merge_op_queue(const size_t num_subtables_up_to_tail)
static void prove_and_verify_merge(const std::shared_ptr< ECCOpQueue > &op_queue, const bool run_analyzer=false)
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
TYPED_TEST_SUITE(BoomerangRecursiveMergeVerifierTest, Builder)
TYPED_TEST(BoomerangRecursiveMergeVerifierTest, RecursiveMergeVerification)
Definition graph.cpp:21
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
VectorField result