1use crate::Suite;
32use crate::utils;
33use crate::utils::common::DomSep;
34use crate::utils::straus::short_msm;
35use crate::*;
36use ark_ec::VariableBaseMSM;
37
38pub const PEDERSEN_BLINDING_BASE_SEED: &[u8] = b"pedersen-blinding";
40
41pub trait PedersenSuite: Suite {
45 const BLINDING_BASE: AffinePoint<Self>;
47
48 fn blinding(secret: &ScalarField<Self>, mut transcript: Self::Transcript) -> ScalarField<Self> {
52 transcript.absorb_raw(&[DomSep::PedersenBlinding as u8]);
53 Self::nonce(secret, Some(transcript))
54 }
55}
56
57#[derive(Debug, Clone, CanonicalSerialize, CanonicalDeserialize)]
69pub struct Proof<S: PedersenSuite> {
70 pk_com: AffinePoint<S>,
71 r: AffinePoint<S>,
72 ok: AffinePoint<S>,
73 s: ScalarField<S>,
74 sb: ScalarField<S>,
75}
76
77impl<S: PedersenSuite> Proof<S> {
78 pub fn key_commitment(&self) -> AffinePoint<S> {
80 self.pk_com
81 }
82}
83
84pub trait Prover<S: PedersenSuite> {
86 fn prove(
92 &self,
93 ios: impl AsRef<[VrfIo<S>]>,
94 ad: impl AsRef<[u8]>,
95 ) -> (Proof<S>, ScalarField<S>);
96}
97
98pub trait Verifier<S: PedersenSuite> {
115 fn verify(
121 ios: impl AsRef<[VrfIo<S>]>,
122 ad: impl AsRef<[u8]>,
123 proof: &Proof<S>,
124 ) -> Result<(), Error>;
125}
126
127impl<S: PedersenSuite> Prover<S> for Secret<S> {
128 fn prove(
129 &self,
130 ios: impl AsRef<[VrfIo<S>]>,
131 ad: impl AsRef<[u8]>,
132 ) -> (Proof<S>, ScalarField<S>) {
133 let (mut t, io) = utils::vrf_transcript::<S>(DomSep::PedersenVrf, ios, ad);
134
135 let blinding = S::blinding(&self.scalar, t.clone());
137
138 let bb = smul!(S::BLINDING_BASE, blinding);
140 let pk_com = (self.public.0.into_group() + bb).into_affine();
141
142 t.absorb_serialize(&pk_com);
144
145 let k = S::nonce(&self.scalar, Some(t.clone()));
147 let kb = S::nonce(&blinding, Some(t.clone()));
148
149 let kg = smul!(S::generator(), k);
151 let kbb = smul!(S::BLINDING_BASE, kb);
152 let r = kg + kbb;
153
154 let ok = smul!(io.input.0, k);
156
157 let norms = CurveGroup::normalize_batch(&[r, ok]);
158 let (r, ok) = (norms[0], norms[1]);
159
160 let c = S::challenge(&[&r, &ok], Some(t));
162
163 let s = k + c * self.scalar;
165 let sb = kb + c * blinding;
167
168 let proof = Proof {
169 pk_com,
170 r,
171 ok,
172 s,
173 sb,
174 };
175 (proof, blinding)
176 }
177}
178
179impl<S: PedersenSuite> Verifier<S> for Public<S> {
180 fn verify(
181 ios: impl AsRef<[VrfIo<S>]>,
182 ad: impl AsRef<[u8]>,
183 proof: &Proof<S>,
184 ) -> Result<(), Error> {
185 let Proof {
186 pk_com,
187 r,
188 ok,
189 s,
190 sb,
191 } = proof;
192
193 let (mut t, io) = utils::vrf_transcript::<S>(DomSep::PedersenVrf, ios, ad);
194
195 t.absorb_serialize(pk_com);
197
198 let c = S::challenge(&[r, ok], Some(t));
200
201 let neg_c = -c;
202
203 let lhs1 = short_msm(&[io.input.0, io.output.0], &[*s, neg_c], 2);
208 if lhs1 != ok.into_group() {
209 return Err(Error::VerificationFailure);
210 }
211
212 let lhs2 = short_msm(
217 &[S::generator(), S::BLINDING_BASE, *pk_com],
218 &[*s, *sb, neg_c],
219 1,
220 );
221 if lhs2 != r.into_group() {
222 return Err(Error::VerificationFailure);
223 }
224
225 Ok(())
226 }
227}
228
229pub struct BatchItem<S: PedersenSuite> {
234 c: ScalarField<S>,
235 input: AffinePoint<S>,
236 output: AffinePoint<S>,
237 pk_com: AffinePoint<S>,
238 r: AffinePoint<S>,
239 ok: AffinePoint<S>,
240 s: ScalarField<S>,
241 sb: ScalarField<S>,
242}
243
244impl<S: PedersenSuite> BatchItem<S> {
245 pub fn new(ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>, proof: &Proof<S>) -> Self {
251 let (mut t, io) = utils::vrf_transcript::<S>(DomSep::PedersenVrf, ios, ad);
252 t.absorb_serialize(&proof.pk_com);
253 let c = S::challenge(&[&proof.r, &proof.ok], Some(t));
254 Self {
255 c,
256 input: io.input.0,
257 output: io.output.0,
258 pk_com: proof.pk_com,
259 r: proof.r,
260 ok: proof.ok,
261 s: proof.s,
262 sb: proof.sb,
263 }
264 }
265}
266
267pub struct BatchVerifier<S: PedersenSuite> {
275 items: Vec<BatchItem<S>>,
276}
277
278impl<S: PedersenSuite> Default for BatchVerifier<S> {
279 fn default() -> Self {
280 Self { items: Vec::new() }
281 }
282}
283
284impl<S: PedersenSuite> BatchVerifier<S> {
285 pub fn new() -> Self {
287 Self::default()
288 }
289
290 pub fn push_prepared(&mut self, entry: BatchItem<S>) {
292 self.items.push(entry);
293 }
294
295 pub fn push(&mut self, ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>, proof: &Proof<S>) {
297 self.push_prepared(BatchItem::new(ios, ad, proof));
298 }
299
300 pub fn verify(&self) -> Result<(), Error> {
311 let items = &self.items;
312 if items.is_empty() {
313 return Ok(());
314 }
315
316 let n = items.len();
317
318 let mut t = S::Transcript::new(S::SUITE_ID);
323 t.absorb_raw(&[DomSep::BatchVerify as u8]);
324 for e in items {
325 t.absorb_serialize(&e.c);
326 t.absorb_serialize(&e.s);
327 t.absorb_serialize(&e.sb);
328 }
329 let random_scalars: Vec<(ScalarField<S>, ScalarField<S>)> = (0..n)
335 .map(|_| {
336 let mut buf = [0u8; 32];
337 t.squeeze_raw(&mut buf);
338 let t = ScalarField::<S>::from_le_bytes_mod_order(&buf[..16]);
339 let u = ScalarField::<S>::from_le_bytes_mod_order(&buf[16..]);
340 (t, u)
341 })
342 .collect();
343
344 let mut bases = Vec::with_capacity(5 * n + 2);
346 let mut scalars = Vec::with_capacity(5 * n + 2);
347
348 let mut g_scalar = ScalarField::<S>::zero();
349 let mut b_scalar = ScalarField::<S>::zero();
350
351 for (e, (t, u)) in items.iter().zip(random_scalars.iter()) {
352 bases.push(e.output);
354 scalars.push(*t * e.c);
355
356 bases.push(e.ok);
357 scalars.push(*t);
358
359 bases.push(e.input);
360 scalars.push(-(*t * e.s));
361
362 bases.push(e.pk_com);
364 scalars.push(*u * e.c);
365
366 bases.push(e.r);
367 scalars.push(*u);
368
369 g_scalar += *u * e.s;
371 b_scalar += *u * e.sb;
372 }
373
374 bases.push(S::generator());
376 scalars.push(-g_scalar);
377
378 bases.push(S::BLINDING_BASE);
379 scalars.push(-b_scalar);
380
381 let result = <S::Affine as AffineRepr>::Group::msm_unchecked(&bases, &scalars);
382 if !result.is_zero() {
383 return Err(Error::VerificationFailure);
384 }
385
386 Ok(())
387 }
388}
389
390#[cfg(test)]
391pub(crate) mod testing {
392 use super::*;
393 use crate::testing::{self as common, CheckPoint, SuiteExt, TEST_SEED, random_val};
394
395 pub fn prove_verify<S: PedersenSuite>() {
396 use pedersen::{Prover, Verifier};
397
398 let secret = Secret::<S>::from_seed(TEST_SEED);
399 let input = Input::from_affine_unchecked(random_val(None));
400 let io = secret.vrf_io(input);
401
402 let (proof, blinding) = secret.prove(io, b"foo");
403 let result = Public::verify(io, b"foo", &proof);
404 assert!(result.is_ok());
405
406 assert_eq!(
407 proof.key_commitment(),
408 (secret.public().0 + S::BLINDING_BASE * blinding).into()
409 );
410 }
411
412 pub fn batch_verify<S: PedersenSuite>() {
413 use pedersen::{BatchItem, BatchVerifier, Prover, Verifier};
414
415 let secret = Secret::<S>::from_seed(TEST_SEED);
416 let input = Input::from_affine_unchecked(random_val(None));
417 let io = secret.vrf_io(input);
418
419 let (proof1, _) = secret.prove(io, b"foo");
420 let (proof2, _) = secret.prove(io, b"bar");
421
422 assert!(Public::verify(io, b"foo", &proof1).is_ok());
424 assert!(Public::verify(io, b"bar", &proof2).is_ok());
425
426 let mut batch = BatchVerifier::new();
428 batch.push(io, b"foo", &proof1);
429 batch.push(io, b"bar", &proof2);
430 assert!(batch.verify().is_ok());
431
432 let mut batch = BatchVerifier::new();
434 let entry1 = BatchItem::new(io, b"foo", &proof1);
435 let entry2 = BatchItem::new(io, b"bar", &proof2);
436 batch.push_prepared(entry1);
437 batch.push_prepared(entry2);
438 assert!(batch.verify().is_ok());
439
440 let batch = BatchVerifier::<S>::new();
442 assert!(batch.verify().is_ok());
443
444 let mut batch = BatchVerifier::new();
446 batch.push(io, b"foo", &proof1);
447 batch.push(io, b"wrong", &proof2);
448 assert!(batch.verify().is_err());
449 }
450
451 pub fn prove_verify_multi_single<S: PedersenSuite>() {
453 use pedersen::{Prover, Verifier};
454
455 let secret = Secret::<S>::from_seed(TEST_SEED);
456 let input = Input::from_affine_unchecked(random_val(None));
457 let io = secret.vrf_io(input);
458
459 let (proof_single, blinding_single) = secret.prove(io, b"foo");
460 let (proof_slice, blinding_slice) = secret.prove([io], b"foo");
461
462 let encode = |p: &pedersen::Proof<S>| {
464 let mut buf = Vec::new();
465 p.serialize_compressed(&mut buf).unwrap();
466 buf
467 };
468 assert_eq!(encode(&proof_single), encode(&proof_slice));
469 assert_eq!(blinding_single, blinding_slice);
470
471 assert!(Public::verify(io, b"foo", &proof_slice).is_ok());
473 assert!(Public::verify([io], b"foo", &proof_single).is_ok());
474 }
475
476 pub fn prove_verify_multi<S: PedersenSuite>() {
478 use pedersen::{Prover, Verifier};
479
480 let secret = Secret::<S>::from_seed(TEST_SEED);
481
482 let mut ios: Vec<VrfIo<S>> = (0..3u8)
483 .map(|i| {
484 let input = Input::new(&[i + 1]).unwrap();
485 secret.vrf_io(input)
486 })
487 .collect();
488 ios.push(VrfIo {
489 input: Input(S::Affine::generator()),
490 output: Output(secret.public().0),
491 });
492
493 let (proof, _) = secret.prove(&ios[..], b"bar");
494 assert!(Public::verify(&ios[..], b"bar", &proof).is_ok());
495
496 let mut bad_ios = ios.clone();
498 bad_ios[1].output = secret.output(ios[0].input);
499 assert!(Public::verify(&bad_ios[..], b"bar", &proof).is_err());
500
501 let mut bad_ios = ios.clone();
503 bad_ios[0].input = ios[1].input;
504 assert!(Public::verify(&bad_ios[..], b"bar", &proof).is_err());
505
506 assert!(Public::verify(&ios[..], b"baz", &proof).is_err());
508 }
509
510 pub fn prove_verify_multi_empty<S: PedersenSuite>() {
512 use pedersen::{Prover, Verifier};
513
514 let secret = Secret::<S>::from_seed(TEST_SEED);
515
516 let ios: [VrfIo<S>; 0] = [];
517 let (proof, _) = secret.prove(ios, b"bar");
518
519 assert!(Public::verify(ios, b"bar", &proof).is_ok());
520
521 assert!(Public::verify(ios, b"baz", &proof).is_err());
523 }
524
525 pub fn blinding_base_check<S: PedersenSuite>()
526 where
527 AffinePoint<S>: CheckPoint,
528 {
529 assert_eq!(
531 S::BLINDING_BASE,
532 S::data_to_point(PEDERSEN_BLINDING_BASE_SEED).unwrap()
533 );
534 assert!(S::BLINDING_BASE.check(true).is_ok());
536 }
537
538 #[macro_export]
539 macro_rules! pedersen_suite_tests {
540 ($suite:ty) => {
541 mod pedersen {
542 use super::*;
543
544 #[test]
545 fn prove_verify() {
546 $crate::pedersen::testing::prove_verify::<$suite>();
547 }
548
549 #[test]
550 fn prove_verify_multi_single() {
551 $crate::pedersen::testing::prove_verify_multi_single::<$suite>();
552 }
553
554 #[test]
555 fn prove_verify_multi() {
556 $crate::pedersen::testing::prove_verify_multi::<$suite>();
557 }
558
559 #[test]
560 fn prove_verify_multi_empty() {
561 $crate::pedersen::testing::prove_verify_multi_empty::<$suite>();
562 }
563
564 #[test]
565 fn batch_verify() {
566 $crate::pedersen::testing::batch_verify::<$suite>();
567 }
568
569 #[test]
570 fn blinding_base_check() {
571 $crate::pedersen::testing::blinding_base_check::<$suite>();
572 }
573
574 $crate::test_vectors!($crate::pedersen::testing::TestVector<$suite>);
575 }
576 };
577 }
578
579 pub struct TestVector<S: PedersenSuite> {
580 pub base: common::TestVector<S>,
581 pub blind: ScalarField<S>,
582 pub proof: Proof<S>,
583 }
584
585 impl<S: PedersenSuite> core::fmt::Debug for TestVector<S> {
586 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
587 f.debug_struct("TestVector")
588 .field("base", &self.base)
589 .field("blinding", &self.blind)
590 .field("proof_pk_com", &self.proof.pk_com)
591 .field("proof_r", &self.proof.r)
592 .field("proof_ok", &self.proof.ok)
593 .field("proof_s", &self.proof.s)
594 .field("proof_sb", &self.proof.sb)
595 .finish()
596 }
597 }
598
599 impl<S> common::TestVectorTrait for TestVector<S>
600 where
601 S: PedersenSuite + SuiteExt + std::fmt::Debug,
602 {
603 fn name() -> String {
604 S::SUITE_NAME.to_string() + "_pedersen"
605 }
606
607 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
608 use super::Prover;
609 let base = common::TestVector::new(comment, seed, alpha, ad);
610 let io = VrfIo {
611 input: Input::<S>::from_affine_unchecked(base.h),
612 output: Output::from_affine_unchecked(base.gamma),
613 };
614 let secret = Secret::from_scalar(base.sk);
615 let (proof, blind) = secret.prove(io, ad);
616 Self { base, blind, proof }
617 }
618
619 fn from_map(map: &common::TestVectorMap) -> Self {
620 let base = common::TestVector::from_map(map);
621 let blind = common::scalar_decode::<S>(&map.get_bytes("blinding"));
622 let pk_com = common::point_decode::<S>(&map.get_bytes("proof_pk_com")).unwrap();
623 let r = common::point_decode::<S>(&map.get_bytes("proof_r")).unwrap();
624 let ok = common::point_decode::<S>(&map.get_bytes("proof_ok")).unwrap();
625 let s = common::scalar_decode::<S>(&map.get_bytes("proof_s"));
626 let sb = common::scalar_decode::<S>(&map.get_bytes("proof_sb"));
627 let proof = Proof {
628 pk_com,
629 r,
630 ok,
631 s,
632 sb,
633 };
634 Self { base, blind, proof }
635 }
636
637 fn to_map(&self) -> common::TestVectorMap {
638 let items = [
639 (
640 "blinding",
641 hex::encode(common::scalar_encode::<S>(&self.blind)),
642 ),
643 (
644 "proof_pk_com",
645 hex::encode(common::point_encode::<S>(&self.proof.pk_com)),
646 ),
647 (
648 "proof_r",
649 hex::encode(common::point_encode::<S>(&self.proof.r)),
650 ),
651 (
652 "proof_ok",
653 hex::encode(common::point_encode::<S>(&self.proof.ok)),
654 ),
655 (
656 "proof_s",
657 hex::encode(common::scalar_encode::<S>(&self.proof.s)),
658 ),
659 (
660 "proof_sb",
661 hex::encode(common::scalar_encode::<S>(&self.proof.sb)),
662 ),
663 ];
664 let mut map = self.base.to_map();
665 items.into_iter().for_each(|(name, value)| {
666 map.0.insert(name.to_string(), value);
667 });
668 map
669 }
670
671 fn run(&self) {
672 self.base.run();
673 let io = VrfIo {
674 input: Input::<S>::from_affine_unchecked(self.base.h),
675 output: Output::from_affine_unchecked(self.base.gamma),
676 };
677 let sk = Secret::from_scalar(self.base.sk);
678 let (proof, blind) = sk.prove(io, &self.base.ad);
679 assert_eq!(self.blind, blind, "Blinding factor mismatch");
680 assert_eq!(self.proof.pk_com, proof.pk_com, "Proof pkb mismatch");
681 assert_eq!(self.proof.r, proof.r, "Proof r mismatch");
682 assert_eq!(self.proof.ok, proof.ok, "Proof ok mismatch");
683 assert_eq!(self.proof.s, proof.s, "Proof s mismatch");
684 assert_eq!(self.proof.sb, proof.sb, "Proof sb mismatch");
685
686 assert!(Public::verify(io, &self.base.ad, &proof).is_ok());
687 }
688 }
689}