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
244pub struct BatchVerifier<S: PedersenSuite> {
252 items: Vec<BatchItem<S>>,
253}
254
255impl<S: PedersenSuite> Default for BatchVerifier<S> {
256 fn default() -> Self {
257 Self { items: Vec::new() }
258 }
259}
260
261impl<S: PedersenSuite> BatchVerifier<S> {
262 pub fn new() -> Self {
264 Self::default()
265 }
266
267 pub fn prepare(
273 ios: impl AsRef<[VrfIo<S>]>,
274 ad: impl AsRef<[u8]>,
275 proof: &Proof<S>,
276 ) -> BatchItem<S> {
277 let (mut t, io) = utils::vrf_transcript::<S>(DomSep::PedersenVrf, ios, ad);
278 t.absorb_serialize(&proof.pk_com);
279 let c = S::challenge(&[&proof.r, &proof.ok], Some(t));
280 BatchItem {
281 c,
282 input: io.input.0,
283 output: io.output.0,
284 pk_com: proof.pk_com,
285 r: proof.r,
286 ok: proof.ok,
287 s: proof.s,
288 sb: proof.sb,
289 }
290 }
291
292 pub fn push_prepared(&mut self, entry: BatchItem<S>) {
294 self.items.push(entry);
295 }
296
297 pub fn push(&mut self, ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>, proof: &Proof<S>) {
299 let entry = Self::prepare(ios, ad, proof);
300 self.push_prepared(entry);
301 }
302
303 pub fn verify(&self) -> Result<(), Error> {
314 let items = &self.items;
315 if items.is_empty() {
316 return Ok(());
317 }
318
319 let n = items.len();
320
321 let mut t = S::Transcript::new(S::SUITE_ID);
326 t.absorb_raw(&[DomSep::PedersenBatch as u8]);
327 for e in items {
328 t.absorb_serialize(&e.c);
329 t.absorb_serialize(&e.s);
330 t.absorb_serialize(&e.sb);
331 }
332 let random_scalars: Vec<(ScalarField<S>, ScalarField<S>)> = (0..n)
338 .map(|_| {
339 let mut buf = [0u8; 32];
340 t.squeeze_raw(&mut buf);
341 let t = ScalarField::<S>::from_le_bytes_mod_order(&buf[..16]);
342 let u = ScalarField::<S>::from_le_bytes_mod_order(&buf[16..]);
343 (t, u)
344 })
345 .collect();
346
347 let mut bases = Vec::with_capacity(5 * n + 2);
349 let mut scalars = Vec::with_capacity(5 * n + 2);
350
351 let mut g_scalar = ScalarField::<S>::zero();
352 let mut b_scalar = ScalarField::<S>::zero();
353
354 for (e, (t, u)) in items.iter().zip(random_scalars.iter()) {
355 bases.push(e.output);
357 scalars.push(*t * e.c);
358
359 bases.push(e.ok);
360 scalars.push(*t);
361
362 bases.push(e.input);
363 scalars.push(-(*t * e.s));
364
365 bases.push(e.pk_com);
367 scalars.push(*u * e.c);
368
369 bases.push(e.r);
370 scalars.push(*u);
371
372 g_scalar += *u * e.s;
374 b_scalar += *u * e.sb;
375 }
376
377 bases.push(S::generator());
379 scalars.push(-g_scalar);
380
381 bases.push(S::BLINDING_BASE);
382 scalars.push(-b_scalar);
383
384 let result = <S::Affine as AffineRepr>::Group::msm_unchecked(&bases, &scalars);
385 if !result.is_zero() {
386 return Err(Error::VerificationFailure);
387 }
388
389 Ok(())
390 }
391}
392
393#[cfg(test)]
394pub(crate) mod testing {
395 use super::*;
396 use crate::testing::{self as common, CheckPoint, SuiteExt, TEST_SEED, random_val};
397
398 pub fn prove_verify<S: PedersenSuite>() {
399 use pedersen::{Prover, Verifier};
400
401 let secret = Secret::<S>::from_seed(TEST_SEED);
402 let input = Input::from_affine_unchecked(random_val(None));
403 let io = secret.vrf_io(input);
404
405 let (proof, blinding) = secret.prove(io, b"foo");
406 let result = Public::verify(io, b"foo", &proof);
407 assert!(result.is_ok());
408
409 assert_eq!(
410 proof.key_commitment(),
411 (secret.public().0 + S::BLINDING_BASE * blinding).into()
412 );
413 }
414
415 pub fn batch_verify<S: PedersenSuite>() {
416 use pedersen::{BatchVerifier, Prover, Verifier};
417
418 let secret = Secret::<S>::from_seed(TEST_SEED);
419 let input = Input::from_affine_unchecked(random_val(None));
420 let io = secret.vrf_io(input);
421
422 let (proof1, _) = secret.prove(io, b"foo");
423 let (proof2, _) = secret.prove(io, b"bar");
424
425 assert!(Public::verify(io, b"foo", &proof1).is_ok());
427 assert!(Public::verify(io, b"bar", &proof2).is_ok());
428
429 let mut batch = BatchVerifier::new();
431 batch.push(io, b"foo", &proof1);
432 batch.push(io, b"bar", &proof2);
433 assert!(batch.verify().is_ok());
434
435 let mut batch = BatchVerifier::new();
437 let entry1 = BatchVerifier::prepare(io, b"foo", &proof1);
438 let entry2 = BatchVerifier::prepare(io, b"bar", &proof2);
439 batch.push_prepared(entry1);
440 batch.push_prepared(entry2);
441 assert!(batch.verify().is_ok());
442
443 let batch = BatchVerifier::<S>::new();
445 assert!(batch.verify().is_ok());
446
447 let mut batch = BatchVerifier::new();
449 batch.push(io, b"foo", &proof1);
450 batch.push(io, b"wrong", &proof2);
451 assert!(batch.verify().is_err());
452 }
453
454 pub fn prove_verify_multi_single<S: PedersenSuite>() {
456 use pedersen::{Prover, Verifier};
457
458 let secret = Secret::<S>::from_seed(TEST_SEED);
459 let input = Input::from_affine_unchecked(random_val(None));
460 let io = secret.vrf_io(input);
461
462 let (proof_single, blinding_single) = secret.prove(io, b"foo");
463 let (proof_slice, blinding_slice) = secret.prove([io], b"foo");
464
465 let encode = |p: &pedersen::Proof<S>| {
467 let mut buf = Vec::new();
468 p.serialize_compressed(&mut buf).unwrap();
469 buf
470 };
471 assert_eq!(encode(&proof_single), encode(&proof_slice));
472 assert_eq!(blinding_single, blinding_slice);
473
474 assert!(Public::verify(io, b"foo", &proof_slice).is_ok());
476 assert!(Public::verify([io], b"foo", &proof_single).is_ok());
477 }
478
479 pub fn prove_verify_multi<S: PedersenSuite>() {
481 use pedersen::{Prover, Verifier};
482
483 let secret = Secret::<S>::from_seed(TEST_SEED);
484
485 let mut ios: Vec<VrfIo<S>> = (0..3u8)
486 .map(|i| {
487 let input = Input::new(&[i + 1]).unwrap();
488 secret.vrf_io(input)
489 })
490 .collect();
491 ios.push(VrfIo {
492 input: Input(S::Affine::generator()),
493 output: Output(secret.public().0),
494 });
495
496 let (proof, _) = secret.prove(&ios[..], b"bar");
497 assert!(Public::verify(&ios[..], b"bar", &proof).is_ok());
498
499 let mut bad_ios = ios.clone();
501 bad_ios[1].output = secret.output(ios[0].input);
502 assert!(Public::verify(&bad_ios[..], b"bar", &proof).is_err());
503
504 let mut bad_ios = ios.clone();
506 bad_ios[0].input = ios[1].input;
507 assert!(Public::verify(&bad_ios[..], b"bar", &proof).is_err());
508
509 assert!(Public::verify(&ios[..], b"baz", &proof).is_err());
511 }
512
513 pub fn prove_verify_multi_empty<S: PedersenSuite>() {
515 use pedersen::{Prover, Verifier};
516
517 let secret = Secret::<S>::from_seed(TEST_SEED);
518
519 let ios: [VrfIo<S>; 0] = [];
520 let (proof, _) = secret.prove(ios, b"bar");
521
522 assert!(Public::verify(ios, b"bar", &proof).is_ok());
523
524 assert!(Public::verify(ios, b"baz", &proof).is_err());
526 }
527
528 pub fn blinding_base_check<S: PedersenSuite>()
529 where
530 AffinePoint<S>: CheckPoint,
531 {
532 assert_eq!(
534 S::BLINDING_BASE,
535 S::data_to_point(PEDERSEN_BLINDING_BASE_SEED).unwrap()
536 );
537 assert!(S::BLINDING_BASE.check(true).is_ok());
539 }
540
541 #[macro_export]
542 macro_rules! pedersen_suite_tests {
543 ($suite:ty) => {
544 mod pedersen {
545 use super::*;
546
547 #[test]
548 fn prove_verify() {
549 $crate::pedersen::testing::prove_verify::<$suite>();
550 }
551
552 #[test]
553 fn prove_verify_multi_single() {
554 $crate::pedersen::testing::prove_verify_multi_single::<$suite>();
555 }
556
557 #[test]
558 fn prove_verify_multi() {
559 $crate::pedersen::testing::prove_verify_multi::<$suite>();
560 }
561
562 #[test]
563 fn prove_verify_multi_empty() {
564 $crate::pedersen::testing::prove_verify_multi_empty::<$suite>();
565 }
566
567 #[test]
568 fn batch_verify() {
569 $crate::pedersen::testing::batch_verify::<$suite>();
570 }
571
572 #[test]
573 fn blinding_base_check() {
574 $crate::pedersen::testing::blinding_base_check::<$suite>();
575 }
576
577 $crate::test_vectors!($crate::pedersen::testing::TestVector<$suite>);
578 }
579 };
580 }
581
582 pub struct TestVector<S: PedersenSuite> {
583 pub base: common::TestVector<S>,
584 pub blind: ScalarField<S>,
585 pub proof: Proof<S>,
586 }
587
588 impl<S: PedersenSuite> core::fmt::Debug for TestVector<S> {
589 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
590 f.debug_struct("TestVector")
591 .field("base", &self.base)
592 .field("blinding", &self.blind)
593 .field("proof_pk_com", &self.proof.pk_com)
594 .field("proof_r", &self.proof.r)
595 .field("proof_ok", &self.proof.ok)
596 .field("proof_s", &self.proof.s)
597 .field("proof_sb", &self.proof.sb)
598 .finish()
599 }
600 }
601
602 impl<S> common::TestVectorTrait for TestVector<S>
603 where
604 S: PedersenSuite + SuiteExt + std::fmt::Debug,
605 {
606 fn name() -> String {
607 S::SUITE_NAME.to_string() + "_pedersen"
608 }
609
610 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
611 use super::Prover;
612 let base = common::TestVector::new(comment, seed, alpha, ad);
613 let io = VrfIo {
614 input: Input::<S>::from_affine_unchecked(base.h),
615 output: Output::from_affine_unchecked(base.gamma),
616 };
617 let secret = Secret::from_scalar(base.sk);
618 let (proof, blind) = secret.prove(io, ad);
619 Self { base, blind, proof }
620 }
621
622 fn from_map(map: &common::TestVectorMap) -> Self {
623 let base = common::TestVector::from_map(map);
624 let blind = common::scalar_decode::<S>(&map.get_bytes("blinding"));
625 let pk_com = common::point_decode::<S>(&map.get_bytes("proof_pk_com")).unwrap();
626 let r = common::point_decode::<S>(&map.get_bytes("proof_r")).unwrap();
627 let ok = common::point_decode::<S>(&map.get_bytes("proof_ok")).unwrap();
628 let s = common::scalar_decode::<S>(&map.get_bytes("proof_s"));
629 let sb = common::scalar_decode::<S>(&map.get_bytes("proof_sb"));
630 let proof = Proof {
631 pk_com,
632 r,
633 ok,
634 s,
635 sb,
636 };
637 Self { base, blind, proof }
638 }
639
640 fn to_map(&self) -> common::TestVectorMap {
641 let items = [
642 (
643 "blinding",
644 hex::encode(common::scalar_encode::<S>(&self.blind)),
645 ),
646 (
647 "proof_pk_com",
648 hex::encode(common::point_encode::<S>(&self.proof.pk_com)),
649 ),
650 (
651 "proof_r",
652 hex::encode(common::point_encode::<S>(&self.proof.r)),
653 ),
654 (
655 "proof_ok",
656 hex::encode(common::point_encode::<S>(&self.proof.ok)),
657 ),
658 (
659 "proof_s",
660 hex::encode(common::scalar_encode::<S>(&self.proof.s)),
661 ),
662 (
663 "proof_sb",
664 hex::encode(common::scalar_encode::<S>(&self.proof.sb)),
665 ),
666 ];
667 let mut map = self.base.to_map();
668 items.into_iter().for_each(|(name, value)| {
669 map.0.insert(name.to_string(), value);
670 });
671 map
672 }
673
674 fn run(&self) {
675 self.base.run();
676 let io = VrfIo {
677 input: Input::<S>::from_affine_unchecked(self.base.h),
678 output: Output::from_affine_unchecked(self.base.gamma),
679 };
680 let sk = Secret::from_scalar(self.base.sk);
681 let (proof, blind) = sk.prove(io, &self.base.ad);
682 assert_eq!(self.blind, blind, "Blinding factor mismatch");
683 assert_eq!(self.proof.pk_com, proof.pk_com, "Proof pkb mismatch");
684 assert_eq!(self.proof.r, proof.r, "Proof r mismatch");
685 assert_eq!(self.proof.ok, proof.ok, "Proof ok mismatch");
686 assert_eq!(self.proof.s, proof.s, "Proof s mismatch");
687 assert_eq!(self.proof.sb, proof.sb, "Proof sb mismatch");
688
689 assert!(Public::verify(io, &self.base.ad, &proof).is_ok());
690 }
691 }
692}