diff --git a/src/aggregation/multiple.rs b/src/aggregation/multiple.rs index b98200d..82fe136 100644 --- a/src/aggregation/multiple.rs +++ b/src/aggregation/multiple.rs @@ -66,7 +66,7 @@ pub fn aggregate_polys, T: Transcript>( let q = poly::sum_with_powers(gamma, &qs); let t_commit = start_timer!(|| ark_std::format!("commitment to a degree-{} polynomial", q.degree())); - let qc = CS::commit(ck, &q); + let qc = CS::commit(ck, &q).unwrap(); // "W" in the paper end_timer!(t_commit); transcript.commit_to_q(&qc); @@ -236,13 +236,13 @@ mod tests { end_timer!(t_aggregate_polys); let claims = group_by_commitment(&opening.fcs, &opening.xss, &opening.yss); - let onec = CS::commit(&vk.clone().into(), &poly::constant(F::one())); + let onec = CS::commit(&vk.clone().into(), &poly::constant(F::one())).unwrap(); let t_aggregate_claims = start_timer!(|| format!("Aggregate {} claims", claims.len())); let agg_claim = aggregate_claims::<_, CS, _>(claims, &agg_proof, &onec, transcript); end_timer!(t_aggregate_claims); - assert_eq!(CS::commit(&ck, &agg_poly), agg_claim.c); + assert_eq!(CS::commit(&ck, &agg_poly).unwrap(), agg_claim.c); assert_eq!(zeta, agg_claim.xs[0]); assert_eq!(agg_poly.evaluate(&zeta), agg_claim.ys[0]); assert!(agg_claim.ys[0].is_zero()); diff --git a/src/aggregation/single.rs b/src/aggregation/single.rs index 6ecf2cd..e88ec10 100644 --- a/src/aggregation/single.rs +++ b/src/aggregation/single.rs @@ -23,7 +23,7 @@ impl> Claim { CS: PCS, { Claim { - c: CS::commit(ck, poly), + c: CS::commit(ck, poly).unwrap(), x: at, y: poly.evaluate(&at), } @@ -126,7 +126,7 @@ mod tests { .collect::>(); let agg_claim = aggregate_claims::(&claims_at_same_x, &rs); - assert_eq!(CS::commit(&ck, &agg_poly), agg_claim.c); + assert_eq!(CS::commit(&ck, &agg_poly).unwrap(), agg_claim.c); assert_eq!(same_x, agg_claim.x); assert_eq!(agg_poly.evaluate(&same_x), agg_claim.y); } diff --git a/src/lib.rs b/src/lib.rs index 2f8e43d..db7292e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,7 +208,7 @@ mod tests { let (fs, roots, vss) = generate_test_data(rng, d, t, m); let g = Fflonk::combine(t, &fs); - let gc = CS::commit(¶ms.ck(), &g); + let gc = CS::commit(¶ms.ck(), &g).unwrap(); let proof = FflonkyKzg::::open_single(¶ms.ck(), &fs, t, &roots, transcript); assert!(FflonkyKzg::::verify_single( @@ -245,7 +245,7 @@ mod tests { let gcs: Vec<_> = fss .iter() .zip(ts) - .map(|(fs, t)| CS::commit(¶ms.ck(), &Fflonk::combine(t, &fs))) + .map(|(fs, t)| CS::commit(¶ms.ck(), &Fflonk::combine(t, &fs)).unwrap()) .collect(); let proof = FflonkyKzg::::open(¶ms.ck(), &fss, &ts, &rootss, transcript); diff --git a/src/pcs/id/mod.rs b/src/pcs/id/mod.rs index a08a2b2..b2ab83b 100644 --- a/src/pcs/id/mod.rs +++ b/src/pcs/id/mod.rs @@ -110,15 +110,15 @@ impl PCS for IdentityCommitment { () } - fn commit(_ck: &(), p: &Poly) -> Self::C { - WrappedPolynomial(p.clone()) + fn commit(_ck: &(), p: &Poly) -> Result { + Ok(WrappedPolynomial(p.clone())) } - fn open(_ck: &(), _p: &Poly, _x: F) -> Self::Proof { - () + fn open(_ck: &(), _p: &Poly, _x: F) -> Result { + Ok(()) } - fn verify(_vk: &(), c: Self::C, x: F, z: F, _proof: Self::Proof) -> bool { - c.evaluate(&x) == z + fn verify(_vk: &(), c: Self::C, x: F, z: F, _proof: Self::Proof) -> Result<(), ()> { + (c.evaluate(&x) == z).then(|| ()).ok_or(()) } } diff --git a/src/pcs/kzg/mod.rs b/src/pcs/kzg/mod.rs index b286fc5..cbb5d7c 100644 --- a/src/pcs/kzg/mod.rs +++ b/src/pcs/kzg/mod.rs @@ -65,7 +65,6 @@ impl KZG { rs: &[E::ScalarField], vk: &KzgVerifierKey, ) -> AccumulatedOpening { - assert_eq!(openings.len(), rs.len()); let openings = Self::parse(openings); let ((accs, proofs), ys): ((Vec, Vec), Vec) = openings.into_iter().unzip(); @@ -117,8 +116,7 @@ impl KZG { fn _commit(coeffs: &[E::ScalarField], bases: &[E::G1Affine]) -> KzgCommitment { // `msm` allows to call into implementation of `VariableBaseMSM` for `Projective. // This allows to call into custom implementations of `msm` (`msm_unchecked` not). - let len = usize::min(coeffs.len(), bases.len()); - let proj = ::msm(&bases[..len], &coeffs[..len]).unwrap(); + let proj = ::msm(&bases[..coeffs.len()], &coeffs).unwrap(); KzgCommitment(proj.into_affine()) } } @@ -135,35 +133,28 @@ impl PCS for KZG { URS::::generate(max_degree + 1, 2, rng) } - fn commit(ck: &Self::CK, p: &Poly) -> Self::C { + fn commit(ck: &Self::CK, p: &Poly) -> Result { let ck = &ck.monomial; - assert!( - p.degree() <= ck.max_degree(), - "Can't commit to degree {} polynomial using {} bases", - p.degree(), - ck.max_evals() - ); - Self::_commit(&p.coeffs, &ck.powers_in_g1) + if p.degree() > ck.max_degree() { + return Err(()); + } + Ok(Self::_commit(&p.coeffs, &ck.powers_in_g1)) } - fn commit_evals(ck: &Self::CK, evals: &Evaluations) -> Self::C { + fn commit_evals(ck: &Self::CK, evals: &Evaluations) -> Result { let ck = ck .lagrangian .as_ref() .expect("lagrangian key hadn't been generated"); - assert_eq!(evals.domain(), ck.domain); - assert!( - evals.evals.len() <= ck.max_evals(), - "Can't commit to {} values using {} bases", - evals.evals.len(), - ck.max_evals() - ); - Self::_commit(&evals.evals, &ck.lis_in_g) + if evals.evals.len() > ck.max_evals() || evals.domain() != ck.domain { + return Err(()); + } + Ok(Self::_commit(&evals.evals, &ck.lis_in_g)) } - fn open(ck: &Self::CK, p: &Poly, x: E::ScalarField) -> Self::Proof { + fn open(ck: &Self::CK, p: &Poly, x: E::ScalarField) -> Result { let q = Self::compute_quotient(p, x); - Self::commit(ck, &q).0 + Self::commit(ck, &q).map(|c| c.0) } fn verify( @@ -172,14 +163,14 @@ impl PCS for KZG { x: E::ScalarField, y: E::ScalarField, proof: Self::Proof, - ) -> bool { + ) -> Result<(), ()> { let opening = KzgOpening { c: c.0, x, y, proof, }; - Self::verify_single(opening, vk) + Self::verify_single(opening, vk).then(|| ()).ok_or(()) } fn batch_verify( @@ -189,9 +180,10 @@ impl PCS for KZG { y: Vec, proof: Vec, rng: &mut R, - ) -> bool { - assert_eq!(c.len(), x.len()); - assert_eq!(c.len(), y.len()); + ) -> Result<(), ()> { + if c.len() != x.len() || c.len() != y.len() { + return Err(()); + } let openings = c .into_iter() .zip(x.into_iter()) @@ -204,7 +196,7 @@ impl PCS for KZG { proof, }) .collect(); - Self::verify_batch(openings, vk, rng) + Self::verify_batch(openings, vk, rng).then(|| ()).ok_or(()) } } @@ -247,15 +239,15 @@ mod tests { "Committing to a dense degree-{} polynomial", ck.max_degree() )); - let c = KZG::::commit(&ck, &p); + let c = KZG::::commit(&ck, &p).unwrap(); end_timer!(t_commit); let t_prove = start_timer!(|| "Generating an opening proof for a single point"); - let proof = KZG::::open(&ck, &p, x); + let proof = KZG::::open(&ck, &p, x).unwrap(); end_timer!(t_prove); let t_verify = start_timer!(|| "Verification of a single-point opening"); - assert!(KZG::::verify(&vk, c, x, z, proof)); + assert!(KZG::::verify(&vk, c, x, z, proof).is_ok()); end_timer!(t_verify); } @@ -273,8 +265,8 @@ mod tests { let f = Poly::::rand(d, rng); let x = xs[i]; let y = f.evaluate(&x); - let c = KZG::::commit(ck, &f).0; - let proof = KZG::::open(ck, &f, x); + let c = KZG::::commit(ck, &f).unwrap().0; + let proof = KZG::::open(ck, &f, x).unwrap(); KzgOpening { c, x, y, proof } }) .collect() diff --git a/src/pcs/mod.rs b/src/pcs/mod.rs index 743144d..7a8f576 100644 --- a/src/pcs/mod.rs +++ b/src/pcs/mod.rs @@ -82,21 +82,23 @@ pub trait PCS { // vk needs to be convertible to a ck that is only required to commit to the p=1 constant polynomial, // see https://eprint.iacr.org/archive/2020/1536/1629188090.pdf, section 4.2 type VK: VerifierKey + Into; + type Params: PcsParams; fn setup(max_degree: usize, rng: &mut R) -> Self::Params; - fn commit(ck: &Self::CK, p: &Poly) -> Self::C; + fn commit(ck: &Self::CK, p: &Poly) -> Result; - fn commit_evals(ck: &Self::CK, evals: &Evaluations) -> Self::C { + fn commit_evals(ck: &Self::CK, evals: &Evaluations) -> Result { let poly = evals.interpolate_by_ref(); Self::commit(ck, &poly) } - fn open(ck: &Self::CK, p: &Poly, x: F) -> Self::Proof; //TODO: eval? + fn open(ck: &Self::CK, p: &Poly, x: F) -> Result; - fn verify(vk: &Self::VK, c: Self::C, x: F, z: F, proof: Self::Proof) -> bool; + fn verify(vk: &Self::VK, c: Self::C, x: F, z: F, proof: Self::Proof) -> Result<(), ()>; + // TODO: is the default implementation useful? fn batch_verify( vk: &Self::VK, c: Vec, @@ -104,13 +106,15 @@ pub trait PCS { y: Vec, proof: Vec, _rng: &mut R, - ) -> bool { + ) -> Result<(), ()> { assert_eq!(c.len(), x.len()); assert_eq!(c.len(), y.len()); c.into_iter() .zip(x.into_iter()) .zip(y.into_iter()) .zip(proof.into_iter()) - .all(|(((c, x), y), proof)| Self::verify(vk, c, x, y, proof)) + .all(|(((c, x), y), proof)| Self::verify(vk, c, x, y, proof).is_ok()) + .then(|| ()) + .ok_or(()) } } diff --git a/src/shplonk.rs b/src/shplonk.rs index 1078e39..278aaa6 100644 --- a/src/shplonk.rs +++ b/src/shplonk.rs @@ -31,7 +31,7 @@ impl> Shplonk { ) -> AggregateProof { let (agg_poly, zeta, agg_proof) = aggregate_polys::(ck, fs, xss, transcript); assert!(agg_poly.evaluate(&zeta).is_zero()); - let opening_proof = CS::open(ck, &agg_poly, zeta); + let opening_proof = CS::open(ck, &agg_poly, zeta).unwrap(); AggregateProof { agg_proof, opening_proof, @@ -53,7 +53,8 @@ impl> Shplonk { let onec = CS::commit( &vk.clone().into(), &Poly::from_coefficients_slice(&[F::one()]), - ); + ) + .unwrap(); let claims = group_by_commitment(fcs, xss, yss); let agg_claim = aggregate_claims::(claims, &agg_proof, &onec, transcript); CS::verify( @@ -63,6 +64,7 @@ impl> Shplonk { agg_claim.ys[0], opening_proof, ) + .is_ok() } } @@ -115,7 +117,7 @@ pub(crate) mod tests { // polynomials let fs: Vec<_> = (0..t).map(|_| Poly::::rand(d, rng)).collect(); // commitments - let fcs: Vec<_> = fs.iter().map(|fi| CS::commit(&ck, fi)).collect(); + let fcs: Vec<_> = fs.iter().map(|fi| CS::commit(&ck, fi).unwrap()).collect(); // evaluations per polynomial let yss: Vec<_> = fs diff --git a/tests/plonk/batchy.rs b/tests/plonk/batchy.rs index c39aeb8..52eccd3 100644 --- a/tests/plonk/batchy.rs +++ b/tests/plonk/batchy.rs @@ -99,7 +99,7 @@ impl> PlonkBatchKzgTest { fn commit_polynomial(&self, ck: &CS::CK, poly: &Poly) -> CS::C { let t_commitment = start_timer!(|| format!("Committing to degree {} polynomials", poly.degree())); - let commitment = CS::commit(ck, poly); + let commitment = CS::commit(ck, poly).unwrap(); end_timer!(t_commitment); commitment } @@ -182,9 +182,9 @@ impl> DecoyPlonk for PlonkBatchKzgTest { let agg_poly_at_zeta = poly::sum_with_coeffs(self.challenges.nus.clone(), &polys_to_open_at_zeta); - let proof_at_zeta = CS::open(ck, &agg_poly_at_zeta, zeta); + let proof_at_zeta = CS::open(ck, &agg_poly_at_zeta, zeta).unwrap(); let proof_at_zeta_omega = - CS::open(ck, &self.polys.poly_to_open_at_zeta_omega_5(), zeta_omega); + CS::open(ck, &self.polys.poly_to_open_at_zeta_omega_5(), zeta_omega).unwrap(); // TODO: compute let t_extra = start_timer!(|| "Extra: commiting to the linearization polynomial"); @@ -262,6 +262,6 @@ impl> DecoyPlonk for PlonkBatchKzgTest { ); end_timer!(t_kzg_batch_opening); end_timer!(t_kzg); - valid + valid.is_ok() } } diff --git a/tests/plonk/fflonky.rs b/tests/plonk/fflonky.rs index f602474..2d23164 100644 --- a/tests/plonk/fflonky.rs +++ b/tests/plonk/fflonky.rs @@ -117,7 +117,7 @@ impl> PlonkWithFflonkTest { "committing to the combined polynomial: degree = {}", poly.degree() )); - let commitment = CS::commit(ck, &poly); + let commitment = CS::commit(ck, &poly).unwrap(); end_timer!(t_commit_combined); end_timer!(t_commit);