1use crate::*;
56use ark_ec::{
57 pairing::Pairing,
58 twisted_edwards::{Affine as TEAffine, TECurveConfig},
59};
60use ark_std::ops::Range;
61use pedersen::{PedersenSuite, Proof as PedersenProof};
62use utils::te_sw_map::TEMapping;
63use w3f_ring_proof as ring_proof;
64
65pub const ACCUMULATOR_BASE_SEED: &[u8] = b"ring-accumulator";
67
68pub const PADDING_SEED: &[u8] = b"ring-padding";
70
71pub trait RingSuite:
76 PedersenSuite<
77 Affine: AffineRepr<BaseField: ark_ff::PrimeField, Config: TECurveConfig + Clone>
78 + TEMapping<<Self::Affine as AffineRepr>::Config>,
79>
80{
81 type Pairing: ark_ec::pairing::Pairing<ScalarField = BaseField<Self>>;
83
84 const ACCUMULATOR_BASE: AffinePoint<Self>;
89
90 const PADDING: AffinePoint<Self>;
92}
93
94pub type Kzg<S> = ring_proof::pcs::kzg::KZG<<S as RingSuite>::Pairing>;
96
97pub type PcsCommitment<S> =
99 ring_proof::pcs::kzg::commitment::KzgCommitment<<S as RingSuite>::Pairing>;
100
101pub type PcsParams<S> = ring_proof::pcs::kzg::urs::URS<<S as RingSuite>::Pairing>;
105
106pub type PcsVerifierParams<S> = <PcsParams<S> as ring_proof::pcs::PcsParams>::RVK;
113
114pub type PiopParams<S> = ring_proof::PiopParams<BaseField<S>, CurveConfig<S>>;
119
120pub type RingCommitment<S> = ring_proof::FixedColumnsCommitted<BaseField<S>, PcsCommitment<S>>;
122
123pub type RingProverKey<S> = ring_proof::ProverKey<BaseField<S>, Kzg<S>, TEAffine<CurveConfig<S>>>;
125
126pub type RingVerifierKey<S> = ring_proof::VerifierKey<BaseField<S>, Kzg<S>>;
128
129pub type RingProver<S> = ring_proof::ring_prover::RingProver<BaseField<S>, Kzg<S>, CurveConfig<S>>;
131
132pub type RingVerifier<S> =
134 ring_proof::ring_verifier::RingVerifier<BaseField<S>, Kzg<S>, CurveConfig<S>>;
135
136pub type RingBatchVerifier<S> = ring_proof::multi_ring_batch_verifier::BatchVerifier<
141 <S as RingSuite>::Pairing,
142 ring_proof::ArkTranscript,
143>;
144
145pub type RingBareProof<S> = ring_proof::RingProof<BaseField<S>, Kzg<S>>;
150
151#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
160pub struct Proof<S: RingSuite> {
161 pub pedersen_proof: PedersenProof<S>,
163 pub ring_proof: RingBareProof<S>,
165}
166
167pub trait Prover<S: RingSuite> {
169 fn prove(
173 &self,
174 ios: impl AsRef<[VrfIo<S>]>,
175 ad: impl AsRef<[u8]>,
176 prover: &RingProver<S>,
177 ) -> Proof<S>;
178}
179
180pub trait Verifier<S: RingSuite> {
197 fn verify(
203 ios: impl AsRef<[VrfIo<S>]>,
204 ad: impl AsRef<[u8]>,
205 sig: &Proof<S>,
206 verifier: &RingVerifier<S>,
207 ) -> Result<(), Error>;
208}
209
210impl<S: RingSuite> Prover<S> for Secret<S> {
211 fn prove(
212 &self,
213 ios: impl AsRef<[VrfIo<S>]>,
214 ad: impl AsRef<[u8]>,
215 ring_prover: &RingProver<S>,
216 ) -> Proof<S> {
217 use pedersen::Prover as PedersenProver;
218 let (pedersen_proof, secret_blinding) = <Self as PedersenProver<S>>::prove(self, ios, ad);
219 let ring_proof = ring_prover.prove(secret_blinding);
220 Proof {
221 pedersen_proof,
222 ring_proof,
223 }
224 }
225}
226
227impl<S: RingSuite> Verifier<S> for Public<S> {
228 fn verify(
229 ios: impl AsRef<[VrfIo<S>]>,
230 ad: impl AsRef<[u8]>,
231 proof: &Proof<S>,
232 verifier: &RingVerifier<S>,
233 ) -> Result<(), Error> {
234 use pedersen::Verifier as PedersenVerifier;
235 <Self as PedersenVerifier<S>>::verify(ios, ad, &proof.pedersen_proof)?;
236 let key_commitment = proof
237 .pedersen_proof
238 .key_commitment()
239 .into_te()
240 .ok_or(Error::InvalidData)?;
241 if !verifier.verify(proof.ring_proof.clone(), key_commitment) {
242 return Err(Error::VerificationFailure);
243 }
244 Ok(())
245 }
246}
247
248#[derive(Clone)]
256pub struct RingContext<S: RingSuite> {
257 pub piop_params: PiopParams<S>,
259}
260
261impl<S: RingSuite> RingContext<S> {
262 pub fn new(ring_size: usize) -> Self {
264 let domain_size = piop_domain_size::<S>(ring_size);
265 let piop_params = PiopParams::<S>::setup(
266 ring_proof::Domain::new(domain_size, true),
267 S::BLINDING_BASE
268 .into_te()
269 .expect("BLINDING_BASE must not be identity"),
270 S::ACCUMULATOR_BASE
271 .into_te()
272 .expect("ACCUMULATOR_BASE must not be identity"),
273 S::PADDING.into_te().expect("PADDING must not be identity"),
274 );
275 Self { piop_params }
276 }
277
278 #[inline(always)]
280 pub fn max_ring_size(&self) -> usize {
281 self.piop_params.keyset_part_size
282 }
283
284 pub fn ring_prover(&self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
286 self.clone().into_ring_prover(prover_key, key_index)
287 }
288
289 pub fn ring_verifier(&self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
291 self.clone().into_ring_verifier(verifier_key)
292 }
293
294 pub fn into_ring_prover(self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
296 RingProver::<S>::init(
297 prover_key,
298 self.piop_params,
299 key_index,
300 ring_proof::ArkTranscript::new(S::SUITE_ID),
301 )
302 }
303
304 pub fn into_ring_verifier(self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
306 RingVerifier::<S>::init(
307 verifier_key,
308 self.piop_params,
309 ring_proof::ArkTranscript::new(S::SUITE_ID),
310 )
311 }
312}
313
314#[derive(Clone)]
321pub struct RingSetup<S: RingSuite> {
322 pub pcs_params: PcsParams<S>,
324 pub ring_ctx: RingContext<S>,
326}
327
328impl<S: RingSuite> core::ops::Deref for RingSetup<S> {
329 type Target = RingContext<S>;
330
331 fn deref(&self) -> &Self::Target {
332 &self.ring_ctx
333 }
334}
335
336impl<S: RingSuite> RingSetup<S> {
337 pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self {
341 let mut t = S::Transcript::new(S::SUITE_ID);
342 t.absorb_raw(&seed);
343 let mut rng = t.to_rng();
344 Self::from_rand(ring_size, &mut rng)
345 }
346
347 pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self {
351 use ring_proof::pcs::PCS;
352 let max_degree = pcs_domain_size::<S>(ring_size) - 1;
353 let pcs_params = Kzg::<S>::setup(max_degree, rng);
354 Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct")
355 }
356
357 pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams<S>) -> Result<Self, Error> {
362 let pcs_domain_size = pcs_domain_size::<S>(ring_size);
363 if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 {
364 return Err(Error::InvalidData);
365 }
366 pcs_params.powers_in_g1.truncate(pcs_domain_size);
368 pcs_params.powers_in_g2.truncate(2);
369
370 Ok(Self {
371 pcs_params,
372 ring_ctx: RingContext::new(ring_size),
373 })
374 }
375
376 pub fn prover_key(&self, pks: &[AffinePoint<S>]) -> Result<RingProverKey<S>, Error> {
380 if pks.len() > self.piop_params.keyset_part_size {
381 return Err(Error::InvalidData);
382 }
383 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
384 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).0)
385 }
386
387 pub fn verifier_key(&self, pks: &[AffinePoint<S>]) -> Result<RingVerifierKey<S>, Error> {
391 if pks.len() > self.piop_params.keyset_part_size {
392 return Err(Error::InvalidData);
393 }
394 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
395 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).1)
396 }
397
398 pub fn verifier_key_from_commitment(
403 &self,
404 commitment: RingCommitment<S>,
405 ) -> RingVerifierKey<S> {
406 verifier_key_from_commitment::<S>(commitment, self.pcs_verifier_params())
407 }
408
409 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
415 use ring_proof::pcs::PcsParams;
416 self.pcs_params.raw_vk()
417 }
418
419 pub fn verifier_key_builder(&self) -> (VerifierKeyBuilder<S>, RingBuilderPcsParams<S>) {
421 type RingBuilderKey<S> =
422 ring_proof::ring::RingBuilderKey<BaseField<S>, <S as RingSuite>::Pairing>;
423 let piop_domain_size = piop_domain_size::<S>(self.piop_params.keyset_part_size);
424 let builder_key = RingBuilderKey::<S>::from_srs(&self.pcs_params, piop_domain_size);
425 let builder_pcs_params = RingBuilderPcsParams(builder_key.lis_in_g1);
426 let builder = VerifierKeyBuilder::new(self, &builder_pcs_params);
427 (builder, builder_pcs_params)
428 }
429
430 pub fn ring_context(&self) -> &RingContext<S> {
432 &self.ring_ctx
433 }
434
435 #[inline(always)]
440 pub const fn padding_point() -> AffinePoint<S> {
441 S::PADDING
442 }
443}
444
445pub fn verifier_key_from_commitment<S: RingSuite>(
457 commitment: RingCommitment<S>,
458 pcs_params: PcsVerifierParams<S>,
459) -> RingVerifierKey<S> {
460 RingVerifierKey::<S>::from_commitment_and_kzg_vk(commitment, pcs_params)
461}
462
463impl<S: RingSuite> CanonicalSerialize for RingSetup<S> {
464 fn serialize_with_mode<W: ark_serialize::Write>(
465 &self,
466 mut writer: W,
467 compress: ark_serialize::Compress,
468 ) -> Result<(), ark_serialize::SerializationError> {
469 self.pcs_params.serialize_with_mode(&mut writer, compress)
470 }
471
472 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
473 self.pcs_params.serialized_size(compress)
474 }
475}
476
477impl<S: RingSuite> CanonicalDeserialize for RingSetup<S> {
478 fn deserialize_with_mode<R: ark_serialize::Read>(
479 mut reader: R,
480 compress: ark_serialize::Compress,
481 validate: ark_serialize::Validate,
482 ) -> Result<Self, ark_serialize::SerializationError> {
483 let pcs_params = <PcsParams<S> as CanonicalDeserialize>::deserialize_with_mode(
484 &mut reader,
485 compress,
486 validate,
487 )?;
488 let ring_size = max_ring_size_from_pcs_domain_size::<S>(pcs_params.powers_in_g1.len());
489 Ok(Self {
490 pcs_params,
491 ring_ctx: RingContext::new(ring_size),
492 })
493 }
494}
495
496impl<S: RingSuite> ark_serialize::Valid for RingSetup<S> {
497 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
498 self.pcs_params.check()
499 }
500}
501
502#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
507pub struct RingBuilderPcsParams<S: RingSuite>(pub Vec<G1Affine<S>>);
508
509type PartialRingCommitment<S> =
511 ring_proof::ring::Ring<BaseField<S>, <S as RingSuite>::Pairing, CurveConfig<S>>;
512
513#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
518pub struct VerifierKeyBuilder<S: RingSuite> {
519 partial: PartialRingCommitment<S>,
520 pcs_params: PcsVerifierParams<S>,
521}
522
523pub type G1Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G1Affine;
525pub type G2Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G2Affine;
527
528pub trait SrsLookup<S: RingSuite> {
532 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>>;
534}
535
536impl<S: RingSuite, F> SrsLookup<S> for F
537where
538 F: Fn(Range<usize>) -> Option<Vec<G1Affine<S>>>,
539{
540 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
541 self(range)
542 }
543}
544
545impl<S: RingSuite> SrsLookup<S> for &RingBuilderPcsParams<S> {
546 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
547 if range.end > self.0.len() {
548 return None;
549 }
550 Some(self.0[range].to_vec())
551 }
552}
553
554impl<S: RingSuite> VerifierKeyBuilder<S> {
555 pub fn new(ring_setup: &RingSetup<S>, lookup: impl SrsLookup<S>) -> Self {
557 let lookup = |range: Range<usize>| lookup.lookup(range).ok_or(());
558 let pcs_params = ring_setup.pcs_verifier_params();
559 let partial = PartialRingCommitment::<S>::empty(
560 &ring_setup.piop_params,
561 lookup,
562 pcs_params.g1.into_group(),
563 );
564 VerifierKeyBuilder {
565 partial,
566 pcs_params,
567 }
568 }
569
570 #[inline(always)]
572 pub fn free_slots(&self) -> usize {
573 self.partial.max_keys - self.partial.curr_keys
574 }
575
576 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
581 self.pcs_params.clone()
582 }
583
584 pub fn append(
589 &mut self,
590 pks: &[AffinePoint<S>],
591 lookup: impl SrsLookup<S>,
592 ) -> Result<(), usize> {
593 let avail_slots = self.free_slots();
594 if avail_slots < pks.len() {
595 return Err(avail_slots);
596 }
597 let segment = lookup
600 .lookup(self.partial.curr_keys..self.partial.curr_keys + pks.len())
601 .ok_or(usize::MAX)?;
602 let lookup = |range: Range<usize>| {
603 debug_assert_eq!(segment.len(), range.len());
604 Ok(segment.clone())
605 };
606 let pks = TEMapping::to_te_slice(pks).ok_or(usize::MAX)?;
607 self.partial.append(&pks, lookup);
608 Ok(())
609 }
610
611 pub fn finalize(self) -> RingVerifierKey<S> {
613 RingVerifierKey::<S>::from_ring_and_kzg_vk(&self.partial, self.pcs_params)
614 }
615}
616
617type RingProofBatchItem<S> =
618 ring_proof::multi_ring_batch_verifier::BatchItem<<S as RingSuite>::Pairing, CurveConfig<S>>;
619
620pub struct BatchItem<S: RingSuite> {
622 ring: RingProofBatchItem<S>,
623 pedersen: pedersen::BatchItem<S>,
624}
625
626impl<S: RingSuite> BatchItem<S> {
627 pub fn new(
636 verifier: &RingVerifier<S>,
637 ios: impl AsRef<[VrfIo<S>]>,
638 ad: impl AsRef<[u8]>,
639 proof: &Proof<S>,
640 ) -> Result<Self, Error> {
641 let key_commitment = proof
642 .pedersen_proof
643 .key_commitment()
644 .into_te()
645 .ok_or(Error::InvalidData)?;
646 let pedersen = pedersen::BatchItem::new(ios, ad, &proof.pedersen_proof);
647 let ring = RingProofBatchItem::<S>::new(verifier, proof.ring_proof.clone(), key_commitment);
648 Ok(Self { ring, pedersen })
649 }
650}
651
652pub struct BatchVerifier<S: RingSuite> {
661 ring_batch: RingBatchVerifier<S>,
662 pedersen_batch: pedersen::BatchVerifier<S>,
663}
664
665impl<S: RingSuite> BatchVerifier<S> {
666 pub fn new(ring_verifier: &RingVerifier<S>) -> Self {
672 Self {
673 ring_batch: RingBatchVerifier::<S>::new(
674 ring_verifier.pcs_vk().clone(),
675 ring_proof::ArkTranscript::new(S::SUITE_ID),
676 ),
677 pedersen_batch: pedersen::BatchVerifier::new(),
678 }
679 }
680
681 pub fn push_prepared(&mut self, item: BatchItem<S>) {
683 self.pedersen_batch.push_prepared(item.pedersen);
684 self.ring_batch.push_prepared(item.ring);
685 }
686
687 pub fn push(
692 &mut self,
693 verifier: &RingVerifier<S>,
694 ios: impl AsRef<[VrfIo<S>]>,
695 ad: impl AsRef<[u8]>,
696 proof: &Proof<S>,
697 ) -> Result<(), Error> {
698 let item = BatchItem::new(verifier, ios, ad, proof)?;
699 self.push_prepared(item);
700 Ok(())
701 }
702
703 pub fn verify(&self) -> Result<(), Error> {
708 self.pedersen_batch.verify()?;
709 self.ring_batch
710 .verify()
711 .then_some(())
712 .ok_or(Error::VerificationFailure)
713 }
714}
715
716#[macro_export]
718macro_rules! ring_suite_types {
719 ($suite:ident) => {
720 #[allow(dead_code)]
721 pub type PcsParams = $crate::ring::PcsParams<$suite>;
722 #[allow(dead_code)]
723 pub type PcsVerifierParams = $crate::ring::PcsVerifierParams<$suite>;
724 #[allow(dead_code)]
725 pub type PiopParams = $crate::ring::PiopParams<$suite>;
726 #[allow(dead_code)]
727 pub type RingContext = $crate::ring::RingContext<$suite>;
728 #[allow(dead_code)]
729 pub type RingSetup = $crate::ring::RingSetup<$suite>;
730 #[allow(dead_code)]
731 pub type RingProverKey = $crate::ring::RingProverKey<$suite>;
732 #[allow(dead_code)]
733 pub type RingVerifierKey = $crate::ring::RingVerifierKey<$suite>;
734 #[allow(dead_code)]
735 pub type RingCommitment = $crate::ring::RingCommitment<$suite>;
736 #[allow(dead_code)]
737 pub type RingProver = $crate::ring::RingProver<$suite>;
738 #[allow(dead_code)]
739 pub type RingVerifier = $crate::ring::RingVerifier<$suite>;
740 #[allow(dead_code)]
741 pub type RingProof = $crate::ring::Proof<$suite>;
742 #[allow(dead_code)]
743 pub type RingVerifierKeyBuilder = $crate::ring::VerifierKeyBuilder<$suite>;
744 #[allow(dead_code)]
745 pub type RingBatchItem = $crate::ring::BatchItem<$suite>;
746 #[allow(dead_code)]
747 pub type RingBatchVerifier = $crate::ring::BatchVerifier<$suite>;
748 };
749}
750
751pub mod dom_utils {
774 use super::*;
775
776 pub const fn max_ring_size<S: Suite>(min_ring_size: usize) -> usize {
784 max_ring_size_from_piop_domain_size::<S>(piop_domain_size::<S>(min_ring_size))
785 }
786
787 pub const fn piop_overhead<S: Suite>() -> usize {
789 4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize
790 }
791
792 pub const fn piop_domain_size<S: Suite>(min_ring_capacity: usize) -> usize {
798 (min_ring_capacity + piop_overhead::<S>()).next_power_of_two()
799 }
800
801 pub const fn max_ring_size_from_piop_domain_size<S: Suite>(piop_domain_size: usize) -> usize {
805 piop_domain_size - piop_overhead::<S>()
806 }
807
808 pub const fn pcs_domain_size<S: Suite>(min_ring_size: usize) -> usize {
813 pcs_domain_size_from_piop_domain_size(piop_domain_size::<S>(min_ring_size))
814 }
815
816 pub const fn pcs_domain_size_from_piop_domain_size(piop_domain_size: usize) -> usize {
820 3 * piop_domain_size + 1
821 }
822
823 pub const fn piop_domain_size_from_pcs_domain_size(pcs_domain_size: usize) -> usize {
828 1 << ((pcs_domain_size - 1) / 3).ilog2()
829 }
830
831 pub const fn max_ring_size_from_pcs_domain_size<S: Suite>(pcs_domain_size: usize) -> usize {
835 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_domain_size);
836 max_ring_size_from_piop_domain_size::<S>(piop_domain_size)
837 }
838}
839pub use dom_utils::*;
840
841#[cfg(test)]
842pub(crate) mod testing {
843 use super::*;
844 use crate::pedersen;
845 use crate::testing::{self as common, CheckPoint, TEST_SEED};
846 use ark_ec::{
847 short_weierstrass::{Affine as SWAffine, SWCurveConfig},
848 twisted_edwards::{Affine as TEAffine, TECurveConfig},
849 };
850
851 pub const TEST_RING_SIZE: usize = 8;
852
853 const MAX_AD_LEN: usize = 100;
854
855 fn find_complement_point<C: SWCurveConfig>() -> SWAffine<C> {
856 use ark_ff::{One, Zero};
857 assert!(!C::cofactor_is_one());
858 let mut x = C::BaseField::zero();
859 loop {
860 if let Some(p) = SWAffine::get_point_from_x_unchecked(x, false)
861 .filter(|p| !p.is_in_correct_subgroup_assuming_on_curve())
862 {
863 return p;
864 }
865 x += C::BaseField::one();
866 }
867 }
868
869 pub trait FindAccumulatorBase<S: Suite>: Sized {
870 const IN_PRIME_ORDER_SUBGROUP: bool;
871 fn find_accumulator_base(data: &[u8]) -> Option<Self>;
872 }
873
874 impl<S, C> FindAccumulatorBase<S> for SWAffine<C>
875 where
876 C: SWCurveConfig,
877 S: Suite<Affine = Self>,
878 {
879 const IN_PRIME_ORDER_SUBGROUP: bool = false;
880
881 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
882 let p = S::data_to_point(data)?;
883 let c = find_complement_point();
884 let res = (p + c).into_affine();
885 debug_assert!(!res.is_in_correct_subgroup_assuming_on_curve());
886 Some(res)
887 }
888 }
889
890 impl<S, C> FindAccumulatorBase<S> for TEAffine<C>
891 where
892 C: TECurveConfig,
893 S: Suite<Affine = Self>,
894 {
895 const IN_PRIME_ORDER_SUBGROUP: bool = true;
896
897 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
898 let res = S::data_to_point(data)?;
899 debug_assert!(res.is_in_correct_subgroup_assuming_on_curve());
900 Some(res)
901 }
902 }
903
904 struct TestItem<S: RingSuite> {
905 io: VrfIo<S>,
906 ad: Vec<u8>,
907 proof: Proof<S>,
908 }
909
910 impl<S: RingSuite> TestItem<S> {
911 fn new(
912 secret: &Secret<S>,
913 prover: &RingProver<S>,
914 rng: &mut dyn ark_std::rand::RngCore,
915 ) -> Self {
916 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
917 let io = secret.vrf_io(input);
918 let ad_len = common::random_val::<usize>(Some(rng)) % (MAX_AD_LEN + 1);
919 let ad = common::random_vec(ad_len, Some(rng));
920 let proof = secret.prove(io, &ad, prover);
921 Self { io, ad, proof }
922 }
923 }
924
925 #[allow(unused)]
926 pub fn prove_verify<S: RingSuite>() {
927 let rng = &mut ark_std::test_rng();
928 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
929
930 let secret = Secret::<S>::from_seed(TEST_SEED);
931 let public = secret.public();
932
933 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
934 let prover_idx = 3;
935 pks[prover_idx] = public.0;
936
937 let ring_ctx = ring_setup.ring_context();
938 let prover_key = ring_setup.prover_key(&pks).unwrap();
939 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
940
941 let item = TestItem::<S>::new(&secret, &prover, rng);
942
943 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
944 let verifier = ring_ctx.ring_verifier(verifier_key);
945 let result = Public::verify(item.io, &item.ad, &item.proof, &verifier);
946 assert!(result.is_ok());
947 }
948
949 #[allow(unused)]
951 pub fn prove_verify_multi<S: RingSuite>() {
952 use ring::{Prover, Verifier};
953
954 let rng = &mut ark_std::test_rng();
955 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
956
957 let secret = Secret::<S>::from_seed(TEST_SEED);
958 let public = secret.public();
959
960 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
961 let prover_idx = 3;
962 pks[prover_idx] = public.0;
963
964 let ring_ctx = ring_setup.ring_context();
965 let prover_key = ring_setup.prover_key(&pks).unwrap();
966 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
967
968 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
969 let verifier = ring_ctx.ring_verifier(verifier_key);
970
971 let mut ios: Vec<VrfIo<S>> = (0..3u8)
972 .map(|i| {
973 let input = Input::new(&[i + 1]).unwrap();
974 secret.vrf_io(input)
975 })
976 .collect();
977 ios.push(VrfIo {
978 input: Input(S::Affine::generator()),
979 output: Output(public.0),
980 });
981
982 let proof = secret.prove(&ios[..], b"bar", &prover);
983 assert!(Public::verify(&ios[..], b"bar", &proof, &verifier).is_ok());
984
985 let mut bad_ios = ios.clone();
987 bad_ios[1].output = secret.output(ios[0].input);
988 assert!(Public::verify(&bad_ios[..], b"bar", &proof, &verifier).is_err());
989
990 assert!(Public::verify(&ios[..], b"baz", &proof, &verifier).is_err());
992 }
993
994 #[allow(unused)]
995 pub fn prove_verify_batch<S: RingSuite>() {
996 use rayon::prelude::*;
997
998 const BATCH_SIZE: usize = 3 * TEST_RING_SIZE;
999
1000 let rng = &mut ark_std::test_rng();
1001 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1002
1003 let secret = Secret::<S>::from_seed(TEST_SEED);
1004 let public = secret.public();
1005
1006 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1007 let prover_idx = 3;
1008 pks[prover_idx] = public.0;
1009
1010 let ring_ctx = ring_setup.ring_context();
1011 let prover_key = ring_setup.prover_key(&pks).unwrap();
1012 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1013
1014 let batch: Vec<_> = (0..BATCH_SIZE)
1016 .into_par_iter()
1017 .map_init(ark_std::test_rng, |rng, _| {
1018 TestItem::<S>::new(&secret, &prover, rng)
1019 })
1020 .collect();
1021
1022 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
1023 let verifier = ring_ctx.ring_verifier(verifier_key);
1024
1025 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1027 let res = batch_verifier.verify();
1028 assert!(res.is_ok());
1029
1030 for item in batch.iter() {
1032 batch_verifier
1033 .push(&verifier, item.io, &item.ad, &item.proof)
1034 .unwrap();
1035 let res = batch_verifier.verify();
1036 assert!(res.is_ok());
1037 }
1038
1039 println!("Batch size = {BATCH_SIZE}");
1040
1041 println!("============================================================");
1042
1043 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1044 let start = std::time::Instant::now();
1045 common::timed("Proofs push", || {
1046 for item in batch.iter() {
1047 batch_verifier
1048 .push(&verifier, item.io, &item.ad, &item.proof)
1049 .unwrap();
1050 }
1051 });
1052 common::timed("Unprepared batch verification", || batch_verifier.verify());
1053 println!("Total time: {:?}", start.elapsed());
1054
1055 println!("============================================================");
1056
1057 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1058 let start = std::time::Instant::now();
1059 let prepared = common::timed("Proofs prepare", || {
1060 batch
1061 .par_iter()
1062 .map(|item| BatchItem::<S>::new(&verifier, item.io, &item.ad, &item.proof).unwrap())
1063 .collect::<Vec<_>>()
1064 });
1065 common::timed("Proofs push prepared", || {
1066 prepared
1067 .into_iter()
1068 .for_each(|p| batch_verifier.push_prepared(p))
1069 });
1070 common::timed("Prepared batch verification", || batch_verifier.verify());
1071 println!("Total time: {:?}", start.elapsed());
1072
1073 println!("============================================================");
1074
1075 let mut pks_b = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1078 let prover_idx_b = 1;
1079 pks_b[prover_idx_b] = public.0;
1080 let prover_key_b = ring_setup.prover_key(&pks_b).unwrap();
1081 let prover_b = ring_ctx.ring_prover(prover_key_b, prover_idx_b);
1082 let verifier_key_b = ring_setup.verifier_key(&pks_b).unwrap();
1083 let verifier_b = ring_ctx.ring_verifier(verifier_key_b);
1084
1085 let batch_b: Vec<_> = (0..TEST_RING_SIZE)
1086 .into_par_iter()
1087 .map_init(ark_std::test_rng, |rng, _| {
1088 TestItem::<S>::new(&secret, &prover_b, rng)
1089 })
1090 .collect();
1091
1092 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1093 for item in batch.iter() {
1094 batch_verifier
1095 .push(&verifier, item.io, &item.ad, &item.proof)
1096 .unwrap();
1097 }
1098 for item in batch_b.iter() {
1099 batch_verifier
1100 .push(&verifier_b, item.io, &item.ad, &item.proof)
1101 .unwrap();
1102 }
1103 common::timed("Multi-ring batch verification", || batch_verifier.verify())
1104 .expect("multi-ring batch verifies");
1105
1106 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1110 let item_b = &batch_b[0];
1111 batch_verifier
1112 .push(&verifier, item_b.io, &item_b.ad, &item_b.proof)
1113 .unwrap();
1114 assert!(
1115 batch_verifier.verify().is_err(),
1116 "ring-B proof must not verify against verifier_a"
1117 );
1118 }
1119
1120 #[allow(unused)]
1121 pub fn padding_check<S: RingSuite>()
1122 where
1123 AffinePoint<S>: CheckPoint,
1124 {
1125 assert_eq!(S::PADDING, S::data_to_point(PADDING_SEED).unwrap());
1127
1128 assert!(S::PADDING.check(true).is_ok());
1130 }
1131
1132 #[allow(unused)]
1133 pub fn accumulator_base_check<S: RingSuite>()
1134 where
1135 AffinePoint<S>: FindAccumulatorBase<S> + CheckPoint,
1136 {
1137 assert_eq!(
1139 S::ACCUMULATOR_BASE,
1140 AffinePoint::<S>::find_accumulator_base(ACCUMULATOR_BASE_SEED).unwrap()
1141 );
1142
1143 let in_prime_subgroup = <AffinePoint<S> as FindAccumulatorBase<S>>::IN_PRIME_ORDER_SUBGROUP;
1146 assert!(S::ACCUMULATOR_BASE.check(in_prime_subgroup).is_ok());
1147 }
1148
1149 #[allow(unused)]
1150 pub fn verifier_key_from_commitment<S: RingSuite>() {
1151 let rng = &mut ark_std::test_rng();
1152 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1153
1154 let secret = Secret::<S>::from_seed(TEST_SEED);
1155 let public = secret.public();
1156
1157 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1158 let prover_idx = 3;
1159 pks[prover_idx] = public.0;
1160
1161 let prover_key = ring_setup.prover_key(&pks).unwrap();
1162 let prover = ring_setup
1163 .ring_context()
1164 .ring_prover(prover_key, prover_idx);
1165 let item = TestItem::<S>::new(&secret, &prover, rng);
1166
1167 let commitment = ring_setup.verifier_key(&pks).unwrap().commitment();
1168
1169 let mut buf = Vec::new();
1172 ring_setup
1173 .pcs_verifier_params()
1174 .serialize_compressed(&mut buf)
1175 .unwrap();
1176 let pcs_params = PcsVerifierParams::<S>::deserialize_compressed(&buf[..]).unwrap();
1177
1178 let ring_ctx = RingContext::<S>::new(TEST_RING_SIZE);
1179 let verifier_key = super::verifier_key_from_commitment::<S>(commitment, pcs_params);
1180 let verifier = ring_ctx.ring_verifier(verifier_key);
1181 assert!(Public::verify(item.io, &item.ad, &item.proof, &verifier).is_ok());
1182 }
1183
1184 #[allow(unused)]
1185 pub fn verifier_key_builder<S: RingSuite>() {
1186 use crate::testing::{random_val, random_vec};
1187
1188 let rng = &mut ark_std::test_rng();
1189 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1190
1191 let secret = Secret::<S>::from_seed(TEST_SEED);
1192 let public = secret.public();
1193 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
1194 let io = secret.vrf_io(input);
1195
1196 let ring_ctx = ring_setup.ring_context();
1197 let ring_size = ring_ctx.max_ring_size();
1198 let prover_idx = random_val::<usize>(Some(rng)) % ring_size;
1199 let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
1200 pks[prover_idx] = public.0;
1201
1202 let prover_key = ring_setup.prover_key(&pks).unwrap();
1203 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1204 let proof = secret.prove(io, b"foo", &prover);
1205
1206 let (mut vk_builder, lookup) = ring_setup.verifier_key_builder();
1208 assert_eq!(vk_builder.free_slots(), pks.len());
1209 assert_eq!(
1210 vk_builder.pcs_verifier_params(),
1211 ring_setup.pcs_verifier_params()
1212 );
1213
1214 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1215 assert_eq!(
1216 vk_builder.append(&[extra_pk], |_| None).unwrap_err(),
1217 usize::MAX
1218 );
1219
1220 while !pks.is_empty() {
1221 let chunk_len = 1 + random_val::<usize>(Some(rng)) % 5;
1222 let chunk = pks.drain(..pks.len().min(chunk_len)).collect::<Vec<_>>();
1223 vk_builder.append(&chunk[..], &lookup).unwrap();
1224 assert_eq!(vk_builder.free_slots(), pks.len());
1225 }
1226 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1228 assert_eq!(vk_builder.append(&[extra_pk], &lookup).unwrap_err(), 0);
1229 let verifier_key = vk_builder.finalize();
1230 let verifier = ring_ctx.ring_verifier(verifier_key);
1231 let result = Public::verify(io, b"foo", &proof, &verifier);
1232 assert!(result.is_ok());
1233 }
1234
1235 pub fn domain_size_conversions<S: RingSuite>() {
1236 let overhead = piop_overhead::<S>();
1237
1238 for ring_size in [1, 10, 200, 300, 500, 1000, 2000, 10000] {
1239 let piop_dom_size = piop_domain_size::<S>(ring_size);
1240 let pcs_dom_size = pcs_domain_size::<S>(ring_size);
1241 let max_ring_size = max_ring_size_from_piop_domain_size::<S>(piop_dom_size);
1242
1243 assert!(piop_dom_size.is_power_of_two());
1244 assert_eq!(pcs_dom_size, 3 * piop_dom_size + 1);
1245
1246 assert!(piop_dom_size >= ring_size + overhead);
1248 assert!(piop_dom_size / 2 < ring_size + overhead);
1250 assert_eq!(piop_dom_size, piop_domain_size::<S>(max_ring_size));
1252 assert!(ring_size <= max_ring_size);
1254
1255 assert_eq!(dom_utils::max_ring_size::<S>(ring_size), max_ring_size);
1257 assert_eq!(dom_utils::max_ring_size::<S>(max_ring_size), max_ring_size);
1259
1260 let piop_dom_rt = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1262 assert_eq!(piop_dom_size, piop_dom_rt);
1263 let pcs_dom_rt = pcs_domain_size_from_piop_domain_size(piop_dom_rt);
1264 assert_eq!(pcs_dom_size, pcs_dom_rt);
1265
1266 let max_ring_from_pcs = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1267 assert_eq!(max_ring_size, max_ring_from_pcs);
1268
1269 let next_piop = piop_domain_size::<S>(max_ring_size + 1);
1271 assert!(next_piop > piop_dom_size,);
1272 assert!(next_piop.is_power_of_two());
1273 }
1274
1275 for pcs_dom_size in [1 << 11, 1 << 12, 1 << 14, 1 << 16] {
1278 let piop_dom = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1279 let max_ring = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1280
1281 assert!(piop_dom.is_power_of_two());
1282 assert!(3 * piop_dom < pcs_dom_size);
1284 assert!(3 * (2 * piop_dom) + 1 > pcs_dom_size);
1286 assert_eq!(piop_domain_size::<S>(max_ring), piop_dom);
1288 assert!(piop_domain_size::<S>(max_ring + 1) > piop_dom);
1290 }
1291
1292 let piop_zero = piop_domain_size::<S>(0);
1294 assert!(piop_zero.is_power_of_two());
1295 assert_eq!(piop_zero, overhead.next_power_of_two());
1296 }
1297
1298 #[macro_export]
1299 macro_rules! ring_suite_tests {
1300 ($suite:ty) => {
1301 mod ring {
1302 use super::*;
1303
1304 #[test]
1305 fn prove_verify() {
1306 $crate::ring::testing::prove_verify::<$suite>()
1307 }
1308
1309 #[test]
1310 fn prove_verify_multi() {
1311 $crate::ring::testing::prove_verify_multi::<$suite>()
1312 }
1313
1314 #[test]
1315 fn prove_verify_batch() {
1316 $crate::ring::testing::prove_verify_batch::<$suite>()
1317 }
1318
1319 #[test]
1320 fn padding_check() {
1321 $crate::ring::testing::padding_check::<$suite>()
1322 }
1323
1324 #[test]
1325 fn accumulator_base_check() {
1326 $crate::ring::testing::accumulator_base_check::<$suite>()
1327 }
1328
1329 #[test]
1330 fn verifier_key_builder() {
1331 $crate::ring::testing::verifier_key_builder::<$suite>()
1332 }
1333
1334 #[test]
1335 fn verifier_key_from_commitment() {
1336 $crate::ring::testing::verifier_key_from_commitment::<$suite>()
1337 }
1338
1339 #[test]
1340 fn domain_size_conversions() {
1341 $crate::ring::testing::domain_size_conversions::<$suite>()
1342 }
1343
1344 $crate::test_vectors!($crate::ring::testing::TestVector<$suite>);
1345 }
1346 };
1347 }
1348
1349 pub trait RingSuiteExt: RingSuite + crate::testing::SuiteExt {
1350 const SRS_FILE: &str;
1351
1352 fn ring_setup() -> &'static RingSetup<Self>;
1353
1354 #[allow(unused)]
1355 fn load_ring_setup() -> RingSetup<Self> {
1356 use ark_serialize::CanonicalDeserialize;
1357 use std::{fs::File, io::Read};
1358 let mut file = File::open(Self::SRS_FILE).unwrap();
1359 let mut buf = Vec::new();
1360 file.read_to_end(&mut buf).unwrap();
1361 let pcs_params =
1362 PcsParams::<Self>::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
1363 RingSetup::from_pcs_params(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
1364 }
1365
1366 #[allow(unused)]
1367 fn write_ring_setup(ring_setup: &RingSetup<Self>) {
1368 use ark_serialize::CanonicalSerialize;
1369 use std::{fs::File, io::Write};
1370 let mut file = File::create(Self::SRS_FILE).unwrap();
1371 let mut buf = Vec::new();
1372 ring_setup
1373 .pcs_params
1374 .serialize_uncompressed(&mut buf)
1375 .unwrap();
1376 file.write_all(&buf).unwrap();
1377 }
1378 }
1379
1380 pub struct TestVector<S: RingSuite> {
1381 pub pedersen: pedersen::testing::TestVector<S>,
1382 pub ring_pks: [AffinePoint<S>; TEST_RING_SIZE],
1383 pub ring_pks_com: RingCommitment<S>,
1384 pub ring_proof: RingBareProof<S>,
1385 }
1386
1387 impl<S: RingSuite> core::fmt::Debug for TestVector<S> {
1388 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1389 f.debug_struct("TestVector")
1390 .field("pedersen", &self.pedersen)
1391 .field("ring_proof", &"...")
1392 .finish()
1393 }
1394 }
1395
1396 impl<S> common::TestVectorTrait for TestVector<S>
1397 where
1398 S: RingSuiteExt + std::fmt::Debug + 'static,
1399 {
1400 fn name() -> String {
1401 S::SUITE_NAME.to_string() + "_ring"
1402 }
1403
1404 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
1405 use super::Prover;
1406 let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, ad);
1407
1408 let secret = Secret::<S>::from_scalar(pedersen.base.sk);
1409 let public = secret.public();
1410
1411 let io = VrfIo {
1412 input: Input::<S>::from_affine_unchecked(pedersen.base.h),
1413 output: Output::from_affine_unchecked(pedersen.base.gamma),
1414 };
1415
1416 let ring_setup = <S as RingSuiteExt>::ring_setup();
1417
1418 use ark_std::rand::SeedableRng;
1419 let rng = &mut ark_std::rand::rngs::StdRng::from_seed([42; 32]);
1420 let prover_idx = 3;
1421 let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1422 ring_pks[prover_idx] = public.0;
1423
1424 let ring_ctx = ring_setup.ring_context();
1425 let prover_key = ring_setup.prover_key(&ring_pks).unwrap();
1426 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1427 let proof = secret.prove(io, ad, &prover);
1428
1429 let verifier_key = ring_setup.verifier_key(&ring_pks).unwrap();
1430 let ring_pks_com = verifier_key.commitment();
1431
1432 {
1433 let mut p = (Vec::new(), Vec::new());
1435 pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1436 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1437 assert_eq!(p.0, p.1);
1438 }
1439
1440 Self {
1441 pedersen,
1442 ring_pks: ring_pks.try_into().unwrap(),
1443 ring_pks_com,
1444 ring_proof: proof.ring_proof,
1445 }
1446 }
1447
1448 fn from_map(map: &common::TestVectorMap) -> Self {
1449 let pedersen = pedersen::testing::TestVector::from_map(map);
1450
1451 let ring_pks = map.get::<[AffinePoint<S>; TEST_RING_SIZE]>("ring_pks");
1452 let ring_pks_com = map.get::<RingCommitment<S>>("ring_pks_com");
1453 let ring_proof = map.get::<RingBareProof<S>>("ring_proof");
1454
1455 Self {
1456 pedersen,
1457 ring_pks,
1458 ring_pks_com,
1459 ring_proof,
1460 }
1461 }
1462
1463 fn to_map(&self) -> common::TestVectorMap {
1464 let mut map = self.pedersen.to_map();
1465 map.set("ring_pks", &self.ring_pks);
1466 map.set("ring_pks_com", &self.ring_pks_com);
1467 map.set("ring_proof", &self.ring_proof);
1468 map
1469 }
1470
1471 fn run(&self) {
1472 self.pedersen.run();
1473
1474 let io = VrfIo {
1475 input: Input::<S>::from_affine_unchecked(self.pedersen.base.h),
1476 output: Output::from_affine_unchecked(self.pedersen.base.gamma),
1477 };
1478 let secret = Secret::from_scalar(self.pedersen.base.sk);
1479 let public = secret.public();
1480 assert_eq!(public.0, self.pedersen.base.pk);
1481
1482 let ring_setup = <S as RingSuiteExt>::ring_setup();
1483
1484 let prover_idx = self.ring_pks.iter().position(|&pk| pk == public.0).unwrap();
1485
1486 let ring_ctx = ring_setup.ring_context();
1487 let prover_key = ring_setup.prover_key(&self.ring_pks).unwrap();
1488 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1489
1490 let verifier_key = ring_setup.verifier_key(&self.ring_pks).unwrap();
1491 let verifier = ring_ctx.ring_verifier(verifier_key);
1492
1493 let proof = secret.prove(io, &self.pedersen.base.ad, &prover);
1494
1495 {
1496 let mut p = (Vec::new(), Vec::new());
1498 self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1499 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1500 assert_eq!(p.0, p.1);
1501 }
1502
1503 #[cfg(feature = "test-vectors")]
1504 {
1505 let mut p = (Vec::new(), Vec::new());
1508 self.ring_proof.serialize_compressed(&mut p.0).unwrap();
1509 proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
1510 assert_eq!(p.0, p.1);
1511 }
1512
1513 assert!(Public::verify(io, &self.pedersen.base.ad, &proof, &verifier).is_ok());
1514 }
1515 }
1516}