From 3fe48f96bd6592df5a5f69de75aa47c671636751 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Tue, 3 Dec 2024 19:38:43 +0100 Subject: [PATCH 1/2] PCS methods return Results --- src/aggregation/multiple.rs | 6 +++--- src/aggregation/single.rs | 4 ++-- src/lib.rs | 4 ++-- src/pcs/id/mod.rs | 14 ++++++++------ src/pcs/kzg/mod.rs | 31 ++++++++++++++++++------------- src/pcs/mod.rs | 18 ++++++++++++------ src/shplonk.rs | 8 ++++---- tests/plonk/batchy.rs | 8 ++++---- tests/plonk/fflonky.rs | 2 +- 9 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/aggregation/multiple.rs b/src/aggregation/multiple.rs index 748ab95..ca12b8f 100644 --- a/src/aggregation/multiple.rs +++ b/src/aggregation/multiple.rs @@ -61,7 +61,7 @@ pub fn aggregate_polys, T: Transcript>( // By (**) qi = (fi - ri) / zi, thus q = sum(gamma^i * qi) 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); @@ -216,13 +216,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 ce8b5fc..cc31c06 100644 --- a/src/aggregation/single.rs +++ b/src/aggregation/single.rs @@ -20,7 +20,7 @@ pub struct Claim> { impl> Claim { pub fn new(ck: &CS::CK, poly: &Poly, at: F) -> Claim where CS: PCS { Claim { - c: CS::commit(ck, poly), + c: CS::commit(ck, poly).unwrap(), x: at, y: poly.evaluate(&at), } @@ -114,7 +114,7 @@ mod tests { 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 1f33a4b..64ebed3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -209,7 +209,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(¶ms.vk(), &gc, t, proof, &roots, &vss, transcript)); @@ -240,7 +240,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 b49c862..8fed0ac 100644 --- a/src/pcs/id/mod.rs +++ b/src/pcs/id/mod.rs @@ -109,16 +109,18 @@ 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 6991596..fd134c0 100644 --- a/src/pcs/kzg/mod.rs +++ b/src/pcs/kzg/mod.rs @@ -117,36 +117,41 @@ 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) + 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) + 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(vk: &KzgVerifierKey, c: Self::C, x: E::ScalarField, y: E::ScalarField, proof: Self::Proof) -> bool { + fn verify(vk: &KzgVerifierKey, c: Self::C, x: E::ScalarField, y: E::ScalarField, proof: Self::Proof) -> Result<(), ()> { let opening = KzgOpening { c: c.0, x, y, proof }; Self::verify_single(opening, vk) + .then(|| ()) + .ok_or(()) } - fn batch_verify(vk: &KzgVerifierKey, c: Vec, x: Vec, y: Vec, proof: Vec, rng: &mut R) -> bool { + fn batch_verify(vk: &KzgVerifierKey, c: Vec, x: Vec, y: Vec, proof: Vec, rng: &mut R) -> Result<(), ()> { assert_eq!(c.len(), x.len()); assert_eq!(c.len(), y.len()); let openings = c.into_iter().zip(x.into_iter()).zip(y.into_iter()).zip(proof.into_iter()) .map(|(((c, x), y), proof)| KzgOpening { c: c.0, x, y, proof }) .collect(); Self::verify_batch(openings, vk, rng) + .then(|| ()) + .ok_or(()) } } @@ -182,15 +187,15 @@ mod tests { let z = p.evaluate(&x); let t_commit = start_timer!(|| format!("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); } @@ -208,8 +213,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 31dab7e..9945ae3 100644 --- a/src/pcs/mod.rs +++ b/src/pcs/mod.rs @@ -85,25 +85,31 @@ 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<(), ()>; - fn batch_verify(vk: &Self::VK, c: Vec, x: Vec, y: Vec, proof: Vec, _rng: &mut R) -> bool { + // TODO: is the default implementation useful? + fn batch_verify(vk: &Self::VK, c: Vec, x: Vec, y: Vec, proof: Vec, _rng: &mut R) -> 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 a2f5b94..d642963 100644 --- a/src/shplonk.rs +++ b/src/shplonk.rs @@ -30,7 +30,7 @@ impl> Shplonk { { 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} } @@ -44,10 +44,10 @@ impl> Shplonk { ) -> bool { let AggregateProof {agg_proof, opening_proof} = proof; - let onec = CS::commit(&vk.clone().into(), &Poly::from_coefficients_slice(&[F::one()])); + 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(vk, agg_claim.c, agg_claim.xs[0], agg_claim.ys[0], opening_proof) + CS::verify(vk, agg_claim.c, agg_claim.xs[0], agg_claim.ys[0], opening_proof).is_ok() } } @@ -100,7 +100,7 @@ pub(crate) mod tests { .collect(); // commitments let fcs: Vec<_> = fs.iter() - .map(|fi| CS::commit(&ck, fi)) + .map(|fi| CS::commit(&ck, fi).unwrap()) .collect(); // evaluations per polynomial diff --git a/tests/plonk/batchy.rs b/tests/plonk/batchy.rs index 69530d2..f8a70ff 100644 --- a/tests/plonk/batchy.rs +++ b/tests/plonk/batchy.rs @@ -88,7 +88,7 @@ pub struct PlonkBatchKzgTest> { 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 } @@ -152,8 +152,8 @@ impl> DecoyPlonk for PlonkBatchKzgTest { polys_to_open_at_zeta.extend_from_slice(&self.polys.polys_to_open_at_zeta_5()); 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_omega = CS::open(ck, &self.polys.poly_to_open_at_zeta_omega_5(), zeta_omega); + 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).unwrap(); // TODO: compute let t_extra = start_timer!(|| "Extra: commiting to the linearization polynomial"); @@ -214,6 +214,6 @@ impl> DecoyPlonk for PlonkBatchKzgTest { &mut test_rng()); 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 ee42dc1..ae43ea9 100644 --- a/tests/plonk/fflonky.rs +++ b/tests/plonk/fflonky.rs @@ -92,7 +92,7 @@ impl> PlonkWithFflonkTest { end_timer!(t_combine); let t_commit_combined = start_timer!(|| format!("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); From c29fe0f95b8742f623a03395a2279cfb3ebe65c0 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Tue, 3 Dec 2024 20:08:32 +0100 Subject: [PATCH 2/2] asserts removed --- src/pcs/kzg/mod.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/pcs/kzg/mod.rs b/src/pcs/kzg/mod.rs index fd134c0..375a120 100644 --- a/src/pcs/kzg/mod.rs +++ b/src/pcs/kzg/mod.rs @@ -60,7 +60,6 @@ impl KZG { } pub fn accumulate(openings: Vec>, 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(); let sum_ry = rs.iter().zip(ys.into_iter()).map(|(r, y)| y * r).sum::(); @@ -99,8 +98,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()) } } @@ -119,14 +117,17 @@ impl PCS for KZG { 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()); + 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) -> 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()); + if evals.evals.len() > ck.max_evals() || evals.domain() != ck.domain { + return Err(()) + } Ok(Self::_commit(&evals.evals, &ck.lis_in_g)) } @@ -144,8 +145,9 @@ impl PCS for KZG { } fn batch_verify(vk: &KzgVerifierKey, c: Vec, x: Vec, y: Vec, proof: Vec, rng: &mut R) -> Result<(), ()> { - assert_eq!(c.len(), x.len()); - assert_eq!(c.len(), y.len()); + if c.len() != x.len() || c.len() != y.len() { + return Err(()) + } let openings = c.into_iter().zip(x.into_iter()).zip(y.into_iter()).zip(proof.into_iter()) .map(|(((c, x), y), proof)| KzgOpening { c: c.0, x, y, proof }) .collect();