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<
78 BaseField: ark_ff::PrimeField + ring_proof::CondSelect,
79 Config: TECurveConfig + Clone,
80 > + TEMapping<<Self::Affine as AffineRepr>::Config>,
81>
82{
83 type Pairing: ark_ec::pairing::Pairing<ScalarField = BaseField<Self>>;
85
86 const ACCUMULATOR_BASE: AffinePoint<Self>;
91
92 const PADDING: AffinePoint<Self>;
94}
95
96pub type Kzg<S> = ring_proof::pcs::kzg::KZG<<S as RingSuite>::Pairing>;
98
99pub type PcsCommitment<S> = <Kzg<S> as ring_proof::pcs::PCS<BaseField<S>>>::C;
101
102pub type PcsParams<S> = ring_proof::pcs::kzg::urs::URS<<S as RingSuite>::Pairing>;
106
107pub type PcsVerifierParams<S> = <PcsParams<S> as ring_proof::pcs::PcsParams>::RVK;
114
115pub type PiopParams<S> = ring_proof::PiopParams<TEAffine<CurveConfig<S>>>;
120
121pub type RingCommitment<S> = ring_proof::FixedColumnsCommitted<BaseField<S>, PcsCommitment<S>>;
123
124pub type RingProverKey<S> = ring_proof::ProverKey<BaseField<S>, Kzg<S>, TEAffine<CurveConfig<S>>>;
126
127pub type RingVerifierKey<S> = ring_proof::VerifierKey<BaseField<S>, Kzg<S>>;
129
130pub type RingProver<S> = ring_proof::ring_prover::RingProver<BaseField<S>, Kzg<S>, CurveConfig<S>>;
132
133pub type RingVerifier<S> =
135 ring_proof::ring_verifier::RingVerifier<BaseField<S>, Kzg<S>, CurveConfig<S>>;
136
137pub type RingBatchVerifier<S> = ring_proof::multi_ring_batch_verifier::BatchVerifier<
142 <S as RingSuite>::Pairing,
143 ring_proof::ArkTranscript,
144>;
145
146pub type RingBareProof<S> = ring_proof::RingProof<BaseField<S>, Kzg<S>>;
151
152#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
161pub struct Proof<S: RingSuite> {
162 pub pedersen_proof: PedersenProof<S>,
164 pub ring_proof: RingBareProof<S>,
166}
167
168pub trait Prover<S: RingSuite> {
170 fn prove(
174 &self,
175 ios: impl AsRef<[VrfIo<S>]>,
176 ad: impl AsRef<[u8]>,
177 prover: &RingProver<S>,
178 ) -> Proof<S>;
179}
180
181pub trait Verifier<S: RingSuite> {
198 fn verify(
204 ios: impl AsRef<[VrfIo<S>]>,
205 ad: impl AsRef<[u8]>,
206 sig: &Proof<S>,
207 verifier: &RingVerifier<S>,
208 ) -> Result<(), Error>;
209}
210
211impl<S: RingSuite> Prover<S> for Secret<S> {
212 fn prove(
213 &self,
214 ios: impl AsRef<[VrfIo<S>]>,
215 ad: impl AsRef<[u8]>,
216 ring_prover: &RingProver<S>,
217 ) -> Proof<S> {
218 use pedersen::Prover as PedersenProver;
219 let (pedersen_proof, secret_blinding) = <Self as PedersenProver<S>>::prove(self, ios, ad);
220 let ring_proof = ring_prover.prove(secret_blinding);
221 Proof {
222 pedersen_proof,
223 ring_proof,
224 }
225 }
226}
227
228impl<S: RingSuite> Verifier<S> for Public<S> {
229 fn verify(
230 ios: impl AsRef<[VrfIo<S>]>,
231 ad: impl AsRef<[u8]>,
232 proof: &Proof<S>,
233 verifier: &RingVerifier<S>,
234 ) -> Result<(), Error> {
235 use pedersen::Verifier as PedersenVerifier;
236 <Self as PedersenVerifier<S>>::verify(ios, ad, &proof.pedersen_proof)?;
237 let key_commitment = proof
238 .pedersen_proof
239 .key_commitment()
240 .into_te()
241 .ok_or(Error::InvalidData)?;
242 if !verifier.verify(proof.ring_proof.clone(), key_commitment) {
243 return Err(Error::VerificationFailure);
244 }
245 Ok(())
246 }
247}
248
249#[derive(Clone)]
257pub struct RingContext<S: RingSuite> {
258 pub piop_params: PiopParams<S>,
260}
261
262impl<S: RingSuite> RingContext<S> {
263 pub fn new(ring_size: usize) -> Self {
265 Self::construct(ring_size, true)
266 }
267
268 pub fn new_without_blinding(ring_size: usize) -> Self {
274 Self::construct(ring_size, false)
275 }
276
277 fn construct(ring_size: usize, blinding: bool) -> Self {
278 let domain_size = piop_domain_size::<S>(ring_size);
279 let mut domain =
280 ring_proof::Domain::with_zk_rows(domain_size, ring_proof::piop::params::ZK_ROWS);
281 if !blinding {
282 domain = domain.without_blinding();
283 }
284 let piop_params = PiopParams::<S>::setup(
285 domain,
286 S::BLINDING_BASE
287 .into_te()
288 .expect("BLINDING_BASE must not be identity"),
289 S::ACCUMULATOR_BASE
290 .into_te()
291 .expect("ACCUMULATOR_BASE must not be identity"),
292 S::PADDING.into_te().expect("PADDING must not be identity"),
293 );
294 Self { piop_params }
295 }
296
297 #[inline(always)]
299 pub fn max_ring_size(&self) -> usize {
300 self.piop_params.keyset_part_size
301 }
302
303 pub fn ring_prover(&self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
305 self.clone().into_ring_prover(prover_key, key_index)
306 }
307
308 pub fn ring_verifier(&self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
310 self.clone().into_ring_verifier(verifier_key)
311 }
312
313 pub fn into_ring_prover(self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
315 RingProver::<S>::init(
316 prover_key,
317 self.piop_params,
318 key_index,
319 ring_proof::ArkTranscript::new(S::SUITE_ID),
320 )
321 }
322
323 pub fn into_ring_verifier(self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
325 RingVerifier::<S>::init(
326 verifier_key,
327 self.piop_params,
328 ring_proof::ArkTranscript::new(S::SUITE_ID),
329 )
330 }
331}
332
333#[derive(Clone)]
340pub struct RingSetup<S: RingSuite> {
341 pub pcs_params: PcsParams<S>,
343 pub ring_ctx: RingContext<S>,
345}
346
347impl<S: RingSuite> core::ops::Deref for RingSetup<S> {
348 type Target = RingContext<S>;
349
350 fn deref(&self) -> &Self::Target {
351 &self.ring_ctx
352 }
353}
354
355impl<S: RingSuite> RingSetup<S> {
356 pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self {
360 let mut t = S::Transcript::new(S::SUITE_ID);
361 t.absorb_raw(&seed);
362 let mut rng = t.to_rng();
363 Self::from_rand(ring_size, &mut rng)
364 }
365
366 pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self {
370 use ring_proof::pcs::PCS;
371 let max_degree = pcs_domain_size::<S>(ring_size) - 1;
372 let pcs_params = Kzg::<S>::setup(max_degree, rng);
373 Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct")
374 }
375
376 pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams<S>) -> Result<Self, Error> {
381 let pcs_domain_size = pcs_domain_size::<S>(ring_size);
382 if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 {
383 return Err(Error::RingCapacityExceeded);
384 }
385 pcs_params.powers_in_g1.truncate(pcs_domain_size);
387 pcs_params.powers_in_g2.truncate(2);
388
389 Ok(Self {
390 pcs_params,
391 ring_ctx: RingContext::new(ring_size),
392 })
393 }
394
395 pub fn prover_key(&self, pks: &[AffinePoint<S>]) -> Result<RingProverKey<S>, Error> {
400 if pks.len() > self.piop_params.keyset_part_size {
401 return Err(Error::RingCapacityExceeded);
402 }
403 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
404 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).0)
405 }
406
407 pub fn verifier_key(&self, pks: &[AffinePoint<S>]) -> Result<RingVerifierKey<S>, Error> {
412 if pks.len() > self.piop_params.keyset_part_size {
413 return Err(Error::RingCapacityExceeded);
414 }
415 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
416 Ok(ring_proof::index(&self.pcs_params, &self.piop_params, &pks).1)
417 }
418
419 pub fn verifier_key_from_commitment(
424 &self,
425 commitment: RingCommitment<S>,
426 ) -> RingVerifierKey<S> {
427 verifier_key_from_commitment::<S>(commitment, self.pcs_verifier_params())
428 }
429
430 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
436 use ring_proof::pcs::PcsParams;
437 self.pcs_params.raw_vk()
438 }
439
440 pub fn verifier_key_builder(&self) -> (VerifierKeyBuilder<S>, RingBuilderPcsParams<S>) {
442 type RingBuilderKey<S> =
443 ring_proof::ring::RingBuilderKey<BaseField<S>, <S as RingSuite>::Pairing>;
444 let piop_domain_size = piop_domain_size::<S>(self.piop_params.keyset_part_size);
445 let builder_key = RingBuilderKey::<S>::from_srs(&self.pcs_params, piop_domain_size);
446 let builder_pcs_params = RingBuilderPcsParams(builder_key.lis_in_g1);
447 let builder = VerifierKeyBuilder::new(self, &builder_pcs_params);
448 (builder, builder_pcs_params)
449 }
450
451 pub fn ring_context(&self) -> &RingContext<S> {
453 &self.ring_ctx
454 }
455
456 #[inline(always)]
461 pub const fn padding_point() -> AffinePoint<S> {
462 S::PADDING
463 }
464}
465
466pub fn verifier_key_from_commitment<S: RingSuite>(
478 commitment: RingCommitment<S>,
479 pcs_params: PcsVerifierParams<S>,
480) -> RingVerifierKey<S> {
481 RingVerifierKey::<S>::from_commitment_and_kzg_vk(commitment, pcs_params)
482}
483
484impl<S: RingSuite> CanonicalSerialize for RingSetup<S> {
485 fn serialize_with_mode<W: ark_serialize::Write>(
486 &self,
487 mut writer: W,
488 compress: ark_serialize::Compress,
489 ) -> Result<(), ark_serialize::SerializationError> {
490 self.pcs_params.serialize_with_mode(&mut writer, compress)
491 }
492
493 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
494 self.pcs_params.serialized_size(compress)
495 }
496}
497
498impl<S: RingSuite> CanonicalDeserialize for RingSetup<S> {
499 fn deserialize_with_mode<R: ark_serialize::Read>(
500 mut reader: R,
501 compress: ark_serialize::Compress,
502 validate: ark_serialize::Validate,
503 ) -> Result<Self, ark_serialize::SerializationError> {
504 let pcs_params = <PcsParams<S> as CanonicalDeserialize>::deserialize_with_mode(
505 &mut reader,
506 compress,
507 validate,
508 )?;
509 let ring_size = max_ring_size_from_pcs_domain_size::<S>(pcs_params.powers_in_g1.len());
510 Ok(Self {
511 pcs_params,
512 ring_ctx: RingContext::new(ring_size),
513 })
514 }
515}
516
517impl<S: RingSuite> ark_serialize::Valid for RingSetup<S> {
518 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
519 self.pcs_params.check()
520 }
521}
522
523#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
528pub struct RingBuilderPcsParams<S: RingSuite>(pub Vec<G1Affine<S>>);
529
530type PartialRingCommitment<S> =
532 ring_proof::ring::Ring<BaseField<S>, <S as RingSuite>::Pairing, TEAffine<CurveConfig<S>>>;
533
534#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
539pub struct VerifierKeyBuilder<S: RingSuite> {
540 partial: PartialRingCommitment<S>,
541 pcs_params: PcsVerifierParams<S>,
542}
543
544pub type G1Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G1Affine;
546pub type G2Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G2Affine;
548
549pub trait SrsLookup<S: RingSuite> {
553 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>>;
555}
556
557impl<S: RingSuite, F> SrsLookup<S> for F
558where
559 F: Fn(Range<usize>) -> Option<Vec<G1Affine<S>>>,
560{
561 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
562 self(range)
563 }
564}
565
566impl<S: RingSuite> SrsLookup<S> for &RingBuilderPcsParams<S> {
567 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
568 if range.end > self.0.len() {
569 return None;
570 }
571 Some(self.0[range].to_vec())
572 }
573}
574
575impl<S: RingSuite> VerifierKeyBuilder<S> {
576 pub fn new(ring_setup: &RingSetup<S>, lookup: impl SrsLookup<S>) -> Self {
578 let lookup = |range: Range<usize>| lookup.lookup(range).ok_or(());
579 let pcs_params = ring_setup.pcs_verifier_params();
580 let partial = PartialRingCommitment::<S>::empty(
581 &ring_setup.piop_params,
582 lookup,
583 pcs_params.g1.into_group(),
584 );
585 VerifierKeyBuilder {
586 partial,
587 pcs_params,
588 }
589 }
590
591 #[inline(always)]
593 pub fn free_slots(&self) -> usize {
594 self.partial.max_keys - self.partial.curr_keys
595 }
596
597 pub fn pcs_verifier_params(&self) -> PcsVerifierParams<S> {
602 self.pcs_params.clone()
603 }
604
605 pub fn append(
612 &mut self,
613 pks: &[AffinePoint<S>],
614 lookup: impl SrsLookup<S>,
615 ) -> Result<(), Error> {
616 if self.free_slots() < pks.len() {
617 return Err(Error::RingCapacityExceeded);
618 }
619 let segment = lookup
622 .lookup(self.partial.curr_keys..self.partial.curr_keys + pks.len())
623 .ok_or(Error::SrsLookupFailed)?;
624 let lookup = |range: Range<usize>| {
625 debug_assert_eq!(segment.len(), range.len());
626 Ok(segment.clone())
627 };
628 let pks = TEMapping::to_te_slice(pks).ok_or(Error::InvalidData)?;
629 self.partial.append(&pks, lookup);
630 Ok(())
631 }
632
633 pub fn finalize(self) -> RingVerifierKey<S> {
635 RingVerifierKey::<S>::from_ring_and_kzg_vk(&self.partial, self.pcs_params)
636 }
637}
638
639type RingProofBatchItem<S> =
640 ring_proof::multi_ring_batch_verifier::BatchItem<<S as RingSuite>::Pairing, CurveConfig<S>>;
641
642pub struct BatchItem<S: RingSuite> {
644 ring: RingProofBatchItem<S>,
645 pedersen: pedersen::BatchItem<S>,
646}
647
648impl<S: RingSuite> BatchItem<S> {
649 pub fn new(
658 verifier: &RingVerifier<S>,
659 ios: impl AsRef<[VrfIo<S>]>,
660 ad: impl AsRef<[u8]>,
661 proof: &Proof<S>,
662 ) -> Result<Self, Error> {
663 let key_commitment = proof
664 .pedersen_proof
665 .key_commitment()
666 .into_te()
667 .ok_or(Error::InvalidData)?;
668 let pedersen = pedersen::BatchItem::new(ios, ad, &proof.pedersen_proof);
669 let ring = RingProofBatchItem::<S>::new(verifier, proof.ring_proof.clone(), key_commitment);
670 Ok(Self { ring, pedersen })
671 }
672}
673
674pub struct BatchVerifier<S: RingSuite> {
683 ring_batch: RingBatchVerifier<S>,
684 pedersen_batch: pedersen::BatchVerifier<S>,
685}
686
687impl<S: RingSuite> BatchVerifier<S> {
688 pub fn new(ring_verifier: &RingVerifier<S>) -> Self {
694 Self {
695 ring_batch: RingBatchVerifier::<S>::new(
696 ring_verifier.pcs_vk().clone(),
697 ring_proof::ArkTranscript::new(S::SUITE_ID),
698 ),
699 pedersen_batch: pedersen::BatchVerifier::new(),
700 }
701 }
702
703 pub fn push_prepared(&mut self, item: BatchItem<S>) {
705 self.pedersen_batch.push_prepared(item.pedersen);
706 self.ring_batch.push_prepared(item.ring);
707 }
708
709 pub fn push(
714 &mut self,
715 verifier: &RingVerifier<S>,
716 ios: impl AsRef<[VrfIo<S>]>,
717 ad: impl AsRef<[u8]>,
718 proof: &Proof<S>,
719 ) -> Result<(), Error> {
720 let item = BatchItem::new(verifier, ios, ad, proof)?;
721 self.push_prepared(item);
722 Ok(())
723 }
724
725 pub fn verify(&self) -> Result<(), Error> {
730 self.pedersen_batch.verify()?;
731 self.ring_batch
732 .verify()
733 .then_some(())
734 .ok_or(Error::VerificationFailure)
735 }
736}
737
738#[macro_export]
740macro_rules! ring_suite_types {
741 ($suite:ident) => {
742 #[allow(dead_code)]
743 pub type PcsParams = $crate::ring::PcsParams<$suite>;
744 #[allow(dead_code)]
745 pub type PcsVerifierParams = $crate::ring::PcsVerifierParams<$suite>;
746 #[allow(dead_code)]
747 pub type PiopParams = $crate::ring::PiopParams<$suite>;
748 #[allow(dead_code)]
749 pub type RingContext = $crate::ring::RingContext<$suite>;
750 #[allow(dead_code)]
751 pub type RingSetup = $crate::ring::RingSetup<$suite>;
752 #[allow(dead_code)]
753 pub type RingProverKey = $crate::ring::RingProverKey<$suite>;
754 #[allow(dead_code)]
755 pub type RingVerifierKey = $crate::ring::RingVerifierKey<$suite>;
756 #[allow(dead_code)]
757 pub type RingCommitment = $crate::ring::RingCommitment<$suite>;
758 #[allow(dead_code)]
759 pub type RingProver = $crate::ring::RingProver<$suite>;
760 #[allow(dead_code)]
761 pub type RingVerifier = $crate::ring::RingVerifier<$suite>;
762 #[allow(dead_code)]
763 pub type RingProof = $crate::ring::Proof<$suite>;
764 #[allow(dead_code)]
765 pub type RingVerifierKeyBuilder = $crate::ring::VerifierKeyBuilder<$suite>;
766 #[allow(dead_code)]
767 pub type RingBatchItem = $crate::ring::BatchItem<$suite>;
768 #[allow(dead_code)]
769 pub type RingBatchVerifier = $crate::ring::BatchVerifier<$suite>;
770 };
771}
772
773pub mod dom_utils {
796 use super::*;
797
798 pub const fn max_ring_size<S: Suite>(min_ring_size: usize) -> usize {
806 max_ring_size_from_piop_domain_size::<S>(piop_domain_size::<S>(min_ring_size))
807 }
808
809 pub const fn piop_overhead<S: Suite>() -> usize {
811 4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize
812 }
813
814 pub const fn piop_domain_size<S: Suite>(min_ring_capacity: usize) -> usize {
820 (min_ring_capacity + piop_overhead::<S>()).next_power_of_two()
821 }
822
823 pub const fn max_ring_size_from_piop_domain_size<S: Suite>(piop_domain_size: usize) -> usize {
827 piop_domain_size - piop_overhead::<S>()
828 }
829
830 pub const fn pcs_domain_size<S: Suite>(min_ring_size: usize) -> usize {
835 pcs_domain_size_from_piop_domain_size(piop_domain_size::<S>(min_ring_size))
836 }
837
838 pub const fn pcs_domain_size_from_piop_domain_size(piop_domain_size: usize) -> usize {
842 3 * piop_domain_size + 1
843 }
844
845 pub const fn piop_domain_size_from_pcs_domain_size(pcs_domain_size: usize) -> usize {
850 1 << ((pcs_domain_size - 1) / 3).ilog2()
851 }
852
853 pub const fn max_ring_size_from_pcs_domain_size<S: Suite>(pcs_domain_size: usize) -> usize {
857 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_domain_size);
858 max_ring_size_from_piop_domain_size::<S>(piop_domain_size)
859 }
860}
861pub use dom_utils::*;
862
863#[cfg(test)]
864pub(crate) mod testing {
865 use super::*;
866 use crate::pedersen;
867 use crate::testing::{self as common, CheckPoint, TEST_SEED};
868 use ark_ec::{
869 short_weierstrass::{Affine as SWAffine, SWCurveConfig},
870 twisted_edwards::{Affine as TEAffine, TECurveConfig},
871 };
872
873 pub const TEST_RING_SIZE: usize = 8;
874
875 const MAX_AD_LEN: usize = 100;
876
877 fn find_complement_point<C: SWCurveConfig>() -> SWAffine<C> {
878 use ark_ff::{One, Zero};
879 assert!(!C::cofactor_is_one());
880 let mut x = C::BaseField::zero();
881 loop {
882 if let Some(p) = SWAffine::get_point_from_x_unchecked(x, false)
883 .filter(|p| !p.is_in_correct_subgroup_assuming_on_curve())
884 {
885 return p;
886 }
887 x += C::BaseField::one();
888 }
889 }
890
891 pub trait FindAccumulatorBase<S: Suite>: Sized {
892 const IN_PRIME_ORDER_SUBGROUP: bool;
893 fn find_accumulator_base(data: &[u8]) -> Option<Self>;
894 }
895
896 impl<S, C> FindAccumulatorBase<S> for SWAffine<C>
897 where
898 C: SWCurveConfig,
899 S: Suite<Affine = Self>,
900 {
901 const IN_PRIME_ORDER_SUBGROUP: bool = false;
902
903 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
904 let p = S::data_to_point(data)?;
905 let c = find_complement_point();
906 let res = (p + c).into_affine();
907 debug_assert!(!res.is_in_correct_subgroup_assuming_on_curve());
908 Some(res)
909 }
910 }
911
912 impl<S, C> FindAccumulatorBase<S> for TEAffine<C>
913 where
914 C: TECurveConfig,
915 S: Suite<Affine = Self>,
916 {
917 const IN_PRIME_ORDER_SUBGROUP: bool = true;
918
919 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
920 let res = S::data_to_point(data)?;
921 debug_assert!(res.is_in_correct_subgroup_assuming_on_curve());
922 Some(res)
923 }
924 }
925
926 struct TestItem<S: RingSuite> {
927 io: VrfIo<S>,
928 ad: Vec<u8>,
929 proof: Proof<S>,
930 }
931
932 impl<S: RingSuite> TestItem<S> {
933 fn new(
934 secret: &Secret<S>,
935 prover: &RingProver<S>,
936 rng: &mut dyn ark_std::rand::RngCore,
937 ) -> Self {
938 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
939 let io = secret.vrf_io(input);
940 let ad_len = common::random_val::<usize>(Some(rng)) % (MAX_AD_LEN + 1);
941 let ad = common::random_vec(ad_len, Some(rng));
942 let proof = secret.prove(io, &ad, prover);
943 Self { io, ad, proof }
944 }
945 }
946
947 #[allow(unused)]
948 pub fn prove_verify<S: RingSuite>() {
949 let rng = &mut ark_std::test_rng();
950 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
951
952 let secret = Secret::<S>::from_seed(TEST_SEED);
953 let public = secret.public();
954
955 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
956 let prover_idx = 3;
957 pks[prover_idx] = public.0;
958
959 let ring_ctx = ring_setup.ring_context();
960 let prover_key = ring_setup.prover_key(&pks).unwrap();
961 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
962
963 let item = TestItem::<S>::new(&secret, &prover, rng);
964
965 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
966 let verifier = ring_ctx.ring_verifier(verifier_key);
967 let result = Public::verify(item.io, &item.ad, &item.proof, &verifier);
968 assert!(result.is_ok());
969 }
970
971 #[allow(unused)]
973 pub fn prove_verify_multi<S: RingSuite>() {
974 use ring::{Prover, Verifier};
975
976 let rng = &mut ark_std::test_rng();
977 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
978
979 let secret = Secret::<S>::from_seed(TEST_SEED);
980 let public = secret.public();
981
982 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
983 let prover_idx = 3;
984 pks[prover_idx] = public.0;
985
986 let ring_ctx = ring_setup.ring_context();
987 let prover_key = ring_setup.prover_key(&pks).unwrap();
988 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
989
990 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
991 let verifier = ring_ctx.ring_verifier(verifier_key);
992
993 let mut ios: Vec<VrfIo<S>> = (0..3u8)
994 .map(|i| {
995 let input = Input::new(&[i + 1]).unwrap();
996 secret.vrf_io(input)
997 })
998 .collect();
999 ios.push(VrfIo {
1000 input: Input(S::Affine::generator()),
1001 output: Output(public.0),
1002 });
1003
1004 let proof = secret.prove(&ios[..], b"bar", &prover);
1005 assert!(Public::verify(&ios[..], b"bar", &proof, &verifier).is_ok());
1006
1007 let mut bad_ios = ios.clone();
1009 bad_ios[1].output = secret.output(ios[0].input);
1010 assert!(Public::verify(&bad_ios[..], b"bar", &proof, &verifier).is_err());
1011
1012 assert!(Public::verify(&ios[..], b"baz", &proof, &verifier).is_err());
1014 }
1015
1016 #[allow(unused)]
1017 pub fn prove_verify_batch<S: RingSuite>() {
1018 use rayon::prelude::*;
1019
1020 const BATCH_SIZE: usize = 3 * TEST_RING_SIZE;
1021
1022 let rng = &mut ark_std::test_rng();
1023 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1024
1025 let secret = Secret::<S>::from_seed(TEST_SEED);
1026 let public = secret.public();
1027
1028 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1029 let prover_idx = 3;
1030 pks[prover_idx] = public.0;
1031
1032 let ring_ctx = ring_setup.ring_context();
1033 let prover_key = ring_setup.prover_key(&pks).unwrap();
1034 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1035
1036 let batch: Vec<_> = (0..BATCH_SIZE)
1038 .into_par_iter()
1039 .map_init(ark_std::test_rng, |rng, _| {
1040 TestItem::<S>::new(&secret, &prover, rng)
1041 })
1042 .collect();
1043
1044 let verifier_key = ring_setup.verifier_key(&pks).unwrap();
1045 let verifier = ring_ctx.ring_verifier(verifier_key);
1046
1047 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1049 let res = batch_verifier.verify();
1050 assert!(res.is_ok());
1051
1052 for item in batch.iter() {
1054 batch_verifier
1055 .push(&verifier, item.io, &item.ad, &item.proof)
1056 .unwrap();
1057 let res = batch_verifier.verify();
1058 assert!(res.is_ok());
1059 }
1060
1061 println!("Batch size = {BATCH_SIZE}");
1062
1063 println!("============================================================");
1064
1065 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1066 let start = std::time::Instant::now();
1067 common::timed("Proofs push", || {
1068 for item in batch.iter() {
1069 batch_verifier
1070 .push(&verifier, item.io, &item.ad, &item.proof)
1071 .unwrap();
1072 }
1073 });
1074 common::timed("Unprepared batch verification", || batch_verifier.verify());
1075 println!("Total time: {:?}", start.elapsed());
1076
1077 println!("============================================================");
1078
1079 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1080 let start = std::time::Instant::now();
1081 let prepared = common::timed("Proofs prepare", || {
1082 batch
1083 .par_iter()
1084 .map(|item| BatchItem::<S>::new(&verifier, item.io, &item.ad, &item.proof).unwrap())
1085 .collect::<Vec<_>>()
1086 });
1087 common::timed("Proofs push prepared", || {
1088 prepared
1089 .into_iter()
1090 .for_each(|p| batch_verifier.push_prepared(p))
1091 });
1092 common::timed("Prepared batch verification", || batch_verifier.verify());
1093 println!("Total time: {:?}", start.elapsed());
1094
1095 println!("============================================================");
1096
1097 let mut pks_b = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1100 let prover_idx_b = 1;
1101 pks_b[prover_idx_b] = public.0;
1102 let prover_key_b = ring_setup.prover_key(&pks_b).unwrap();
1103 let prover_b = ring_ctx.ring_prover(prover_key_b, prover_idx_b);
1104 let verifier_key_b = ring_setup.verifier_key(&pks_b).unwrap();
1105 let verifier_b = ring_ctx.ring_verifier(verifier_key_b);
1106
1107 let batch_b: Vec<_> = (0..TEST_RING_SIZE)
1108 .into_par_iter()
1109 .map_init(ark_std::test_rng, |rng, _| {
1110 TestItem::<S>::new(&secret, &prover_b, rng)
1111 })
1112 .collect();
1113
1114 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1115 for item in batch.iter() {
1116 batch_verifier
1117 .push(&verifier, item.io, &item.ad, &item.proof)
1118 .unwrap();
1119 }
1120 for item in batch_b.iter() {
1121 batch_verifier
1122 .push(&verifier_b, item.io, &item.ad, &item.proof)
1123 .unwrap();
1124 }
1125 common::timed("Multi-ring batch verification", || batch_verifier.verify())
1126 .expect("multi-ring batch verifies");
1127
1128 let mut batch_verifier = BatchVerifier::<S>::new(&verifier);
1132 let item_b = &batch_b[0];
1133 batch_verifier
1134 .push(&verifier, item_b.io, &item_b.ad, &item_b.proof)
1135 .unwrap();
1136 assert!(
1137 batch_verifier.verify().is_err(),
1138 "ring-B proof must not verify against verifier_a"
1139 );
1140 }
1141
1142 #[allow(unused)]
1145 pub fn ring_size_exceeded<S: RingSuite>() {
1146 let rng = &mut ark_std::test_rng();
1147 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1148
1149 let max_ring_size = ring_setup.max_ring_size();
1150 let pks = common::random_vec::<AffinePoint<S>>(max_ring_size + 1, Some(rng));
1151 assert!(matches!(
1152 ring_setup.prover_key(&pks),
1153 Err(Error::RingCapacityExceeded)
1154 ));
1155 assert!(matches!(
1156 ring_setup.verifier_key(&pks),
1157 Err(Error::RingCapacityExceeded)
1158 ));
1159
1160 let pcs_params = ring_setup.pcs_params.clone();
1162 assert!(matches!(
1163 RingSetup::<S>::from_pcs_params(max_ring_size + 1, pcs_params),
1164 Err(Error::RingCapacityExceeded)
1165 ));
1166 }
1167
1168 #[allow(unused)]
1169 pub fn padding_check<S: RingSuite>()
1170 where
1171 AffinePoint<S>: CheckPoint,
1172 {
1173 assert_eq!(S::PADDING, S::data_to_point(PADDING_SEED).unwrap());
1175
1176 assert!(S::PADDING.check(true).is_ok());
1178 }
1179
1180 #[allow(unused)]
1181 pub fn accumulator_base_check<S: RingSuite>()
1182 where
1183 AffinePoint<S>: FindAccumulatorBase<S> + CheckPoint,
1184 {
1185 assert_eq!(
1187 S::ACCUMULATOR_BASE,
1188 AffinePoint::<S>::find_accumulator_base(ACCUMULATOR_BASE_SEED).unwrap()
1189 );
1190
1191 let in_prime_subgroup = <AffinePoint<S> as FindAccumulatorBase<S>>::IN_PRIME_ORDER_SUBGROUP;
1194 assert!(S::ACCUMULATOR_BASE.check(in_prime_subgroup).is_ok());
1195 }
1196
1197 #[allow(unused)]
1198 pub fn verifier_key_from_commitment<S: RingSuite>() {
1199 let rng = &mut ark_std::test_rng();
1200 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1201
1202 let secret = Secret::<S>::from_seed(TEST_SEED);
1203 let public = secret.public();
1204
1205 let mut pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1206 let prover_idx = 3;
1207 pks[prover_idx] = public.0;
1208
1209 let prover_key = ring_setup.prover_key(&pks).unwrap();
1210 let prover = ring_setup
1211 .ring_context()
1212 .ring_prover(prover_key, prover_idx);
1213 let item = TestItem::<S>::new(&secret, &prover, rng);
1214
1215 let commitment = ring_setup.verifier_key(&pks).unwrap().commitment();
1216
1217 let mut buf = Vec::new();
1220 ring_setup
1221 .pcs_verifier_params()
1222 .serialize_compressed(&mut buf)
1223 .unwrap();
1224 let pcs_params = PcsVerifierParams::<S>::deserialize_compressed(&buf[..]).unwrap();
1225
1226 let ring_ctx = RingContext::<S>::new(TEST_RING_SIZE);
1227 let verifier_key = super::verifier_key_from_commitment::<S>(commitment, pcs_params);
1228 let verifier = ring_ctx.ring_verifier(verifier_key);
1229 assert!(Public::verify(item.io, &item.ad, &item.proof, &verifier).is_ok());
1230 }
1231
1232 #[allow(unused)]
1233 pub fn verifier_key_builder<S: RingSuite>() {
1234 use crate::testing::{random_val, random_vec};
1235
1236 let rng = &mut ark_std::test_rng();
1237 let ring_setup = RingSetup::<S>::from_rand(TEST_RING_SIZE, rng);
1238
1239 let secret = Secret::<S>::from_seed(TEST_SEED);
1240 let public = secret.public();
1241 let input = Input::from_affine_unchecked(common::random_val(Some(rng)));
1242 let io = secret.vrf_io(input);
1243
1244 let ring_ctx = ring_setup.ring_context();
1245 let ring_size = ring_ctx.max_ring_size();
1246 let prover_idx = random_val::<usize>(Some(rng)) % ring_size;
1247 let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
1248 pks[prover_idx] = public.0;
1249
1250 let prover_key = ring_setup.prover_key(&pks).unwrap();
1251 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1252 let proof = secret.prove(io, b"foo", &prover);
1253
1254 let (mut vk_builder, lookup) = ring_setup.verifier_key_builder();
1256 assert_eq!(vk_builder.free_slots(), pks.len());
1257 assert_eq!(
1258 vk_builder.pcs_verifier_params(),
1259 ring_setup.pcs_verifier_params()
1260 );
1261
1262 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1263 assert_eq!(
1264 vk_builder.append(&[extra_pk], |_| None).unwrap_err(),
1265 Error::SrsLookupFailed
1266 );
1267
1268 while !pks.is_empty() {
1269 let chunk_len = 1 + random_val::<usize>(Some(rng)) % 5;
1270 let chunk = pks.drain(..pks.len().min(chunk_len)).collect::<Vec<_>>();
1271 vk_builder.append(&chunk[..], &lookup).unwrap();
1272 assert_eq!(vk_builder.free_slots(), pks.len());
1273 }
1274 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
1276 assert_eq!(
1277 vk_builder.append(&[extra_pk], &lookup).unwrap_err(),
1278 Error::RingCapacityExceeded
1279 );
1280 assert_eq!(vk_builder.free_slots(), 0);
1281 let verifier_key = vk_builder.finalize();
1282 let verifier = ring_ctx.ring_verifier(verifier_key);
1283 let result = Public::verify(io, b"foo", &proof, &verifier);
1284 assert!(result.is_ok());
1285 }
1286
1287 pub fn domain_size_conversions<S: RingSuite>() {
1288 let overhead = piop_overhead::<S>();
1289
1290 for ring_size in [1, 10, 200, 300, 500, 1000, 2000, 10000] {
1291 let piop_dom_size = piop_domain_size::<S>(ring_size);
1292 let pcs_dom_size = pcs_domain_size::<S>(ring_size);
1293 let max_ring_size = max_ring_size_from_piop_domain_size::<S>(piop_dom_size);
1294
1295 assert!(piop_dom_size.is_power_of_two());
1296 assert_eq!(pcs_dom_size, 3 * piop_dom_size + 1);
1297
1298 assert!(piop_dom_size >= ring_size + overhead);
1300 assert!(piop_dom_size / 2 < ring_size + overhead);
1302 assert_eq!(piop_dom_size, piop_domain_size::<S>(max_ring_size));
1304 assert!(ring_size <= max_ring_size);
1306
1307 assert_eq!(dom_utils::max_ring_size::<S>(ring_size), max_ring_size);
1309 assert_eq!(dom_utils::max_ring_size::<S>(max_ring_size), max_ring_size);
1311
1312 let piop_dom_rt = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1314 assert_eq!(piop_dom_size, piop_dom_rt);
1315 let pcs_dom_rt = pcs_domain_size_from_piop_domain_size(piop_dom_rt);
1316 assert_eq!(pcs_dom_size, pcs_dom_rt);
1317
1318 let max_ring_from_pcs = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1319 assert_eq!(max_ring_size, max_ring_from_pcs);
1320
1321 let next_piop = piop_domain_size::<S>(max_ring_size + 1);
1323 assert!(next_piop > piop_dom_size,);
1324 assert!(next_piop.is_power_of_two());
1325 }
1326
1327 for pcs_dom_size in [1 << 11, 1 << 12, 1 << 14, 1 << 16] {
1330 let piop_dom = piop_domain_size_from_pcs_domain_size(pcs_dom_size);
1331 let max_ring = max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size);
1332
1333 assert!(piop_dom.is_power_of_two());
1334 assert!(3 * piop_dom < pcs_dom_size);
1336 assert!(3 * (2 * piop_dom) + 1 > pcs_dom_size);
1338 assert_eq!(piop_domain_size::<S>(max_ring), piop_dom);
1340 assert!(piop_domain_size::<S>(max_ring + 1) > piop_dom);
1342 }
1343
1344 let piop_zero = piop_domain_size::<S>(0);
1346 assert!(piop_zero.is_power_of_two());
1347 assert_eq!(piop_zero, overhead.next_power_of_two());
1348 }
1349
1350 #[macro_export]
1351 macro_rules! ring_suite_tests {
1352 ($suite:ty) => {
1353 mod ring {
1354 use super::*;
1355
1356 #[test]
1357 fn prove_verify() {
1358 $crate::ring::testing::prove_verify::<$suite>()
1359 }
1360
1361 #[test]
1362 fn prove_verify_multi() {
1363 $crate::ring::testing::prove_verify_multi::<$suite>()
1364 }
1365
1366 #[test]
1367 fn prove_verify_batch() {
1368 $crate::ring::testing::prove_verify_batch::<$suite>()
1369 }
1370
1371 #[test]
1372 fn ring_size_exceeded() {
1373 $crate::ring::testing::ring_size_exceeded::<$suite>()
1374 }
1375
1376 #[test]
1377 fn padding_check() {
1378 $crate::ring::testing::padding_check::<$suite>()
1379 }
1380
1381 #[test]
1382 fn accumulator_base_check() {
1383 $crate::ring::testing::accumulator_base_check::<$suite>()
1384 }
1385
1386 #[test]
1387 fn verifier_key_builder() {
1388 $crate::ring::testing::verifier_key_builder::<$suite>()
1389 }
1390
1391 #[test]
1392 fn verifier_key_from_commitment() {
1393 $crate::ring::testing::verifier_key_from_commitment::<$suite>()
1394 }
1395
1396 #[test]
1397 fn domain_size_conversions() {
1398 $crate::ring::testing::domain_size_conversions::<$suite>()
1399 }
1400
1401 $crate::test_vectors!($crate::ring::testing::TestVector<$suite>);
1402 }
1403 };
1404 }
1405
1406 pub trait RingSuiteExt: RingSuite + crate::testing::SuiteExt {
1407 const SRS_FILE: &str;
1408
1409 fn ring_setup() -> &'static RingSetup<Self>;
1410
1411 #[allow(unused)]
1412 fn load_ring_setup() -> RingSetup<Self> {
1413 use ark_serialize::CanonicalDeserialize;
1414 use std::{fs::File, io::Read};
1415 let mut file = File::open(Self::SRS_FILE).unwrap();
1416 let mut buf = Vec::new();
1417 file.read_to_end(&mut buf).unwrap();
1418 let pcs_params =
1419 PcsParams::<Self>::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
1420 RingSetup::from_pcs_params(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
1421 }
1422
1423 #[allow(unused)]
1424 fn write_ring_setup(ring_setup: &RingSetup<Self>) {
1425 use ark_serialize::CanonicalSerialize;
1426 use std::{fs::File, io::Write};
1427 let mut file = File::create(Self::SRS_FILE).unwrap();
1428 let mut buf = Vec::new();
1429 ring_setup
1430 .pcs_params
1431 .serialize_uncompressed(&mut buf)
1432 .unwrap();
1433 file.write_all(&buf).unwrap();
1434 }
1435 }
1436
1437 pub struct TestVector<S: RingSuite> {
1438 pub pedersen: pedersen::testing::TestVector<S>,
1439 pub ring_pks: [AffinePoint<S>; TEST_RING_SIZE],
1440 pub ring_pks_com: RingCommitment<S>,
1441 pub ring_proof: RingBareProof<S>,
1442 }
1443
1444 impl<S: RingSuite> core::fmt::Debug for TestVector<S> {
1445 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1446 f.debug_struct("TestVector")
1447 .field("pedersen", &self.pedersen)
1448 .field("ring_proof", &"...")
1449 .finish()
1450 }
1451 }
1452
1453 impl<S> common::TestVectorTrait for TestVector<S>
1454 where
1455 S: RingSuiteExt + std::fmt::Debug + 'static,
1456 {
1457 fn name() -> String {
1458 S::SUITE_NAME.to_string() + "_ring"
1459 }
1460
1461 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
1462 use super::Prover;
1463 let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, ad);
1464
1465 let secret = Secret::<S>::from_scalar(pedersen.base.sk);
1466 let public = secret.public();
1467
1468 let io = VrfIo {
1469 input: Input::<S>::from_affine_unchecked(pedersen.base.h),
1470 output: Output::from_affine_unchecked(pedersen.base.gamma),
1471 };
1472
1473 let ring_setup = <S as RingSuiteExt>::ring_setup();
1474
1475 use ark_std::rand::SeedableRng;
1476 let rng = &mut ark_std::rand::rngs::StdRng::from_seed([42; 32]);
1477 let prover_idx = 3;
1478 let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
1479 ring_pks[prover_idx] = public.0;
1480
1481 let ring_ctx = RingContext::<S>::new_without_blinding(TEST_RING_SIZE);
1483 let prover_key = ring_setup.prover_key(&ring_pks).unwrap();
1484 let prover = ring_ctx.into_ring_prover(prover_key, prover_idx);
1485 let proof = secret.prove(io, ad, &prover);
1486
1487 let verifier_key = ring_setup.verifier_key(&ring_pks).unwrap();
1488 let ring_pks_com = verifier_key.commitment();
1489
1490 {
1491 let mut p = (Vec::new(), Vec::new());
1493 pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1494 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1495 assert_eq!(p.0, p.1);
1496 }
1497
1498 Self {
1499 pedersen,
1500 ring_pks: ring_pks.try_into().unwrap(),
1501 ring_pks_com,
1502 ring_proof: proof.ring_proof,
1503 }
1504 }
1505
1506 fn from_map(map: &common::TestVectorMap) -> Self {
1507 let pedersen = pedersen::testing::TestVector::from_map(map);
1508
1509 let ring_pks = map.get::<[AffinePoint<S>; TEST_RING_SIZE]>("ring_pks");
1510 let ring_pks_com = map.get::<RingCommitment<S>>("ring_pks_com");
1511 let ring_proof = map.get::<RingBareProof<S>>("ring_proof");
1512
1513 Self {
1514 pedersen,
1515 ring_pks,
1516 ring_pks_com,
1517 ring_proof,
1518 }
1519 }
1520
1521 fn to_map(&self) -> common::TestVectorMap {
1522 let mut map = self.pedersen.to_map();
1523 map.set("ring_pks", &self.ring_pks);
1524 map.set("ring_pks_com", &self.ring_pks_com);
1525 map.set("ring_proof", &self.ring_proof);
1526 map
1527 }
1528
1529 fn run(&self) {
1530 self.pedersen.run();
1531
1532 let io = VrfIo {
1533 input: Input::<S>::from_affine_unchecked(self.pedersen.base.h),
1534 output: Output::from_affine_unchecked(self.pedersen.base.gamma),
1535 };
1536 let secret = Secret::from_scalar(self.pedersen.base.sk);
1537 let public = secret.public();
1538 assert_eq!(public.0, self.pedersen.base.pk);
1539
1540 let ring_setup = <S as RingSuiteExt>::ring_setup();
1541
1542 let prover_idx = self.ring_pks.iter().position(|&pk| pk == public.0).unwrap();
1543
1544 let ring_ctx = RingContext::<S>::new_without_blinding(TEST_RING_SIZE);
1546 let prover_key = ring_setup.prover_key(&self.ring_pks).unwrap();
1547 let prover = ring_ctx.ring_prover(prover_key, prover_idx);
1548
1549 let verifier_key = ring_setup.verifier_key(&self.ring_pks).unwrap();
1550 let verifier = ring_ctx.ring_verifier(verifier_key);
1551
1552 let proof = secret.prove(io, &self.pedersen.base.ad, &prover);
1553
1554 {
1555 let mut p = (Vec::new(), Vec::new());
1557 self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
1558 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
1559 assert_eq!(p.0, p.1);
1560 }
1561
1562 {
1563 let mut p = (Vec::new(), Vec::new());
1565 self.ring_proof.serialize_compressed(&mut p.0).unwrap();
1566 proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
1567 assert_eq!(p.0, p.1);
1568 }
1569
1570 assert!(Public::verify(io, &self.pedersen.base.ad, &proof, &verifier).is_ok());
1571 }
1572 }
1573}