From d1dd2eb248faf82190305f4e18bacd723aa1cf5b Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Sun, 7 Apr 2024 20:25:51 +0200 Subject: [PATCH] chore: add vb errors and failing test --- air/src/trace/main_trace.rs | 7 ++ .../src/trace/virtual_bus/circuit/error.rs | 8 +- .../src/trace/virtual_bus/circuit/prover.rs | 93 ++++++++++--------- .../src/trace/virtual_bus/circuit/verifier.rs | 12 +-- processor/src/trace/virtual_bus/error.rs | 12 +++ processor/src/trace/virtual_bus/prover.rs | 12 ++- processor/src/trace/virtual_bus/tests.rs | 42 ++++++++- processor/src/trace/virtual_bus/verifier.rs | 19 +++- 8 files changed, 143 insertions(+), 62 deletions(-) diff --git a/air/src/trace/main_trace.rs b/air/src/trace/main_trace.rs index 454074a714..782e8bcad6 100644 --- a/air/src/trace/main_trace.rs +++ b/air/src/trace/main_trace.rs @@ -41,6 +41,13 @@ impl Deref for MainTrace { } } +#[cfg(any(test, feature = "internals"))] +impl core::ops::DerefMut for MainTrace { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.columns + } +} + impl MainTrace { pub fn new(main_trace: ColMatrix) -> Self { Self { diff --git a/processor/src/trace/virtual_bus/circuit/error.rs b/processor/src/trace/virtual_bus/circuit/error.rs index 64390684fd..0d89880d94 100644 --- a/processor/src/trace/virtual_bus/circuit/error.rs +++ b/processor/src/trace/virtual_bus/circuit/error.rs @@ -1,13 +1,17 @@ #[derive(Debug, thiserror::Error)] pub enum ProverError { #[error("failed to generate multi-linear from the given evaluations")] - FailedGenerateML, + FailedToGenerateML, #[error("the inputs to the circuit's input layer have incompatible lengths")] MismatchingLengthsCircuitInputs, #[error("the inputs to the circuit's input layer must have power-of-two lengths")] InputsMustBePowerTwo, #[error("the inputs to the circuit's input layer must have at least two evaluations")] InputsAtLeastTwo, + #[error("failed to generate the sum-check proof")] + FailedToProveSumCheck, + #[error("failed to generate the random challenge")] + FailedToGenerateChallenge, } #[derive(Debug, thiserror::Error)] @@ -17,7 +21,7 @@ pub enum VerifierError { #[error("the output of the fraction circuit is not equal to the expected value")] MismatchingCircuitOutput, #[error("failed to generate the random challenge")] - FailedGenerateRandomness, + FailedToGenerateChallenge, #[error("failed to verify the sum-check proof")] FailedToVerifySumCheck, } diff --git a/processor/src/trace/virtual_bus/circuit/prover.rs b/processor/src/trace/virtual_bus/circuit/prover.rs index 0fafc0173e..dbccafe411 100644 --- a/processor/src/trace/virtual_bus/circuit/prover.rs +++ b/processor/src/trace/virtual_bus/circuit/prover.rs @@ -72,13 +72,13 @@ impl FractionalSumCircuit { let mut q_1_vec: Vec> = Vec::with_capacity(num_layers); let p_0 = MultiLinearPoly::from_evaluations(num_den[0].to_owned()) - .map_err(|_| ProverError::FailedGenerateML)?; + .map_err(|_| ProverError::FailedToGenerateML)?; let p_1 = MultiLinearPoly::from_evaluations(num_den[1].to_owned()) - .map_err(|_| ProverError::FailedGenerateML)?; + .map_err(|_| ProverError::FailedToGenerateML)?; let q_0 = MultiLinearPoly::from_evaluations(num_den[2].to_owned()) - .map_err(|_| ProverError::FailedGenerateML)?; + .map_err(|_| ProverError::FailedToGenerateML)?; let q_1 = MultiLinearPoly::from_evaluations(num_den[3].to_owned()) - .map_err(|_| ProverError::FailedGenerateML)?; + .map_err(|_| ProverError::FailedToGenerateML)?; p_0_vec.push(p_0); p_1_vec.push(p_1); q_0_vec.push(q_0); @@ -129,13 +129,13 @@ impl FractionalSumCircuit { Ok(( MultiLinearPoly::from_evaluations(outp_p_0) - .map_err(|_| ProverError::FailedGenerateML)?, + .map_err(|_| ProverError::FailedToGenerateML)?, MultiLinearPoly::from_evaluations(outp_p_1) - .map_err(|_| ProverError::FailedGenerateML)?, + .map_err(|_| ProverError::FailedToGenerateML)?, MultiLinearPoly::from_evaluations(outp_q_0) - .map_err(|_| ProverError::FailedGenerateML)?, + .map_err(|_| ProverError::FailedToGenerateML)?, MultiLinearPoly::from_evaluations(outp_q_1) - .map_err(|_| ProverError::FailedGenerateML)?, + .map_err(|_| ProverError::FailedToGenerateML)?, )) } @@ -148,12 +148,12 @@ impl FractionalSumCircuit { assert_eq!(self.q_0_vec[len - 1].num_variables(), 0); assert_eq!(self.q_1_vec[len - 1].num_variables(), 0); - let mut p_ = self.p_0_vec[len - 1].clone(); - p_.extend(&self.p_1_vec[len - 1]); - let mut q_ = self.q_0_vec[len - 1].clone(); - q_.extend(&self.q_1_vec[len - 1]); + let mut p = self.p_0_vec[len - 1].clone(); + p.extend(&self.p_1_vec[len - 1]); + let mut q = self.q_0_vec[len - 1].clone(); + q.extend(&self.q_1_vec[len - 1]); - (p_.evaluate(&[r]), q_.evaluate(&[r])) + (p.evaluate(&[r]), q.evaluate(&[r])) } /// Outputs the value of the circuit output layer. @@ -187,14 +187,14 @@ impl FractionalSumCircuit { /// /// The composition polynomials `g` are provided as inputs and then used in order to compute /// the evaluations of each of the four merge polynomials over {0, 1}^{μ + ν}. The resulting -/// evaluations are then used in order to evaluate [FractionalSumCircuit]. +/// evaluations are then used in order to evaluate [`FractionalSumCircuit`]. /// At this point, the GKR protocol is used to prove the correctness of circuit evaluation. It /// should be noted that the input layer, which corresponds to the last layer treated by the GKR /// protocol, is handled differently from the other layers. /// More specifically, the sum-check protocol used for the input layer is composed of two sum-check /// protocols, the first one works directly with the evaluations of the `m`'s over {0, 1}^{μ + ν} /// and runs for μ rounds. -/// After these μ rounds, and using the resulting [RoundClaim], we run the second and final +/// After these μ rounds, and using the resulting [`RoundClaim`], we run the second and final /// sum-check protocol for ν rounds on the composed multi-linear polynomial given by /// /// \sum_{y ∈ {0,1}^μ} EQ(ρ', y) * g_{[y]}(f_0(x_0, ... , x_{ν - 1}), ... , f_{κ - 1}(x_0, ... , x_{ν - 1})) @@ -202,7 +202,7 @@ impl FractionalSumCircuit { /// where ρ' is the randomness sampled during the first sum-check protocol. /// /// As part of the final sum-check protocol, the openings {f_j(ρ)} are provided as part of -/// a [FinalOpeningClaim]. This latter claim will be proven by the STARK prover later on using +/// a [`FinalOpeningClaim`]. This latter claim will be proven by the STARK prover later on using /// the auxiliary trace. pub fn prove< E: FieldElement + 'static, @@ -212,16 +212,16 @@ pub fn prove< composition_polys: Vec>>>, mls: &mut Vec>, transcript: &mut C, -) -> GkrCircuitProof { +) -> Result, ProverError> { // evaluate the numerators and denominators over the boolean hyper-cube {0, 1}^{μ + ν} let input: Vec> = evaluate_composition_polys(mls, &composition_polys); // evaluate the GKR fractional sum circuit - let mut circuit = FractionalSumCircuit::new(input).unwrap(); + let mut circuit = FractionalSumCircuit::new(input)?; // run the GKR prover for all layers except the input layer let (before_final_layer_proofs, gkr_claim) = - prove_before_final_circuit_layers(&mut circuit, transcript); + prove_before_final_circuit_layers(&mut circuit, transcript)?; // run the GKR prover for the input layer let num_rounds_before_merge = composition_polys[0].len().ilog2() as usize; @@ -232,16 +232,16 @@ pub fn prove< gkr_claim, &mut circuit, transcript, - ); + )?; // include the circuit output as part of the final proof let circuit_outputs = circuit.output_layer(); - GkrCircuitProof { + Ok(GkrCircuitProof { circuit_outputs, before_final_layer_proofs, final_layer_proof, - } + }) } /// Proves the final GKR layer which corresponds to the input circuit layer. @@ -256,7 +256,7 @@ fn prove_final_circuit_layer< gkr_claim: GkrClaim, circuit: &mut FractionalSumCircuit, transcript: &mut C, -) -> FinalLayerProof { +) -> Result, ProverError> { // parse the [GkrClaim] resulting from the previous GKR layer let GkrClaim { evaluation_point, @@ -279,7 +279,7 @@ fn prove_final_circuit_layer< num_rounds_merge, &mut merged_mls, transcript, - ); + )?; // parse the output of the first sum-check protocol let RoundClaim { @@ -297,12 +297,14 @@ fn prove_final_circuit_layer< // run the second sum-check protocol let main_prover = SumCheckProver::new(gkr_composition, SimpleGkrFinalClaimBuilder(PhantomData)); - let after_merge_proof = main_prover.prove(claim, mls, transcript).unwrap(); + let after_merge_proof = main_prover + .prove(claim, mls, transcript) + .map_err(|_| ProverError::FailedToProveSumCheck)?; - FinalLayerProof { + Ok(FinalLayerProof { before_merge_proof, after_merge_proof, - } + }) } /// Proves all GKR layers except for input layer. @@ -313,7 +315,7 @@ fn prove_before_final_circuit_layers< >( circuit: &mut FractionalSumCircuit, transcript: &mut C, -) -> (BeforeFinalLayerProof, GkrClaim) { +) -> Result<(BeforeFinalLayerProof, GkrClaim), ProverError> { // absorb the circuit output layer. This corresponds to sending the four values of the output // layer to the verifier. The verifier then replies with a challenge `r` in order to evaluate // `p` and `q` at `r` as multi-linears. @@ -328,7 +330,7 @@ fn prove_before_final_circuit_layers< transcript.reseed(H::hash_elements(&data)); // generate the challenge and reduce [p0, p1, q0, q1] to [pr, qr] - let r = transcript.draw().unwrap(); + let r = transcript.draw().map_err(|_| ProverError::FailedToGenerateChallenge)?; let mut claim = circuit.evaluate_output_layer(r); let mut proof_layers: Vec> = Vec::new(); @@ -346,11 +348,11 @@ fn prove_before_final_circuit_layers< let mut mls = vec![poly_a, poly_b, poly_c, poly_d, poly_x]; // run the sumcheck protocol - let (proof, _) = sum_check_prover_plain_full(claim, &mut mls, transcript); + let (proof, _) = sum_check_prover_plain_full(claim, &mut mls, transcript)?; // sample a random challenge to reduce claims transcript.reseed(H::hash_elements(&proof.openings_claim.openings)); - let r_layer = transcript.draw().unwrap(); + let r_layer = transcript.draw().map_err(|_| ProverError::FailedToGenerateChallenge)?; // reduce the claim let p0 = proof.openings_claim.openings[0]; @@ -367,7 +369,7 @@ fn prove_before_final_circuit_layers< proof_layers.push(proof); } - ( + Ok(( BeforeFinalLayerProof { proof: proof_layers, }, @@ -375,10 +377,11 @@ fn prove_before_final_circuit_layers< evaluation_point: rand, claimed_evaluation: claim, }, - ) + )) } /// Runs the first sum-check prover for the input layer. +#[allow(clippy::type_complexity)] fn sum_check_prover_plain_partial< E: FieldElement + 'static, C: RandomCoin, @@ -388,11 +391,11 @@ fn sum_check_prover_plain_partial< num_rounds: usize, ml_polys: &mut [MultiLinearPoly], transcript: &mut C, -) -> ((RoundClaim, Vec>), E) { +) -> Result<((RoundClaim, Vec>), E), ProverError> { // generate challenge to batch two sumchecks let data = vec![claim.0, claim.1]; transcript.reseed(H::hash_elements(&data)); - let r_batch = transcript.draw().unwrap(); + let r_batch = transcript.draw().map_err(|_| ProverError::FailedToGenerateChallenge)?; let claim = claim.0 + claim.1 * r_batch; // generate the composition polynomial @@ -400,9 +403,11 @@ fn sum_check_prover_plain_partial< // run the sum-check protocol let main_prover = SumCheckProver::new(composer, SimpleGkrFinalClaimBuilder(PhantomData)); - let proof = main_prover.prove_rounds(claim, ml_polys, num_rounds, transcript).unwrap(); + let proof = main_prover + .prove_rounds(claim, ml_polys, num_rounds, transcript) + .map_err(|_| ProverError::FailedToProveSumCheck)?; - (proof, r_batch) + Ok((proof, r_batch)) } /// Runs the sum-check prover used in all but the input layer. @@ -414,11 +419,11 @@ fn sum_check_prover_plain_full< claim: (E, E), ml_polys: &mut [MultiLinearPoly], transcript: &mut C, -) -> (SumCheckProof, E) { +) -> Result<(SumCheckProof, E), ProverError> { // generate challenge to batch two sumchecks let data = vec![claim.0, claim.1]; transcript.reseed(H::hash_elements(&data)); - let r_batch = transcript.draw().unwrap(); + let r_batch = transcript.draw().map_err(|_| ProverError::FailedToGenerateChallenge)?; let claim_ = claim.0 + claim.1 * r_batch; // generate the composition polynomial @@ -426,9 +431,11 @@ fn sum_check_prover_plain_full< // run the sum-check protocol let main_prover = SumCheckProver::new(composer, SimpleGkrFinalClaimBuilder(PhantomData)); - let proof = main_prover.prove(claim_, ml_polys, transcript).unwrap(); + let proof = main_prover + .prove(claim_, ml_polys, transcript) + .map_err(|_| ProverError::FailedToProveSumCheck)?; - (proof, r_batch) + Ok((proof, r_batch)) } /// Computes the evaluations over {0, 1}^{μ + ν} of @@ -456,9 +463,9 @@ fn evaluate_composition_polys + 'static>( num_den } -/// Constructs [FinalOpeningClaim] for the sum-checks used in the GKR protocol. +/// Constructs [`FinalOpeningClaim`] for the sum-checks used in the GKR protocol. /// -/// TODO: currently, this just removes the EQ evaluation as it can computed by the verifier. +/// TODO: currently, this just removes the EQ evaluation as it can be computed by the verifier. /// This should be generalized for other "transparent" multi-linears e.g., periodic columns. struct SimpleGkrFinalClaimBuilder(PhantomData); diff --git a/processor/src/trace/virtual_bus/circuit/verifier.rs b/processor/src/trace/virtual_bus/circuit/verifier.rs index 640796ce4f..5be8efb8fc 100644 --- a/processor/src/trace/virtual_bus/circuit/verifier.rs +++ b/processor/src/trace/virtual_bus/circuit/verifier.rs @@ -47,7 +47,7 @@ pub fn verify< // generate the random challenge to reduce two claims into a single claim transcript.reseed(H::hash_elements(&circuit_outputs)); - let r = transcript.draw().map_err(|_| VerifierError::FailedGenerateRandomness)?; + let r = transcript.draw().map_err(|_| VerifierError::FailedToGenerateChallenge)?; // reduce the claim let p_r = p0 + r * (p1 - p0); @@ -70,7 +70,7 @@ pub fn verify< // generate the random challenge to reduce two claims into a single claim transcript.reseed(H::hash_elements(&openings)); - let r_layer = transcript.draw().unwrap(); + let r_layer = transcript.draw().map_err(|_| VerifierError::FailedToGenerateChallenge)?; let p0 = openings[0]; let p1 = openings[1]; @@ -110,7 +110,7 @@ pub fn verify_sum_check_proof_before_last< ) -> Result, VerifierError> { // generate challenge to batch sum-checks transcript.reseed(H::hash_elements(&[claim.0, claim.1])); - let r_batch: E = transcript.draw().unwrap(); + let r_batch: E = transcript.draw().map_err(|_| VerifierError::FailedToGenerateChallenge)?; // compute the claim for the batched sum-check let reduced_claim = claim.0 + claim.1 * r_batch; @@ -143,7 +143,7 @@ pub fn verify_sum_check_proof_last< // generate challenge to batch sum-checks transcript.reseed(H::hash_elements(&[claim.0, claim.1])); - let r_sum_check: E = transcript.draw().unwrap(); + let r_sum_check: E = transcript.draw().map_err(|_| VerifierError::FailedToGenerateChallenge)?; // compute the claim for the batched sum-check let reduced_claim = claim.0 + claim.1 * r_sum_check; @@ -174,7 +174,7 @@ pub fn verify_sum_check_proof_last< .map_err(|_| VerifierError::FailedToVerifySumCheck) } -/// A [FinalQueryBuilder] for the sum-check verifier used for all sum-checks but for the final one. +/// A [`FinalQueryBuilder`] for the sum-check verifier used for all sum-checks but for the final one. #[derive(Default)] struct GkrQueryBuilder { gkr_eval_point: Vec, @@ -198,7 +198,7 @@ impl CompositionPolyQueryBuilder for GkrQueryBuilder { } } -/// A [FinalQueryBuilder] for the sum-check verifier used for the final sum-check. +/// A [`FinalQueryBuilder`] for the sum-check verifier used for the final sum-check. #[derive(Default)] struct GkrMergeQueryBuilder { gkr_eval_point: Vec, diff --git a/processor/src/trace/virtual_bus/error.rs b/processor/src/trace/virtual_bus/error.rs index 1a79e1540d..ba9ade0052 100644 --- a/processor/src/trace/virtual_bus/error.rs +++ b/processor/src/trace/virtual_bus/error.rs @@ -5,3 +5,15 @@ pub enum Error { #[error("number of numerators and denominators should be at least two")] NumeratorDenominatorLessThanTwo, } + +#[derive(Debug, thiserror::Error)] +pub enum ProverError { + #[error("failed to generate a proof for the virtual bus relation")] + FailedToGenerateProof, +} + +#[derive(Debug, thiserror::Error)] +pub enum VerifierError { + #[error("failed to generate a proof for the virtual bus relation")] + FailedToVerifyProof, +} diff --git a/processor/src/trace/virtual_bus/prover.rs b/processor/src/trace/virtual_bus/prover.rs index dc947882d7..8ca3778e0e 100644 --- a/processor/src/trace/virtual_bus/prover.rs +++ b/processor/src/trace/virtual_bus/prover.rs @@ -1,6 +1,6 @@ use super::{ circuit::GkrCircuitProof, - error::Error, + error::{Error, ProverError}, generate, multilinear::{CompositionPolynomial, MultiLinearPoly}, prove, @@ -50,7 +50,7 @@ where C: RandomCoin, H: ElementHasher, { - /// Constructs a new [VirtualBusProver] given a set of random values for the GKR-LogUp relation. + /// Constructs a new [`VirtualBusProver`] given a set of random values for the GKR-LogUp relation. /// /// The constructor uses the randomness to do two things: /// @@ -86,7 +86,11 @@ where } /// Proves the GKR-LogUp relation. - pub fn prove(&self, trace: &MainTrace, transcript: &mut C) -> GkrCircuitProof { + pub fn prove( + &self, + trace: &MainTrace, + transcript: &mut C, + ) -> Result, ProverError> { // TODO: Optimize this so that we can work with base field element directly and thus save // on memory usage. let trace_len = trace.num_rows(); @@ -98,6 +102,8 @@ where MultiLinearPoly::from_evaluations(values).unwrap() }) .collect(); + prove(self.composition_polynomials(), &mut mls, transcript) + .map_err(|_| ProverError::FailedToGenerateProof) } } diff --git a/processor/src/trace/virtual_bus/tests.rs b/processor/src/trace/virtual_bus/tests.rs index 64129b5802..5a36fd53a5 100644 --- a/processor/src/trace/virtual_bus/tests.rs +++ b/processor/src/trace/virtual_bus/tests.rs @@ -3,7 +3,10 @@ use crate::{ DefaultHost, ExecutionTrace, Process, }; use alloc::vec::Vec; -use miden_air::{trace::main_trace::MainTrace, ExecutionOptions}; +use miden_air::{ + trace::{main_trace::MainTrace, range::M_COL_IDX}, + ExecutionOptions, +}; use vm_core::crypto::random::RpoRandomCoin; use vm_core::{ code_blocks::CodeBlock, CodeBlockTable, Felt, FieldElement, Kernel, Operation, StackInputs, @@ -29,12 +32,45 @@ fn test_vb_prover_verifier() { let seed = [Felt::ZERO; 4]; // should be initialized with the appropriate transcript let mut transcript = RpoRandomCoin::new(seed.into()); let vb_prover = VirtualBusProver::new(alphas.clone()).unwrap(); - let proof = vb_prover.prove(&trace, &mut transcript); + let proof = vb_prover.prove(&trace, &mut transcript).unwrap(); + + let seed = [Felt::ZERO; 4]; // should be initialized with the appropriate transcript + let mut transcript = RpoRandomCoin::new(seed.into()); + let vb_verifier = VirtualBusVerifier::new(alphas).unwrap(); + let final_opening_claim = vb_verifier.verify(proof, &mut transcript); + assert!(final_opening_claim.is_ok()) +} + +#[test] +fn test_vb_prover_verifier_failure() { + let s = 6; + let o = 6; + let stack: Vec<_> = (0..(1 << s)).into_iter().collect(); + let operations: Vec<_> = (0..(1 << o)) + .flat_map(|_| { + vec![Operation::U32split, Operation::U32add, Operation::U32xor, Operation::MStoreW] + }) + .collect(); + + // modifying the multiplicity + let mut trace = build_full_trace(&stack, operations, Kernel::default()); + let index = trace.get_column(M_COL_IDX).iter().position(|v| *v != Felt::ZERO).unwrap(); + trace.get_column_mut(M_COL_IDX)[index] = Felt::ONE; + + // this should be generated using the transcript up to when the prover sends the commitment + // to the main trace. + let alphas: Vec = vec![test_utils::rand::rand_value()]; + + let seed = [Felt::ZERO; 4]; // should be initialized with the appropriate transcript + let mut transcript = RpoRandomCoin::new(seed.into()); + let vb_prover = VirtualBusProver::new(alphas.clone()).unwrap(); + let proof = vb_prover.prove(&trace, &mut transcript).unwrap(); let seed = [Felt::ZERO; 4]; // should be initialized with the appropriate transcript let mut transcript = RpoRandomCoin::new(seed.into()); let vb_verifier = VirtualBusVerifier::new(alphas).unwrap(); - let _final_opening_claim = vb_verifier.verify(proof, &mut transcript); + let final_opening_claim = vb_verifier.verify(proof, &mut transcript); + assert!(final_opening_claim.is_err()) } fn build_full_trace(stack_inputs: &[u64], operations: Vec, kernel: Kernel) -> MainTrace { diff --git a/processor/src/trace/virtual_bus/verifier.rs b/processor/src/trace/virtual_bus/verifier.rs index 5ee2766663..1f4754afcb 100644 --- a/processor/src/trace/virtual_bus/verifier.rs +++ b/processor/src/trace/virtual_bus/verifier.rs @@ -1,6 +1,10 @@ use super::{ - circuit::GkrCircuitProof, error::Error, generate, multilinear::CompositionPolynomial, - sum_check::FinalOpeningClaim, verify, + circuit::GkrCircuitProof, + error::{Error, VerifierError}, + generate, + multilinear::CompositionPolynomial, + sum_check::FinalOpeningClaim, + verify, }; use alloc::{sync::Arc, vec::Vec}; use core::marker::PhantomData; @@ -26,7 +30,7 @@ where C: RandomCoin, H: ElementHasher, { - /// Constructs a new [VirtualBusVerifier] given a set of random values for the GKR-LogUp relation. + /// Constructs a new [`VirtualBusVerifier`] given a set of random values for the GKR-LogUp relation. pub fn new(log_up_randomness: Vec) -> Result { let (claim, composition_polynomials) = generate(log_up_randomness)?; @@ -51,7 +55,12 @@ where /// Verifies the GKR-LogUp relation. This output, in the case the proof is accepted, /// a [FinalOpeningClaim] which is passed on to the STARK verifier in order to check /// the correctness of the claimed openings. - pub fn verify(&self, proof: GkrCircuitProof, transcript: &mut C) -> FinalOpeningClaim { - verify(self.claim, proof, self.composition_polynomials(), transcript).unwrap() + pub fn verify( + &self, + proof: GkrCircuitProof, + transcript: &mut C, + ) -> Result, VerifierError> { + verify(self.claim, proof, self.composition_polynomials(), transcript) + .map_err(|_| VerifierError::FailedToVerifyProof) } }