From a922e325f0fdd19ac1069c5dd4745a0762fd8fce Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 9 Apr 2026 14:50:01 +0300 Subject: [PATCH 01/11] ring-proof switched to SW jubjub --- w3f-ring-proof/benches/ring_proof.rs | 30 +++++++++---------- w3f-ring-proof/src/lib.rs | 24 +++++++-------- .../src/multi_ring_batch_verifier.rs | 10 +++---- w3f-ring-proof/src/piop/mod.rs | 8 ++--- w3f-ring-proof/src/piop/params.rs | 16 +++++----- w3f-ring-proof/src/piop/prover.rs | 8 ++--- w3f-ring-proof/src/piop/verifier.rs | 4 +-- w3f-ring-proof/src/ring.rs | 26 ++++++++-------- w3f-ring-proof/src/ring_prover.rs | 6 ++-- w3f-ring-proof/src/ring_verifier.rs | 14 ++++----- 10 files changed, 73 insertions(+), 73 deletions(-) diff --git a/w3f-ring-proof/benches/ring_proof.rs b/w3f-ring-proof/benches/ring_proof.rs index b0ab568..f9816d8 100644 --- a/w3f-ring-proof/benches/ring_proof.rs +++ b/w3f-ring-proof/benches/ring_proof.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criteri use ark_bls12_381::Bls12_381; use ark_ec::CurveGroup; -use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr}; +use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; use ark_serialize::CanonicalSerialize; use ark_std::ops::Mul; use ark_std::rand::Rng; @@ -25,9 +25,9 @@ fn setup( let setup_degree = 3 * domain_size; let pcs_params = CS::setup(setup_degree, rng); let domain = Domain::new(domain_size, true); - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); + let h = SWAffine::rand(rng); + let seed = SWAffine::rand(rng); + let padding = SWAffine::rand(rng); let piop_params = PiopParams::setup(domain, h, seed, padding); (pcs_params, piop_params) } @@ -37,7 +37,7 @@ fn make_transcript() -> ArkTranscript { } /// Get the Pedersen blinding base H from the PIOP params (first element of the power-of-2 multiples). -fn get_h(piop_params: &PiopParams) -> EdwardsAffine { +fn get_h(piop_params: &PiopParams) -> SWAffine { piop_params.power_of_2_multiples_of_h()[0] } @@ -45,9 +45,9 @@ fn get_h(piop_params: &PiopParams) -> EdwardsAffine { fn generate_proof( piop_params: &PiopParams, pcs_params: &>::Params, - pks: &[EdwardsAffine], + pks: &[SWAffine], rng: &mut impl Rng, -) -> (EdwardsAffine, RingProof) { +) -> (SWAffine, RingProof) { let h = get_h(piop_params); let prover_idx = rng.gen_range(0..pks.len()); let (prover_key, _) = index::<_, CS, _>(pcs_params, piop_params, pks); @@ -86,7 +86,7 @@ fn bench_index(c: &mut Criterion) { let n = 1usize << log_n; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); group.bench_with_input(BenchmarkId::new("full_keyset", n), &n, |b, _| { b.iter(|| index::<_, CS, _>(&pcs_params, &piop_params, &pks)); @@ -104,7 +104,7 @@ fn bench_prove(c: &mut Criterion) { let n = 1usize << log_n; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let (prover_key, _) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); let prover_idx = rng.gen_range(0..keyset_size); @@ -132,7 +132,7 @@ fn bench_verify(c: &mut Criterion) { let n = 1usize << log_n; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let (blinded_pk, proof) = generate_proof(&piop_params, &pcs_params, &pks, rng); let (_, verifier_key) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); @@ -154,11 +154,11 @@ fn bench_verify_batch_sequential(c: &mut Criterion) { let n = 1usize << log_n; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); // Pre-generate proofs for the largest batch. let max_batch = 32; - let claims: Vec<(EdwardsAffine, RingProof)> = (0..max_batch) + let claims: Vec<(SWAffine, RingProof)> = (0..max_batch) .map(|_| generate_proof(&piop_params, &pcs_params, &pks, rng)) .collect(); @@ -188,10 +188,10 @@ fn bench_verify_batch_kzg(c: &mut Criterion) { let n = 1usize << log_n; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let max_batch = 32; - let claims: Vec<(EdwardsAffine, RingProof)> = (0..max_batch) + let claims: Vec<(SWAffine, RingProof)> = (0..max_batch) .map(|_| generate_proof(&piop_params, &pcs_params, &pks, rng)) .collect(); @@ -227,7 +227,7 @@ fn bench_proof_size(c: &mut Criterion) { let n = 1usize << 10; let (pcs_params, piop_params) = setup(rng, n); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let (_, proof) = generate_proof(&piop_params, &pcs_params, &pks, rng); diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index d2e355e..c600c0f 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -53,7 +53,7 @@ impl ArkTranscript { mod tests { use ark_bls12_381::Bls12_381; use ark_ec::CurveGroup; - use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr}; + use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; use ark_std::ops::Mul; use ark_std::rand::Rng; use ark_std::{end_timer, start_timer, test_rng, UniformRand}; @@ -73,17 +73,17 @@ mod tests { batch_size: usize, ) -> ( RingVerifier, - Vec<(EdwardsAffine, RingProof)>, + Vec<(SWAffine, RingProof)>, ) { let rng = &mut test_rng(); let (pcs_params, piop_params) = setup::<_, CS>(rng, domain_size); let keyset_size = piop_params.keyset_part_size; - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let (prover_key, verifier_key) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); let t_prove = start_timer!(|| "Prove"); - let claims: Vec<(EdwardsAffine, RingProof)> = (0..batch_size) + let claims: Vec<(SWAffine, RingProof)> = (0..batch_size) .map(|_| { let prover_idx = rng.gen_range(0..keyset_size); let prover = RingProver::init( @@ -125,7 +125,7 @@ mod tests { let max_keyset_size = piop_params.keyset_part_size; let keyset_size: usize = rng.gen_range(0..max_keyset_size); - let pks = random_vec::(keyset_size, rng); + let pks = random_vec::(keyset_size, rng); let (_, verifier_key) = index::<_, KZG, _>(&pcs_params, &piop_params, &pks); @@ -146,9 +146,9 @@ mod tests { let pcs_params = CS::setup(setup_degree, rng); let domain = Domain::new(domain_size, true); - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); + let h = SWAffine::rand(rng); + let seed = SWAffine::rand(rng); + let padding = SWAffine::rand(rng); let piop_params = PiopParams::setup(domain, h, seed, padding); (pcs_params, piop_params) @@ -197,18 +197,18 @@ mod tests { // Ring A let keyset_size_a = piop_params.keyset_part_size; - let pks_a = random_vec::(keyset_size_a, rng); + let pks_a = random_vec::(keyset_size_a, rng); let (prover_key_a, verifier_key_a) = index::<_, KZG, _>(&pcs_params, &piop_params, &pks_a); // Ring B (smaller keyset) let keyset_size_b = piop_params.keyset_part_size / 2; - let pks_b = random_vec::(keyset_size_b, rng); + let pks_b = random_vec::(keyset_size_b, rng); let (prover_key_b, verifier_key_b) = index::<_, KZG, _>(&pcs_params, &piop_params, &pks_b); - let mut generate_claims = |prover_key: &ProverKey, EdwardsAffine>, - pks: &[EdwardsAffine], + let mut generate_claims = |prover_key: &ProverKey, SWAffine>, + pks: &[SWAffine], keyset_size: usize| { (0..proofs_per_ring) .map(|_| { diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index 3d048f5..69b0eba 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -1,5 +1,5 @@ use ark_ec::pairing::Pairing; -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::CurveGroup; use ark_std::rand::RngCore; use w3f_pcs::pcs::kzg::params::KzgVerifierKey; @@ -21,7 +21,7 @@ use crate::RingProof; pub struct PreparedMultiRingItem<'a, E, J, T> where E: Pairing, - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { verifier: &'a RingVerifier, J, T>, @@ -61,7 +61,7 @@ impl MultiRingBatchVerifier { result: Affine, ) -> PreparedMultiRingItem<'a, E, J, T> where - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { let (challenges, mut rng) = verifier.plonk_verifier.restore_challenges( @@ -101,7 +101,7 @@ impl MultiRingBatchVerifier { /// 2. `push_prepared` - must be called sequentially (mutates the accumulator) pub fn push_prepared(&mut self, item: PreparedMultiRingItem<'_, E, J, T>) where - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { let mut ts = item.verifier.plonk_verifier.transcript_prelude.clone(); @@ -117,7 +117,7 @@ impl MultiRingBatchVerifier { proof: RingProof>, result: Affine, ) where - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { let item = Self::prepare(verifier, proof, result); diff --git a/w3f-ring-proof/src/piop/mod.rs b/w3f-ring-proof/src/piop/mod.rs index 9e2d1ba..d26eae7 100644 --- a/w3f-ring-proof/src/piop/mod.rs +++ b/w3f-ring-proof/src/piop/mod.rs @@ -1,5 +1,5 @@ use ark_ec::pairing::Pairing; -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::AffineRepr; use ark_ff::PrimeField; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; @@ -97,7 +97,7 @@ impl> FixedColumnsCommitted { } impl FixedColumnsCommitted> { - pub fn from_ring>( + pub fn from_ring>( ring: &Ring, ) -> Self { let cx = KzgCommitment(ring.cx); @@ -159,7 +159,7 @@ impl> Clone for VerifierKey { } impl VerifierKey> { - pub fn from_ring_and_kzg_vk>( + pub fn from_ring_and_kzg_vk>( ring: &Ring, kzg_vk: RawKzgVerifierKey, ) -> Self { @@ -181,7 +181,7 @@ impl VerifierKey> { } } -pub fn index, Curve: TECurveConfig>( +pub fn index, Curve: SWCurveConfig>( pcs_params: &CS::Params, piop_params: &PiopParams, keys: &[Affine], diff --git a/w3f-ring-proof/src/piop/params.rs b/w3f-ring-proof/src/piop/params.rs index 22bd21e..e980117 100644 --- a/w3f-ring-proof/src/piop/params.rs +++ b/w3f-ring-proof/src/piop/params.rs @@ -1,4 +1,4 @@ -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::{AdditiveGroup, AffineRepr, CurveGroup}; use ark_ff::{BigInteger, PrimeField}; use ark_std::{vec, vec::Vec}; @@ -10,7 +10,7 @@ use crate::piop::FixedColumns; /// Plonk Interactive Oracle Proofs (PIOP) parameters. #[derive(Clone)] -pub struct PiopParams> { +pub struct PiopParams> { /// Domain over which the piop is represented. pub(crate) domain: Domain, /// Number of bits used to represent a jubjub scalar. @@ -25,7 +25,7 @@ pub struct PiopParams> { pub(crate) padding: Affine, } -impl> PiopParams { +impl> PiopParams { /// Initialize PIOP parameters. /// /// - `domain`: polynomials evaluation domain. @@ -100,9 +100,9 @@ impl> PiopParams { #[cfg(test)] mod tests { - use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr}; - use ark_std::ops::Mul; + use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; use ark_std::{test_rng, UniformRand}; + use ark_std::ops::Mul; use w3f_plonk_common::domain::Domain; use w3f_plonk_common::test_helpers::cond_sum; @@ -112,9 +112,9 @@ mod tests { #[test] fn test_powers_of_h() { let rng = &mut test_rng(); - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); + let h = SWAffine::rand(rng); + let seed = SWAffine::rand(rng); + let padding = SWAffine::rand(rng); let domain = Domain::new(1024, false); let params = PiopParams::::setup(domain, h, seed, padding); diff --git a/w3f-ring-proof/src/piop/prover.rs b/w3f-ring-proof/src/piop/prover.rs index 07267c3..d0050d0 100644 --- a/w3f-ring-proof/src/piop/prover.rs +++ b/w3f-ring-proof/src/piop/prover.rs @@ -1,4 +1,4 @@ -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ff::PrimeField; use ark_poly::univariate::DensePolynomial; use ark_poly::Evaluations; @@ -22,7 +22,7 @@ use w3f_plonk_common::{Column, FieldColumn}; // The 'table': columns representing the execution trace of the computation // and the constraints -- polynomials that vanish on every 2 consecutive rows. -pub struct PiopProver> { +pub struct PiopProver> { domain: Domain, /// Advice (public input) columns points: AffineColumn>, @@ -38,7 +38,7 @@ pub struct PiopProver> { cond_add_acc_y: FixedCells, } -impl> PiopProver { +impl> PiopProver { pub fn build( params: &PiopParams, fixed_columns: FixedColumns>, @@ -90,7 +90,7 @@ impl ProverPiop for PiopProver where F: PrimeField, C: Commitment, - Curve: TECurveConfig, + Curve: SWCurveConfig, { type Commitments = RingCommitments; type Evaluations = RingEvaluations; diff --git a/w3f-ring-proof/src/piop/verifier.rs b/w3f-ring-proof/src/piop/verifier.rs index 8eb663f..e5ec773 100644 --- a/w3f-ring-proof/src/piop/verifier.rs +++ b/w3f-ring-proof/src/piop/verifier.rs @@ -1,4 +1,4 @@ -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::AffineRepr; use ark_ff::PrimeField; use ark_std::marker::PhantomData; @@ -101,7 +101,7 @@ impl, P: AffineRepr> PiopVerifier } } -impl, Jubjub: TECurveConfig> VerifierPiop +impl, Jubjub: SWCurveConfig> VerifierPiop for PiopVerifier> { const N_CONSTRAINTS: usize = 7; diff --git a/w3f-ring-proof/src/ring.rs b/w3f-ring-proof/src/ring.rs index 600455d..a41c0a5 100644 --- a/w3f-ring-proof/src/ring.rs +++ b/w3f-ring-proof/src/ring.rs @@ -1,5 +1,5 @@ use ark_ec::pairing::Pairing; -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::{AffineRepr, CurveGroup, VariableBaseMSM}; use ark_ff::PrimeField; use ark_poly::EvaluationDomain; @@ -36,7 +36,7 @@ const IDLE_ROWS: usize = ZK_ROWS + 1; pub struct Ring< F: PrimeField, KzgCurve: Pairing, - VrfCurveConfig: TECurveConfig, + VrfCurveConfig: SWCurveConfig, > { /// KZG commitment to the x coordinates of the described vector. pub cx: KzgCurve::G1Affine, @@ -55,7 +55,7 @@ pub struct Ring< impl< F: PrimeField, KzgCurve: Pairing, - VrfCurveConfig: TECurveConfig, + VrfCurveConfig: SWCurveConfig, > fmt::Debug for Ring { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -70,7 +70,7 @@ impl< impl< F: PrimeField, KzgCurve: Pairing, - VrfCurveConfig: TECurveConfig, + VrfCurveConfig: SWCurveConfig, > Ring { /// Builds the commitment to the vector @@ -257,7 +257,7 @@ impl> RingBuilderKey| Ok(ring_builder_key.lis_in_g1[range].to_vec()); // piop params - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); + let h = SWAffine::rand(rng); + let seed = SWAffine::rand(rng); + let padding = SWAffine::rand(rng); let domain = Domain::new(domain_size, true); let piop_params = PiopParams::setup(domain, h, seed, padding); @@ -295,7 +295,7 @@ mod tests { assert_eq!(ring.cx, monimial_cx); assert_eq!(ring.cy, monimial_cy); - let keys = random_vec::(ring.max_keys, rng); + let keys = random_vec::(ring.max_keys, rng); ring.append(&keys, srs); let (monimial_cx, monimial_cy) = get_monomial_commitment(&pcs_params, &piop_params, &keys); assert_eq!(ring.cx, monimial_cx); @@ -316,9 +316,9 @@ mod tests { let srs = |range: Range| Ok(ring_builder_key.lis_in_g1[range].to_vec()); // piop params - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); + let h = SWAffine::rand(rng); + let seed = SWAffine::rand(rng); + let padding = SWAffine::rand(rng); let domain = Domain::new(domain_size, true); let piop_params = PiopParams::setup(domain, h, seed, padding); @@ -330,7 +330,7 @@ mod tests { fn get_monomial_commitment( pcs_params: &URS, piop_params: &PiopParams, - keys: &[EdwardsAffine], + keys: &[SWAffine], ) -> (G1Affine, G1Affine) { let (_, verifier_key) = crate::piop::index::<_, KZG, _>(pcs_params, piop_params, keys); diff --git a/w3f-ring-proof/src/ring_prover.rs b/w3f-ring-proof/src/ring_prover.rs index ac4db81..4428454 100644 --- a/w3f-ring-proof/src/ring_prover.rs +++ b/w3f-ring-proof/src/ring_prover.rs @@ -1,4 +1,4 @@ -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ff::PrimeField; use ark_std::{end_timer, start_timer}; use w3f_pcs::pcs::PCS; @@ -14,7 +14,7 @@ pub struct RingProver where F: PrimeField, CS: PCS, - Curve: TECurveConfig, + Curve: SWCurveConfig, T: PlonkTranscript, { piop_params: PiopParams, @@ -27,7 +27,7 @@ impl RingProver where F: PrimeField, CS: PCS, - Curve: TECurveConfig, + Curve: SWCurveConfig, T: PlonkTranscript, { pub fn init( diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 9765b11..b2aef8a 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -1,5 +1,5 @@ use ark_ec::pairing::Pairing; -use ark_ec::twisted_edwards::{Affine, TECurveConfig}; +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ec::CurveGroup; use ark_ff::PrimeField; use ark_std::rand::RngCore; @@ -19,7 +19,7 @@ pub struct RingVerifier where F: PrimeField, CS: PCS, - Jubjub: TECurveConfig, + Jubjub: SWCurveConfig, T: PlonkTranscript, { pub(crate) piop_params: PiopParams, @@ -31,7 +31,7 @@ impl RingVerifier where F: PrimeField, CS: PCS, - Jubjub: TECurveConfig, + Jubjub: SWCurveConfig, T: PlonkTranscript, { pub fn init( @@ -99,7 +99,7 @@ where pub struct KzgBatchVerifier where E: Pairing, - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { pub acc: KzgAccumulator, @@ -110,7 +110,7 @@ where pub struct PreparedBatchItem where E: Pairing, - J: TECurveConfig, + J: SWCurveConfig, { piop: PiopVerifier as PCS>::C, Affine>, proof: RingProof>, @@ -121,7 +121,7 @@ where impl KzgBatchVerifier where E: Pairing, - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { /// Prepares a ring proof for batch verification without accumulating it. @@ -200,7 +200,7 @@ where impl RingVerifier, J, T> where E: Pairing, - J: TECurveConfig, + J: SWCurveConfig, T: PlonkTranscript>, { /// Build a new batch verifier. From 5f1bfae8abd15f9d5f32d37d83955af528ab5e40 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 9 Apr 2026 14:50:14 +0300 Subject: [PATCH 02/11] fmt --- w3f-ring-proof/benches/ring_proof.rs | 2 +- w3f-ring-proof/src/lib.rs | 2 +- w3f-ring-proof/src/piop/params.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/w3f-ring-proof/benches/ring_proof.rs b/w3f-ring-proof/benches/ring_proof.rs index f9816d8..ac21ab6 100644 --- a/w3f-ring-proof/benches/ring_proof.rs +++ b/w3f-ring-proof/benches/ring_proof.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criteri use ark_bls12_381::Bls12_381; use ark_ec::CurveGroup; -use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; +use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr, SWAffine}; use ark_serialize::CanonicalSerialize; use ark_std::ops::Mul; use ark_std::rand::Rng; diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index c600c0f..512626b 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -53,7 +53,7 @@ impl ArkTranscript { mod tests { use ark_bls12_381::Bls12_381; use ark_ec::CurveGroup; - use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; + use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr, SWAffine}; use ark_std::ops::Mul; use ark_std::rand::Rng; use ark_std::{end_timer, start_timer, test_rng, UniformRand}; diff --git a/w3f-ring-proof/src/piop/params.rs b/w3f-ring-proof/src/piop/params.rs index e980117..37b9f39 100644 --- a/w3f-ring-proof/src/piop/params.rs +++ b/w3f-ring-proof/src/piop/params.rs @@ -100,9 +100,9 @@ impl> PiopParams { #[cfg(test)] mod tests { - use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, SWAffine, Fq, Fr}; - use ark_std::{test_rng, UniformRand}; + use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr, SWAffine}; use ark_std::ops::Mul; + use ark_std::{test_rng, UniformRand}; use w3f_plonk_common::domain::Domain; use w3f_plonk_common::test_helpers::cond_sum; From ddddbfefaf5be3994f3f23b0ebce09f2a9400474 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 9 Apr 2026 16:17:06 +0300 Subject: [PATCH 03/11] pasta-tree crate --- Cargo.toml | 14 +++++---- pasta-tree/Cargo.toml | 54 ++++++++++++++++++++++++++++++++++ pasta-tree/src/lib.rs | 14 +++++++++ w3f-ring-proof/Cargo.toml | 6 ++-- w3f-ring-proof/src/piop/mod.rs | 18 ++++++------ 5 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 pasta-tree/Cargo.toml create mode 100644 pasta-tree/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 72ebe25..c2b0144 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,26 @@ [workspace] resolver = "2" members = [ - # "evm-vrfier", + "pasta-tree", +# "evm-vrfier", "w3f-plonk-common", "w3f-ring-proof", - "w3f-ring-vrf-snark", +# "w3f-ring-vrf-snark", ] [workspace.dependencies] +w3f-pcs = { path = "../fflonk", default-features = false } +#w3f-pcs = { git = "https://github.com/paritytech/fflonk", branch = "ipa-pcs", default-features = false } +w3f-plonk-common = { path = "w3f-plonk-common", default-features = false } +#w3f-pcs = { version = "0.0.5", default-features = false } +#w3f-plonk-common = { version = "0.0.6", default-features = false } +ark-transcript = { version = "0.0.3", default-features = false } ark-std = { version = "0.5", default-features = false } ark-ff = { version = "0.5", default-features = false } ark-ec = { version = "0.5", default-features = false } ark-poly = { version = "0.5", default-features = false } ark-serialize = { version = "0.5", default-features = false, features = ["derive"] } -w3f-pcs = { version = "0.0.5", default-features = false } -w3f-plonk-common = { version = "0.0.6", default-features = false } rayon = { version = "1", default-features = false } -ark-transcript = { version = "0.0.3", default-features = false } blake2 = { version = "0.10", default-features = false } ark-bls12-381 = { version = "0.5", default-features = false, features = ["curve"] } ark-ed-on-bls12-381-bandersnatch = { version = "0.5", default-features = false } diff --git a/pasta-tree/Cargo.toml b/pasta-tree/Cargo.toml new file mode 100644 index 0000000..78919f8 --- /dev/null +++ b/pasta-tree/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "pasta-tree" +version = "0.0.1" +edition = "2024" +authors = ["Sergey Vasilyev "] +license = "MIT/Apache-2.0" +description = "Hiding Verkle Tree over Pasta Curves" +keywords = ["cryptography", "accumulator", "verkle", "ring-vrf"] +repository = "https://github.com/w3f/ring-proof" + +[dependencies] +w3f-pcs.workspace = true +w3f-plonk-common.workspace = true +w3f-ring-proof = { path = "../w3f-ring-proof" } +ark-pallas = { version = "0.5", default-features = false, features = ["curve"] } +ark-vesta = { version = "0.5", default-features = false } +ark-transcript.workspace = true +ark-std.workspace = true +ark-ff.workspace = true +ark-ec.workspace = true +ark-poly.workspace = true +ark-serialize.workspace = true +rayon = { workspace = true, optional = true } + +[dev-dependencies] +criterion.workspace = true + +[features] +default = [ "std" ] +std = [ + "ark-std/std", + "ark-ff/std", + "ark-ec/std", + "ark-poly/std", + "ark-serialize/std", + "w3f-pcs/std", + "w3f-plonk-common/std", + "w3f-ring-proof/std", +] +parallel = [ + "std", + "rayon", + "ark-std/parallel", + "ark-ff/parallel", + "ark-ec/parallel", + "ark-poly/parallel", + "w3f-pcs/parallel", + "w3f-plonk-common/parallel", + "w3f-ring-proof/parallel", +] +print-trace = [ + "ark-std/print-trace", +] +asm = [ "w3f-pcs/asm" ] \ No newline at end of file diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/pasta-tree/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/w3f-ring-proof/Cargo.toml b/w3f-ring-proof/Cargo.toml index 6f1fef5..06674a8 100644 --- a/w3f-ring-proof/Cargo.toml +++ b/w3f-ring-proof/Cargo.toml @@ -9,15 +9,15 @@ keywords = ["cryptography", "ring-vrf"] repository = "https://github.com/w3f/ring-proof" [dependencies] +w3f-pcs.workspace = true +w3f-plonk-common.workspace = true +ark-transcript.workspace = true ark-std.workspace = true ark-ff.workspace = true ark-ec.workspace = true ark-poly.workspace = true ark-serialize.workspace = true -w3f-pcs.workspace = true rayon = { workspace = true, optional = true } -w3f-plonk-common.workspace = true -ark-transcript.workspace = true [dev-dependencies] ark-bls12-381.workspace = true diff --git a/w3f-ring-proof/src/piop/mod.rs b/w3f-ring-proof/src/piop/mod.rs index d26eae7..5a8d3ac 100644 --- a/w3f-ring-proof/src/piop/mod.rs +++ b/w3f-ring-proof/src/piop/mod.rs @@ -5,7 +5,7 @@ use ark_ff::PrimeField; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::marker::PhantomData; use ark_std::{vec, vec::Vec}; -use w3f_pcs::pcs::kzg::commitment::KzgCommitment; +use w3f_pcs::pcs::kzg::commitment::WrappedAffine; use w3f_pcs::pcs::kzg::params::RawKzgVerifierKey; use w3f_pcs::pcs::kzg::KZG; use w3f_pcs::pcs::{Commitment, PcsParams, PCS}; @@ -96,15 +96,15 @@ impl> FixedColumnsCommitted { } } -impl FixedColumnsCommitted> { - pub fn from_ring>( - ring: &Ring, +impl> FixedColumnsCommitted> { + pub fn from_ring, G: SWCurveConfig>( + ring: &Ring, ) -> Self { - let cx = KzgCommitment(ring.cx); - let cy = KzgCommitment(ring.cy); + let cx = WrappedAffine(ring.cx); + let cy = WrappedAffine(ring.cy); Self { points: [cx, cy], - ring_selector: KzgCommitment(ring.selector), + ring_selector: WrappedAffine(ring.selector), phantom: Default::default(), } } @@ -167,7 +167,7 @@ impl VerifierKey> { } pub fn from_commitment_and_kzg_vk( - commitment: FixedColumnsCommitted>, + commitment: FixedColumnsCommitted>, kzg_vk: RawKzgVerifierKey, ) -> Self { Self { @@ -176,7 +176,7 @@ impl VerifierKey> { } } - pub fn commitment(&self) -> FixedColumnsCommitted> { + pub fn commitment(&self) -> FixedColumnsCommitted> { self.fixed_columns_committed.clone() } } From 3ccf9d8771c483260c45d2fa3f15af88adfdd0fe Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 9 Apr 2026 16:24:25 +0300 Subject: [PATCH 04/11] test_setup --- w3f-ring-proof/src/lib.rs | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 512626b..7a35324 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -1,8 +1,10 @@ #![cfg_attr(not(feature = "std"), no_std)] +use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ff::PrimeField; use ark_serialize::CanonicalSerialize; -use ark_std::rand::RngCore; +use ark_std::rand::{Rng, RngCore}; +use ark_std::UniformRand; use w3f_pcs::pcs::PCS; pub use piop::index; @@ -27,7 +29,7 @@ pub use w3f_pcs::pcs; pub struct ArkTranscript(ark_transcript::Transcript); impl> w3f_plonk_common::transcript::PlonkTranscript - for ArkTranscript +for ArkTranscript { fn _128_bit_point(&mut self, label: &'static [u8]) -> F { self.0.challenge(label).read_reduce() @@ -49,6 +51,17 @@ impl ArkTranscript { } } +pub fn test_setup, G: SWCurveConfig>(rng: &mut R, domain_size: usize) -> (CS::Params, PiopParams) { + let setup_degree = 3 * domain_size; + let pcs_params = CS::setup(setup_degree, rng); + let domain = Domain::new(domain_size, true); + let h = Affine::::rand(rng); + let seed = Affine::::rand(rng); + let padding = Affine::::rand(rng); + let piop_params = PiopParams::setup(domain, h, seed, padding); + (pcs_params, piop_params) +} + #[cfg(test)] mod tests { use ark_bls12_381::Bls12_381; @@ -77,7 +90,7 @@ mod tests { ) { let rng = &mut test_rng(); - let (pcs_params, piop_params) = setup::<_, CS>(rng, domain_size); + let (pcs_params, piop_params) = test_setup::<_, _, CS, BandersnatchConfig>(rng, domain_size); let keyset_size = piop_params.keyset_part_size; let pks = random_vec::(keyset_size, rng); let (prover_key, verifier_key) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); @@ -120,7 +133,7 @@ mod tests { let domain_size = 2usize.pow(9); - let (pcs_params, piop_params) = setup::<_, KZG>(rng, domain_size); + let (pcs_params, piop_params) = test_setup::<_, Fq, KZG, BandersnatchConfig>(rng, domain_size); let ring_builder_key = RingBuilderKey::from_srs(&pcs_params, domain_size); let max_keyset_size = piop_params.keyset_part_size; @@ -138,22 +151,6 @@ mod tests { ); } - fn setup>( - rng: &mut R, - domain_size: usize, - ) -> (CS::Params, PiopParams) { - let setup_degree = 3 * domain_size; - let pcs_params = CS::setup(setup_degree, rng); - - let domain = Domain::new(domain_size, true); - let h = SWAffine::rand(rng); - let seed = SWAffine::rand(rng); - let padding = SWAffine::rand(rng); - let piop_params = PiopParams::setup(domain, h, seed, padding); - - (pcs_params, piop_params) - } - // cargo test test_ring_proof_kzg --release --features="print-trace" -- --show-output // // Batch vs sequential verification times (ms): @@ -193,7 +190,7 @@ mod tests { let domain_size = 2usize.pow(9); let proofs_per_ring = 4; - let (pcs_params, piop_params) = setup::<_, KZG>(rng, domain_size); + let (pcs_params, piop_params) = test_setup::<_, Fq, KZG, BandersnatchConfig>(rng, domain_size); // Ring A let keyset_size_a = piop_params.keyset_part_size; From 587235847222b27737bc128cf69e9731eede3798 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 9 Apr 2026 16:51:20 +0300 Subject: [PATCH 05/11] pasta ring works --- pasta-tree/src/lib.rs | 43 ++++++++++++++++++++++++++++--- w3f-ring-proof/src/piop/params.rs | 2 +- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index b93cf3f..c02d888 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -4,11 +4,46 @@ pub fn add(left: u64, right: u64) -> u64 { #[cfg(test)] mod tests { - use super::*; + use ark_ec::CurveGroup; + use ark_std::rand::Rng; + use ark_std::{end_timer, start_timer, test_rng, UniformRand}; + use w3f_pcs::pcs::ipa::IPA; + use w3f_plonk_common::test_helpers::random_vec; + use w3f_ring_proof::ring_prover::RingProver; + use w3f_ring_proof::{index, test_setup, ArkTranscript}; + use w3f_ring_proof::ring_verifier::RingVerifier; #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); + fn test_pasta_ring() { + let rng = &mut test_rng(); + + let (pcs_params, piop_params) = test_setup::<_, _, IPA, ark_vesta::VestaConfig>(rng, 512); + let keyset_size = piop_params.keyset_part_size; + let pks = random_vec::(keyset_size, rng); + let (prover_key, verifier_key) = index::<_, IPA, _>(&pcs_params, &piop_params, &pks); + + let t_prove = start_timer!(|| "Prove"); + let prover_idx = rng.gen_range(0..keyset_size); + let prover = RingProver::init( + prover_key.clone(), + piop_params.clone(), + prover_idx, + ArkTranscript::new(b"w3f-ring-proof-test"), + ); + let prover_pk = pks[prover_idx].clone(); + let blinding_factor = ark_vesta::Fr::rand(rng); + let blinded_pk = prover_pk + piop_params.h * blinding_factor; + let blinded_pk = blinded_pk.into_affine(); + let proof = prover.prove(blinding_factor); + end_timer!(t_prove); + + let ring_verifier = RingVerifier::init( + verifier_key, + piop_params, + ArkTranscript::new(b"w3f-ring-proof-test"), + ); + let t_verify = start_timer!(|| "Verify"); + assert!(ring_verifier.verify(proof, blinded_pk)); + end_timer!(t_verify); } } diff --git a/w3f-ring-proof/src/piop/params.rs b/w3f-ring-proof/src/piop/params.rs index 37b9f39..31eae71 100644 --- a/w3f-ring-proof/src/piop/params.rs +++ b/w3f-ring-proof/src/piop/params.rs @@ -18,7 +18,7 @@ pub struct PiopParams> { /// Length of the part of the column representing the public keys (including the padding). pub keyset_part_size: usize, /// Blinding base point. - pub(crate) h: Affine, + pub h: Affine, //TODO: make a method /// Summation base point. pub(crate) seed: Affine, /// The point used to pad the list of public keys. From f7b07315e210a41cf5a0ee1771bbf35e1a41fd8d Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Fri, 10 Apr 2026 03:00:41 +0300 Subject: [PATCH 06/11] Cargo.tomls cleaned up --- pasta-tree/Cargo.toml | 8 +++----- w3f-ring-proof/Cargo.toml | 5 +---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/pasta-tree/Cargo.toml b/pasta-tree/Cargo.toml index 78919f8..37f94ea 100644 --- a/pasta-tree/Cargo.toml +++ b/pasta-tree/Cargo.toml @@ -26,7 +26,7 @@ rayon = { workspace = true, optional = true } criterion.workspace = true [features] -default = [ "std" ] +default = ["std"] std = [ "ark-std/std", "ark-ff/std", @@ -48,7 +48,5 @@ parallel = [ "w3f-plonk-common/parallel", "w3f-ring-proof/parallel", ] -print-trace = [ - "ark-std/print-trace", -] -asm = [ "w3f-pcs/asm" ] \ No newline at end of file +print-trace = ["ark-std/print-trace", ] +asm = ["w3f-pcs/asm"] \ No newline at end of file diff --git a/w3f-ring-proof/Cargo.toml b/w3f-ring-proof/Cargo.toml index 06674a8..f488ec1 100644 --- a/w3f-ring-proof/Cargo.toml +++ b/w3f-ring-proof/Cargo.toml @@ -49,9 +49,6 @@ parallel = [ "w3f-plonk-common/parallel", "w3f-pcs/parallel" ] -print-trace = [ - "ark-std/print-trace", - "w3f-plonk-common/print-trace" -] +print-trace = ["ark-std/print-trace"] asm = [ "w3f-pcs/asm" ] test-vectors = [ "w3f-plonk-common/test-vectors" ] From a3d2683f8813fa08c7c7b7f1bc8b4b630f767b74 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Fri, 10 Apr 2026 04:41:03 +0300 Subject: [PATCH 07/11] stuff made pub mostly --- w3f-plonk-common/src/domain.rs | 2 +- w3f-plonk-common/src/prover.rs | 18 +++++++++++++++--- w3f-ring-proof/src/lib.rs | 6 +++--- w3f-ring-proof/src/piop/mod.rs | 16 ++++++++-------- w3f-ring-proof/src/piop/params.rs | 2 +- w3f-ring-proof/src/ring_prover.rs | 3 --- 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/w3f-plonk-common/src/domain.rs b/w3f-plonk-common/src/domain.rs index 42241dc..c961bd5 100644 --- a/w3f-plonk-common/src/domain.rs +++ b/w3f-plonk-common/src/domain.rs @@ -95,7 +95,7 @@ impl Domain { } } - pub(crate) fn divide_by_vanishing_poly(&self, poly: &DensePolynomial) -> DensePolynomial { + pub fn divide_by_vanishing_poly(&self, poly: &DensePolynomial) -> DensePolynomial { let (quotient, remainder) = if self.hiding { let exclude_zk_rows = poly * self.zk_rows_vanishing_poly.as_ref().unwrap(); exclude_zk_rows.divide_by_vanishing_poly(self.domains.x1) diff --git a/w3f-plonk-common/src/prover.rs b/w3f-plonk-common/src/prover.rs index 6dc96be..c221191 100644 --- a/w3f-plonk-common/src/prover.rs +++ b/w3f-plonk-common/src/prover.rs @@ -1,7 +1,7 @@ use ark_ff::PrimeField; use ark_poly::{Evaluations, Polynomial}; use ark_serialize::CanonicalSerialize; -use ark_std::vec; +use ark_std::{end_timer, start_timer, vec}; use w3f_pcs::aggregation::single::aggregate_polys; use w3f_pcs::pcs::PCS; @@ -40,7 +40,13 @@ impl, T: PlonkTranscript> PlonkProver transcript.add_instance(&piop.result()); // ROUND 1 // The prover commits to the columns. - let column_commitments = piop.committed_columns(|p| CS::commit(&self.pcs_ck, p).unwrap()); + + let column_commitments = piop.committed_columns(|p| { + let _t_commit_col = start_timer!(|| format!("Committing to deg(f)={}", p.degree())); + let c = CS::commit(&self.pcs_ck, p).unwrap(); + end_timer!(_t_commit_col); + c + }); transcript.add_committed_cols(&column_commitments); // ROUND 2 @@ -52,7 +58,9 @@ impl, T: PlonkTranscript> PlonkProver let agg_constraint_poly = agg_constraint_poly.interpolate(); let quotient_poly = piop.domain().divide_by_vanishing_poly(&agg_constraint_poly); // The prover commits to the quotient polynomial... + let _t_commit_q = start_timer!(|| format!("Committing to deg(f)={}", quotient_poly.degree())); let quotient_commitment = CS::commit(&self.pcs_ck, "ient_poly).unwrap(); + end_timer!(_t_commit_q); transcript.add_quotient_commitment("ient_commitment); // and receives the evaluation point in response @@ -71,8 +79,12 @@ impl, T: PlonkTranscript> PlonkProver let polys_at_zeta = [columns_to_open, vec![quotient_poly]].concat(); let nus = transcript.get_kzg_aggregation_challenges(polys_at_zeta.len()); let agg_at_zeta = aggregate_polys(&polys_at_zeta, &nus); + let _t_open_zeta = start_timer!(|| format!("Opening deg(f)={}", agg_at_zeta.degree())); let agg_at_zeta_proof = CS::open(&self.pcs_ck, &agg_at_zeta, zeta).unwrap(); + end_timer!(_t_open_zeta); + let _t_open_zeta_omega = start_timer!(|| format!("Opening deg(f)={}", lin.degree())); let lin_at_zeta_omega_proof = CS::open(&self.pcs_ck, &lin, zeta_omega).unwrap(); + end_timer!(_t_open_zeta_omega); Proof { column_commitments, quotient_commitment, @@ -83,7 +95,7 @@ impl, T: PlonkTranscript> PlonkProver } } - fn aggregate_evaluations(polys: &[Evaluations], coeffs: &[F]) -> Evaluations { + pub fn aggregate_evaluations(polys: &[Evaluations], coeffs: &[F]) -> Evaluations { assert_eq!(coeffs.len(), polys.len()); polys .iter() diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 7a35324..11e6ada 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -15,7 +15,7 @@ pub use crate::piop::{params::PiopParams, FixedColumnsCommitted, ProverKey, Veri use crate::piop::{RingCommitments, RingEvaluations}; pub mod multi_ring_batch_verifier; -mod piop; +pub mod piop; pub mod ring; pub mod ring_prover; pub mod ring_verifier; @@ -171,8 +171,8 @@ mod tests { // Batch verification scales sub-linearly. #[test] fn test_ring_proof_kzg() { - let batch_size: usize = 16; - let (verifier, claims) = _test_ring_proof::>(2usize.pow(10), batch_size); + let batch_size: usize = 1; + let (verifier, claims) = _test_ring_proof::>(2usize.pow(9), batch_size); let t_verify_batch = start_timer!(|| format!("Verify Batch KZG (batch={batch_size})")); let (blinded_pks, proofs) = claims.into_iter().unzip(); assert!(verifier.verify_batch_kzg(proofs, blinded_pks)); diff --git a/w3f-ring-proof/src/piop/mod.rs b/w3f-ring-proof/src/piop/mod.rs index 5a8d3ac..16d8d75 100644 --- a/w3f-ring-proof/src/piop/mod.rs +++ b/w3f-ring-proof/src/piop/mod.rs @@ -19,8 +19,8 @@ use crate::ring::Ring; use crate::PiopParams; pub mod params; -mod prover; -mod verifier; +pub mod prover; +pub mod verifier; #[derive(Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct RingCommitments> { @@ -87,7 +87,7 @@ pub struct FixedColumnsCommitted> { } impl> FixedColumnsCommitted { - fn as_vec(&self) -> Vec { + pub fn as_vec(&self) -> Vec { vec![ self.points[0].clone(), self.points[1].clone(), @@ -127,9 +127,9 @@ impl> FixedColumns { #[derive(CanonicalSerialize, CanonicalDeserialize)] pub struct ProverKey, G: AffineRepr> { - pub(crate) pcs_ck: CS::CK, - pub(crate) fixed_columns: FixedColumns, - pub(crate) verifier_key: VerifierKey, // used in the Fiat-Shamir transform + pub pcs_ck: CS::CK, + pub fixed_columns: FixedColumns, + pub verifier_key: VerifierKey, // used in the Fiat-Shamir transform } impl, G: AffineRepr> Clone for ProverKey { @@ -144,8 +144,8 @@ impl, G: AffineRepr> Clone for ProverKe #[derive(Debug, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct VerifierKey> { - pub(crate) pcs_raw_vk: ::RVK, - pub(crate) fixed_columns_committed: FixedColumnsCommitted, + pub pcs_raw_vk: ::RVK, + pub fixed_columns_committed: FixedColumnsCommitted, //TODO: domain } diff --git a/w3f-ring-proof/src/piop/params.rs b/w3f-ring-proof/src/piop/params.rs index 31eae71..a0ffb86 100644 --- a/w3f-ring-proof/src/piop/params.rs +++ b/w3f-ring-proof/src/piop/params.rs @@ -12,7 +12,7 @@ use crate::piop::FixedColumns; #[derive(Clone)] pub struct PiopParams> { /// Domain over which the piop is represented. - pub(crate) domain: Domain, + pub domain: Domain, /// Number of bits used to represent a jubjub scalar. pub(crate) scalar_bitlen: usize, /// Length of the part of the column representing the public keys (including the padding). diff --git a/w3f-ring-proof/src/ring_prover.rs b/w3f-ring-proof/src/ring_prover.rs index 4428454..5e951b2 100644 --- a/w3f-ring-proof/src/ring_prover.rs +++ b/w3f-ring-proof/src/ring_prover.rs @@ -1,6 +1,5 @@ use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; use ark_ff::PrimeField; -use ark_std::{end_timer, start_timer}; use w3f_pcs::pcs::PCS; use w3f_plonk_common::prover::PlonkProver; @@ -53,9 +52,7 @@ where } pub fn prove(&self, t: Curve::ScalarField) -> RingProof { - let t_witgen = start_timer!(|| "witgen"); let piop = PiopProver::build(&self.piop_params, self.fixed_columns.clone(), self.k, t); - end_timer!(t_witgen); self.plonk_prover.prove(piop) } From 20cb45195b8f3ae5c7c237847b2ec8795e5cd897 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Fri, 10 Apr 2026 04:41:18 +0300 Subject: [PATCH 08/11] shplonk openning --- pasta-tree/src/lib.rs | 154 +++++++++++++++++++++++++++++++++++------- 1 file changed, 131 insertions(+), 23 deletions(-) diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index c02d888..39e0f2d 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -5,45 +5,153 @@ pub fn add(left: u64, right: u64) -> u64 { #[cfg(test)] mod tests { use ark_ec::CurveGroup; + use ark_ff::PrimeField; + use ark_poly::Polynomial; + use ark_std::iterable::Iterable; use ark_std::rand::Rng; use ark_std::{end_timer, start_timer, test_rng, UniformRand}; + use ark_vesta::VestaConfig; + use std::collections::BTreeSet; + use w3f_pcs::aggregation::multiple::Transcript; use w3f_pcs::pcs::ipa::IPA; + use w3f_pcs::pcs::kzg::commitment::WrappedAffine; + use w3f_pcs::pcs::{RawVerifierKey, PCS}; + use w3f_pcs::shplonk::Shplonk; + use w3f_plonk_common::piop::ProverPiop; + use w3f_plonk_common::prover::PlonkProver; use w3f_plonk_common::test_helpers::random_vec; + use w3f_ring_proof::piop::prover::PiopProver; use w3f_ring_proof::ring_prover::RingProver; - use w3f_ring_proof::{index, test_setup, ArkTranscript}; use w3f_ring_proof::ring_verifier::RingVerifier; + use w3f_ring_proof::{index, test_setup, ArkTranscript}; + + type PallasIPA = IPA; + type PallasC = WrappedAffine; + // cargo test test_pasta_ring_plonk --release --features="print-trace" -- --show-output #[test] - fn test_pasta_ring() { + fn test_pasta_ring_plonk() { let rng = &mut test_rng(); - let (pcs_params, piop_params) = test_setup::<_, _, IPA, ark_vesta::VestaConfig>(rng, 512); + // setup + let domain_size = 2usize.pow(9); + let (pcs_params, piop_params) = test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); let keyset_size = piop_params.keyset_part_size; let pks = random_vec::(keyset_size, rng); - let (prover_key, verifier_key) = index::<_, IPA, _>(&pcs_params, &piop_params, &pks); - - let t_prove = start_timer!(|| "Prove"); - let prover_idx = rng.gen_range(0..keyset_size); - let prover = RingProver::init( - prover_key.clone(), - piop_params.clone(), - prover_idx, - ArkTranscript::new(b"w3f-ring-proof-test"), + let (prover_key, verifier_key) = index::<_, PallasIPA, _>(&pcs_params, &piop_params, &pks); + let blinding = ark_vesta::Fr::rand(rng); + let pk_idx = rng.gen_range(0..keyset_size); + let blinded_pk = { + let prover_pk = pks[pk_idx].clone(); + let blinded_pk = prover_pk + piop_params.h * blinding; + blinded_pk.into_affine() + }; + + // prover + let fs = ArkTranscript::new(b"pasta-ring-proof-test"); + let prover = RingProver::init(prover_key, piop_params.clone(), pk_idx, fs.clone()); + let t_prove = start_timer!(|| format!("Proving IPA ring-proof with plonk, domain_size={domain_size}, keyset_size={keyset_size}")); + let proof = prover.prove(blinding); + end_timer!(t_prove); + + // verifier + let ring_verifier = RingVerifier::init(verifier_key, piop_params, fs); + let t_verify = start_timer!(|| "Verifying IPA plonk opening"); + let valid = ring_verifier.verify(proof, blinded_pk); + end_timer!(t_verify); + assert!(valid); + } + + struct Coeffs(F, F); + impl> Transcript for Coeffs { + fn get_gamma(&mut self) -> F { + self.0 + } + + fn commit_to_q(&mut self, _q: &CS::C) {} + + fn get_zeta(&mut self) -> F { + self.1 + } + } + + // cargo test test_pasta_ring_shplonk --release --features="print-trace" -- --show-output + #[test] + fn test_pasta_ring_shplonk() { + let rng = &mut test_rng(); + + // setup + let domain_size = 2usize.pow(9); + let (pcs_params, piop_params) = test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); + let keyset_size = piop_params.keyset_part_size; + let pks = random_vec::(keyset_size, rng); + let (prover_key, verifier_key) = index::<_, PallasIPA, _>(&pcs_params, &piop_params, &pks); + let blinding = ark_vesta::Fr::rand(rng); + let pk_idx = rng.gen_range(0..keyset_size); + // let blinded_pk = { + // let prover_pk = pks[pk_idx].clone(); + // let blinded_pk = prover_pk + piop_params.h * blinding; + // blinded_pk.into_affine() + // }; + let pcs_ck = prover_key.pcs_ck; + let pcs_vk = verifier_key.pcs_raw_vk.prepare(); + + // prover + let piop = PiopProver::::build(&piop_params, prover_key.fixed_columns.clone(), pk_idx, blinding); + let t_prove = start_timer!(|| format!("Proving IPA ring-proof with shplonk, domain_size={domain_size}, keyset_size={keyset_size}")); + let zeta = ark_pallas::Fr::rand(rng); + let columns = as ProverPiop>::columns(&piop); + let (quotient, agg_lin) = { + let constraints = as ProverPiop>::constraints(&piop); + let alphas: Vec<_> = (0..constraints.len()).map(|_| ark_pallas::Fr::rand(rng)).collect(); + let agg_constraint_poly = PlonkProver::::aggregate_evaluations(&constraints, &alphas).interpolate(); + let quotient = piop_params.domain.divide_by_vanishing_poly(&agg_constraint_poly); + let constraints_lin = as ProverPiop>::constraints_lin(&piop, &zeta); + let agg_lin = w3f_pcs::aggregation::single::aggregate_polys(&constraints_lin, &alphas); + (quotient, agg_lin) + }; + + let mut polys = columns; + polys.push(quotient); + let mut coord_vecs = vec![vec![zeta]; polys.len()]; + polys.push(agg_lin.clone()); + coord_vecs.push(vec![zeta * piop_params.domain.omega()]); + + // commitments + let mut poly_cs = verifier_key.fixed_columns_committed.as_vec(); + let t_commit = start_timer!(|| format!("Commiting to {} columns of degree = {} and the quotient of degree = {}", polys.len()-5, polys[3].degree(), polys[7].degree())); + // skip the instance columns and the linearirization polynomial `agg_lin` + poly_cs.extend(polys[3..polys.len() - 1].iter().map(|p| PallasIPA::commit(&pcs_ck, p).unwrap())); + end_timer!(t_commit); + poly_cs.push(PallasIPA::commit(&pcs_ck, &agg_lin).unwrap()); + + let coord_sets: Vec> = coord_vecs.iter().cloned().map(BTreeSet::from_iter).collect(); + let vals: Vec<_> = polys.iter().zip(coord_vecs.iter()) + .map(|(f, xs)| xs.iter().map(|x| f.evaluate(&x)).collect::>()) + .collect(); + + let transcript = &mut Coeffs(ark_pallas::Fr::rand(rng), ark_pallas::Fr::rand(rng)); + let t_open = start_timer!(|| format!("Opening IPA ring-proof with shplonk, {} polys, max_degree = {}", polys.len(), polys[7].degree())); + let proof = Shplonk::::open_many( + &pcs_ck, + &polys, + &coord_sets, + transcript, ); - let prover_pk = pks[prover_idx].clone(); - let blinding_factor = ark_vesta::Fr::rand(rng); - let blinded_pk = prover_pk + piop_params.h * blinding_factor; - let blinded_pk = blinded_pk.into_affine(); - let proof = prover.prove(blinding_factor); + end_timer!(t_open); end_timer!(t_prove); - let ring_verifier = RingVerifier::init( - verifier_key, - piop_params, - ArkTranscript::new(b"w3f-ring-proof-test"), + // verifier + let t_verify = start_timer!(|| "Verifying IPA shplonk opening"); + let valid = Shplonk::::verify_many( + &pcs_vk, + &poly_cs, + proof, + &coord_vecs, + &vals, + transcript, ); - let t_verify = start_timer!(|| "Verify"); - assert!(ring_verifier.verify(proof, blinded_pk)); end_timer!(t_verify); + assert!(valid); } } From d37d0e3f912cc4666effb731bf7f63630281e2f4 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Fri, 10 Apr 2026 14:57:42 +0300 Subject: [PATCH 09/11] cosmetic --- pasta-tree/src/lib.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index 39e0f2d..523229c 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -4,7 +4,6 @@ pub fn add(left: u64, right: u64) -> u64 { #[cfg(test)] mod tests { - use ark_ec::CurveGroup; use ark_ff::PrimeField; use ark_poly::Polynomial; use ark_std::iterable::Iterable; @@ -41,18 +40,15 @@ mod tests { let (prover_key, verifier_key) = index::<_, PallasIPA, _>(&pcs_params, &piop_params, &pks); let blinding = ark_vesta::Fr::rand(rng); let pk_idx = rng.gen_range(0..keyset_size); - let blinded_pk = { - let prover_pk = pks[pk_idx].clone(); - let blinded_pk = prover_pk + piop_params.h * blinding; - blinded_pk.into_affine() - }; + let blinded_pk = piop_params.blind_pk(pks[pk_idx], blinding); // prover let fs = ArkTranscript::new(b"pasta-ring-proof-test"); - let prover = RingProver::init(prover_key, piop_params.clone(), pk_idx, fs.clone()); + let prover = RingProver::init(prover_key, piop_params.clone(), 0, fs.clone()); let t_prove = start_timer!(|| format!("Proving IPA ring-proof with plonk, domain_size={domain_size}, keyset_size={keyset_size}")); - let proof = prover.prove(blinding); + let (blinded_pk_, proof) = prover.rerandomize_pk(pk_idx, blinding); end_timer!(t_prove); + assert_eq!(blinded_pk_, blinded_pk); // verifier let ring_verifier = RingVerifier::init(verifier_key, piop_params, fs); From 1c17388ce1f2a105d697606390afefc94ab6ccab Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 16 Apr 2026 17:30:55 +0300 Subject: [PATCH 10/11] folding fun --- pasta-tree/Cargo.toml | 1 + pasta-tree/src/lib.rs | 235 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 2 deletions(-) diff --git a/pasta-tree/Cargo.toml b/pasta-tree/Cargo.toml index 37f94ea..1684883 100644 --- a/pasta-tree/Cargo.toml +++ b/pasta-tree/Cargo.toml @@ -23,6 +23,7 @@ ark-serialize.workspace = true rayon = { workspace = true, optional = true } [dev-dependencies] +ark-bls12-381.workspace = true criterion.workspace = true [features] diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index 523229c..60dd3a5 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -4,11 +4,20 @@ pub fn add(left: u64, right: u64) -> u64 { #[cfg(test)] mod tests { + use ark_ec::scalar_mul::glv::GLVConfig; + use w3f_pcs::pcs::PcsParams; + use ark_ec::scalar_mul::wnaf::WnafContext; + use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; + use ark_ec::AdditiveGroup; + use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::PrimeField; + use ark_ff::{BigInteger, Field, Zero}; + use ark_pallas::PallasConfig; + use ark_poly::DenseUVPolynomial; use ark_poly::Polynomial; use ark_std::iterable::Iterable; use ark_std::rand::Rng; - use ark_std::{end_timer, start_timer, test_rng, UniformRand}; + use ark_std::{cfg_iter_mut, end_timer, start_timer, test_rng, UniformRand}; use ark_vesta::VestaConfig; use std::collections::BTreeSet; use w3f_pcs::aggregation::multiple::Transcript; @@ -24,6 +33,10 @@ mod tests { use w3f_ring_proof::ring_verifier::RingVerifier; use w3f_ring_proof::{index, test_setup, ArkTranscript}; + #[cfg(feature = "parallel")] + use rayon::prelude::*; + use w3f_pcs::Poly; + type PallasIPA = IPA; type PallasC = WrappedAffine; @@ -115,7 +128,7 @@ mod tests { // commitments let mut poly_cs = verifier_key.fixed_columns_committed.as_vec(); - let t_commit = start_timer!(|| format!("Commiting to {} columns of degree = {} and the quotient of degree = {}", polys.len()-5, polys[3].degree(), polys[7].degree())); + let t_commit = start_timer!(|| format!("Commiting to {} columns of degree = {} and the quotient of degree = {}", polys.len()-5, polys[3].degree(), polys[7].degree())); // skip the instance columns and the linearirization polynomial `agg_lin` poly_cs.extend(polys[3..polys.len() - 1].iter().map(|p| PallasIPA::commit(&pcs_ck, p).unwrap())); end_timer!(t_commit); @@ -150,4 +163,222 @@ mod tests { end_timer!(t_verify); assert!(valid); } + + fn _bench_msm(log_n: u32) { + let rng = &mut test_rng(); + let n = 2usize.pow(log_n); + let (scalars, bases): (Vec<_>, Vec<_>) = (0..n).map(|_| (C::ScalarField::rand(rng), C::Affine::rand(rng))).unzip(); + let t_msm = start_timer!(|| format!("log(n)={log_n}, MSM on {}", ark_std::any::type_name::())); + let _res = C::msm(&bases, &scalars); + end_timer!(t_msm); + } + + // cargo test bench_msms --release --features="print-trace" -- --show-output + // qcargo test bench_msms --release --features="parallel print-trace" -- --show-output + #[test] + fn bench_msms() { + let log_n = 9; + + _bench_msm::(log_n); + _bench_msm::(log_n + 1); + // _bench_msm::(log_n); + // _bench_msm::(log_n); + // _bench_folding::(log_n); + // _bench_folding::(log_n + 1); + _bench_folding(log_n); + _bench_folding(log_n + 1); + + let rng = &mut test_rng(); + let n = 2usize.pow(log_n); + + let n3 = 3 * n; + let pcs_params = PallasIPA::setup(n3, rng); + + let p = Poly::::rand(n, rng); + let t_ipa_commit = start_timer!(|| format!("IPA commitment to a degree {n} polynomial")); + let _c = PallasIPA::commit(&pcs_params.ck(), &p); + end_timer!(t_ipa_commit); + + let p = Poly::::rand(n3, rng); + let t_ipa_commit = start_timer!(|| format!("IPA commitment to a degree 3*{n} polynomial")); + let _c = PallasIPA::commit(&pcs_params.ck(), &p); + end_timer!(t_ipa_commit); + } + + fn mul_endo_wnaf(p: ark_pallas::Projective, k1: (bool, ark_pallas::Fr), k2: (bool, ark_pallas::Fr)) -> ark_pallas::Projective { + let mut p1 = p; + let mut p2 = PallasConfig::endomorphism(&p); + if !k1.0 { + p1 = -p1; + } + if !k2.0 { + p2 = -p2; + } + let w_size = 4; + let wnaf = WnafContext::new(w_size); + let p1_table = wnaf.table(p1); + let p2_table = wnaf.table(p2); + let k1_wnaf = k1.1.into_bigint().find_wnaf(w_size).unwrap(); + let mut k2_wnaf = k2.1.into_bigint().find_wnaf(w_size).unwrap(); + k2_wnaf.resize(k1_wnaf.len(), 0); + + let mut result = ark_pallas::Projective::zero(); + let mut found_non_zero = false; + for (n1, n2) in k1_wnaf.into_iter().zip(k2_wnaf).rev() { + if found_non_zero { + result.double_in_place(); + } + + if n1 != 0 || n2 != 0 { + found_non_zero = true; + if n1 > 0 { + result += &p1_table[(n1 / 2) as usize]; + } + if n1 < 0 { + result -= &p1_table[((-n1) / 2) as usize]; + } + if n2 > 0 { + result += &p2_table[(n2 / 2) as usize]; + } + if n2 < 0 { + result -= &p2_table[((-n2) / 2) as usize]; + } + } + } + result + } + + fn _bench_folding(log_n: u32) { + let rng = &mut test_rng(); + let n = 2usize.pow(log_n); + let (l, r): (Vec, Vec) = (0..n).map(|_| (ark_pallas::Affine::rand(rng), ark_pallas::Affine::rand(rng))).unzip(); + let x = ark_pallas::Fr::rand(rng); + let _timer = start_timer!(|| format!("Naive folding, log(n) = {log_n}")); + let res: Vec = ark_std::cfg_iter!(l).zip(r.clone()) + .map(|(l, r)| r * x + l) + .collect(); + end_timer!(_timer); + + let _timer = start_timer!(|| format!("Naive folding with endo, log(n) = {log_n}")); + let res_: Vec = ark_std::cfg_into_iter!(l.clone()).zip(ark_std::cfg_into_iter!(r.clone())) + .map(|(l, r)| l + ::glv_mul_affine(r, x)) + .collect(); + end_timer!(_timer); + assert_eq!(res_, res); + + let _timer = start_timer!(|| format!("Naive folding with endo and w-NAF, log(n) = {log_n}")); + let ((sgn_k1, k1), (sgn_k2, k2)) = PallasConfig::scalar_decomposition(x); + let res_: Vec = ark_std::cfg_into_iter!(l).zip(ark_std::cfg_iter!(r)) + .map(|(l, r)| l + mul_endo_wnaf(r.into_group(), (sgn_k1, k1), (sgn_k2, k2))) + .collect(); + end_timer!(_timer); + assert_eq!(res_, res); + } + + fn batch_double_affine(bases: Vec>) -> Vec> { + let mut denoms: Vec = ark_std::cfg_iter!(bases) + .map(|p| p.y + p.y) + .collect(); + + ark_ff::batch_inversion(&mut denoms); + + ark_std::cfg_iter!(bases).zip(denoms).map(|(p, _2y_inv)| { + let (x, y) = p.xy().unwrap(); + let t = _2y_inv * (x.square() * C::BaseField::from(3) + ::COEFF_A); // (3x^2 + a) / 2y + let x_n = t.square() - x - x; + let y_n = t * (x - x_n) - y; + Affine::::new_unchecked(x_n, y_n) + }).collect() + } + + fn batch_double_affine_in_place(bases: &mut [Affine]) { + let three = C::BaseField::from(3); + let sw_a = ::COEFF_A; + let mut denoms: Vec = ark_std::cfg_iter!(bases) + .map(|p| p.y + p.y) + .collect(); + + ark_ff::batch_inversion(&mut denoms); + // ark_ff::batch_inversion_and_mul(&mut denoms, &C::BaseField::one()); + + cfg_iter_mut!(bases).zip(ark_std::cfg_into_iter!(denoms)) + .for_each(|(p, _2y_inv)| { + let t = _2y_inv * (p.x.square() * three + sw_a); // (3x^2 + a) / 2y + let old_x = p.x; + p.x = t.square() - p.x - p.x; + p.y = t * (old_x - p.x) - p.y; + }) + } + + fn batch_add_affine(bases1: Vec>, bases2: Vec>) -> Vec> { + let mut denoms: Vec = ark_std::cfg_iter!(bases1) + .zip(ark_std::cfg_iter!(bases2)) + .map(|(p1, p2)| p2.x - p1.x) + .collect(); + + ark_ff::batch_inversion(&mut denoms); + + ark_std::cfg_iter!(bases1) + .zip(ark_std::cfg_iter!(bases2)) + .zip(ark_std::cfg_iter!(denoms)) + .map(|((p1, p2), _x2_m_x1)| { + let (x1, y1) = p1.xy().unwrap(); + let (x2, y2) = p2.xy().unwrap(); + let t = (y2 - y1) * _x2_m_x1; + let x_n = t.square() - x1 - x2; + let y_n = t * (x1 - x_n) - y1; + Affine::::new_unchecked(x_n, y_n) + }).collect() + } + + fn batch_mul_by_x_affine(bases: Vec>, x: C::ScalarField) -> Vec> { + let mut res: Vec> = bases.clone(); + for b in ark_ff::BitIteratorBE::without_leading_zeros(x.into_bigint()).skip(1) { + batch_double_affine_in_place(&mut res); + if b { + res = batch_add_affine(res, bases.clone()); + } + } + res + } + + #[test] + fn bench_folding() { + let rng = &mut test_rng(); + let log_n = 10; + _bench_folding(log_n); + + let n = 2usize.pow(log_n); + let bases: Vec<_> = (0..n).map(|_| ark_pallas::Affine::rand(rng)).collect(); + let x = ark_pallas::Fr::rand(rng); + let dbl: Vec<_> = bases.iter().map(|p| { + let mut p = p.into_group(); + p.double_in_place(); + p.into_affine() + }).collect(); + assert_eq!(dbl, batch_double_affine(bases.clone())); + + let bases2: Vec<_> = (0..n).map(|_| ark_pallas::Affine::rand(rng)).collect(); + let bases1 = bases.clone(); + let add: Vec<_> = bases.into_iter().zip(bases2.iter()) + .map(|(p1, p2)| p1 + p2) + .collect(); + assert_eq!(add, batch_add_affine(bases1.clone(), bases2.clone())); + + let _timer = start_timer!(|| format!("Batch affine folding, log(n) = {log_n}")); + let x_bases2 = batch_mul_by_x_affine(bases2.clone(), x); + let res = batch_add_affine(bases1.clone(), x_bases2); + end_timer!(_timer); + + let _timer = start_timer!(|| format!("Naive folding, log(n) = {log_n}")); + let res_: Vec = ark_std::cfg_into_iter!(bases1).zip(ark_std::cfg_into_iter!(bases2)) + .map(|(l, r)| l + r * x) + .collect(); + let _to_affine = start_timer!(|| "batch affine conversion"); + let res_ = ark_pallas::Projective::normalize_batch(&res_); + end_timer!(_to_affine); + end_timer!(_timer); + + assert_eq!(res_, res); + } } From 2ffde5a1b3c4f277394a4088d5c1ab5f2d0c28e4 Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Thu, 16 Apr 2026 17:31:24 +0300 Subject: [PATCH 11/11] fmt --- pasta-tree/src/lib.rs | 176 +++++++++++++++++++++++---------- w3f-plonk-common/src/prover.rs | 3 +- w3f-ring-proof/src/lib.rs | 7 +- w3f-ring-proof/src/piop/mod.rs | 4 +- 4 files changed, 133 insertions(+), 57 deletions(-) diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index 60dd3a5..c2ee81e 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -4,11 +4,10 @@ pub fn add(left: u64, right: u64) -> u64 { #[cfg(test)] mod tests { + use ark_ec::AdditiveGroup; use ark_ec::scalar_mul::glv::GLVConfig; - use w3f_pcs::pcs::PcsParams; use ark_ec::scalar_mul::wnaf::WnafContext; use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; - use ark_ec::AdditiveGroup; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::PrimeField; use ark_ff::{BigInteger, Field, Zero}; @@ -17,13 +16,14 @@ mod tests { use ark_poly::Polynomial; use ark_std::iterable::Iterable; use ark_std::rand::Rng; - use ark_std::{cfg_iter_mut, end_timer, start_timer, test_rng, UniformRand}; + use ark_std::{UniformRand, cfg_iter_mut, end_timer, start_timer, test_rng}; use ark_vesta::VestaConfig; use std::collections::BTreeSet; use w3f_pcs::aggregation::multiple::Transcript; + use w3f_pcs::pcs::PcsParams; use w3f_pcs::pcs::ipa::IPA; use w3f_pcs::pcs::kzg::commitment::WrappedAffine; - use w3f_pcs::pcs::{RawVerifierKey, PCS}; + use w3f_pcs::pcs::{PCS, RawVerifierKey}; use w3f_pcs::shplonk::Shplonk; use w3f_plonk_common::piop::ProverPiop; use w3f_plonk_common::prover::PlonkProver; @@ -31,7 +31,7 @@ mod tests { use w3f_ring_proof::piop::prover::PiopProver; use w3f_ring_proof::ring_prover::RingProver; use w3f_ring_proof::ring_verifier::RingVerifier; - use w3f_ring_proof::{index, test_setup, ArkTranscript}; + use w3f_ring_proof::{ArkTranscript, index, test_setup}; #[cfg(feature = "parallel")] use rayon::prelude::*; @@ -47,7 +47,8 @@ mod tests { // setup let domain_size = 2usize.pow(9); - let (pcs_params, piop_params) = test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); + let (pcs_params, piop_params) = + test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); let keyset_size = piop_params.keyset_part_size; let pks = random_vec::(keyset_size, rng); let (prover_key, verifier_key) = index::<_, PallasIPA, _>(&pcs_params, &piop_params, &pks); @@ -58,7 +59,9 @@ mod tests { // prover let fs = ArkTranscript::new(b"pasta-ring-proof-test"); let prover = RingProver::init(prover_key, piop_params.clone(), 0, fs.clone()); - let t_prove = start_timer!(|| format!("Proving IPA ring-proof with plonk, domain_size={domain_size}, keyset_size={keyset_size}")); + let t_prove = start_timer!(|| format!( + "Proving IPA ring-proof with plonk, domain_size={domain_size}, keyset_size={keyset_size}" + )); let (blinded_pk_, proof) = prover.rerandomize_pk(pk_idx, blinding); end_timer!(t_prove); assert_eq!(blinded_pk_, blinded_pk); @@ -91,7 +94,8 @@ mod tests { // setup let domain_size = 2usize.pow(9); - let (pcs_params, piop_params) = test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); + let (pcs_params, piop_params) = + test_setup::<_, _, PallasIPA, VestaConfig>(rng, domain_size); let keyset_size = piop_params.keyset_part_size; let pks = random_vec::(keyset_size, rng); let (prover_key, verifier_key) = index::<_, PallasIPA, _>(&pcs_params, &piop_params, &pks); @@ -106,16 +110,36 @@ mod tests { let pcs_vk = verifier_key.pcs_raw_vk.prepare(); // prover - let piop = PiopProver::::build(&piop_params, prover_key.fixed_columns.clone(), pk_idx, blinding); - let t_prove = start_timer!(|| format!("Proving IPA ring-proof with shplonk, domain_size={domain_size}, keyset_size={keyset_size}")); + let piop = PiopProver::::build( + &piop_params, + prover_key.fixed_columns.clone(), + pk_idx, + blinding, + ); + let t_prove = start_timer!(|| format!( + "Proving IPA ring-proof with shplonk, domain_size={domain_size}, keyset_size={keyset_size}" + )); let zeta = ark_pallas::Fr::rand(rng); let columns = as ProverPiop>::columns(&piop); let (quotient, agg_lin) = { - let constraints = as ProverPiop>::constraints(&piop); - let alphas: Vec<_> = (0..constraints.len()).map(|_| ark_pallas::Fr::rand(rng)).collect(); - let agg_constraint_poly = PlonkProver::::aggregate_evaluations(&constraints, &alphas).interpolate(); - let quotient = piop_params.domain.divide_by_vanishing_poly(&agg_constraint_poly); - let constraints_lin = as ProverPiop>::constraints_lin(&piop, &zeta); + let constraints = + as ProverPiop>::constraints(&piop); + let alphas: Vec<_> = (0..constraints.len()) + .map(|_| ark_pallas::Fr::rand(rng)) + .collect(); + let agg_constraint_poly = + PlonkProver::::aggregate_evaluations( + &constraints, + &alphas, + ) + .interpolate(); + let quotient = piop_params + .domain + .divide_by_vanishing_poly(&agg_constraint_poly); + let constraints_lin = + as ProverPiop>::constraints_lin( + &piop, &zeta, + ); let agg_lin = w3f_pcs::aggregation::single::aggregate_polys(&constraints_lin, &alphas); (quotient, agg_lin) }; @@ -128,19 +152,38 @@ mod tests { // commitments let mut poly_cs = verifier_key.fixed_columns_committed.as_vec(); - let t_commit = start_timer!(|| format!("Commiting to {} columns of degree = {} and the quotient of degree = {}", polys.len()-5, polys[3].degree(), polys[7].degree())); + let t_commit = start_timer!(|| format!( + "Commiting to {} columns of degree = {} and the quotient of degree = {}", + polys.len() - 5, + polys[3].degree(), + polys[7].degree() + )); // skip the instance columns and the linearirization polynomial `agg_lin` - poly_cs.extend(polys[3..polys.len() - 1].iter().map(|p| PallasIPA::commit(&pcs_ck, p).unwrap())); + poly_cs.extend( + polys[3..polys.len() - 1] + .iter() + .map(|p| PallasIPA::commit(&pcs_ck, p).unwrap()), + ); end_timer!(t_commit); poly_cs.push(PallasIPA::commit(&pcs_ck, &agg_lin).unwrap()); - let coord_sets: Vec> = coord_vecs.iter().cloned().map(BTreeSet::from_iter).collect(); - let vals: Vec<_> = polys.iter().zip(coord_vecs.iter()) + let coord_sets: Vec> = coord_vecs + .iter() + .cloned() + .map(BTreeSet::from_iter) + .collect(); + let vals: Vec<_> = polys + .iter() + .zip(coord_vecs.iter()) .map(|(f, xs)| xs.iter().map(|x| f.evaluate(&x)).collect::>()) .collect(); let transcript = &mut Coeffs(ark_pallas::Fr::rand(rng), ark_pallas::Fr::rand(rng)); - let t_open = start_timer!(|| format!("Opening IPA ring-proof with shplonk, {} polys, max_degree = {}", polys.len(), polys[7].degree())); + let t_open = start_timer!(|| format!( + "Opening IPA ring-proof with shplonk, {} polys, max_degree = {}", + polys.len(), + polys[7].degree() + )); let proof = Shplonk::::open_many( &pcs_ck, &polys, @@ -167,8 +210,13 @@ mod tests { fn _bench_msm(log_n: u32) { let rng = &mut test_rng(); let n = 2usize.pow(log_n); - let (scalars, bases): (Vec<_>, Vec<_>) = (0..n).map(|_| (C::ScalarField::rand(rng), C::Affine::rand(rng))).unzip(); - let t_msm = start_timer!(|| format!("log(n)={log_n}, MSM on {}", ark_std::any::type_name::())); + let (scalars, bases): (Vec<_>, Vec<_>) = (0..n) + .map(|_| (C::ScalarField::rand(rng), C::Affine::rand(rng))) + .unzip(); + let t_msm = start_timer!(|| format!( + "log(n)={log_n}, MSM on {}", + ark_std::any::type_name::() + )); let _res = C::msm(&bases, &scalars); end_timer!(t_msm); } @@ -205,7 +253,11 @@ mod tests { end_timer!(t_ipa_commit); } - fn mul_endo_wnaf(p: ark_pallas::Projective, k1: (bool, ark_pallas::Fr), k2: (bool, ark_pallas::Fr)) -> ark_pallas::Projective { + fn mul_endo_wnaf( + p: ark_pallas::Projective, + k1: (bool, ark_pallas::Fr), + k2: (bool, ark_pallas::Fr), + ) -> ark_pallas::Projective { let mut p1 = p; let mut p2 = PallasConfig::endomorphism(&p); if !k1.0 { @@ -251,24 +303,30 @@ mod tests { fn _bench_folding(log_n: u32) { let rng = &mut test_rng(); let n = 2usize.pow(log_n); - let (l, r): (Vec, Vec) = (0..n).map(|_| (ark_pallas::Affine::rand(rng), ark_pallas::Affine::rand(rng))).unzip(); + let (l, r): (Vec, Vec) = (0..n) + .map(|_| (ark_pallas::Affine::rand(rng), ark_pallas::Affine::rand(rng))) + .unzip(); let x = ark_pallas::Fr::rand(rng); let _timer = start_timer!(|| format!("Naive folding, log(n) = {log_n}")); - let res: Vec = ark_std::cfg_iter!(l).zip(r.clone()) + let res: Vec = ark_std::cfg_iter!(l) + .zip(r.clone()) .map(|(l, r)| r * x + l) .collect(); end_timer!(_timer); let _timer = start_timer!(|| format!("Naive folding with endo, log(n) = {log_n}")); - let res_: Vec = ark_std::cfg_into_iter!(l.clone()).zip(ark_std::cfg_into_iter!(r.clone())) + let res_: Vec = ark_std::cfg_into_iter!(l.clone()) + .zip(ark_std::cfg_into_iter!(r.clone())) .map(|(l, r)| l + ::glv_mul_affine(r, x)) .collect(); end_timer!(_timer); assert_eq!(res_, res); - let _timer = start_timer!(|| format!("Naive folding with endo and w-NAF, log(n) = {log_n}")); + let _timer = + start_timer!(|| format!("Naive folding with endo and w-NAF, log(n) = {log_n}")); let ((sgn_k1, k1), (sgn_k2, k2)) = PallasConfig::scalar_decomposition(x); - let res_: Vec = ark_std::cfg_into_iter!(l).zip(ark_std::cfg_iter!(r)) + let res_: Vec = ark_std::cfg_into_iter!(l) + .zip(ark_std::cfg_iter!(r)) .map(|(l, r)| l + mul_endo_wnaf(r.into_group(), (sgn_k1, k1), (sgn_k2, k2))) .collect(); end_timer!(_timer); @@ -276,32 +334,33 @@ mod tests { } fn batch_double_affine(bases: Vec>) -> Vec> { - let mut denoms: Vec = ark_std::cfg_iter!(bases) - .map(|p| p.y + p.y) - .collect(); + let mut denoms: Vec = ark_std::cfg_iter!(bases).map(|p| p.y + p.y).collect(); ark_ff::batch_inversion(&mut denoms); - ark_std::cfg_iter!(bases).zip(denoms).map(|(p, _2y_inv)| { - let (x, y) = p.xy().unwrap(); - let t = _2y_inv * (x.square() * C::BaseField::from(3) + ::COEFF_A); // (3x^2 + a) / 2y - let x_n = t.square() - x - x; - let y_n = t * (x - x_n) - y; - Affine::::new_unchecked(x_n, y_n) - }).collect() + ark_std::cfg_iter!(bases) + .zip(denoms) + .map(|(p, _2y_inv)| { + let (x, y) = p.xy().unwrap(); + let t = + _2y_inv * (x.square() * C::BaseField::from(3) + ::COEFF_A); // (3x^2 + a) / 2y + let x_n = t.square() - x - x; + let y_n = t * (x - x_n) - y; + Affine::::new_unchecked(x_n, y_n) + }) + .collect() } fn batch_double_affine_in_place(bases: &mut [Affine]) { let three = C::BaseField::from(3); let sw_a = ::COEFF_A; - let mut denoms: Vec = ark_std::cfg_iter!(bases) - .map(|p| p.y + p.y) - .collect(); + let mut denoms: Vec = ark_std::cfg_iter!(bases).map(|p| p.y + p.y).collect(); ark_ff::batch_inversion(&mut denoms); // ark_ff::batch_inversion_and_mul(&mut denoms, &C::BaseField::one()); - cfg_iter_mut!(bases).zip(ark_std::cfg_into_iter!(denoms)) + cfg_iter_mut!(bases) + .zip(ark_std::cfg_into_iter!(denoms)) .for_each(|(p, _2y_inv)| { let t = _2y_inv * (p.x.square() * three + sw_a); // (3x^2 + a) / 2y let old_x = p.x; @@ -310,7 +369,10 @@ mod tests { }) } - fn batch_add_affine(bases1: Vec>, bases2: Vec>) -> Vec> { + fn batch_add_affine( + bases1: Vec>, + bases2: Vec>, + ) -> Vec> { let mut denoms: Vec = ark_std::cfg_iter!(bases1) .zip(ark_std::cfg_iter!(bases2)) .map(|(p1, p2)| p2.x - p1.x) @@ -328,10 +390,14 @@ mod tests { let x_n = t.square() - x1 - x2; let y_n = t * (x1 - x_n) - y1; Affine::::new_unchecked(x_n, y_n) - }).collect() + }) + .collect() } - fn batch_mul_by_x_affine(bases: Vec>, x: C::ScalarField) -> Vec> { + fn batch_mul_by_x_affine( + bases: Vec>, + x: C::ScalarField, + ) -> Vec> { let mut res: Vec> = bases.clone(); for b in ark_ff::BitIteratorBE::without_leading_zeros(x.into_bigint()).skip(1) { batch_double_affine_in_place(&mut res); @@ -351,16 +417,21 @@ mod tests { let n = 2usize.pow(log_n); let bases: Vec<_> = (0..n).map(|_| ark_pallas::Affine::rand(rng)).collect(); let x = ark_pallas::Fr::rand(rng); - let dbl: Vec<_> = bases.iter().map(|p| { - let mut p = p.into_group(); - p.double_in_place(); - p.into_affine() - }).collect(); + let dbl: Vec<_> = bases + .iter() + .map(|p| { + let mut p = p.into_group(); + p.double_in_place(); + p.into_affine() + }) + .collect(); assert_eq!(dbl, batch_double_affine(bases.clone())); let bases2: Vec<_> = (0..n).map(|_| ark_pallas::Affine::rand(rng)).collect(); let bases1 = bases.clone(); - let add: Vec<_> = bases.into_iter().zip(bases2.iter()) + let add: Vec<_> = bases + .into_iter() + .zip(bases2.iter()) .map(|(p1, p2)| p1 + p2) .collect(); assert_eq!(add, batch_add_affine(bases1.clone(), bases2.clone())); @@ -371,7 +442,8 @@ mod tests { end_timer!(_timer); let _timer = start_timer!(|| format!("Naive folding, log(n) = {log_n}")); - let res_: Vec = ark_std::cfg_into_iter!(bases1).zip(ark_std::cfg_into_iter!(bases2)) + let res_: Vec = ark_std::cfg_into_iter!(bases1) + .zip(ark_std::cfg_into_iter!(bases2)) .map(|(l, r)| l + r * x) .collect(); let _to_affine = start_timer!(|| "batch affine conversion"); diff --git a/w3f-plonk-common/src/prover.rs b/w3f-plonk-common/src/prover.rs index c221191..b446e2d 100644 --- a/w3f-plonk-common/src/prover.rs +++ b/w3f-plonk-common/src/prover.rs @@ -58,7 +58,8 @@ impl, T: PlonkTranscript> PlonkProver let agg_constraint_poly = agg_constraint_poly.interpolate(); let quotient_poly = piop.domain().divide_by_vanishing_poly(&agg_constraint_poly); // The prover commits to the quotient polynomial... - let _t_commit_q = start_timer!(|| format!("Committing to deg(f)={}", quotient_poly.degree())); + let _t_commit_q = + start_timer!(|| format!("Committing to deg(f)={}", quotient_poly.degree())); let quotient_commitment = CS::commit(&self.pcs_ck, "ient_poly).unwrap(); end_timer!(_t_commit_q); transcript.add_quotient_commitment("ient_commitment); diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 7290a5c..8a16a80 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -51,7 +51,10 @@ impl ArkTranscript { } } -pub fn test_setup, G: SWCurveConfig>(rng: &mut R, domain_size: usize) -> (CS::Params, PiopParams) { +pub fn test_setup, G: SWCurveConfig>( + rng: &mut R, + domain_size: usize, +) -> (CS::Params, PiopParams) { let setup_degree = 3 * domain_size; let pcs_params = CS::setup(setup_degree, rng); let domain = Domain::new(domain_size, true); @@ -66,7 +69,7 @@ pub fn test_setup, G: SWCurveConfig> FixedColumnsCommitted { } } -impl> FixedColumnsCommitted> { - pub fn from_ring, G: SWCurveConfig>( +impl> FixedColumnsCommitted> { + pub fn from_ring, G: SWCurveConfig>( ring: &Ring, ) -> Self { let cx = WrappedAffine(ring.cx);