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> = <Kzg<S> as ring_proof::pcs::PCS<BaseField<S>>>::C;
99
100pub type PcsParams<S> = ring_proof::pcs::kzg::urs::URS<<S as RingSuite>::Pairing>;
104
105pub type PcsVerifierParams<S> = <PcsParams<S> as ring_proof::pcs::PcsParams>::RVK;
112
113pub type PiopParams<S> = ring_proof::PiopParams<TEAffine<CurveConfig<S>>>;
118
119pub type RingCommitment<S> = ring_proof::FixedColumnsCommitted<BaseField<S>, PcsCommitment<S>>;
121
122pub type RingProverKey<S> = ring_proof::ProverKey<BaseField<S>, Kzg<S>, TEAffine<CurveConfig<S>>>;
124
125pub type RingVerifierKey<S> = ring_proof::VerifierKey<BaseField<S>, Kzg<S>>;
127
128pub type RingProver<S> = ring_proof::ring_prover::RingProver<BaseField<S>, Kzg<S>, CurveConfig<S>>;
130
131pub type RingVerifier<S> =
133 ring_proof::ring_verifier::RingVerifier<BaseField<S>, Kzg<S>, CurveConfig<S>>;
134
135pub type RingBatchVerifier<S> = ring_proof::multi_ring_batch_verifier::BatchVerifier<
140 <S as RingSuite>::Pairing,
141 ring_proof::ArkTranscript,
142>;
143
144pub type RingBareProof<S> = ring_proof::RingProof<BaseField<S>, Kzg<S>>;
149
150#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
159pub struct Proof<S: RingSuite> {
160 pub pedersen_proof: PedersenProof<S>,
162 pub ring_proof: RingBareProof<S>,
164}
165
166pub trait Prover<S: RingSuite> {
168 fn prove(
172 &self,
173 ios: impl AsRef<[VrfIo<S>]>,
174 ad: impl AsRef<[u8]>,
175 prover: &RingProver<S>,
176 ) -> Proof<S>;
177}
178
179pub trait Verifier<S: RingSuite> {
196 fn verify(
202 ios: impl AsRef<[VrfIo<S>]>,
203 ad: impl AsRef<[u8]>,
204 sig: &Proof<S>,
205 verifier: &RingVerifier<S>,
206 ) -> Result<(), Error>;
207}
208
209impl<S: RingSuite> Prover<S> for Secret<S> {
210 fn prove(
211 &self,
212 ios: impl AsRef<[VrfIo<S>]>,
213 ad: impl AsRef<[u8]>,
214 ring_prover: &RingProver<S>,
215 ) -> Proof<S> {
216 use pedersen::Prover as PedersenProver;
217 let (pedersen_proof, secret_blinding) = <Self as PedersenProver<S>>::prove(self, ios, ad);
218 let ring_proof = ring_prover.prove(secret_blinding);
219 Proof {
220 pedersen_proof,
221 ring_proof,
222 }
223 }
224}
225
226impl<S: RingSuite> Verifier<S> for Public<S> {
227 fn verify(
228 ios: impl AsRef<[VrfIo<S>]>,
229 ad: impl AsRef<[u8]>,
230 proof: &Proof<S>,
231 verifier: &RingVerifier<S>,
232 ) -> Result<(), Error> {
233 use pedersen::Verifier as PedersenVerifier;
234 <Self as PedersenVerifier<S>>::verify(ios, ad, &proof.pedersen_proof)?;
235 let key_commitment = proof
236 .pedersen_proof
237 .key_commitment()
238 .into_te()
239 .ok_or(Error::InvalidData)?;
240 if !verifier.verify(proof.ring_proof.clone(), key_commitment) {
241 return Err(Error::VerificationFailure);
242 }
243 Ok(())
244 }
245}
246
247#[derive(Clone)]
255pub struct RingContext<S: RingSuite> {
256 pub piop_params: PiopParams<S>,
258}
259
260impl<S: RingSuite> RingContext<S> {
261 pub fn new(ring_size: usize) -> Self {
263 Self::construct(ring_size, true)
264 }
265
266 pub fn new_without_blinding(ring_size: usize) -> Self {
272 Self::construct(ring_size, false)
273 }
274
275 fn construct(ring_size: usize, blinding: bool) -> Self {
276 let domain_size = piop_domain_size::<S>(ring_size);
277 let mut domain =
278 ring_proof::Domain::with_zk_rows(domain_size, ring_proof::piop::params::ZK_ROWS);
279 if !blinding {
280 domain = domain.without_blinding();
281 }
282 let piop_params = PiopParams::<S>::setup(
283 domain,
284 S::BLINDING_BASE
285 .into_te()
286 .expect("BLINDING_BASE must not be identity"),
287 S::ACCUMULATOR_BASE
288 .into_te()
289 .expect("ACCUMULATOR_BASE must not be identity"),
290 S::PADDING.into_te().expect("PADDING must not be identity"),
291 );
292 Self { piop_params }
293 }
294
295 #[inline(always)]
297 pub fn max_ring_size(&self) -> usize {
298 self.piop_params.keyset_part_size
299 }
300
301 pub fn ring_prover(&self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
303 self.clone().into_ring_prover(prover_key, key_index)
304 }
305
306 pub fn ring_verifier(&self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
308 self.clone().into_ring_verifier(verifier_key)
309 }
310
311 pub fn into_ring_prover(self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
313 RingProver::<S>::init(
314 prover_key,
315 self.piop_params,
316 key_index,
317 ring_proof::ArkTranscript::new(S::SUITE_ID),
318 )
319 }
320
321 pub fn into_ring_verifier(self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
323 RingVerifier::<S>::init(
324 verifier_key,
325 self.piop_params,
326 ring_proof::ArkTranscript::new(S::SUITE_ID),
327 )
328 }
329}
330
331#[derive(Clone)]
338pub struct RingSetup<S: RingSuite> {
339 pub pcs_params: PcsParams<S>,
341 pub ring_ctx: RingContext<S>,
343}
344
345impl<S: RingSuite> core::ops::Deref for RingSetup<S> {
346 type Target = RingContext<S>;
347
348 fn deref(&self) -> &Self::Target {
349 &self.ring_ctx
350 }
351}
352
353impl<S: RingSuite> RingSetup<S> {
354 pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self {
358 let mut t = S::Transcript::new(S::SUITE_ID);
359 t.absorb_raw(&seed);
360 let mut rng = t.to_rng();
361 Self::from_rand(ring_size, &mut rng)
362 }
363
364 pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self {
368 use ring_proof::pcs::PCS;
369 let max_degree = pcs_domain_size::<S>(ring_size) - 1;
370 let pcs_params = Kzg::<S>::setup(max_degree, rng);
371 Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct")
372 }
373
374 pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams<S>) -> Result<Self, Error> {
379 let pcs_domain_size = pcs_domain_size::<S>(ring_size);
380 if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 {
381 return Err(Error::InvalidData);
382 }
383 pcs_params.powers_in_g1.truncate(pcs_domain_size);
385 pcs_params.powers_in_g2.truncate(2);
386
387 Ok(Self {
388 pcs_params,
389 ring_ctx: RingContext::new(ring_size),
390 })
391 }
392
393 pub fn prover_key(&self, pks: &[AffinePoint<S>]) -> Result<RingProverKey<S>, Error> {
397 if pks.len() > self.piop_params.keyset_part_size {
398 return Err(Error::InvalidData);
399 }
400 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
401 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).0)
402 }
403
404 pub fn verifier_key(&self, pks: &[AffinePoint<S>]) -> Result<RingVerifierKey<S>, Error> {
408 if pks.len() > self.piop_params.keyset_part_size {
409 return Err(Error::InvalidData);
410 }
411 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
412 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).1)
413 }
414
415 pub fn verifier_key_from_commitment(
420 &self,
421 commitment: RingCommitment<S>,
422 ) -> RingVerifierKey<S> {
423 verifier_key_from_commitment::<S>(commitment, self.pcs_verifier_params())
424 }
425
426 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
432 use ring_proof::pcs::PcsParams;
433 self.pcs_params.raw_vk()
434 }
435
436 pub fn verifier_key_builder(&self) -> (VerifierKeyBuilder<S>, RingBuilderPcsParams<S>) {
438 type RingBuilderKey<S> =
439 ring_proof::ring::RingBuilderKey<BaseField<S>, <S as RingSuite>::Pairing>;
440 let piop_domain_size = piop_domain_size::<S>(self.piop_params.keyset_part_size);
441 let builder_key = RingBuilderKey::<S>::from_srs(&self.pcs_params, piop_domain_size);
442 let builder_pcs_params = RingBuilderPcsParams(builder_key.lis_in_g1);
443 let builder = VerifierKeyBuilder::new(self, &builder_pcs_params);
444 (builder, builder_pcs_params)
445 }
446
447 pub fn ring_context(&self) -> &RingContext<S> {
449 &self.ring_ctx
450 }
451
452 #[inline(always)]
457 pub const fn padding_point() -> AffinePoint<S> {
458 S::PADDING
459 }
460}
461
462pub fn verifier_key_from_commitment<S: RingSuite>(
474 commitment: RingCommitment<S>,
475 pcs_params: PcsVerifierParams<S>,
476) -> RingVerifierKey<S> {
477 RingVerifierKey::<S>::from_commitment_and_kzg_vk(commitment, pcs_params)
478}
479
480impl<S: RingSuite> CanonicalSerialize for RingSetup<S> {
481 fn serialize_with_mode<W: ark_serialize::Write>(
482 &self,
483 mut writer: W,
484 compress: ark_serialize::Compress,
485 ) -> Result<(), ark_serialize::SerializationError> {
486 self.pcs_params.serialize_with_mode(&mut writer, compress)
487 }
488
489 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
490 self.pcs_params.serialized_size(compress)
491 }
492}
493
494impl<S: RingSuite> CanonicalDeserialize for RingSetup<S> {
495 fn deserialize_with_mode<R: ark_serialize::Read>(
496 mut reader: R,
497 compress: ark_serialize::Compress,
498 validate: ark_serialize::Validate,
499 ) -> Result<Self, ark_serialize::SerializationError> {
500 let pcs_params = <PcsParams<S> as CanonicalDeserialize>::deserialize_with_mode(
501 &mut reader,
502 compress,
503 validate,
504 )?;
505 let ring_size = max_ring_size_from_pcs_domain_size::<S>(pcs_params.powers_in_g1.len());
506 Ok(Self {
507 pcs_params,
508 ring_ctx: RingContext::new(ring_size),
509 })
510 }
511}
512
513impl<S: RingSuite> ark_serialize::Valid for RingSetup<S> {
514 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
515 self.pcs_params.check()
516 }
517}
518
519#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
524pub struct RingBuilderPcsParams<S: RingSuite>(pub Vec<G1Affine<S>>);
525
526type PartialRingCommitment<S> =
528 ring_proof::ring::Ring<BaseField<S>, <S as RingSuite>::Pairing, TEAffine<CurveConfig<S>>>;
529
530#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
535pub struct VerifierKeyBuilder<S: RingSuite> {
536 partial: PartialRingCommitment<S>,
537 pcs_params: PcsVerifierParams<S>,
538}
539
540pub type G1Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G1Affine;
542pub type G2Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G2Affine;
544
545pub trait SrsLookup<S: RingSuite> {
549 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>>;
551}
552
553impl<S: RingSuite, F> SrsLookup<S> for F
554where
555 F: Fn(Range<usize>) -> Option<Vec<G1Affine<S>>>,
556{
557 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
558 self(range)
559 }
560}
561
562impl<S: RingSuite> SrsLookup<S> for &RingBuilderPcsParams<S> {
563 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
564 if range.end > self.0.len() {
565 return None;
566 }
567 Some(self.0[range].to_vec())
568 }
569}
570
571impl<S: RingSuite> VerifierKeyBuilder<S> {
572 pub fn new(ring_setup: &RingSetup<S>, lookup: impl SrsLookup<S>) -> Self {
574 let lookup = |range: Range<usize>| lookup.lookup(range).ok_or(());
575 let pcs_params = ring_setup.pcs_verifier_params();
576 let partial = PartialRingCommitment::<S>::empty(
577 &ring_setup.piop_params,
578 lookup,
579 pcs_params.g1.into_group(),
580 );
581 VerifierKeyBuilder {
582 partial,
583 pcs_params,
584 }
585 }
586
587 #[inline(always)]
589 pub fn free_slots(&self) -> usize {
590 self.partial.max_keys - self.partial.curr_keys
591 }
592
593 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
598 self.pcs_params.clone()
599 }
600
601 pub fn append(
606 &mut self,
607 pks: &[AffinePoint<S>],
608 lookup: impl SrsLookup<S>,
609 ) -> Result<(), usize> {
610 let avail_slots = self.free_slots();
611 if avail_slots < pks.len() {
612 return Err(avail_slots);
613 }
614 let segment = lookup
617 .lookup(self.partial.curr_keys..self.partial.curr_keys + pks.len())
618 .ok_or(usize::MAX)?;
619 let lookup = |range: Range<usize>| {
620 debug_assert_eq!(segment.len(), range.len());
621 Ok(segment.clone())
622 };
623 let pks = TEMapping::to_te_slice(pks).ok_or(usize::MAX)?;
624 self.partial.append(&pks, lookup);
625 Ok(())
626 }
627
628 pub fn finalize(self) -> RingVerifierKey<S> {
630 RingVerifierKey::<S>::from_ring_and_kzg_vk(&self.partial, self.pcs_params)
631 }
632}
633
634type RingProofBatchItem<S> =
635 ring_proof::multi_ring_batch_verifier::BatchItem<<S as RingSuite>::Pairing, CurveConfig<S>>;
636
637pub struct BatchItem<S: RingSuite> {
639 ring: RingProofBatchItem<S>,
640 pedersen: pedersen::BatchItem<S>,
641}
642
643impl<S: RingSuite> BatchItem<S> {
644 pub fn new(
653 verifier: &RingVerifier<S>,
654 ios: impl AsRef<[VrfIo<S>]>,
655 ad: impl AsRef<[u8]>,
656 proof: &Proof<S>,
657 ) -> Result<Self, Error> {
658 let key_commitment = proof
659 .pedersen_proof
660 .key_commitment()
661 .into_te()
662 .ok_or(Error::InvalidData)?;
663 let pedersen = pedersen::BatchItem::new(ios, ad, &proof.pedersen_proof);
664 let ring = RingProofBatchItem::<S>::new(verifier, proof.ring_proof.clone(), key_commitment);
665 Ok(Self { ring, pedersen })
666 }
667}
668
669pub struct BatchVerifier<S: RingSuite> {
678 ring_batch: RingBatchVerifier<S>,
679 pedersen_batch: pedersen::BatchVerifier<S>,
680}
681
682impl<S: RingSuite> BatchVerifier<S> {
683 pub fn new(ring_verifier: &RingVerifier<S>) -> Self {
689 Self {
690 ring_batch: RingBatchVerifier::<S>::new(
691 ring_verifier.pcs_vk().clone(),
692 ring_proof::ArkTranscript::new(S::SUITE_ID),
693 ),
694 pedersen_batch: pedersen::BatchVerifier::new(),
695 }
696 }
697
698 pub fn push_prepared(&mut self, item: BatchItem<S>) {
700 self.pedersen_batch.push_prepared(item.pedersen);
701 self.ring_batch.push_prepared(item.ring);
702 }
703
704 pub fn push(
709 &mut self,
710 verifier: &RingVerifier<S>,
711 ios: impl AsRef<[VrfIo<S>]>,
712 ad: impl AsRef<[u8]>,
713 proof: &Proof<S>,
714 ) -> Result<(), Error> {
715 let item = BatchItem::new(verifier, ios, ad, proof)?;
716 self.push_prepared(item);
717 Ok(())
718 }
719
720 pub fn verify(&self) -> Result<(), Error> {
725 self.pedersen_batch.verify()?;
726 self.ring_batch
727 .verify()
728 .then_some(())
729 .ok_or(Error::VerificationFailure)
730 }
731}
732
733#[macro_export]
735macro_rules! ring_suite_types {
736 ($suite:ident) => {
737 #[allow(dead_code)]
738 pub type PcsParams = $crate::ring::PcsParams<$suite>;
739 #[allow(dead_code)]
740 pub type PcsVerifierParams = $crate::ring::PcsVerifierParams<$suite>;
741 #[allow(dead_code)]
742 pub type PiopParams = $crate::ring::PiopParams<$suite>;
743 #[allow(dead_code)]
744 pub type RingContext = $crate::ring::RingContext<$suite>;
745 #[allow(dead_code)]
746 pub type RingSetup = $crate::ring::RingSetup<$suite>;
747 #[allow(dead_code)]
748 pub type RingProverKey = $crate::ring::RingProverKey<$suite>;
749 #[allow(dead_code)]
750 pub type RingVerifierKey = $crate::ring::RingVerifierKey<$suite>;
751 #[allow(dead_code)]
752 pub type RingCommitment = $crate::ring::RingCommitment<$suite>;
753 #[allow(dead_code)]
754 pub type RingProver = $crate::ring::RingProver<$suite>;
755 #[allow(dead_code)]
756 pub type RingVerifier = $crate::ring::RingVerifier<$suite>;
757 #[allow(dead_code)]
758 pub type RingProof = $crate::ring::Proof<$suite>;
759 #[allow(dead_code)]
760 pub type RingVerifierKeyBuilder = $crate::ring::VerifierKeyBuilder<$suite>;
761 #[allow(dead_code)]
762 pub type RingBatchItem = $crate::ring::BatchItem<$suite>;
763 #[allow(dead_code)]
764 pub type RingBatchVerifier = $crate::ring::BatchVerifier<$suite>;
765 };
766}
767
768pub mod dom_utils {
791 use super::*;
792
793 pub const fn max_ring_size<S: Suite>(min_ring_size: usize) -> usize {
801 max_ring_size_from_piop_domain_size::<S>(piop_domain_size::<S>(min_ring_size))
802 }
803
804 pub const fn piop_overhead<S: Suite>() -> usize {
806 4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize
807 }
808
809 pub const fn piop_domain_size<S: Suite>(min_ring_capacity: usize) -> usize {
815 (min_ring_capacity + piop_overhead::<S>()).next_power_of_two()
816 }
817
818 pub const fn max_ring_size_from_piop_domain_size<S: Suite>(piop_domain_size: usize) -> usize {
822 piop_domain_size - piop_overhead::<S>()
823 }
824
825 pub const fn pcs_domain_size<S: Suite>(min_ring_size: usize) -> usize {
830 pcs_domain_size_from_piop_domain_size(piop_domain_size::<S>(min_ring_size))
831 }
832
833 pub const fn pcs_domain_size_from_piop_domain_size(piop_domain_size: usize) -> usize {
837 3 * piop_domain_size + 1
838 }
839
840 pub const fn piop_domain_size_from_pcs_domain_size(pcs_domain_size: usize) -> usize {
845 1 << ((pcs_domain_size - 1) / 3).ilog2()
846 }
847
848 pub const fn max_ring_size_from_pcs_domain_size<S: Suite>(pcs_domain_size: usize) -> usize {
852 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_domain_size);
853 max_ring_size_from_piop_domain_size::<S>(piop_domain_size)
854 }
855}
856pub use dom_utils::*;
857
858#[cfg(test)]
859pub(crate) mod testing {
860 use super::*;
861 use crate::pedersen;
862 use crate::testing::{self as common, CheckPoint, TEST_SEED};
863 use ark_ec::{
864 short_weierstrass::{Affine as SWAffine, SWCurveConfig},
865 twisted_edwards::{Affine as TEAffine, TECurveConfig},
866 };
867
868 pub const TEST_RING_SIZE: usize = 8;
869
870 const MAX_AD_LEN: usize = 100;
871
872 fn find_complement_point<C: SWCurveConfig>() -> SWAffine<C> {
873 use ark_ff::{One, Zero};
874 assert!(!C::cofactor_is_one());
875 let mut x = C::BaseField::zero();
876 loop {
877 if let Some(p) = SWAffine::get_point_from_x_unchecked(x, false)
878 .filter(|p| !p.is_in_correct_subgroup_assuming_on_curve())
879 {
880 return p;
881 }
882 x += C::BaseField::one();
883 }
884 }
885
886 pub trait FindAccumulatorBase<S: Suite>: Sized {
887 const IN_PRIME_ORDER_SUBGROUP: bool;
888 fn find_accumulator_base(data: &[u8]) -> Option<Self>;
889 }
890
891 impl<S, C> FindAccumulatorBase<S> for SWAffine<C>
892 where
893 C: SWCurveConfig,
894 S: Suite<Affine = Self>,
895 {
896 const IN_PRIME_ORDER_SUBGROUP: bool = false;
897
898 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
899 let p = S::data_to_point(data)?;
900 let c = find_complement_point();
901 let res = (p + c).into_affine();
902 debug_assert!(!res.is_in_correct_subgroup_assuming_on_curve());
903 Some(res)
904 }
905 }
906
907 impl<S, C> FindAccumulatorBase<S> for TEAffine<C>
908 where
909 C: TECurveConfig,
910 S: Suite<Affine = Self>,
911 {
912 const IN_PRIME_ORDER_SUBGROUP: bool = true;
913
914 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
915 let res = S::data_to_point(data)?;
916 debug_assert!(res.is_in_correct_subgroup_assuming_on_curve());
917 Some(res)
918 }
919 }
920
921 struct TestItem<S: RingSuite> {
922 io: VrfIo<S>,
923 ad: Vec<u8>,
924 proof: Proof<S>,
925 }
926
927 impl<S: RingSuite> TestItem<S> {
928 fn new(
929 secret: &Secret<S>,
930 prover: &RingProver<S>,
931 rng: &mut dyn ark_std::rand::RngCore,
932 ) -> Self {
933 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
934 let io = secret.vrf_io(input);
935 let ad_len = common::random_val::<usize>(Some(rng)) % (MAX_AD_LEN + 1);
936 let ad = common::random_vec(ad_len, Some(rng));
937 let proof = secret.prove(io, &ad, prover);
938 Self { io, ad, proof }
939 }
940 }
941
942 #[allow(unused)]
943 pub fn prove_verify<S: RingSuite>() {
944 let rng = &mut ark_std::test_rng();
945 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
946
947 let secret = Secret::<S>::from_seed(TEST_SEED);
948 let public = secret.public();
949
950 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
951 let prover_idx = 3;
952 pks[prover_idx] = public.0;
953
954 let ring_ctx = ring_setup.ring_context();
955 let prover_key = ring_setup.prover_key(&pks).unwrap();
956 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
957
958 let item = TestItem::<S>::new(&secret, &prover, rng);
959
960 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
961 let verifier = ring_ctx.ring_verifier(verifier_key);
962 let result = Public::verify(item.io, &item.ad, &item.proof, &verifier);
963 assert!(result.is_ok());
964 }
965
966 #[allow(unused)]
968 pub fn prove_verify_multi<S: RingSuite>() {
969 use ring::{Prover, Verifier};
970
971 let rng = &mut ark_std::test_rng();
972 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
973
974 let secret = Secret::<S>::from_seed(TEST_SEED);
975 let public = secret.public();
976
977 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
978 let prover_idx = 3;
979 pks[prover_idx] = public.0;
980
981 let ring_ctx = ring_setup.ring_context();
982 let prover_key = ring_setup.prover_key(&pks).unwrap();
983 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
984
985 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
986 let verifier = ring_ctx.ring_verifier(verifier_key);
987
988 let mut ios: Vec<VrfIo<S>> = (0..3u8)
989 .map(|i| {
990 let input = Input::new(&[i + 1]).unwrap();
991 secret.vrf_io(input)
992 })
993 .collect();
994 ios.push(VrfIo {
995 input: Input(S::Affine::generator()),
996 output: Output(public.0),
997 });
998
999 let proof = secret.prove(&ios[..], b"bar", &prover);
1000 assert!(Public::verify(&ios[..], b"bar", &proof, &verifier).is_ok());
1001
1002 let mut bad_ios = ios.clone();
1004 bad_ios[1].output = secret.output(ios[0].input);
1005 assert!(Public::verify(&bad_ios[..], b"bar", &proof, &verifier).is_err());
1006
1007 assert!(Public::verify(&ios[..], b"baz", &proof, &verifier).is_err());
1009 }
1010
1011 #[allow(unused)]
1012 pub fn prove_verify_batch<S: RingSuite>() {
1013 use rayon::prelude::*;
1014
1015 const BATCH_SIZE: usize = 3 * TEST_RING_SIZE;
1016
1017 let rng = &mut ark_std::test_rng();
1018 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1019
1020 let secret = Secret::<S>::from_seed(TEST_SEED);
1021 let public = secret.public();
1022
1023 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1024 let prover_idx = 3;
1025 pks[prover_idx] = public.0;
1026
1027 let ring_ctx = ring_setup.ring_context();
1028 let prover_key = ring_setup.prover_key(&pks).unwrap();
1029 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1030
1031 let batch: Vec<_> = (0..BATCH_SIZE)
1033 .into_par_iter()
1034 .map_init(ark_std::test_rng, |rng, _| {
1035 TestItem::<S>::new(&secret, &prover, rng)
1036 })
1037 .collect();
1038
1039 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
1040 let verifier = ring_ctx.ring_verifier(verifier_key);
1041
1042 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1044 let res = batch_verifier.verify();
1045 assert!(res.is_ok());
1046
1047 for item in batch.iter() {
1049 batch_verifier
1050 .push(&verifier, item.io, &item.ad, &item.proof)
1051 .unwrap();
1052 let res = batch_verifier.verify();
1053 assert!(res.is_ok());
1054 }
1055
1056 println!("Batch size = {BATCH_SIZE}");
1057
1058 println!("============================================================");
1059
1060 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1061 let start = std::time::Instant::now();
1062 common::timed("Proofs push", || {
1063 for item in batch.iter() {
1064 batch_verifier
1065 .push(&verifier, item.io, &item.ad, &item.proof)
1066 .unwrap();
1067 }
1068 });
1069 common::timed("Unprepared batch verification", || batch_verifier.verify());
1070 println!("Total time: {:?}", start.elapsed());
1071
1072 println!("============================================================");
1073
1074 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1075 let start = std::time::Instant::now();
1076 let prepared = common::timed("Proofs prepare", || {
1077 batch
1078 .par_iter()
1079 .map(|item| BatchItem::<S>::new(&verifier, item.io, &item.ad, &item.proof).unwrap())
1080 .collect::<Vec<_>>()
1081 });
1082 common::timed("Proofs push prepared", || {
1083 prepared
1084 .into_iter()
1085 .for_each(|p| batch_verifier.push_prepared(p))
1086 });
1087 common::timed("Prepared batch verification", || batch_verifier.verify());
1088 println!("Total time: {:?}", start.elapsed());
1089
1090 println!("============================================================");
1091
1092 let mut pks_b = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1095 let prover_idx_b = 1;
1096 pks_b[prover_idx_b] = public.0;
1097 let prover_key_b = ring_setup.prover_key(&pks_b).unwrap();
1098 let prover_b = ring_ctx.ring_prover(prover_key_b, prover_idx_b);
1099 let verifier_key_b = ring_setup.verifier_key(&pks_b).unwrap();
1100 let verifier_b = ring_ctx.ring_verifier(verifier_key_b);
1101
1102 let batch_b: Vec<_> = (0..TEST_RING_SIZE)
1103 .into_par_iter()
1104 .map_init(ark_std::test_rng, |rng, _| {
1105 TestItem::<S>::new(&secret, &prover_b, rng)
1106 })
1107 .collect();
1108
1109 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1110 for item in batch.iter() {
1111 batch_verifier
1112 .push(&verifier, item.io, &item.ad, &item.proof)
1113 .unwrap();
1114 }
1115 for item in batch_b.iter() {
1116 batch_verifier
1117 .push(&verifier_b, item.io, &item.ad, &item.proof)
1118 .unwrap();
1119 }
1120 common::timed("Multi-ring batch verification", || batch_verifier.verify())
1121 .expect("multi-ring batch verifies");
1122
1123 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1127 let item_b = &batch_b[0];
1128 batch_verifier
1129 .push(&verifier, item_b.io, &item_b.ad, &item_b.proof)
1130 .unwrap();
1131 assert!(
1132 batch_verifier.verify().is_err(),
1133 "ring-B proof must not verify against verifier_a"
1134 );
1135 }
1136
1137 #[allow(unused)]
1138 pub fn padding_check<S: RingSuite>()
1139 where
1140 AffinePoint<S>: CheckPoint,
1141 {
1142 assert_eq!(S::PADDING, S::data_to_point(PADDING_SEED).unwrap());
1144
1145 assert!(S::PADDING.check(true).is_ok());
1147 }
1148
1149 #[allow(unused)]
1150 pub fn accumulator_base_check<S: RingSuite>()
1151 where
1152 AffinePoint<S>: FindAccumulatorBase<S> + CheckPoint,
1153 {
1154 assert_eq!(
1156 S::ACCUMULATOR_BASE,
1157 AffinePoint::<S>::find_accumulator_base(ACCUMULATOR_BASE_SEED).unwrap()
1158 );
1159
1160 let in_prime_subgroup = <AffinePoint<S> as FindAccumulatorBase<S>>::IN_PRIME_ORDER_SUBGROUP;
1163 assert!(S::ACCUMULATOR_BASE.check(in_prime_subgroup).is_ok());
1164 }
1165
1166 #[allow(unused)]
1167 pub fn verifier_key_from_commitment<S: RingSuite>() {
1168 let rng = &mut ark_std::test_rng();
1169 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1170
1171 let secret = Secret::<S>::from_seed(TEST_SEED);
1172 let public = secret.public();
1173
1174 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1175 let prover_idx = 3;
1176 pks[prover_idx] = public.0;
1177
1178 let prover_key = ring_setup.prover_key(&pks).unwrap();
1179 let prover = ring_setup
1180 .ring_context()
1181 .ring_prover(prover_key, prover_idx);
1182 let item = TestItem::<S>::new(&secret, &prover, rng);
1183
1184 let commitment = ring_setup.verifier_key(&pks).unwrap().commitment();
1185
1186 let mut buf = Vec::new();
1189 ring_setup
1190 .pcs_verifier_params()
1191 .serialize_compressed(&mut buf)
1192 .unwrap();
1193 let pcs_params = PcsVerifierParams::<S>::deserialize_compressed(&buf[..]).unwrap();
1194
1195 let ring_ctx = RingContext::<S>::new(TEST_RING_SIZE);
1196 let verifier_key = super::verifier_key_from_commitment::<S>(commitment, pcs_params);
1197 let verifier = ring_ctx.ring_verifier(verifier_key);
1198 assert!(Public::verify(item.io, &item.ad, &item.proof, &verifier).is_ok());
1199 }
1200
1201 #[allow(unused)]
1202 pub fn verifier_key_builder<S: RingSuite>() {
1203 use crate::testing::{random_val, random_vec};
1204
1205 let rng = &mut ark_std::test_rng();
1206 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1207
1208 let secret = Secret::<S>::from_seed(TEST_SEED);
1209 let public = secret.public();
1210 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
1211 let io = secret.vrf_io(input);
1212
1213 let ring_ctx = ring_setup.ring_context();
1214 let ring_size = ring_ctx.max_ring_size();
1215 let prover_idx = random_val::<usize>(Some(rng)) % ring_size;
1216 let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
1217 pks[prover_idx] = public.0;
1218
1219 let prover_key = ring_setup.prover_key(&pks).unwrap();
1220 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1221 let proof = secret.prove(io, b"foo", &prover);
1222
1223 let (mut vk_builder, lookup) = ring_setup.verifier_key_builder();
1225 assert_eq!(vk_builder.free_slots(), pks.len());
1226 assert_eq!(
1227 vk_builder.pcs_verifier_params(),
1228 ring_setup.pcs_verifier_params()
1229 );
1230
1231 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1232 assert_eq!(
1233 vk_builder.append(&[extra_pk], |_| None).unwrap_err(),
1234 usize::MAX
1235 );
1236
1237 while !pks.is_empty() {
1238 let chunk_len = 1 + random_val::<usize>(Some(rng)) % 5;
1239 let chunk = pks.drain(..pks.len().min(chunk_len)).collect::<Vec<_>>();
1240 vk_builder.append(&chunk[..], &lookup).unwrap();
1241 assert_eq!(vk_builder.free_slots(), pks.len());
1242 }
1243 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1245 assert_eq!(vk_builder.append(&[extra_pk], &lookup).unwrap_err(), 0);
1246 let verifier_key = vk_builder.finalize();
1247 let verifier = ring_ctx.ring_verifier(verifier_key);
1248 let result = Public::verify(io, b"foo", &proof, &verifier);
1249 assert!(result.is_ok());
1250 }
1251
1252 pub fn domain_size_conversions<S: RingSuite>() {
1253 let overhead = piop_overhead::<S>();
1254
1255 for ring_size in [1, 10, 200, 300, 500, 1000, 2000, 10000] {
1256 let piop_dom_size = piop_domain_size::<S>(ring_size);
1257 let pcs_dom_size = pcs_domain_size::<S>(ring_size);
1258 let max_ring_size = max_ring_size_from_piop_domain_size::<S>(piop_dom_size);
1259
1260 assert!(piop_dom_size.is_power_of_two());
1261 assert_eq!(pcs_dom_size, 3 * piop_dom_size + 1);
1262
1263 assert!(piop_dom_size >= ring_size + overhead);
1265 assert!(piop_dom_size / 2 < ring_size + overhead);
1267 assert_eq!(piop_dom_size, piop_domain_size::<S>(max_ring_size));
1269 assert!(ring_size <= max_ring_size);
1271
1272 assert_eq!(dom_utils::max_ring_size::<S>(ring_size), max_ring_size);
1274 assert_eq!(dom_utils::max_ring_size::<S>(max_ring_size), max_ring_size);
1276
1277 let piop_dom_rt = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1279 assert_eq!(piop_dom_size, piop_dom_rt);
1280 let pcs_dom_rt = pcs_domain_size_from_piop_domain_size(piop_dom_rt);
1281 assert_eq!(pcs_dom_size, pcs_dom_rt);
1282
1283 let max_ring_from_pcs = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1284 assert_eq!(max_ring_size, max_ring_from_pcs);
1285
1286 let next_piop = piop_domain_size::<S>(max_ring_size + 1);
1288 assert!(next_piop > piop_dom_size,);
1289 assert!(next_piop.is_power_of_two());
1290 }
1291
1292 for pcs_dom_size in [1 << 11, 1 << 12, 1 << 14, 1 << 16] {
1295 let piop_dom = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1296 let max_ring = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1297
1298 assert!(piop_dom.is_power_of_two());
1299 assert!(3 * piop_dom < pcs_dom_size);
1301 assert!(3 * (2 * piop_dom) + 1 > pcs_dom_size);
1303 assert_eq!(piop_domain_size::<S>(max_ring), piop_dom);
1305 assert!(piop_domain_size::<S>(max_ring + 1) > piop_dom);
1307 }
1308
1309 let piop_zero = piop_domain_size::<S>(0);
1311 assert!(piop_zero.is_power_of_two());
1312 assert_eq!(piop_zero, overhead.next_power_of_two());
1313 }
1314
1315 #[macro_export]
1316 macro_rules! ring_suite_tests {
1317 ($suite:ty) => {
1318 mod ring {
1319 use super::*;
1320
1321 #[test]
1322 fn prove_verify() {
1323 $crate::ring::testing::prove_verify::<$suite>()
1324 }
1325
1326 #[test]
1327 fn prove_verify_multi() {
1328 $crate::ring::testing::prove_verify_multi::<$suite>()
1329 }
1330
1331 #[test]
1332 fn prove_verify_batch() {
1333 $crate::ring::testing::prove_verify_batch::<$suite>()
1334 }
1335
1336 #[test]
1337 fn padding_check() {
1338 $crate::ring::testing::padding_check::<$suite>()
1339 }
1340
1341 #[test]
1342 fn accumulator_base_check() {
1343 $crate::ring::testing::accumulator_base_check::<$suite>()
1344 }
1345
1346 #[test]
1347 fn verifier_key_builder() {
1348 $crate::ring::testing::verifier_key_builder::<$suite>()
1349 }
1350
1351 #[test]
1352 fn verifier_key_from_commitment() {
1353 $crate::ring::testing::verifier_key_from_commitment::<$suite>()
1354 }
1355
1356 #[test]
1357 fn domain_size_conversions() {
1358 $crate::ring::testing::domain_size_conversions::<$suite>()
1359 }
1360
1361 $crate::test_vectors!($crate::ring::testing::TestVector<$suite>);
1362 }
1363 };
1364 }
1365
1366 pub trait RingSuiteExt: RingSuite + crate::testing::SuiteExt {
1367 const SRS_FILE: &str;
1368
1369 fn ring_setup() -> &'static RingSetup<Self>;
1370
1371 #[allow(unused)]
1372 fn load_ring_setup() -> RingSetup<Self> {
1373 use ark_serialize::CanonicalDeserialize;
1374 use std::{fs::File, io::Read};
1375 let mut file = File::open(Self::SRS_FILE).unwrap();
1376 let mut buf = Vec::new();
1377 file.read_to_end(&mut buf).unwrap();
1378 let pcs_params =
1379 PcsParams::<Self>::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
1380 RingSetup::from_pcs_params(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
1381 }
1382
1383 #[allow(unused)]
1384 fn write_ring_setup(ring_setup: &RingSetup<Self>) {
1385 use ark_serialize::CanonicalSerialize;
1386 use std::{fs::File, io::Write};
1387 let mut file = File::create(Self::SRS_FILE).unwrap();
1388 let mut buf = Vec::new();
1389 ring_setup
1390 .pcs_params
1391 .serialize_uncompressed(&mut buf)
1392 .unwrap();
1393 file.write_all(&buf).unwrap();
1394 }
1395 }
1396
1397 pub struct TestVector<S: RingSuite> {
1398 pub pedersen: pedersen::testing::TestVector<S>,
1399 pub ring_pks: [AffinePoint<S>; TEST_RING_SIZE],
1400 pub ring_pks_com: RingCommitment<S>,
1401 pub ring_proof: RingBareProof<S>,
1402 }
1403
1404 impl<S: RingSuite> core::fmt::Debug for TestVector<S> {
1405 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1406 f.debug_struct("TestVector")
1407 .field("pedersen", &self.pedersen)
1408 .field("ring_proof", &"...")
1409 .finish()
1410 }
1411 }
1412
1413 impl<S> common::TestVectorTrait for TestVector<S>
1414 where
1415 S: RingSuiteExt + std::fmt::Debug + 'static,
1416 {
1417 fn name() -> String {
1418 S::SUITE_NAME.to_string() + "_ring"
1419 }
1420
1421 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
1422 use super::Prover;
1423 let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, ad);
1424
1425 let secret = Secret::<S>::from_scalar(pedersen.base.sk);
1426 let public = secret.public();
1427
1428 let io = VrfIo {
1429 input: Input::<S>::from_affine_unchecked(pedersen.base.h),
1430 output: Output::from_affine_unchecked(pedersen.base.gamma),
1431 };
1432
1433 let ring_setup = <S as RingSuiteExt>::ring_setup();
1434
1435 use ark_std::rand::SeedableRng;
1436 let rng = &mut ark_std::rand::rngs::StdRng::from_seed([42; 32]);
1437 let prover_idx = 3;
1438 let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1439 ring_pks[prover_idx] = public.0;
1440
1441 let ring_ctx = RingContext::<S>::new_without_blinding(TEST_RING_SIZE);
1443 let prover_key = ring_setup.prover_key(&ring_pks).unwrap();
1444 let prover = ring_ctx.into_ring_prover(prover_key, prover_idx);
1445 let proof = secret.prove(io, ad, &prover);
1446
1447 let verifier_key = ring_setup.verifier_key(&ring_pks).unwrap();
1448 let ring_pks_com = verifier_key.commitment();
1449
1450 {
1451 let mut p = (Vec::new(), Vec::new());
1453 pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1454 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1455 assert_eq!(p.0, p.1);
1456 }
1457
1458 Self {
1459 pedersen,
1460 ring_pks: ring_pks.try_into().unwrap(),
1461 ring_pks_com,
1462 ring_proof: proof.ring_proof,
1463 }
1464 }
1465
1466 fn from_map(map: &common::TestVectorMap) -> Self {
1467 let pedersen = pedersen::testing::TestVector::from_map(map);
1468
1469 let ring_pks = map.get::<[AffinePoint<S>; TEST_RING_SIZE]>("ring_pks");
1470 let ring_pks_com = map.get::<RingCommitment<S>>("ring_pks_com");
1471 let ring_proof = map.get::<RingBareProof<S>>("ring_proof");
1472
1473 Self {
1474 pedersen,
1475 ring_pks,
1476 ring_pks_com,
1477 ring_proof,
1478 }
1479 }
1480
1481 fn to_map(&self) -> common::TestVectorMap {
1482 let mut map = self.pedersen.to_map();
1483 map.set("ring_pks", &self.ring_pks);
1484 map.set("ring_pks_com", &self.ring_pks_com);
1485 map.set("ring_proof", &self.ring_proof);
1486 map
1487 }
1488
1489 fn run(&self) {
1490 self.pedersen.run();
1491
1492 let io = VrfIo {
1493 input: Input::<S>::from_affine_unchecked(self.pedersen.base.h),
1494 output: Output::from_affine_unchecked(self.pedersen.base.gamma),
1495 };
1496 let secret = Secret::from_scalar(self.pedersen.base.sk);
1497 let public = secret.public();
1498 assert_eq!(public.0, self.pedersen.base.pk);
1499
1500 let ring_setup = <S as RingSuiteExt>::ring_setup();
1501
1502 let prover_idx = self.ring_pks.iter().position(|&pk| pk == public.0).unwrap();
1503
1504 let ring_ctx = RingContext::<S>::new_without_blinding(TEST_RING_SIZE);
1506 let prover_key = ring_setup.prover_key(&self.ring_pks).unwrap();
1507 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1508
1509 let verifier_key = ring_setup.verifier_key(&self.ring_pks).unwrap();
1510 let verifier = ring_ctx.ring_verifier(verifier_key);
1511
1512 let proof = secret.prove(io, &self.pedersen.base.ad, &prover);
1513
1514 {
1515 let mut p = (Vec::new(), Vec::new());
1517 self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1518 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1519 assert_eq!(p.0, p.1);
1520 }
1521
1522 {
1523 let mut p = (Vec::new(), Vec::new());
1525 self.ring_proof.serialize_compressed(&mut p.0).unwrap();
1526 proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
1527 assert_eq!(p.0, p.1);
1528 }
1529
1530 assert!(Public::verify(io, &self.pedersen.base.ad, &proof, &verifier).is_ok());
1531 }
1532 }
1533}