@@ -89,15 +89,18 @@ void ClientIVC::instantiate_stdlib_verification_queue(
8989 * @param accumulation_recursive_transcript Transcript shared across recursive verification of the folding of
9090 * K_{i-1} (kernel), A_{i,1} (app), .., A_{i, n} (app)
9191 *
92- * @return Pair of PairingPoints for final verification and commitments to the merged tables as read from the proof by
93- * the Merge verifier
92+ * @return Triple of output verifier accumulator, PairingPoints for final verification and commitments to the merged
93+ * tables as read from the proof by the Merge verifier
9494 */
95- std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
96- perform_recursive_verification_and_databus_consistency_checks (
97- ClientCircuit& circuit,
98- const StdlibVerifierInputs& verifier_inputs,
99- const TableCommitments& T_prev_commitments,
100- const std::shared_ptr<RecursiveTranscript>& accumulation_recursive_transcript)
95+ std::tuple<std::shared_ptr<ClientIVC::RecursiveDeciderVerificationKey>,
96+ ClientIVC::PairingPoints,
97+ ClientIVC::TableCommitments>
98+ ClientIVC::perform_recursive_verification_and_databus_consistency_checks (
99+ ClientCircuit& circuit,
100+ const StdlibVerifierInputs& verifier_inputs,
101+ const std::shared_ptr<ClientIVC::RecursiveDeciderVerificationKey>& input_stdlib_verifier_accumulator,
102+ const TableCommitments& T_prev_commitments,
103+ const std::shared_ptr<RecursiveTranscript>& accumulation_recursive_transcript)
101104{
102105 using MergeCommitments = Goblin::MergeRecursiveVerifier::InputCommitments;
103106
@@ -110,24 +113,30 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
110113 // Input commitments to be passed to the merge recursive verification
111114 MergeCommitments merge_commitments;
112115 merge_commitments.T_prev_commitments = T_prev_commitments;
116+ std::shared_ptr<ClientIVC::RecursiveDeciderVerificationKey> output_stdlib_verifier_accumulator;
117+ std::optional<StdlibFF> prev_accum_hash = std::nullopt ;
113118 // The decider proof exists if the tail kernel has been accumulated
114119 bool is_hiding_kernel = !decider_proof.empty ();
115120
116121 switch (verifier_inputs.type ) {
117122 case QUEUE_TYPE::PG_TAIL:
118123 case QUEUE_TYPE::PG: {
119- // Construct stdlib verifier accumulator from the native counterpart computed on a previous round
120- auto stdlib_verifier_accum =
121- std::make_shared<RecursiveDeciderVerificationKey>(&circuit, recursive_verifier_native_accum);
122-
124+ BB_ASSERT_NEQ (input_stdlib_verifier_accumulator, nullptr );
125+ if (verifier_inputs
126+ .is_kernel ) { // this is what I'm using to determine if this is the first circuit we're folding...
127+ // Fiat-Shamir the accumulator.
128+ prev_accum_hash =
129+ input_stdlib_verifier_accumulator->hash_through_transcript (" " , *accumulation_recursive_transcript);
130+ accumulation_recursive_transcript->add_to_hash_buffer (" accum_hash" , *prev_accum_hash);
131+ info (" Previous accumulator hash in PG rec verifier: " , *prev_accum_hash);
132+ }
123133 // Perform folding recursive verification to update the verifier accumulator
124- FoldingRecursiveVerifier verifier{
125- &circuit, stdlib_verifier_accum, { verifier_inputs.honk_vk_and_hash }, accumulation_recursive_transcript
126- };
127- auto verifier_accum = verifier.verify_folding_proof (verifier_inputs.proof );
128-
129- // Extract native verifier accumulator from the stdlib accum for use on the next round
130- recursive_verifier_native_accum = std::make_shared<DeciderVerificationKey>(verifier_accum->get_value ());
134+ FoldingRecursiveVerifier verifier{ &circuit,
135+ input_stdlib_verifier_accumulator,
136+ { verifier_inputs.honk_vk_and_hash },
137+ accumulation_recursive_transcript };
138+ output_stdlib_verifier_accumulator =
139+ verifier.verify_folding_proof (verifier_inputs.proof ); // WORKTODO: connect this to previous/next accumulator
131140
132141 witness_commitments = std::move (verifier.keys_to_fold [1 ]->witness_commitments );
133142 public_inputs = std::move (verifier.public_inputs );
@@ -136,20 +145,22 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
136145 }
137146
138147 case QUEUE_TYPE::OINK: {
148+ BB_ASSERT_EQ (input_stdlib_verifier_accumulator, nullptr );
139149 // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key
140- auto verifier_accum =
150+ output_stdlib_verifier_accumulator =
141151 std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_inputs.honk_vk_and_hash );
142152
143153 // Perform oink recursive verification to complete the initial verifier accumulator
144- OinkRecursiveVerifier verifier{ &circuit, verifier_accum, accumulation_recursive_transcript };
154+ OinkRecursiveVerifier verifier{ &circuit,
155+ output_stdlib_verifier_accumulator,
156+ accumulation_recursive_transcript };
145157 verifier.verify_proof (verifier_inputs.proof );
146158
147- // Extract native verifier accumulator from the stdlib accum for use on the next round
148- recursive_verifier_native_accum = std::make_shared<DeciderVerificationKey>(verifier_accum->get_value ());
149- // Initialize the gate challenges to zero for use in first round of folding
150- recursive_verifier_native_accum->gate_challenges = std::vector<FF>(CONST_PG_LOG_N, 0 );
159+ output_stdlib_verifier_accumulator->target_sum = StdlibFF::from_witness_index (&circuit, circuit.zero_idx );
160+ output_stdlib_verifier_accumulator->gate_challenges .assign (
161+ CONST_PG_LOG_N, StdlibFF::from_witness_index (&circuit, circuit.zero_idx ));
151162
152- witness_commitments = std::move (verifier_accum ->witness_commitments );
163+ witness_commitments = std::move (output_stdlib_verifier_accumulator ->witness_commitments );
153164 public_inputs = std::move (verifier.public_inputs );
154165
155166 // T_prev = 0 in the first recursive verification
@@ -158,6 +169,7 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
158169 break ;
159170 }
160171 case QUEUE_TYPE::PG_FINAL: {
172+ BB_ASSERT_NEQ (input_stdlib_verifier_accumulator, nullptr );
161173 BB_ASSERT_EQ (stdlib_verification_queue.size (), size_t (1 ));
162174 auto stdlib_proof = verifier_inputs.proof ;
163175 auto stdlib_vk_and_hash = verifier_inputs.honk_vk_and_hash ;
@@ -169,20 +181,21 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
169181
170182 hide_op_queue_accumulation_result (circuit);
171183
172- // Construct stdlib accumulator, decider vkey and folding proof
173- auto stdlib_verifier_accumulator =
174- std::make_shared<RecursiveDeciderVerificationKey>(&circuit, recursive_verifier_native_accum);
175-
176184 // Propagate the public inputs of the tail kernel by converting them to public inputs of the hiding circuit.
177185 auto num_public_inputs = static_cast <size_t >(honk_vk->num_public_inputs );
178186 num_public_inputs -= KernelIO::PUBLIC_INPUTS_SIZE; // exclude fixed kernel_io public inputs
179187 for (size_t i = 0 ; i < num_public_inputs; i++) {
180188 stdlib_proof[i].set_public ();
181189 }
182190
191+ // Fiat-Shamir the accumulator.
192+ prev_accum_hash =
193+ input_stdlib_verifier_accumulator->hash_through_transcript (" " , *accumulation_recursive_transcript);
194+ accumulation_recursive_transcript->add_to_hash_buffer (" accum_hash" , *prev_accum_hash);
195+ info (" Previous accumulator hash in PG rec verifier: " , *prev_accum_hash);
183196 // Perform recursive folding verification of the last folding proof
184197 FoldingRecursiveVerifier folding_verifier{
185- &circuit, stdlib_verifier_accumulator , { stdlib_vk_and_hash }, accumulation_recursive_transcript
198+ &circuit, input_stdlib_verifier_accumulator , { stdlib_vk_and_hash }, accumulation_recursive_transcript
186199 };
187200 auto recursive_verifier_native_accum = folding_verifier.verify_folding_proof (verifier_inputs.proof );
188201 verification_queue.clear ();
@@ -197,6 +210,8 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
197210 BB_ASSERT_EQ (decider_proof.empty (), false , " Decider proof is empty!" );
198211
199212 decider_pairing_points = decider.verify_proof (decider_proof);
213+
214+ BB_ASSERT_EQ (output_stdlib_verifier_accumulator, nullptr );
200215 break ;
201216 }
202217 default : {
@@ -220,7 +235,14 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
220235 // happens in K_{i}
221236 merge_commitments.T_prev_commitments = std::move (kernel_input.ecc_op_tables );
222237
223- // Set the kernel return data commitment to be propagated via the public inputs
238+ BB_ASSERT_EQ (verifier_inputs.type == QUEUE_TYPE::PG || verifier_inputs.type == QUEUE_TYPE::PG_TAIL ||
239+ verifier_inputs.type == QUEUE_TYPE::PG_FINAL,
240+ true ,
241+ " Kernel circuits should be folded." );
242+ // Get the previous accum hash
243+ info (" PG accum hash from IO: " , kernel_input.output_pg_accum_hash );
244+ ASSERT (prev_accum_hash.has_value ());
245+ kernel_input.output_pg_accum_hash .assert_equal (*prev_accum_hash);
224246
225247 if (!is_hiding_kernel) {
226248 // The hiding kernel has no return data but uses the traditional public-inputs mechanism
@@ -248,7 +270,7 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
248270 pairing_points.aggregate (decider_pairing_points);
249271 }
250272
251- return { pairing_points, merged_table_commitments };
273+ return { output_stdlib_verifier_accumulator, pairing_points, merged_table_commitments };
252274}
253275
254276/* *
@@ -298,35 +320,53 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit)
298320
299321 // Perform Oink/PG and Merge recursive verification + databus consistency checks for each entry in the queue
300322 PairingPoints points_accumulator;
323+ std::shared_ptr<RecursiveDeciderVerificationKey> current_stdlib_verifier_accumulator = nullptr ;
324+ bool is_init_kernel = (recursive_verifier_native_accum == nullptr ); // Should clean this up ideally
325+ if (!is_init_kernel) {
326+ current_stdlib_verifier_accumulator =
327+ std::make_shared<RecursiveDeciderVerificationKey>(&circuit, recursive_verifier_native_accum);
328+ }
301329 while (!stdlib_verification_queue.empty ()) {
302330 const StdlibVerifierInputs& verifier_input = stdlib_verification_queue.front ();
303331
304- auto [pairing_points, merged_table_commitments] = perform_recursive_verification_and_databus_consistency_checks (
305- circuit, verifier_input, T_prev_commitments, accumulation_recursive_transcript);
306-
332+ auto [output_stdlib_verifier_accumulator, pairing_points, merged_table_commitments] =
333+ perform_recursive_verification_and_databus_consistency_checks (circuit,
334+ verifier_input,
335+ current_stdlib_verifier_accumulator,
336+ T_prev_commitments,
337+ accumulation_recursive_transcript);
307338 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1376): Optimize recursion aggregation - seems
308339 // we can use `batch_mul` here to decrease the size of the `ECCOpQueue`, but must be cautious with FS security.
309340 points_accumulator.aggregate (pairing_points);
310-
311341 // Update commitment to the status of the op_queue
312342 T_prev_commitments = merged_table_commitments;
343+ // Update the output verifier accumulator
344+ current_stdlib_verifier_accumulator = output_stdlib_verifier_accumulator;
313345
314346 stdlib_verification_queue.pop_front ();
315347 }
316-
317348 // Set the kernel output data to be propagated via the public inputs
318349 if (is_hiding_kernel) {
350+ BB_ASSERT_EQ (current_stdlib_verifier_accumulator, nullptr );
319351 HidingKernelIO hiding_output{ points_accumulator, T_prev_commitments };
320352 hiding_output.set_public ();
321353 // preserve the hiding circuit so a proof for it can be created
322354 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1502): reconsider approach once integration is
323355 } else {
356+ BB_ASSERT_NEQ (current_stdlib_verifier_accumulator, nullptr );
357+ // Extract native verifier accumulator from the stdlib accum for use on the next round
358+ recursive_verifier_native_accum =
359+ std::make_shared<DeciderVerificationKey>(current_stdlib_verifier_accumulator->get_value ());
360+
324361 KernelIO kernel_output;
325362 kernel_output.pairing_inputs = points_accumulator;
326363 kernel_output.kernel_return_data = bus_depot.get_kernel_return_data_commitment (circuit);
327364 kernel_output.app_return_data = bus_depot.get_app_return_data_commitment (circuit);
328365 kernel_output.ecc_op_tables = T_prev_commitments;
329-
366+ RecursiveTranscript hash_transcript;
367+ kernel_output.output_pg_accum_hash =
368+ current_stdlib_verifier_accumulator->hash_through_transcript (" " , hash_transcript);
369+ info (" kernel output pg hash: " , kernel_output.output_pg_accum_hash );
330370 kernel_output.set_public ();
331371 }
332372}
@@ -410,13 +450,26 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
410450 // make a copy of the prover_accumulation_transcript for the verifier to use
411451 auto verifier_accumulation_transcript =
412452 Transcript::convert_prover_transcript_to_verifier_transcript (prover_accumulation_transcript);
413-
453+ // Only fiat shamir if this is a kernel with the assumption that kernels are always the first being recursively
454+ // verified.
455+ if (is_kernel) {
456+ // Fiat-Shamir the verifier accumulator
457+ FF accum_hash = native_verifier_accum->hash_through_transcript (" " , *prover_accumulation_transcript);
458+ prover_accumulation_transcript->add_to_hash_buffer (" accum_hash" , accum_hash);
459+ info (" Accumulator hash in PG prover: " , accum_hash);
460+ }
414461 FoldingProver folding_prover ({ fold_output.accumulator , proving_key },
415462 { native_verifier_accum, vk },
416463 prover_accumulation_transcript,
417464 trace_usage_tracker);
418465 fold_output = folding_prover.prove ();
419466 vinfo (" constructed folding proof" );
467+ if (is_kernel) {
468+ // Fiat-Shamir the verifier accumulator
469+ FF accum_hash = native_verifier_accum->hash_through_transcript (" " , *verifier_accumulation_transcript);
470+ verifier_accumulation_transcript->add_to_hash_buffer (" accum_hash" , accum_hash);
471+ info (" Accumulator hash in PG verifier: " , accum_hash);
472+ }
420473 FoldingVerifier folding_verifier ({ native_verifier_accum, vk }, verifier_accumulation_transcript);
421474 native_verifier_accum = folding_verifier.verify_folding_proof (fold_output.proof );
422475
0 commit comments