1use crate::*;
49use ark_ec::{
50 pairing::Pairing,
51 twisted_edwards::{Affine as TEAffine, TECurveConfig},
52};
53use ark_std::ops::Range;
54use pedersen::{PedersenSuite, Proof as PedersenProof};
55use utils::te_sw_map::TEMapping;
56use w3f_ring_proof as ring_proof;
57
58pub const ACCUMULATOR_BASE_SEED: &[u8] = b"ring-accumulator";
60
61pub const PADDING_SEED: &[u8] = b"ring-padding";
63
64pub trait RingSuite:
69 PedersenSuite<
70 Affine: AffineRepr<BaseField: ark_ff::PrimeField, Config: TECurveConfig + Clone>
71 + TEMapping<<Self::Affine as AffineRepr>::Config>,
72>
73{
74 type Pairing: ark_ec::pairing::Pairing<ScalarField = BaseField<Self>>;
76
77 const ACCUMULATOR_BASE: AffinePoint<Self>;
82
83 const PADDING: AffinePoint<Self>;
85}
86
87pub type Kzg<S> = ring_proof::pcs::kzg::KZG<<S as RingSuite>::Pairing>;
89
90pub type PcsCommitment<S> =
92 ring_proof::pcs::kzg::commitment::KzgCommitment<<S as RingSuite>::Pairing>;
93
94pub type PcsParams<S> = ring_proof::pcs::kzg::urs::URS<<S as RingSuite>::Pairing>;
98
99pub type PiopParams<S> = ring_proof::PiopParams<BaseField<S>, CurveConfig<S>>;
104
105pub type RingCommitment<S> = ring_proof::FixedColumnsCommitted<BaseField<S>, PcsCommitment<S>>;
107
108pub type RingProverKey<S> = ring_proof::ProverKey<BaseField<S>, Kzg<S>, TEAffine<CurveConfig<S>>>;
110
111pub type RingVerifierKey<S> = ring_proof::VerifierKey<BaseField<S>, Kzg<S>>;
113
114pub type RingProver<S> = ring_proof::ring_prover::RingProver<BaseField<S>, Kzg<S>, CurveConfig<S>>;
116
117pub type RingVerifier<S> =
119 ring_proof::ring_verifier::RingVerifier<BaseField<S>, Kzg<S>, CurveConfig<S>>;
120
121pub type RingBatchVerifier<S> = ring_proof::ring_verifier::KzgBatchVerifier<
123 <S as RingSuite>::Pairing,
124 CurveConfig<S>,
125 ring_proof::ArkTranscript,
126>;
127
128pub type RingBareProof<S> = ring_proof::RingProof<BaseField<S>, Kzg<S>>;
133
134#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
143pub struct Proof<S: RingSuite> {
144 pub pedersen_proof: PedersenProof<S>,
146 pub ring_proof: RingBareProof<S>,
148}
149
150pub trait Prover<S: RingSuite> {
152 fn prove(
156 &self,
157 ios: impl AsRef<[VrfIo<S>]>,
158 ad: impl AsRef<[u8]>,
159 prover: &RingProver<S>,
160 ) -> Proof<S>;
161}
162
163pub trait Verifier<S: RingSuite> {
180 fn verify(
186 ios: impl AsRef<[VrfIo<S>]>,
187 ad: impl AsRef<[u8]>,
188 sig: &Proof<S>,
189 verifier: &RingVerifier<S>,
190 ) -> Result<(), Error>;
191}
192
193impl<S: RingSuite> Prover<S> for Secret<S> {
194 fn prove(
195 &self,
196 ios: impl AsRef<[VrfIo<S>]>,
197 ad: impl AsRef<[u8]>,
198 ring_prover: &RingProver<S>,
199 ) -> Proof<S> {
200 use pedersen::Prover as PedersenProver;
201 let (pedersen_proof, secret_blinding) = <Self as PedersenProver<S>>::prove(self, ios, ad);
202 let ring_proof = ring_prover.prove(secret_blinding);
203 Proof {
204 pedersen_proof,
205 ring_proof,
206 }
207 }
208}
209
210impl<S: RingSuite> Verifier<S> for Public<S> {
211 fn verify(
212 ios: impl AsRef<[VrfIo<S>]>,
213 ad: impl AsRef<[u8]>,
214 proof: &Proof<S>,
215 verifier: &RingVerifier<S>,
216 ) -> Result<(), Error> {
217 use pedersen::Verifier as PedersenVerifier;
218 <Self as PedersenVerifier<S>>::verify(ios, ad, &proof.pedersen_proof)?;
219 let key_commitment = proof.pedersen_proof.key_commitment().into_te();
220 if !verifier.verify(proof.ring_proof.clone(), key_commitment) {
221 return Err(Error::VerificationFailure);
222 }
223 Ok(())
224 }
225}
226
227#[derive(Clone)]
233pub struct RingProofParams<S: RingSuite> {
234 pub pcs: PcsParams<S>,
236 pub piop: PiopParams<S>,
238}
239
240pub(crate) fn piop_params<S: RingSuite>(domain_size: usize) -> PiopParams<S> {
241 PiopParams::<S>::setup(
242 ring_proof::Domain::new(domain_size, true),
243 S::BLINDING_BASE.into_te(),
244 S::ACCUMULATOR_BASE.into_te(),
245 S::PADDING.into_te(),
246 )
247}
248
249impl<S: RingSuite> RingProofParams<S> {
250 pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self {
254 let mut t = S::Transcript::new(S::SUITE_ID);
255 t.absorb_raw(&seed);
256 let mut rng = t.to_rng();
257 Self::from_rand(ring_size, &mut rng)
258 }
259
260 pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self {
264 use ring_proof::pcs::PCS;
265 let max_degree = pcs_domain_size::<S>(ring_size) - 1;
266 let pcs_params = Kzg::<S>::setup(max_degree, rng);
267 Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct")
268 }
269
270 pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams<S>) -> Result<Self, Error> {
275 let pcs_domain_size = pcs_domain_size::<S>(ring_size);
276 if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 {
277 return Err(Error::InvalidData);
278 }
279 pcs_params.powers_in_g1.truncate(pcs_domain_size);
281 pcs_params.powers_in_g2.truncate(2);
282 let piop_domain_size = piop_domain_size::<S>(ring_size);
283 Ok(Self {
284 pcs: pcs_params,
285 piop: piop_params::<S>(piop_domain_size),
286 })
287 }
288
289 #[inline(always)]
291 pub fn max_ring_size(&self) -> usize {
292 self.piop.keyset_part_size
293 }
294
295 pub fn prover_key(&self, pks: &[AffinePoint<S>]) -> Result<RingProverKey<S>, Error> {
299 if pks.len() > self.max_ring_size() {
300 return Err(Error::InvalidData);
301 }
302 let pks = TEMapping::to_te_slice(pks);
303 Ok(ring_proof::index(&self.pcs, &self.piop, &pks).0)
304 }
305
306 pub fn prover(&self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
308 RingProver::<S>::init(
309 prover_key,
310 self.piop.clone(),
311 key_index,
312 ring_proof::ArkTranscript::new(const { &S::SUITE_ID.to_bytes() }),
313 )
314 }
315
316 pub fn verifier_key(&self, pks: &[AffinePoint<S>]) -> Result<RingVerifierKey<S>, Error> {
320 if pks.len() > self.max_ring_size() {
321 return Err(Error::InvalidData);
322 }
323 let pks = TEMapping::to_te_slice(pks);
324 Ok(ring_proof::index(&self.pcs, &self.piop, &pks).1)
325 }
326
327 pub fn verifier_key_from_commitment(
332 &self,
333 commitment: RingCommitment<S>,
334 ) -> RingVerifierKey<S> {
335 use ring_proof::pcs::PcsParams;
336 RingVerifierKey::<S>::from_commitment_and_kzg_vk(commitment, self.pcs.raw_vk())
337 }
338
339 pub fn verifier_key_builder(&self) -> (VerifierKeyBuilder<S>, RingBuilderPcsParams<S>) {
341 type RingBuilderKey<S> =
342 ring_proof::ring::RingBuilderKey<BaseField<S>, <S as RingSuite>::Pairing>;
343 let piop_domain_size = piop_domain_size::<S>(self.piop.keyset_part_size);
344 let builder_key = RingBuilderKey::<S>::from_srs(&self.pcs, piop_domain_size);
345 let builder_pcs_params = RingBuilderPcsParams(builder_key.lis_in_g1);
346 let builder = VerifierKeyBuilder::new(self, &builder_pcs_params);
347 (builder, builder_pcs_params)
348 }
349
350 pub fn verifier(&self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
352 RingVerifier::<S>::init(
353 verifier_key,
354 self.piop.clone(),
355 ring_proof::ArkTranscript::new(const { &S::SUITE_ID.to_bytes() }),
356 )
357 }
358
359 pub fn verifier_no_context(
364 verifier_key: RingVerifierKey<S>,
365 ring_size: usize,
366 ) -> RingVerifier<S> {
367 RingVerifier::<S>::init(
368 verifier_key,
369 piop_params::<S>(piop_domain_size::<S>(ring_size)),
370 ring_proof::ArkTranscript::new(const { &S::SUITE_ID.to_bytes() }),
371 )
372 }
373
374 #[inline(always)]
379 pub const fn padding_point() -> AffinePoint<S> {
380 S::PADDING
381 }
382}
383
384impl<S: RingSuite> CanonicalSerialize for RingProofParams<S> {
385 fn serialize_with_mode<W: ark_serialize::Write>(
386 &self,
387 mut writer: W,
388 compress: ark_serialize::Compress,
389 ) -> Result<(), ark_serialize::SerializationError> {
390 self.pcs.serialize_with_mode(&mut writer, compress)
391 }
392
393 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
394 self.pcs.serialized_size(compress)
395 }
396}
397
398impl<S: RingSuite> CanonicalDeserialize for RingProofParams<S> {
399 fn deserialize_with_mode<R: ark_serialize::Read>(
400 mut reader: R,
401 compress: ark_serialize::Compress,
402 validate: ark_serialize::Validate,
403 ) -> Result<Self, ark_serialize::SerializationError> {
404 let pcs_params = <PcsParams<S> as CanonicalDeserialize>::deserialize_with_mode(
405 &mut reader,
406 compress,
407 validate,
408 )?;
409 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_params.powers_in_g1.len());
410 Ok(Self {
411 pcs: pcs_params,
412 piop: piop_params::<S>(piop_domain_size),
413 })
414 }
415}
416
417impl<S: RingSuite> ark_serialize::Valid for RingProofParams<S> {
418 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
419 self.pcs.check()
420 }
421}
422
423#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
428pub struct RingBuilderPcsParams<S: RingSuite>(pub Vec<G1Affine<S>>);
429
430type PartialRingCommitment<S> =
432 ring_proof::ring::Ring<BaseField<S>, <S as RingSuite>::Pairing, CurveConfig<S>>;
433
434type RawVerifierKey<S> = <PcsParams<S> as ring_proof::pcs::PcsParams>::RVK;
435
436#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
441pub struct VerifierKeyBuilder<S: RingSuite> {
442 partial: PartialRingCommitment<S>,
443 raw_vk: RawVerifierKey<S>,
444}
445
446pub type G1Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G1Affine;
448pub type G2Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G2Affine;
450
451pub trait SrsLookup<S: RingSuite> {
455 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>>;
457}
458
459impl<S: RingSuite, F> SrsLookup<S> for F
460where
461 F: Fn(Range<usize>) -> Option<Vec<G1Affine<S>>>,
462{
463 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
464 self(range)
465 }
466}
467
468impl<S: RingSuite> SrsLookup<S> for &RingBuilderPcsParams<S> {
469 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
470 if range.end > self.0.len() {
471 return None;
472 }
473 Some(self.0[range].to_vec())
474 }
475}
476
477impl<S: RingSuite> VerifierKeyBuilder<S> {
478 pub fn new(params: &RingProofParams<S>, lookup: impl SrsLookup<S>) -> Self {
480 use ring_proof::pcs::PcsParams;
481 let lookup = |range: Range<usize>| lookup.lookup(range).ok_or(());
482 let raw_vk = params.pcs.raw_vk();
483 let partial =
484 PartialRingCommitment::<S>::empty(¶ms.piop, lookup, raw_vk.g1.into_group());
485 VerifierKeyBuilder { partial, raw_vk }
486 }
487
488 #[inline(always)]
490 pub fn free_slots(&self) -> usize {
491 self.partial.max_keys - self.partial.curr_keys
492 }
493
494 pub fn append(
499 &mut self,
500 pks: &[AffinePoint<S>],
501 lookup: impl SrsLookup<S>,
502 ) -> Result<(), usize> {
503 let avail_slots = self.free_slots();
504 if avail_slots < pks.len() {
505 return Err(avail_slots);
506 }
507 let segment = lookup
510 .lookup(self.partial.curr_keys..self.partial.curr_keys + pks.len())
511 .ok_or(usize::MAX)?;
512 let lookup = |range: Range<usize>| {
513 debug_assert_eq!(segment.len(), range.len());
514 Ok(segment.clone())
515 };
516 let pks = TEMapping::to_te_slice(pks);
517 self.partial.append(&pks, lookup);
518 Ok(())
519 }
520
521 pub fn finalize(self) -> RingVerifierKey<S> {
523 RingVerifierKey::<S>::from_ring_and_kzg_vk(&self.partial, self.raw_vk)
524 }
525}
526
527type RingPreparedBatchItem<S> =
528 ring_proof::ring_verifier::PreparedBatchItem<<S as RingSuite>::Pairing, CurveConfig<S>>;
529
530pub struct BatchItem<S: RingSuite> {
532 ring: RingPreparedBatchItem<S>,
533 pedersen: pedersen::BatchItem<S>,
534}
535
536pub struct BatchVerifier<S: RingSuite> {
544 ring_batch: RingBatchVerifier<S>,
545 pedersen_batch: pedersen::BatchVerifier<S>,
546}
547
548impl<S: RingSuite> BatchVerifier<S> {
549 pub fn new(ring_verifier: RingVerifier<S>) -> Self {
551 Self {
552 ring_batch: ring_verifier.kzg_batch_verifier(),
553 pedersen_batch: pedersen::BatchVerifier::new(),
554 }
555 }
556
557 pub fn prepare(
562 &self,
563 ios: impl AsRef<[VrfIo<S>]>,
564 ad: impl AsRef<[u8]>,
565 proof: &Proof<S>,
566 ) -> BatchItem<S> {
567 let pedersen = pedersen::BatchVerifier::prepare(ios, ad, &proof.pedersen_proof);
568 let key_commitment = proof.pedersen_proof.key_commitment().into_te();
569 let ring = self
570 .ring_batch
571 .prepare(proof.ring_proof.clone(), key_commitment);
572 BatchItem { ring, pedersen }
573 }
574
575 pub fn push_prepared(&mut self, item: BatchItem<S>) {
577 self.pedersen_batch.push_prepared(item.pedersen);
578 self.ring_batch.push_prepared(item.ring);
579 }
580
581 pub fn push(&mut self, ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>, proof: &Proof<S>) {
583 let prepared = self.prepare(ios, ad, proof);
584 self.push_prepared(prepared);
585 }
586
587 pub fn verify(&self) -> Result<(), Error> {
592 self.pedersen_batch.verify()?;
593 self.ring_batch
594 .verify()
595 .then_some(())
596 .ok_or(Error::VerificationFailure)
597 }
598}
599
600#[macro_export]
602macro_rules! ring_suite_types {
603 ($suite:ident) => {
604 #[allow(dead_code)]
605 pub type PcsParams = $crate::ring::PcsParams<$suite>;
606 #[allow(dead_code)]
607 pub type PiopParams = $crate::ring::PiopParams<$suite>;
608 #[allow(dead_code)]
609 pub type RingProofParams = $crate::ring::RingProofParams<$suite>;
610 #[allow(dead_code)]
611 pub type RingProverKey = $crate::ring::RingProverKey<$suite>;
612 #[allow(dead_code)]
613 pub type RingVerifierKey = $crate::ring::RingVerifierKey<$suite>;
614 #[allow(dead_code)]
615 pub type RingCommitment = $crate::ring::RingCommitment<$suite>;
616 #[allow(dead_code)]
617 pub type RingProver = $crate::ring::RingProver<$suite>;
618 #[allow(dead_code)]
619 pub type RingVerifier = $crate::ring::RingVerifier<$suite>;
620 #[allow(dead_code)]
621 pub type RingProof = $crate::ring::Proof<$suite>;
622 #[allow(dead_code)]
623 pub type RingVerifierKeyBuilder = $crate::ring::VerifierKeyBuilder<$suite>;
624 #[allow(dead_code)]
625 pub type RingBatchItem = $crate::ring::BatchItem<$suite>;
626 #[allow(dead_code)]
627 pub type RingBatchVerifier = $crate::ring::BatchVerifier<$suite>;
628 };
629}
630
631pub mod dom_utils {
654 use super::*;
655
656 pub const fn max_ring_size<S: Suite>(min_ring_size: usize) -> usize {
664 max_ring_size_from_piop_domain_size::<S>(piop_domain_size::<S>(min_ring_size))
665 }
666
667 pub const fn piop_overhead<S: Suite>() -> usize {
669 4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize
670 }
671
672 pub const fn piop_domain_size<S: Suite>(min_ring_capacity: usize) -> usize {
678 (min_ring_capacity + piop_overhead::<S>()).next_power_of_two()
679 }
680
681 pub const fn max_ring_size_from_piop_domain_size<S: Suite>(piop_domain_size: usize) -> usize {
685 piop_domain_size - piop_overhead::<S>()
686 }
687
688 pub const fn pcs_domain_size<S: Suite>(min_ring_size: usize) -> usize {
693 pcs_domain_size_from_piop_domain_size(piop_domain_size::<S>(min_ring_size))
694 }
695
696 pub const fn pcs_domain_size_from_piop_domain_size(piop_domain_size: usize) -> usize {
700 3 * piop_domain_size + 1
701 }
702
703 pub const fn piop_domain_size_from_pcs_domain_size(pcs_domain_size: usize) -> usize {
708 1 << ((pcs_domain_size - 1) / 3).ilog2()
709 }
710
711 pub const fn max_ring_size_from_pcs_domain_size<S: Suite>(pcs_domain_size: usize) -> usize {
715 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_domain_size);
716 max_ring_size_from_piop_domain_size::<S>(piop_domain_size)
717 }
718}
719pub use dom_utils::*;
720
721#[cfg(test)]
722pub(crate) mod testing {
723 use super::*;
724 use crate::pedersen;
725 use crate::testing::{self as common, CheckPoint, TEST_SEED};
726 use ark_ec::{
727 short_weierstrass::{Affine as SWAffine, SWCurveConfig},
728 twisted_edwards::{Affine as TEAffine, TECurveConfig},
729 };
730
731 pub const TEST_RING_SIZE: usize = 8;
732
733 const MAX_AD_LEN: usize = 100;
734
735 fn find_complement_point<C: SWCurveConfig>() -> SWAffine<C> {
736 use ark_ff::{One, Zero};
737 assert!(!C::cofactor_is_one());
738 let mut x = C::BaseField::zero();
739 loop {
740 if let Some(p) = SWAffine::get_point_from_x_unchecked(x, false)
741 .filter(|p| !p.is_in_correct_subgroup_assuming_on_curve())
742 {
743 return p;
744 }
745 x += C::BaseField::one();
746 }
747 }
748
749 pub trait FindAccumulatorBase<S: Suite>: Sized {
750 const IN_PRIME_ORDER_SUBGROUP: bool;
751 fn find_accumulator_base(data: &[u8]) -> Option<Self>;
752 }
753
754 impl<S, C> FindAccumulatorBase<S> for SWAffine<C>
755 where
756 C: SWCurveConfig,
757 S: Suite<Affine = Self>,
758 {
759 const IN_PRIME_ORDER_SUBGROUP: bool = false;
760
761 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
762 let p = S::data_to_point(data)?;
763 let c = find_complement_point();
764 let res = (p + c).into_affine();
765 debug_assert!(!res.is_in_correct_subgroup_assuming_on_curve());
766 Some(res)
767 }
768 }
769
770 impl<S, C> FindAccumulatorBase<S> for TEAffine<C>
771 where
772 C: TECurveConfig,
773 S: Suite<Affine = Self>,
774 {
775 const IN_PRIME_ORDER_SUBGROUP: bool = true;
776
777 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
778 let res = S::data_to_point(data)?;
779 debug_assert!(res.is_in_correct_subgroup_assuming_on_curve());
780 Some(res)
781 }
782 }
783
784 struct BatchItem<S: RingSuite> {
785 io: VrfIo<S>,
786 ad: Vec<u8>,
787 proof: Proof<S>,
788 }
789
790 impl<S: RingSuite> BatchItem<S> {
791 fn new(
792 secret: &Secret<S>,
793 prover: &RingProver<S>,
794 rng: &mut dyn ark_std::rand::RngCore,
795 ) -> Self {
796 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
797 let io = secret.vrf_io(input);
798 let ad_len = common::random_val::<usize>(Some(rng)) % (MAX_AD_LEN + 1);
799 let ad = common::random_vec(ad_len, Some(rng));
800 let proof = secret.prove(io, &ad, prover);
801 Self { io, ad, proof }
802 }
803 }
804
805 #[allow(unused)]
806 pub fn prove_verify<S: RingSuite>() {
807 let rng = &mut ark_std::test_rng();
808 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
809
810 let secret = Secret::<S>::from_seed(TEST_SEED);
811 let public = secret.public();
812
813 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
814 let prover_idx = 3;
815 pks[prover_idx] = public.0;
816
817 let prover_key = params.prover_key(&pks).unwrap();
818 let prover = params.prover(prover_key, prover_idx);
819
820 let item = BatchItem::<S>::new(&secret, &prover, rng);
821
822 let verifier_key = params.verifier_key(&pks).unwrap();
823 let verifier = params.verifier(verifier_key);
824 let result = Public::verify(item.io, &item.ad, &item.proof, &verifier);
825 assert!(result.is_ok());
826 }
827
828 #[allow(unused)]
830 pub fn prove_verify_multi<S: RingSuite>() {
831 use ring::{Prover, Verifier};
832
833 let rng = &mut ark_std::test_rng();
834 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
835
836 let secret = Secret::<S>::from_seed(TEST_SEED);
837 let public = secret.public();
838
839 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
840 let prover_idx = 3;
841 pks[prover_idx] = public.0;
842
843 let prover_key = params.prover_key(&pks).unwrap();
844 let prover = params.prover(prover_key, prover_idx);
845
846 let verifier_key = params.verifier_key(&pks).unwrap();
847 let verifier = params.verifier(verifier_key);
848
849 let mut ios: Vec<VrfIo<S>> = (0..3u8)
850 .map(|i| {
851 let input = Input::new(&[i + 1]).unwrap();
852 secret.vrf_io(input)
853 })
854 .collect();
855 ios.push(VrfIo {
856 input: Input(S::Affine::generator()),
857 output: Output(public.0),
858 });
859
860 let proof = secret.prove(&ios[..], b"bar", &prover);
861 assert!(Public::verify(&ios[..], b"bar", &proof, &verifier).is_ok());
862
863 let mut bad_ios = ios.clone();
865 bad_ios[1].output = secret.output(ios[0].input);
866 assert!(Public::verify(&bad_ios[..], b"bar", &proof, &verifier).is_err());
867
868 assert!(Public::verify(&ios[..], b"baz", &proof, &verifier).is_err());
870 }
871
872 #[allow(unused)]
873 pub fn prove_verify_batch<S: RingSuite>() {
874 use rayon::prelude::*;
875
876 const BATCH_SIZE: usize = 3 * TEST_RING_SIZE;
877
878 let rng = &mut ark_std::test_rng();
879 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
880
881 let secret = Secret::<S>::from_seed(TEST_SEED);
882 let public = secret.public();
883
884 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
885 let prover_idx = 3;
886 pks[prover_idx] = public.0;
887
888 let prover_key = params.prover_key(&pks).unwrap();
889 let prover = params.prover(prover_key, prover_idx);
890
891 let batch: Vec<_> = (0..BATCH_SIZE)
893 .into_par_iter()
894 .map_init(ark_std::test_rng, |rng, _| {
895 BatchItem::<S>::new(&secret, &prover, rng)
896 })
897 .collect();
898
899 let verifier_key = params.verifier_key(&pks).unwrap();
900 let verifier = params.verifier(verifier_key);
901
902 let mut batch_verifier = BatchVerifier::<S>::new(verifier);
904 let res = batch_verifier.verify();
905 assert!(res.is_ok());
906
907 for item in batch.iter() {
909 batch_verifier.push(item.io, &item.ad, &item.proof);
910 let res = batch_verifier.verify();
911 assert!(res.is_ok());
912 }
913
914 println!("Batch size = {BATCH_SIZE}");
915
916 println!("============================================================");
917
918 let verifier_key = params.verifier_key(&pks).unwrap();
919 let verifier = params.verifier(verifier_key);
920 let mut batch_verifier = BatchVerifier::<S>::new(verifier);
921 let start = std::time::Instant::now();
922 common::timed("Proofs push", || {
923 for item in batch.iter() {
924 batch_verifier.push(item.io, &item.ad, &item.proof);
925 }
926 });
927 common::timed("Unprepared batch verification", || batch_verifier.verify());
928 println!("Total time: {:?}", start.elapsed());
929
930 println!("============================================================");
931
932 let verifier_key = params.verifier_key(&pks).unwrap();
933 let verifier = params.verifier(verifier_key);
934 let mut batch_verifier = BatchVerifier::<S>::new(verifier);
935 let start = std::time::Instant::now();
936 let prepared = common::timed("Proofs prepare", || {
937 batch
938 .par_iter()
939 .map(|item| batch_verifier.prepare(item.io, &item.ad, &item.proof))
940 .collect::<Vec<_>>()
941 });
942 common::timed("Proofs push prepared", || {
943 prepared
944 .into_iter()
945 .for_each(|p| batch_verifier.push_prepared(p))
946 });
947 common::timed("Prepared batch verification", || batch_verifier.verify());
948 println!("Total time: {:?}", start.elapsed());
949 }
950
951 #[allow(unused)]
952 pub fn padding_check<S: RingSuite>()
953 where
954 AffinePoint<S>: CheckPoint,
955 {
956 assert_eq!(S::PADDING, S::data_to_point(PADDING_SEED).unwrap());
958
959 assert!(S::PADDING.check(true).is_ok());
961 }
962
963 #[allow(unused)]
964 pub fn accumulator_base_check<S: RingSuite>()
965 where
966 AffinePoint<S>: FindAccumulatorBase<S> + CheckPoint,
967 {
968 assert_eq!(
970 S::ACCUMULATOR_BASE,
971 AffinePoint::<S>::find_accumulator_base(ACCUMULATOR_BASE_SEED).unwrap()
972 );
973
974 let in_prime_subgroup = <AffinePoint<S> as FindAccumulatorBase<S>>::IN_PRIME_ORDER_SUBGROUP;
977 assert!(S::ACCUMULATOR_BASE.check(in_prime_subgroup).is_ok());
978 }
979
980 #[allow(unused)]
981 pub fn verifier_key_builder<S: RingSuite>() {
982 use crate::testing::{random_val, random_vec};
983
984 let rng = &mut ark_std::test_rng();
985 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
986
987 let secret = Secret::<S>::from_seed(TEST_SEED);
988 let public = secret.public();
989 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
990 let io = secret.vrf_io(input);
991
992 let ring_size = params.max_ring_size();
993 let prover_idx = random_val::<usize>(Some(rng)) % ring_size;
994 let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
995 pks[prover_idx] = public.0;
996
997 let prover_key = params.prover_key(&pks).unwrap();
998 let prover = params.prover(prover_key, prover_idx);
999 let proof = secret.prove(io, b"foo", &prover);
1000
1001 let (mut vk_builder, lookup) = params.verifier_key_builder();
1003 assert_eq!(vk_builder.free_slots(), pks.len());
1004
1005 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1006 assert_eq!(
1007 vk_builder.append(&[extra_pk], |_| None).unwrap_err(),
1008 usize::MAX
1009 );
1010
1011 while !pks.is_empty() {
1012 let chunk_len = 1 + random_val::<usize>(Some(rng)) % 5;
1013 let chunk = pks.drain(..pks.len().min(chunk_len)).collect::<Vec<_>>();
1014 vk_builder.append(&chunk[..], &lookup).unwrap();
1015 assert_eq!(vk_builder.free_slots(), pks.len());
1016 }
1017 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1019 assert_eq!(vk_builder.append(&[extra_pk], &lookup).unwrap_err(), 0);
1020 let verifier_key = vk_builder.finalize();
1021 let verifier = params.verifier(verifier_key);
1022 let result = Public::verify(io, b"foo", &proof, &verifier);
1023 assert!(result.is_ok());
1024 }
1025
1026 pub fn domain_size_conversions<S: RingSuite>() {
1027 let overhead = piop_overhead::<S>();
1028
1029 for ring_size in [1, 10, 200, 300, 500, 1000, 2000, 10000] {
1030 let piop_dom_size = piop_domain_size::<S>(ring_size);
1031 let pcs_dom_size = pcs_domain_size::<S>(ring_size);
1032 let max_ring_size = max_ring_size_from_piop_domain_size::<S>(piop_dom_size);
1033
1034 assert!(piop_dom_size.is_power_of_two());
1035 assert_eq!(pcs_dom_size, 3 * piop_dom_size + 1);
1036
1037 assert!(piop_dom_size >= ring_size + overhead);
1039 assert!(piop_dom_size / 2 < ring_size + overhead);
1041 assert_eq!(piop_dom_size, piop_domain_size::<S>(max_ring_size));
1043 assert!(ring_size <= max_ring_size);
1045
1046 assert_eq!(dom_utils::max_ring_size::<S>(ring_size), max_ring_size);
1048 assert_eq!(dom_utils::max_ring_size::<S>(max_ring_size), max_ring_size);
1050
1051 let piop_dom_rt = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1053 assert_eq!(piop_dom_size, piop_dom_rt);
1054 let pcs_dom_rt = pcs_domain_size_from_piop_domain_size(piop_dom_rt);
1055 assert_eq!(pcs_dom_size, pcs_dom_rt);
1056
1057 let max_ring_from_pcs = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1058 assert_eq!(max_ring_size, max_ring_from_pcs);
1059
1060 let next_piop = piop_domain_size::<S>(max_ring_size + 1);
1062 assert!(next_piop > piop_dom_size,);
1063 assert!(next_piop.is_power_of_two());
1064 }
1065
1066 for pcs_dom_size in [1 << 11, 1 << 12, 1 << 14, 1 << 16] {
1069 let piop_dom = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1070 let max_ring = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1071
1072 assert!(piop_dom.is_power_of_two());
1073 assert!(3 * piop_dom < pcs_dom_size);
1075 assert!(3 * (2 * piop_dom) + 1 > pcs_dom_size);
1077 assert_eq!(piop_domain_size::<S>(max_ring), piop_dom);
1079 assert!(piop_domain_size::<S>(max_ring + 1) > piop_dom);
1081 }
1082
1083 let piop_zero = piop_domain_size::<S>(0);
1085 assert!(piop_zero.is_power_of_two());
1086 assert_eq!(piop_zero, overhead.next_power_of_two());
1087 }
1088
1089 #[macro_export]
1090 macro_rules! ring_suite_tests {
1091 ($suite:ty) => {
1092 mod ring {
1093 use super::*;
1094
1095 #[test]
1096 fn prove_verify() {
1097 $crate::ring::testing::prove_verify::<$suite>()
1098 }
1099
1100 #[test]
1101 fn prove_verify_multi() {
1102 $crate::ring::testing::prove_verify_multi::<$suite>()
1103 }
1104
1105 #[test]
1106 fn prove_verify_batch() {
1107 $crate::ring::testing::prove_verify_batch::<$suite>()
1108 }
1109
1110 #[test]
1111 fn padding_check() {
1112 $crate::ring::testing::padding_check::<$suite>()
1113 }
1114
1115 #[test]
1116 fn accumulator_base_check() {
1117 $crate::ring::testing::accumulator_base_check::<$suite>()
1118 }
1119
1120 #[test]
1121 fn verifier_key_builder() {
1122 $crate::ring::testing::verifier_key_builder::<$suite>()
1123 }
1124
1125 #[test]
1126 fn domain_size_conversions() {
1127 $crate::ring::testing::domain_size_conversions::<$suite>()
1128 }
1129
1130 $crate::test_vectors!($crate::ring::testing::TestVector<$suite>);
1131 }
1132 };
1133 }
1134
1135 pub trait RingSuiteExt: RingSuite + crate::testing::SuiteExt {
1136 const SRS_FILE: &str;
1137
1138 fn params() -> &'static RingProofParams<Self>;
1139
1140 #[allow(unused)]
1141 fn load_context() -> RingProofParams<Self> {
1142 use ark_serialize::CanonicalDeserialize;
1143 use std::{fs::File, io::Read};
1144 let mut file = File::open(Self::SRS_FILE).unwrap();
1145 let mut buf = Vec::new();
1146 file.read_to_end(&mut buf).unwrap();
1147 let pcs_params =
1148 PcsParams::<Self>::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
1149 RingProofParams::from_pcs_params(crate::ring::testing::TEST_RING_SIZE, pcs_params)
1150 .unwrap()
1151 }
1152
1153 #[allow(unused)]
1154 fn write_context(params: &RingProofParams<Self>) {
1155 use ark_serialize::CanonicalSerialize;
1156 use std::{fs::File, io::Write};
1157 let mut file = File::create(Self::SRS_FILE).unwrap();
1158 let mut buf = Vec::new();
1159 params.pcs.serialize_uncompressed(&mut buf).unwrap();
1160 file.write_all(&buf).unwrap();
1161 }
1162 }
1163
1164 pub struct TestVector<S: RingSuite> {
1165 pub pedersen: pedersen::testing::TestVector<S>,
1166 pub ring_pks: [AffinePoint<S>; TEST_RING_SIZE],
1167 pub ring_pks_com: RingCommitment<S>,
1168 pub ring_proof: RingBareProof<S>,
1169 }
1170
1171 impl<S: RingSuite> core::fmt::Debug for TestVector<S> {
1172 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1173 f.debug_struct("TestVector")
1174 .field("pedersen", &self.pedersen)
1175 .field("ring_proof", &"...")
1176 .finish()
1177 }
1178 }
1179
1180 impl<S> common::TestVectorTrait for TestVector<S>
1181 where
1182 S: RingSuiteExt + std::fmt::Debug + 'static,
1183 {
1184 fn name() -> String {
1185 S::SUITE_NAME.to_string() + "_ring"
1186 }
1187
1188 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
1189 use super::Prover;
1190 let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, ad);
1191
1192 let secret = Secret::<S>::from_scalar(pedersen.base.sk);
1193 let public = secret.public();
1194
1195 let io = VrfIo {
1196 input: Input::<S>::from_affine_unchecked(pedersen.base.h),
1197 output: Output::from_affine_unchecked(pedersen.base.gamma),
1198 };
1199
1200 let params = <S as RingSuiteExt>::params();
1201
1202 use ark_std::rand::SeedableRng;
1203 let rng = &mut ark_std::rand::rngs::StdRng::from_seed([42; 32]);
1204 let prover_idx = 3;
1205 let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1206 ring_pks[prover_idx] = public.0;
1207
1208 let prover_key = params.prover_key(&ring_pks).unwrap();
1209 let prover = params.prover(prover_key, prover_idx);
1210 let proof = secret.prove(io, ad, &prover);
1211
1212 let verifier_key = params.verifier_key(&ring_pks).unwrap();
1213 let ring_pks_com = verifier_key.commitment();
1214
1215 {
1216 let mut p = (Vec::new(), Vec::new());
1218 pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1219 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1220 assert_eq!(p.0, p.1);
1221 }
1222
1223 Self {
1224 pedersen,
1225 ring_pks: ring_pks.try_into().unwrap(),
1226 ring_pks_com,
1227 ring_proof: proof.ring_proof,
1228 }
1229 }
1230
1231 fn from_map(map: &common::TestVectorMap) -> Self {
1232 let pedersen = pedersen::testing::TestVector::from_map(map);
1233
1234 let ring_pks = map.get::<[AffinePoint<S>; TEST_RING_SIZE]>("ring_pks");
1235 let ring_pks_com = map.get::<RingCommitment<S>>("ring_pks_com");
1236 let ring_proof = map.get::<RingBareProof<S>>("ring_proof");
1237
1238 Self {
1239 pedersen,
1240 ring_pks,
1241 ring_pks_com,
1242 ring_proof,
1243 }
1244 }
1245
1246 fn to_map(&self) -> common::TestVectorMap {
1247 let mut map = self.pedersen.to_map();
1248 map.set("ring_pks", &self.ring_pks);
1249 map.set("ring_pks_com", &self.ring_pks_com);
1250 map.set("ring_proof", &self.ring_proof);
1251 map
1252 }
1253
1254 fn run(&self) {
1255 self.pedersen.run();
1256
1257 let io = VrfIo {
1258 input: Input::<S>::from_affine_unchecked(self.pedersen.base.h),
1259 output: Output::from_affine_unchecked(self.pedersen.base.gamma),
1260 };
1261 let secret = Secret::from_scalar(self.pedersen.base.sk);
1262 let public = secret.public();
1263 assert_eq!(public.0, self.pedersen.base.pk);
1264
1265 let params = <S as RingSuiteExt>::params();
1266
1267 let prover_idx = self.ring_pks.iter().position(|&pk| pk == public.0).unwrap();
1268
1269 let prover_key = params.prover_key(&self.ring_pks).unwrap();
1270 let prover = params.prover(prover_key, prover_idx);
1271
1272 let verifier_key = params.verifier_key(&self.ring_pks).unwrap();
1273 let verifier = params.verifier(verifier_key);
1274
1275 let proof = secret.prove(io, &self.pedersen.base.ad, &prover);
1276
1277 {
1278 let mut p = (Vec::new(), Vec::new());
1280 self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1281 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1282 assert_eq!(p.0, p.1);
1283 }
1284
1285 #[cfg(feature = "test-vectors")]
1286 {
1287 let mut p = (Vec::new(), Vec::new());
1290 self.ring_proof.serialize_compressed(&mut p.0).unwrap();
1291 proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
1292 assert_eq!(p.0, p.1);
1293 }
1294
1295 assert!(Public::verify(io, &self.pedersen.base.ad, &proof, &verifier).is_ok());
1296 }
1297 }
1298}