1use crate::*;
42use ark_ec::{
43 pairing::Pairing,
44 twisted_edwards::{Affine as TEAffine, TECurveConfig},
45};
46use ark_std::ops::Range;
47use pedersen::{PedersenSuite, Proof as PedersenProof};
48use utils::te_sw_map::TEMapping;
49use w3f_ring_proof as ring_proof;
50
51pub const ACCUMULATOR_BASE_SEED: &[u8] =
55 b"substratum accumulatoris quod in silentio temporis arcanum absconditum custodit";
56
57pub const PADDING_SEED: &[u8] =
61 b"umbra quae vacuum implet ab animabus perditis relictum inter tenebras resonans";
62
63pub const fn max_ring_size_from_pcs_domain_size<S: Suite>(pcs_domain_size: usize) -> usize {
65 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_domain_size);
66 max_ring_size_from_piop_domain_size::<S>(piop_domain_size)
67}
68
69pub const fn pcs_domain_size<S: Suite>(ring_size: usize) -> usize {
72 3 * piop_domain_size::<S>(ring_size) + 1
73}
74
75const fn max_ring_size_from_piop_domain_size<S: Suite>(piop_domain_size: usize) -> usize {
77 piop_domain_size - (4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize)
78}
79
80const fn piop_domain_size<S: Suite>(ring_size: usize) -> usize {
84 (ring_size + 4 + ScalarField::<S>::MODULUS_BIT_SIZE as usize).next_power_of_two()
85}
86
87const fn piop_domain_size_from_pcs_domain_size(pcs_domain_size: usize) -> usize {
90 1 << ((pcs_domain_size - 1) / 3).ilog2()
91}
92
93pub trait RingSuite:
98 PedersenSuite<
99 Affine: AffineRepr<BaseField: ark_ff::PrimeField, Config: TECurveConfig + Clone>
100 + TEMapping<<Self::Affine as AffineRepr>::Config>,
101>
102{
103 type Pairing: ark_ec::pairing::Pairing<ScalarField = BaseField<Self>>;
105
106 const ACCUMULATOR_BASE: AffinePoint<Self>;
111
112 const PADDING: AffinePoint<Self>;
114}
115
116pub type Pcs<S> = ring_proof::pcs::kzg::KZG<<S as RingSuite>::Pairing>;
118
119pub type PcsCommitment<S> =
121 ring_proof::pcs::kzg::commitment::KzgCommitment<<S as RingSuite>::Pairing>;
122
123pub type PcsParams<S> = ring_proof::pcs::kzg::urs::URS<<S as RingSuite>::Pairing>;
127
128pub type PiopParams<S> = ring_proof::PiopParams<BaseField<S>, CurveConfig<S>>;
133
134pub type RingCommitment<S> = ring_proof::FixedColumnsCommitted<BaseField<S>, PcsCommitment<S>>;
136
137pub type RingProverKey<S> = ring_proof::ProverKey<BaseField<S>, Pcs<S>, TEAffine<CurveConfig<S>>>;
139
140pub type RingVerifierKey<S> = ring_proof::VerifierKey<BaseField<S>, Pcs<S>>;
142
143pub type RingProver<S> = ring_proof::ring_prover::RingProver<BaseField<S>, Pcs<S>, CurveConfig<S>>;
145
146pub type RingVerifier<S> =
148 ring_proof::ring_verifier::RingVerifier<BaseField<S>, Pcs<S>, CurveConfig<S>>;
149
150pub type RingBareProof<S> = ring_proof::RingProof<BaseField<S>, Pcs<S>>;
155
156#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
162pub struct Proof<S: RingSuite> {
163 pub pedersen_proof: PedersenProof<S>,
164 pub ring_proof: RingBareProof<S>,
165}
166
167pub trait Prover<S: RingSuite> {
172 fn prove(
183 &self,
184 input: Input<S>,
185 output: Output<S>,
186 ad: impl AsRef<[u8]>,
187 prover: &RingProver<S>,
188 ) -> Proof<S>;
189}
190
191pub trait Verifier<S: RingSuite> {
196 fn verify(
211 input: Input<S>,
212 output: Output<S>,
213 ad: impl AsRef<[u8]>,
214 sig: &Proof<S>,
215 verifier: &RingVerifier<S>,
216 ) -> Result<(), Error>;
217}
218
219impl<S: RingSuite> Prover<S> for Secret<S> {
220 fn prove(
221 &self,
222 input: Input<S>,
223 output: Output<S>,
224 ad: impl AsRef<[u8]>,
225 ring_prover: &RingProver<S>,
226 ) -> Proof<S> {
227 use pedersen::Prover as PedersenProver;
228 let (pedersen_proof, secret_blinding) =
229 <Self as PedersenProver<S>>::prove(self, input, output, ad);
230 let ring_proof = ring_prover.prove(secret_blinding);
231 Proof {
232 pedersen_proof,
233 ring_proof,
234 }
235 }
236}
237
238impl<S: RingSuite> Verifier<S> for Public<S> {
239 fn verify(
240 input: Input<S>,
241 output: Output<S>,
242 ad: impl AsRef<[u8]>,
243 sig: &Proof<S>,
244 verifier: &RingVerifier<S>,
245 ) -> Result<(), Error> {
246 use pedersen::Verifier as PedersenVerifier;
247 <Self as PedersenVerifier<S>>::verify(input, output, ad, &sig.pedersen_proof)?;
248 let key_commitment = sig.pedersen_proof.key_commitment().into_te();
249 if !verifier.verify(sig.ring_proof.clone(), key_commitment) {
250 return Err(Error::VerificationFailure);
251 }
252 Ok(())
253 }
254}
255
256#[derive(Clone)]
262pub struct RingProofParams<S: RingSuite> {
263 pub pcs: PcsParams<S>,
265 pub piop: PiopParams<S>,
267}
268
269pub(crate) fn piop_params<S: RingSuite>(domain_size: usize) -> PiopParams<S> {
270 PiopParams::<S>::setup(
271 ring_proof::Domain::new(domain_size, true),
272 S::BLINDING_BASE.into_te(),
273 S::ACCUMULATOR_BASE.into_te(),
274 S::PADDING.into_te(),
275 )
276}
277
278impl<S: RingSuite> RingProofParams<S> {
279 pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self {
283 use ark_std::rand::SeedableRng;
284 let mut rng = rand_chacha::ChaCha20Rng::from_seed(seed);
285 Self::from_rand(ring_size, &mut rng)
286 }
287
288 pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self {
292 use ring_proof::pcs::PCS;
293 let max_degree = pcs_domain_size::<S>(ring_size) - 1;
294 let pcs_params = Pcs::<S>::setup(max_degree, rng);
295 Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct")
296 }
297
298 pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams<S>) -> Result<Self, Error> {
306 let pcs_domain_size = pcs_domain_size::<S>(ring_size);
307 if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 {
308 return Err(Error::InvalidData);
309 }
310 pcs_params.powers_in_g1.truncate(pcs_domain_size);
312 pcs_params.powers_in_g2.truncate(2);
313 let piop_domain_size = piop_domain_size::<S>(ring_size);
314 Ok(Self {
315 pcs: pcs_params,
316 piop: piop_params::<S>(piop_domain_size),
317 })
318 }
319
320 #[inline(always)]
322 pub fn max_ring_size(&self) -> usize {
323 self.piop.keyset_part_size
324 }
325
326 pub fn prover_key(&self, pks: &[AffinePoint<S>]) -> RingProverKey<S> {
333 let pks = TEMapping::to_te_slice(&pks[..pks.len().min(self.max_ring_size())]);
334 ring_proof::index(&self.pcs, &self.piop, &pks).0
335 }
336
337 pub fn prover(&self, prover_key: RingProverKey<S>, key_index: usize) -> RingProver<S> {
342 RingProver::<S>::init(
343 prover_key,
344 self.piop.clone(),
345 key_index,
346 ring_proof::ArkTranscript::new(S::SUITE_ID),
347 )
348 }
349
350 pub fn verifier_key(&self, pks: &[AffinePoint<S>]) -> RingVerifierKey<S> {
357 let pks = TEMapping::to_te_slice(&pks[..pks.len().min(self.max_ring_size())]);
358 ring_proof::index(&self.pcs, &self.piop, &pks).1
359 }
360
361 pub fn verifier_key_from_commitment(
368 &self,
369 commitment: RingCommitment<S>,
370 ) -> RingVerifierKey<S> {
371 use ring_proof::pcs::PcsParams;
372 RingVerifierKey::<S>::from_commitment_and_kzg_vk(commitment, self.pcs.raw_vk())
373 }
374
375 pub fn verifier_key_builder(&self) -> (RingVerifierKeyBuilder<S>, RingBuilderPcsParams<S>) {
380 type RingBuilderKey<S> =
381 ring_proof::ring::RingBuilderKey<BaseField<S>, <S as RingSuite>::Pairing>;
382 let piop_domain_size = piop_domain_size::<S>(self.piop.keyset_part_size);
383 let builder_key = RingBuilderKey::<S>::from_srs(&self.pcs, piop_domain_size);
384 let builder_pcs_params = RingBuilderPcsParams(builder_key.lis_in_g1);
385 let builder = RingVerifierKeyBuilder::new(self, &builder_pcs_params);
386 (builder, builder_pcs_params)
387 }
388
389 pub fn verifier(&self, verifier_key: RingVerifierKey<S>) -> RingVerifier<S> {
393 RingVerifier::<S>::init(
394 verifier_key,
395 self.piop.clone(),
396 ring_proof::ArkTranscript::new(S::SUITE_ID),
397 )
398 }
399
400 pub fn verifier_no_context(
409 verifier_key: RingVerifierKey<S>,
410 ring_size: usize,
411 ) -> RingVerifier<S> {
412 RingVerifier::<S>::init(
413 verifier_key,
414 piop_params::<S>(piop_domain_size::<S>(ring_size)),
415 ring_proof::ArkTranscript::new(S::SUITE_ID),
416 )
417 }
418
419 #[inline(always)]
424 pub const fn padding_point() -> AffinePoint<S> {
425 S::PADDING
426 }
427}
428
429impl<S: RingSuite> CanonicalSerialize for RingProofParams<S> {
430 fn serialize_with_mode<W: ark_serialize::Write>(
431 &self,
432 mut writer: W,
433 compress: ark_serialize::Compress,
434 ) -> Result<(), ark_serialize::SerializationError> {
435 self.pcs.serialize_with_mode(&mut writer, compress)
436 }
437
438 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
439 self.pcs.serialized_size(compress)
440 }
441}
442
443impl<S: RingSuite> CanonicalDeserialize for RingProofParams<S> {
444 fn deserialize_with_mode<R: ark_serialize::Read>(
445 mut reader: R,
446 compress: ark_serialize::Compress,
447 validate: ark_serialize::Validate,
448 ) -> Result<Self, ark_serialize::SerializationError> {
449 let pcs_params = <PcsParams<S> as CanonicalDeserialize>::deserialize_with_mode(
450 &mut reader,
451 compress,
452 validate,
453 )?;
454 let piop_domain_size = piop_domain_size_from_pcs_domain_size(pcs_params.powers_in_g1.len());
455 Ok(Self {
456 pcs: pcs_params,
457 piop: piop_params::<S>(piop_domain_size),
458 })
459 }
460}
461
462impl<S: RingSuite> ark_serialize::Valid for RingProofParams<S> {
463 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
464 self.pcs.check()
465 }
466}
467
468#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
473pub struct RingBuilderPcsParams<S: RingSuite>(pub Vec<G1Affine<S>>);
474
475type PartialRingCommitment<S> =
477 ring_proof::ring::Ring<BaseField<S>, <S as RingSuite>::Pairing, CurveConfig<S>>;
478
479type RawVerifierKey<S> = <PcsParams<S> as ring_proof::pcs::PcsParams>::RVK;
480
481#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
486pub struct RingVerifierKeyBuilder<S: RingSuite> {
487 partial: PartialRingCommitment<S>,
488 raw_vk: RawVerifierKey<S>,
489}
490
491pub type G1Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G1Affine;
492pub type G2Affine<S> = <<S as RingSuite>::Pairing as Pairing>::G2Affine;
493
494pub trait SrsLookup<S: RingSuite> {
498 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>>;
499}
500
501impl<S: RingSuite, F> SrsLookup<S> for F
502where
503 F: Fn(Range<usize>) -> Option<Vec<G1Affine<S>>>,
504{
505 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
506 self(range)
507 }
508}
509
510impl<S: RingSuite> SrsLookup<S> for &RingBuilderPcsParams<S> {
511 fn lookup(&self, range: Range<usize>) -> Option<Vec<G1Affine<S>>> {
512 if range.end > self.0.len() {
513 return None;
514 }
515 Some(self.0[range].to_vec())
516 }
517}
518
519impl<S: RingSuite> RingVerifierKeyBuilder<S> {
520 pub fn new(params: &RingProofParams<S>, lookup: impl SrsLookup<S>) -> Self {
525 use ring_proof::pcs::PcsParams;
526 let lookup = |range: Range<usize>| lookup.lookup(range).ok_or(());
527 let raw_vk = params.pcs.raw_vk();
528 let partial =
529 PartialRingCommitment::<S>::empty(¶ms.piop, lookup, raw_vk.g1.into_group());
530 RingVerifierKeyBuilder { partial, raw_vk }
531 }
532
533 #[inline(always)]
535 pub fn free_slots(&self) -> usize {
536 self.partial.max_keys - self.partial.curr_keys
537 }
538
539 pub fn append(
547 &mut self,
548 pks: &[AffinePoint<S>],
549 lookup: impl SrsLookup<S>,
550 ) -> Result<(), usize> {
551 let avail_slots = self.free_slots();
552 if avail_slots < pks.len() {
553 return Err(avail_slots);
554 }
555 let segment = lookup
558 .lookup(self.partial.curr_keys..self.partial.curr_keys + pks.len())
559 .ok_or(usize::MAX)?;
560 let lookup = |range: Range<usize>| {
561 debug_assert_eq!(segment.len(), range.len());
562 Ok(segment.clone())
563 };
564 let pks = TEMapping::to_te_slice(pks);
565 self.partial.append(&pks, lookup);
566 Ok(())
567 }
568
569 pub fn finalize(self) -> RingVerifierKey<S> {
571 RingVerifierKey::<S>::from_ring_and_kzg_vk(&self.partial, self.raw_vk)
572 }
573}
574
575#[macro_export]
577macro_rules! ring_suite_types {
578 ($suite:ident) => {
579 #[allow(dead_code)]
580 pub type PcsParams = $crate::ring::PcsParams<$suite>;
581 #[allow(dead_code)]
582 pub type PiopParams = $crate::ring::PiopParams<$suite>;
583 #[allow(dead_code)]
584 pub type RingProofParams = $crate::ring::RingProofParams<$suite>;
585 #[allow(dead_code)]
586 pub type RingProverKey = $crate::ring::RingProverKey<$suite>;
587 #[allow(dead_code)]
588 pub type RingVerifierKey = $crate::ring::RingVerifierKey<$suite>;
589 #[allow(dead_code)]
590 pub type RingCommitment = $crate::ring::RingCommitment<$suite>;
591 #[allow(dead_code)]
592 pub type RingProver = $crate::ring::RingProver<$suite>;
593 #[allow(dead_code)]
594 pub type RingVerifier = $crate::ring::RingVerifier<$suite>;
595 #[allow(dead_code)]
596 pub type RingProof = $crate::ring::Proof<$suite>;
597 #[allow(dead_code)]
598 pub type RingVerifierKeyBuilder = $crate::ring::RingVerifierKeyBuilder<$suite>;
599 };
600}
601
602#[cfg(test)]
603pub(crate) mod testing {
604 use super::*;
605 use crate::pedersen;
606 use crate::testing::{self as common, CheckPoint, TEST_SEED};
607 use ark_ec::{
608 short_weierstrass::{Affine as SWAffine, SWCurveConfig},
609 twisted_edwards::{Affine as TEAffine, TECurveConfig},
610 };
611
612 pub const TEST_RING_SIZE: usize = 8;
613
614 fn find_complement_point<C: SWCurveConfig>() -> SWAffine<C> {
615 use ark_ff::{One, Zero};
616 assert!(!C::cofactor_is_one());
617 let mut x = C::BaseField::zero();
618 loop {
619 if let Some(p) = SWAffine::get_point_from_x_unchecked(x, false)
620 .filter(|p| !p.is_in_correct_subgroup_assuming_on_curve())
621 {
622 return p;
623 }
624 x += C::BaseField::one();
625 }
626 }
627
628 pub trait FindAccumulatorBase<S: Suite>: Sized {
629 const IN_PRIME_ORDER_SUBGROUP: bool;
630 fn find_accumulator_base(data: &[u8]) -> Option<Self>;
631 }
632
633 impl<S, C> FindAccumulatorBase<S> for SWAffine<C>
634 where
635 C: SWCurveConfig,
636 S: Suite<Affine = Self>,
637 {
638 const IN_PRIME_ORDER_SUBGROUP: bool = false;
639
640 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
641 let p = S::data_to_point(data)?;
642 let c = find_complement_point();
643 let res = (p + c).into_affine();
644 debug_assert!(!res.is_in_correct_subgroup_assuming_on_curve());
645 Some(res)
646 }
647 }
648
649 impl<S, C> FindAccumulatorBase<S> for TEAffine<C>
650 where
651 C: TECurveConfig,
652 S: Suite<Affine = Self>,
653 {
654 const IN_PRIME_ORDER_SUBGROUP: bool = true;
655
656 fn find_accumulator_base(data: &[u8]) -> Option<Self> {
657 let res = S::data_to_point(data)?;
658 debug_assert!(res.is_in_correct_subgroup_assuming_on_curve());
659 Some(res)
660 }
661 }
662
663 #[allow(unused)]
664 pub fn prove_verify<S: RingSuite>() {
665 let rng = &mut ark_std::test_rng();
666 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
667
668 let secret = Secret::<S>::from_seed(TEST_SEED);
669 let public = secret.public();
670 let input = Input::from(common::random_val(Some(rng)));
671 let output = secret.output(input);
672
673 let ring_size = params.max_ring_size();
674 let pcs_dom_size = pcs_domain_size::<S>(ring_size);
675 assert_eq!(pcs_dom_size, params.pcs.powers_in_g1.len());
676 assert_eq!(pcs_dom_size / 3, piop_domain_size::<S>(ring_size));
677
678 assert_eq!(
679 max_ring_size_from_pcs_domain_size::<S>(pcs_dom_size),
680 ring_size
681 );
682
683 let prover_idx = 3;
684 let mut pks = common::random_vec::<AffinePoint<S>>(ring_size, Some(rng));
685 pks[prover_idx] = public.0;
686
687 let prover_key = params.prover_key(&pks);
688 let prover = params.prover(prover_key, prover_idx);
689 let proof = secret.prove(input, output, b"foo", &prover);
690
691 let verifier_key = params.verifier_key(&pks);
692 let verifier = params.verifier(verifier_key);
693 let result = Public::verify(input, output, b"foo", &proof, &verifier);
694 assert!(result.is_ok());
695 }
696
697 #[allow(unused)]
698 pub fn padding_check<S: RingSuite>()
699 where
700 AffinePoint<S>: CheckPoint,
701 {
702 assert_eq!(S::PADDING, S::data_to_point(PADDING_SEED).unwrap());
704
705 assert!(S::PADDING.check(true).is_ok());
707 }
708
709 #[allow(unused)]
710 pub fn accumulator_base_check<S: RingSuite>()
711 where
712 AffinePoint<S>: FindAccumulatorBase<S> + CheckPoint,
713 {
714 assert_eq!(
716 S::ACCUMULATOR_BASE,
717 AffinePoint::<S>::find_accumulator_base(ACCUMULATOR_BASE_SEED).unwrap()
718 );
719
720 let in_prime_subgroup = <AffinePoint<S> as FindAccumulatorBase<S>>::IN_PRIME_ORDER_SUBGROUP;
723 assert!(S::ACCUMULATOR_BASE.check(in_prime_subgroup).is_ok());
724 }
725
726 #[allow(unused)]
727 pub fn verifier_key_builder<S: RingSuite>() {
728 use crate::testing::{random_val, random_vec};
729
730 let rng = &mut ark_std::test_rng();
731 let params = RingProofParams::<S>::from_rand(TEST_RING_SIZE, rng);
732
733 let secret = Secret::<S>::from_seed(TEST_SEED);
734 let public = secret.public();
735 let input = Input::from(common::random_val(Some(rng)));
736 let output = secret.output(input);
737
738 let ring_size = params.max_ring_size();
739 let prover_idx = random_val::<usize>(Some(rng)) % ring_size;
740 let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
741 pks[prover_idx] = public.0;
742
743 let prover_key = params.prover_key(&pks);
744 let prover = params.prover(prover_key, prover_idx);
745 let proof = secret.prove(input, output, b"foo", &prover);
746
747 let (mut vk_builder, lookup) = params.verifier_key_builder();
749 assert_eq!(vk_builder.free_slots(), pks.len());
750
751 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
752 assert_eq!(
753 vk_builder.append(&[extra_pk], |_| None).unwrap_err(),
754 usize::MAX
755 );
756
757 while !pks.is_empty() {
758 let chunk_len = 1 + random_val::<usize>(Some(rng)) % 5;
759 let chunk = pks.drain(..pks.len().min(chunk_len)).collect::<Vec<_>>();
760 vk_builder.append(&chunk[..], &lookup).unwrap();
761 assert_eq!(vk_builder.free_slots(), pks.len());
762 }
763 let extra_pk = random_val::<AffinePoint<S>>(Some(rng));
765 assert_eq!(vk_builder.append(&[extra_pk], &lookup).unwrap_err(), 0);
766 let verifier_key = vk_builder.finalize();
767 let verifier = params.verifier(verifier_key);
768 let result = Public::verify(input, output, b"foo", &proof, &verifier);
769 assert!(result.is_ok());
770 }
771
772 #[macro_export]
773 macro_rules! ring_suite_tests {
774 ($suite:ty) => {
775 mod ring {
776 use super::*;
777
778 #[test]
779 fn prove_verify() {
780 $crate::ring::testing::prove_verify::<$suite>()
781 }
782
783 #[test]
784 fn padding_check() {
785 $crate::ring::testing::padding_check::<$suite>()
786 }
787
788 #[test]
789 fn accumulator_base_check() {
790 $crate::ring::testing::accumulator_base_check::<$suite>()
791 }
792
793 #[test]
794 fn verifier_key_builder() {
795 $crate::ring::testing::verifier_key_builder::<$suite>()
796 }
797
798 $crate::test_vectors!($crate::ring::testing::TestVector<$suite>);
799 }
800 };
801 }
802
803 pub trait RingSuiteExt: RingSuite + crate::testing::SuiteExt {
804 const SRS_FILE: &str;
805
806 fn params() -> &'static RingProofParams<Self>;
807
808 #[allow(unused)]
809 fn load_context() -> RingProofParams<Self> {
810 use ark_serialize::CanonicalDeserialize;
811 use std::{fs::File, io::Read};
812 let mut file = File::open(Self::SRS_FILE).unwrap();
813 let mut buf = Vec::new();
814 file.read_to_end(&mut buf).unwrap();
815 let pcs_params =
816 PcsParams::<Self>::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
817 RingProofParams::from_pcs_params(crate::ring::testing::TEST_RING_SIZE, pcs_params)
818 .unwrap()
819 }
820
821 #[allow(unused)]
822 fn write_context(params: &RingProofParams<Self>) {
823 use ark_serialize::CanonicalSerialize;
824 use std::{fs::File, io::Write};
825 let mut file = File::create(Self::SRS_FILE).unwrap();
826 let mut buf = Vec::new();
827 params.pcs.serialize_uncompressed(&mut buf).unwrap();
828 file.write_all(&buf).unwrap();
829 }
830 }
831
832 pub struct TestVector<S: RingSuite> {
833 pub pedersen: pedersen::testing::TestVector<S>,
834 pub ring_pks: [AffinePoint<S>; TEST_RING_SIZE],
835 pub ring_pks_com: RingCommitment<S>,
836 pub ring_proof: RingBareProof<S>,
837 }
838
839 impl<S: RingSuite> core::fmt::Debug for TestVector<S> {
840 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
841 f.debug_struct("TestVector")
842 .field("pedersen", &self.pedersen)
843 .field("ring_proof", &"...")
844 .finish()
845 }
846 }
847
848 impl<S> common::TestVectorTrait for TestVector<S>
849 where
850 S: RingSuiteExt + std::fmt::Debug + 'static,
851 {
852 fn name() -> String {
853 S::suite_name() + "_ring"
854 }
855
856 fn new(comment: &str, seed: &[u8], alpha: &[u8], salt: &[u8], ad: &[u8]) -> Self {
857 use super::Prover;
858 let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, salt, ad);
859
860 let secret = Secret::<S>::from_scalar(pedersen.base.sk);
861 let public = secret.public();
862
863 let input = Input::<S>::from(pedersen.base.h);
864 let output = Output::from(pedersen.base.gamma);
865
866 let params = <S as RingSuiteExt>::params();
867
868 use ark_std::rand::SeedableRng;
869 let rng = &mut rand_chacha::ChaCha20Rng::from_seed([0x11; 32]);
870 let prover_idx = 3;
871 let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
872 ring_pks[prover_idx] = public.0;
873
874 let prover_key = params.prover_key(&ring_pks);
875 let prover = params.prover(prover_key, prover_idx);
876 let proof = secret.prove(input, output, ad, &prover);
877
878 let verifier_key = params.verifier_key(&ring_pks);
879 let ring_pks_com = verifier_key.commitment();
880
881 {
882 let mut p = (Vec::new(), Vec::new());
884 pedersen.proof.serialize_compressed(&mut p.0).unwrap();
885 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
886 assert_eq!(p.0, p.1);
887 }
888
889 Self {
891 pedersen,
892 ring_pks: ring_pks.try_into().unwrap(),
893 ring_pks_com,
894 ring_proof: proof.ring_proof,
895 }
896 }
897
898 fn from_map(map: &common::TestVectorMap) -> Self {
899 let pedersen = pedersen::testing::TestVector::from_map(map);
900
901 let ring_pks = map.get::<[AffinePoint<S>; TEST_RING_SIZE]>("ring_pks");
902 let ring_pks_com = map.get::<RingCommitment<S>>("ring_pks_com");
903 let ring_proof = map.get::<RingBareProof<S>>("ring_proof");
904
905 Self {
906 pedersen,
907 ring_pks,
908 ring_pks_com,
909 ring_proof,
910 }
911 }
912
913 fn to_map(&self) -> common::TestVectorMap {
914 let mut map = self.pedersen.to_map();
915 map.set("ring_pks", &self.ring_pks);
916 map.set("ring_pks_com", &self.ring_pks_com);
917 map.set("ring_proof", &self.ring_proof);
918 map
919 }
920
921 fn run(&self) {
922 self.pedersen.run();
923
924 let input = Input::<S>::from(self.pedersen.base.h);
925 let output = Output::from(self.pedersen.base.gamma);
926 let secret = Secret::from_scalar(self.pedersen.base.sk);
927 let public = secret.public();
928 assert_eq!(public.0, self.pedersen.base.pk);
929
930 let params = <S as RingSuiteExt>::params();
931
932 let prover_idx = self.ring_pks.iter().position(|&pk| pk == public.0).unwrap();
933
934 let prover_key = params.prover_key(&self.ring_pks);
935 let prover = params.prover(prover_key, prover_idx);
936
937 let verifier_key = params.verifier_key(&self.ring_pks);
938 let verifier = params.verifier(verifier_key);
939
940 let proof = secret.prove(input, output, &self.pedersen.base.ad, &prover);
941
942 {
943 let mut p = (Vec::new(), Vec::new());
945 self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
946 proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
947 assert_eq!(p.0, p.1);
948 }
949
950 #[cfg(feature = "test-vectors")]
951 {
952 let mut p = (Vec::new(), Vec::new());
955 self.ring_proof.serialize_compressed(&mut p.0).unwrap();
956 proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
957 assert_eq!(p.0, p.1);
958 }
959
960 assert!(
961 Public::verify(input, output, &self.pedersen.base.ad, &proof, &verifier).is_ok()
962 );
963 }
964 }
965}