@@ -104,75 +104,62 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
104104{
105105 using MergeCommitments = Goblin::MergeRecursiveVerifier::InputCommitments;
106106
107- // Witness commitments and public inputs corresponding to the incoming instance
108- WitnessCommitments witness_commitments;
109107 // The pairing points produced by the verification of the decider proof
110108 PairingPoints decider_pairing_points;
111- std::vector<StdlibFF> public_inputs;
112109
113110 // Input commitments to be passed to the merge recursive verification
114- MergeCommitments merge_commitments;
115- merge_commitments.T_prev_commitments = T_prev_commitments;
111+ MergeCommitments merge_commitments{ .T_prev_commitments = T_prev_commitments };
112+
113+ auto verifier_instance =
114+ std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_inputs.honk_vk_and_hash );
115+
116116 std::shared_ptr<ClientIVC::RecursiveDeciderVerificationKey> output_stdlib_verifier_accumulator;
117117 std::optional<StdlibFF> prev_accum_hash = std::nullopt ;
118118 // The decider proof exists if the tail kernel has been accumulated
119119 bool is_hiding_kernel = !decider_proof.empty ();
120120
121121 switch (verifier_inputs.type ) {
122- case QUEUE_TYPE::PG_TAIL:
123- case QUEUE_TYPE::PG: {
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- }
133- // Perform folding recursive verification to update the verifier accumulator
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
140-
141- witness_commitments = std::move (verifier.keys_to_fold [1 ]->witness_commitments );
142- public_inputs = std::move (verifier.public_inputs );
143-
144- break ;
145- }
146-
147122 case QUEUE_TYPE::OINK: {
148123 BB_ASSERT_EQ (input_stdlib_verifier_accumulator, nullptr );
149- // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key
150- output_stdlib_verifier_accumulator =
151- std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_inputs.honk_vk_and_hash );
152124
153125 // Perform oink recursive verification to complete the initial verifier accumulator
154- OinkRecursiveVerifier verifier{ &circuit,
155- output_stdlib_verifier_accumulator,
156- accumulation_recursive_transcript };
126+ OinkRecursiveVerifier verifier{ &circuit, verifier_instance, accumulation_recursive_transcript };
157127 verifier.verify_proof (verifier_inputs.proof );
158128
129+ output_stdlib_verifier_accumulator = verifier_instance;
159130 output_stdlib_verifier_accumulator->target_sum = StdlibFF::from_witness_index (&circuit, circuit.zero_idx );
160131 output_stdlib_verifier_accumulator->gate_challenges .assign (
161132 CONST_PG_LOG_N, StdlibFF::from_witness_index (&circuit, circuit.zero_idx ));
162133
163- witness_commitments = std::move (output_stdlib_verifier_accumulator->witness_commitments );
164- public_inputs = std::move (verifier.public_inputs );
165-
166134 // T_prev = 0 in the first recursive verification
167135 merge_commitments.T_prev_commitments = stdlib::recursion::honk::empty_ecc_op_tables (circuit);
168136
169137 break ;
170138 }
139+ case QUEUE_TYPE::PG:
140+ case QUEUE_TYPE::PG_TAIL: {
141+ BB_ASSERT_NEQ (input_stdlib_verifier_accumulator, nullptr );
142+ if (verifier_inputs
143+ .is_kernel ) { // this is what I'm using to determine if this is the first circuit we're folding...
144+ // Fiat-Shamir the accumulator.
145+ prev_accum_hash =
146+ input_stdlib_verifier_accumulator->hash_through_transcript (" " , *accumulation_recursive_transcript);
147+ accumulation_recursive_transcript->add_to_hash_buffer (" accum_hash" , *prev_accum_hash);
148+ info (" Previous accumulator hash in PG rec verifier: " , *prev_accum_hash);
149+ }
150+ // Perform folding recursive verification to update the verifier accumulator
151+ FoldingRecursiveVerifier verifier{
152+ &circuit, input_stdlib_verifier_accumulator, verifier_instance, accumulation_recursive_transcript
153+ };
154+ output_stdlib_verifier_accumulator =
155+ verifier.verify_folding_proof (verifier_inputs.proof ); // WORKTODO: connect this to previous/next accumulator
156+
157+ break ;
158+ }
171159 case QUEUE_TYPE::PG_FINAL: {
172160 BB_ASSERT_NEQ (input_stdlib_verifier_accumulator, nullptr );
173161 BB_ASSERT_EQ (stdlib_verification_queue.size (), size_t (1 ));
174- auto stdlib_proof = verifier_inputs.proof ;
175- auto stdlib_vk_and_hash = verifier_inputs.honk_vk_and_hash ;
162+
176163 // Note: reinstate this.
177164 // BB_ASSERT_EQ(num_circuits_accumulated,
178165 // num_circuits - 1,
@@ -184,6 +171,7 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
184171 // Propagate the public inputs of the tail kernel by converting them to public inputs of the hiding circuit.
185172 auto num_public_inputs = static_cast <size_t >(honk_vk->num_public_inputs );
186173 num_public_inputs -= KernelIO::PUBLIC_INPUTS_SIZE; // exclude fixed kernel_io public inputs
174+ auto stdlib_proof = verifier_inputs.proof ;
187175 for (size_t i = 0 ; i < num_public_inputs; i++) {
188176 stdlib_proof[i].set_public ();
189177 }
@@ -195,16 +183,11 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
195183 info (" Previous accumulator hash in PG rec verifier: " , *prev_accum_hash);
196184 // Perform recursive folding verification of the last folding proof
197185 FoldingRecursiveVerifier folding_verifier{
198- &circuit, input_stdlib_verifier_accumulator, { stdlib_vk_and_hash } , accumulation_recursive_transcript
186+ &circuit, input_stdlib_verifier_accumulator, verifier_instance , accumulation_recursive_transcript
199187 };
200188 auto recursive_verifier_native_accum = folding_verifier.verify_folding_proof (verifier_inputs.proof );
201189 verification_queue.clear ();
202190
203- // // Get the completed decider verification key corresponding to the tail kernel from the folding verifier
204- public_inputs = folding_verifier.public_inputs ;
205-
206- witness_commitments = folding_verifier.keys_to_fold [1 ]->witness_commitments ;
207-
208191 // Perform recursive decider verification
209192 DeciderRecursiveVerifier decider{ &circuit, recursive_verifier_native_accum };
210193 BB_ASSERT_EQ (decider_proof.empty (), false , " Decider proof is empty!" );
@@ -219,6 +202,10 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
219202 }
220203 }
221204
205+ // Extract the witness commitments and public inputs from the incoming verifier instance
206+ WitnessCommitments witness_commitments = std::move (verifier_instance->witness_commitments );
207+ std::vector<StdlibFF> public_inputs = std::move (verifier_instance->public_inputs );
208+
222209 PairingPoints nested_pairing_points; // to be extracted from public inputs of app or kernel proof just verified
223210
224211 if (verifier_inputs.is_kernel ) {
@@ -414,14 +401,14 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
414401 prover_accumulation_transcript = std::make_shared<Transcript>();
415402 }
416403
417- VerifierInputs queue_entry{ .honk_vk = honk_vk,
418- // first circuit accumulated should be an app
419- .is_kernel = is_kernel };
404+ // make a copy of the prover_accumulation_transcript for the verifier to use
405+ auto verifier_transcript =
406+ Transcript::convert_prover_transcript_to_verifier_transcript (prover_accumulation_transcript);
407+
408+ VerifierInputs queue_entry{ .honk_vk = honk_vk, .is_kernel = is_kernel };
420409 if (num_circuits_accumulated == 0 ) { // First circuit in the IVC
421- BB_ASSERT_EQ (queue_entry.is_kernel , false , " First circuit accumulated is always be an app" );
410+ BB_ASSERT_EQ (queue_entry.is_kernel , false , " First circuit accumulated must always be an app" );
422411 // For first circuit in the IVC, use oink to complete the decider proving key and generate an oink proof
423- auto oink_verifier_transcript =
424- Transcript::convert_prover_transcript_to_verifier_transcript (prover_accumulation_transcript);
425412 MegaOinkProver oink_prover{ proving_key, honk_vk, prover_accumulation_transcript };
426413 vinfo (" computing oink proof..." );
427414 oink_prover.prove ();
@@ -430,26 +417,17 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
430417
431418 fold_output.accumulator = proving_key; // initialize the prover accum with the completed key
432419
433- auto decider_vk = std::make_shared<DeciderVerificationKey>(honk_vk);
434- oink_verifier_transcript->load_proof (oink_proof);
435- OinkVerifier<Flavor> oink_verifier{ decider_vk, oink_verifier_transcript };
436- oink_verifier.verify ();
437- native_verifier_accum = decider_vk;
438- native_verifier_accum->gate_challenges = std::vector<FF>(CONST_PG_LOG_N, 0 );
439-
440420 queue_entry.type = QUEUE_TYPE::OINK;
441421 queue_entry.proof = oink_proof;
442422 } else if (num_circuits_accumulated == num_circuits - 1 ) {
443- queue_entry.type = QUEUE_TYPE::MEGA;
444423 // construct the mega proof of the hiding circuit
445424 auto mega_proof = prove_hiding_circuit (circuit);
425+
426+ queue_entry.type = QUEUE_TYPE::MEGA;
446427 queue_entry.proof = mega_proof;
447428 } else { // Otherwise, fold the new key into the accumulator
448429 vinfo (" computing folding proof" );
449430 auto vk = std::make_shared<DeciderVerificationKey_<Flavor>>(honk_vk);
450- // make a copy of the prover_accumulation_transcript for the verifier to use
451- auto verifier_accumulation_transcript =
452- Transcript::convert_prover_transcript_to_verifier_transcript (prover_accumulation_transcript);
453431 // Only fiat shamir if this is a kernel with the assumption that kernels are always the first being recursively
454432 // verified.
455433 if (is_kernel) {
@@ -464,14 +442,6 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
464442 trace_usage_tracker);
465443 fold_output = folding_prover.prove ();
466444 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- }
473- FoldingVerifier folding_verifier ({ native_verifier_accum, vk }, verifier_accumulation_transcript);
474- native_verifier_accum = folding_verifier.verify_folding_proof (fold_output.proof );
475445
476446 if (num_circuits_accumulated == num_circuits - 2 ) {
477447 // we are folding in the "Tail" kernel, so the verification_queue entry should have type PG_FINAL
@@ -490,6 +460,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
490460
491461 // Construct merge proof for the present circuit (skipped for hiding since merge proof constructed in goblin prove)
492462 if (num_circuits_accumulated != num_circuits - 1 ) {
463+ update_native_verifier_accumulator (queue_entry, verifier_transcript);
493464 goblin.prove_merge (prover_accumulation_transcript);
494465 }
495466
@@ -726,4 +697,26 @@ ClientIVC::VerificationKey ClientIVC::get_vk() const
726697 return { honk_vk, std::make_shared<ECCVMVerificationKey>(), std::make_shared<TranslatorVerificationKey>() };
727698}
728699
700+ void ClientIVC::update_native_verifier_accumulator (const VerifierInputs& queue_entry,
701+ const std::shared_ptr<Transcript>& verifier_transcript)
702+ {
703+ auto decider_vk = std::make_shared<DeciderVerificationKey>(queue_entry.honk_vk );
704+ if (queue_entry.type == QUEUE_TYPE::OINK) {
705+ verifier_transcript->load_proof (queue_entry.proof );
706+ OinkVerifier<Flavor> oink_verifier{ decider_vk, verifier_transcript };
707+ oink_verifier.verify ();
708+ native_verifier_accum = decider_vk;
709+ native_verifier_accum->gate_challenges = std::vector<FF>(CONST_PG_LOG_N, 0 );
710+ } else {
711+ if (queue_entry.is_kernel ) {
712+ // Fiat-Shamir the verifier accumulator
713+ FF accum_hash = native_verifier_accum->hash_through_transcript (" " , *verifier_transcript);
714+ verifier_transcript->add_to_hash_buffer (" accum_hash" , accum_hash);
715+ info (" Accumulator hash in PG verifier: " , accum_hash);
716+ }
717+ FoldingVerifier folding_verifier ({ native_verifier_accum, decider_vk }, verifier_transcript);
718+ native_verifier_accum = folding_verifier.verify_folding_proof (queue_entry.proof );
719+ }
720+ }
721+
729722} // namespace bb
0 commit comments