1use core::borrow::Borrow;
80
81#[cfg(feature = "alloc")]
82use core::iter::once;
83
84#[cfg(feature = "alloc")]
85use alloc::{boxed::Box, vec::Vec};
86
87use curve25519_dalek::constants;
88use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
89use curve25519_dalek::scalar::Scalar;
90use curve25519_dalek::traits::{IsIdentity}; #[cfg(feature = "alloc")]
92use curve25519_dalek::traits::{MultiscalarMul,VartimeMultiscalarMul};
93
94use merlin::Transcript;
95
96use super::*;
97use crate::context::SigningTranscript;
98use crate::points::RistrettoBoth;
99pub const KUSAMA_VRF : bool = true;
120
121pub const VRF_PREOUT_LENGTH : usize = 32;
123
124pub const VRF_PROOF_LENGTH : usize = 64;
126
127pub const VRF_PROOF_BATCHABLE_LENGTH : usize = 96;
129
130pub trait VRFSigningTranscript {
136 type T: SigningTranscript;
138 fn transcript_with_malleability_addressed(self, publickey: &PublicKey) -> Self::T;
141}
142
143impl<T> VRFSigningTranscript for T where T: SigningTranscript {
144 type T = T;
145 #[inline(always)]
146 fn transcript_with_malleability_addressed(mut self, publickey: &PublicKey) -> T {
147 self.commit_point(b"vrf-nm-pk", publickey.as_compressed());
148 self
149 }
150}
151
152#[derive(Clone)]
163pub struct Malleable<T: SigningTranscript>(pub T);
164impl<T> VRFSigningTranscript for Malleable<T> where T: SigningTranscript {
165 type T = T;
166 #[inline(always)]
167 fn transcript_with_malleability_addressed(self, _publickey: &PublicKey) -> T { self.0 }
168}
169
170
171pub fn vrf_malleable_hash<T: SigningTranscript>(mut t: T) -> RistrettoBoth {
182 let mut b = [0u8; 64];
183 t.challenge_bytes(b"VRFHash", &mut b);
184 RistrettoBoth::from_point(RistrettoPoint::from_uniform_bytes(&b))
185}
186
187impl PublicKey {
188 pub fn vrf_hash<T>(&self, t: T) -> RistrettoBoth
190 where T: VRFSigningTranscript {
191 vrf_malleable_hash(t.transcript_with_malleability_addressed(self))
192 }
193
194 pub fn vrf_attach_hash<T>(&self, output: VRFPreOut, t: T) -> SignatureResult<VRFInOut>
196 where T: VRFSigningTranscript {
197 output.attach_input_hash(self,t)
198 }
199}
200
201#[deprecated(
203 since = "0.9.2",
204 note = "Please use VRFPreOut instead of VRFOutput"
205)]
206pub type VRFOutput = VRFPreOut;
207
208#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
221pub struct VRFPreOut(pub [u8; PUBLIC_KEY_LENGTH]);
222
223impl VRFPreOut {
224 const DESCRIPTION: &'static str =
225 "A Ristretto Schnorr VRF output represented as a 32-byte Ristretto compressed point";
226
227 #[inline]
229 pub fn to_bytes(&self) -> [u8; VRF_PREOUT_LENGTH] {
230 self.0
231 }
232
233 #[inline]
235 pub fn as_bytes(&self) -> &[u8; VRF_PREOUT_LENGTH] {
236 &self.0
237 }
238
239 #[inline]
241 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<VRFPreOut> {
242 if bytes.len() != VRF_PREOUT_LENGTH {
243 return Err(SignatureError::BytesLengthError {
244 name: "VRFPreOut",
245 description: VRFPreOut::DESCRIPTION,
246 length: VRF_PREOUT_LENGTH
247 });
248 }
249 let mut bits: [u8; 32] = [0u8; 32];
250 bits.copy_from_slice(&bytes[..32]);
251 Ok(VRFPreOut(bits))
252 }
253
254 pub fn attach_input_hash<T>(&self, public: &PublicKey, t: T) -> SignatureResult<VRFInOut>
256 where T: VRFSigningTranscript {
257 let input = public.vrf_hash(t);
258 let output = RistrettoBoth::from_bytes_ser("VRFPreOut", VRFPreOut::DESCRIPTION, &self.0) ?;
259 if output.as_point().is_identity() { return Err(SignatureError::PointDecompressionError); }
260 Ok(VRFInOut { input, output })
261 }
262}
263
264serde_boilerplate!(VRFPreOut);
265
266#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
271pub struct VRFInOut {
272 pub input: RistrettoBoth,
274 pub output: RistrettoBoth,
276}
277
278impl SecretKey {
279 pub fn vrf_create_from_point(&self, input: RistrettoBoth) -> VRFInOut {
282 let output = RistrettoBoth::from_point(self.key * input.as_point());
283 VRFInOut { input, output }
284 }
285
286 pub fn vrf_create_from_compressed_point(&self, input: &VRFPreOut) -> SignatureResult<VRFInOut> {
293 let input = RistrettoBoth::from_compressed(CompressedRistretto(input.0)) ?;
294 Ok(self.vrf_create_from_point(input))
295 }
296}
297
298impl Keypair {
299 pub fn vrf_create_hash<T: VRFSigningTranscript>(&self, t: T) -> VRFInOut {
301 self.secret.vrf_create_from_point(self.public.vrf_hash(t))
302 }
303}
304
305impl VRFInOut {
306 pub fn as_output_bytes(&self) -> &[u8; 32] {
308 self.output.as_compressed().as_bytes()
309 }
310
311 pub fn to_preout(&self) -> VRFPreOut {
313 VRFPreOut(self.output.as_compressed().to_bytes())
314 }
315
316 pub fn commit<T: SigningTranscript>(&self, t: &mut T) {
326 t.commit_point(b"vrf-in", self.input.as_compressed());
327 t.commit_point(b"vrf-out", self.output.as_compressed());
328 }
329
330 pub fn make_bytes<B: Default + AsMut<[u8]>>(&self, context: &[u8]) -> B {
341 let mut t = Transcript::new(b"VRFResult");
342 t.append_message(b"",context);
343 self.commit(&mut t);
344 let mut seed = B::default();
345 t.challenge_bytes(b"", seed.as_mut());
346 seed
347 }
348
349 pub fn make_rng<R: rand_core::SeedableRng>(&self, context: &[u8]) -> R {
355 R::from_seed(self.make_bytes::<R::Seed>(context))
356 }
357
358 #[cfg(feature = "rand_chacha")]
370 pub fn make_chacharng(&self, context: &[u8]) -> rand_chacha::ChaChaRng {
371 self.make_rng::<::rand_chacha::ChaChaRng>(context)
372 }
373
374 #[inline(always)]
383 pub fn make_merlin_rng(&self, context: &[u8]) -> merlin::TranscriptRng {
384 struct ZeroFakeRng;
386 impl rand_core::RngCore for ZeroFakeRng {
387 fn next_u32(&mut self) -> u32 { panic!() }
388 fn next_u64(&mut self) -> u64 { panic!() }
389 fn fill_bytes(&mut self, dest: &mut [u8]) {
390 for i in dest.iter_mut() { *i = 0; }
391 }
392 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
393 self.fill_bytes(dest);
394 Ok(())
395 }
396 }
397 impl rand_core::CryptoRng for ZeroFakeRng {}
398
399 let mut t = Transcript::new(b"VRFResult");
400 t.append_message(b"",context);
401 self.commit(&mut t);
402 t.build_rng().finalize(&mut ZeroFakeRng)
403 }
404}
405
406fn challenge_scalar_128<T: SigningTranscript>(mut t: T) -> Scalar {
407 let mut s = [0u8; 16];
408 t.challenge_bytes(b"", &mut s);
409 Scalar::from(u128::from_le_bytes(s))
410}
411
412impl PublicKey {
413 pub fn vrfs_merge<B>(&self, ps: &[B], vartime: bool) -> VRFInOut
431 where
432 B: Borrow<VRFInOut>,
433 {
434 assert!(!ps.is_empty());
435 let mut t = merlin::Transcript::new(b"MergeVRFs");
436 t.commit_point(b"vrf:pk", self.as_compressed());
437 for p in ps.iter() {
438 p.borrow().commit(&mut t);
439 }
440
441 let zf = || ps.iter().map(|p| {
442 let mut t0 = t.clone();
443 p.borrow().commit(&mut t0);
444 challenge_scalar_128(t0)
445 });
446 #[cfg(feature = "alloc")]
447 let zs: Vec<Scalar> = zf().collect();
448 #[cfg(feature = "alloc")]
449 let zf = || zs.iter();
450
451 fn get_input(p: &VRFInOut) -> &RistrettoPoint { p.input.as_point() }
455 fn get_output(p: &VRFInOut) -> &RistrettoPoint { p.output.as_point() }
456 #[cfg(feature = "alloc")]
457 let go = |io: fn(p: &VRFInOut) -> &RistrettoPoint| {
458 let ps = ps.iter().map( |p| io(p.borrow()) );
459 RistrettoBoth::from_point(if vartime {
460 RistrettoPoint::vartime_multiscalar_mul(zf(), ps)
461 } else {
462 RistrettoPoint::multiscalar_mul(zf(), ps)
463 })
464 };
465 #[cfg(not(feature = "alloc"))]
466 let go = |io: fn(p: &VRFInOut) -> &RistrettoPoint| {
467 let _ = vartime; use curve25519_dalek::traits::Identity;
469 let mut acc = RistrettoPoint::identity();
470 for (z,p) in zf().zip(ps) {
471 acc += z * io(p.borrow());
472 }
473 RistrettoBoth::from_point(acc)
474 };
475
476 let input = go( get_input );
477 let output = go( get_output );
478 VRFInOut { input, output }
479 }
480}
481
482#[derive(Debug, Clone, PartialEq, Eq)] pub struct VRFProof {
486 c: Scalar,
488 s: Scalar,
490}
491
492impl VRFProof {
493 const DESCRIPTION : &'static str = "A Ristretto Schnorr VRF proof without batch verification support, which consists of two scalars, making it 64 bytes.";
494
495 #[inline]
497 pub fn to_bytes(&self) -> [u8; VRF_PROOF_LENGTH] {
498 let mut bytes = [0u8; VRF_PROOF_LENGTH];
499
500 bytes[..32].copy_from_slice(&self.c.as_bytes()[..]);
501 bytes[32..].copy_from_slice(&self.s.as_bytes()[..]);
502 bytes
503 }
504
505 #[inline]
507 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<VRFProof> {
508 if bytes.len() != VRF_PROOF_LENGTH {
509 return Err(SignatureError::BytesLengthError {
510 name: "VRFProof",
511 description: VRFProof::DESCRIPTION,
512 length: VRF_PROOF_LENGTH
513 });
514 }
515 let mut c: [u8; 32] = [0u8; 32];
516 let mut s: [u8; 32] = [0u8; 32];
517
518 c.copy_from_slice(&bytes[..32]);
519 s.copy_from_slice(&bytes[32..]);
520
521 let c = crate::scalar_from_canonical_bytes(c).ok_or(SignatureError::ScalarFormatError) ?;
522 let s = crate::scalar_from_canonical_bytes(s).ok_or(SignatureError::ScalarFormatError) ?;
523 Ok(VRFProof { c, s })
524 }
525}
526
527serde_boilerplate!(VRFProof);
528
529#[derive(Debug, Clone, PartialEq, Eq)] #[allow(non_snake_case)]
533pub struct VRFProofBatchable {
534 R: CompressedRistretto,
536 Hr: CompressedRistretto,
538 s: Scalar,
540}
541
542impl VRFProofBatchable {
543 const DESCRIPTION : &'static str = "A Ristretto Schnorr VRF proof that supports batch verification, which consists of two Ristretto compressed points and one scalar, making it 96 bytes.";
544
545 #[allow(non_snake_case)]
547 #[inline]
548 pub fn to_bytes(&self) -> [u8; VRF_PROOF_BATCHABLE_LENGTH] {
549 let mut bytes = [0u8; VRF_PROOF_BATCHABLE_LENGTH];
550
551 bytes[0..32].copy_from_slice(&self.R.as_bytes()[..]);
552 bytes[32..64].copy_from_slice(&self.Hr.as_bytes()[..]);
553 bytes[64..96].copy_from_slice(&self.s.as_bytes()[..]);
554 bytes
555 }
556
557 #[allow(non_snake_case)]
559 #[inline]
560 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<VRFProofBatchable> {
561 if bytes.len() != VRF_PROOF_BATCHABLE_LENGTH {
562 return Err(SignatureError::BytesLengthError {
563 name: "VRFProofBatchable",
564 description: VRFProofBatchable::DESCRIPTION,
565 length: VRF_PROOF_BATCHABLE_LENGTH,
566 });
567 }
568 let mut R: [u8; 32] = [0u8; 32];
569 let mut Hr: [u8; 32] = [0u8; 32];
570 let mut s: [u8; 32] = [0u8; 32];
571
572 R.copy_from_slice(&bytes[0..32]);
573 Hr.copy_from_slice(&bytes[32..64]);
574 s.copy_from_slice(&bytes[64..96]);
575
576 let s = crate::scalar_from_canonical_bytes(s).ok_or(SignatureError::ScalarFormatError) ?;
577 Ok(VRFProofBatchable { R: CompressedRistretto(R), Hr: CompressedRistretto(Hr), s })
578 }
579
580 #[allow(non_snake_case)]
582 pub fn shorten_dleq<T>(&self, mut t: T, public: &PublicKey, p: &VRFInOut, kusama: bool) -> VRFProof
583 where T: SigningTranscript,
584 {
585 t.proto_name(b"DLEQProof");
586 t.commit_point(b"vrf:h", p.input.as_compressed());
588 if !kusama { t.commit_point(b"vrf:pk", public.as_compressed()); }
589
590 t.commit_point(b"vrf:R=g^r", &self.R);
591 t.commit_point(b"vrf:h^r", &self.Hr);
592
593 if kusama { t.commit_point(b"vrf:pk", public.as_compressed()); }
594 t.commit_point(b"vrf:h^sk", p.output.as_compressed());
595
596 VRFProof {
597 c: t.challenge_scalar(b"prove"), s: self.s,
599 }
600 }
601
602 pub fn shorten_vrf<T>( &self, public: &PublicKey, t: T, out: &VRFPreOut)
608 -> SignatureResult<VRFProof>
609 where T: VRFSigningTranscript,
610 {
611 let p = out.attach_input_hash(public,t) ?; let t0 = Transcript::new(b"VRF"); Ok(self.shorten_dleq(t0, public, &p, KUSAMA_VRF))
614 }
615}
616
617serde_boilerplate!(VRFProofBatchable);
618
619impl Keypair {
620 #[allow(non_snake_case)]
627 pub fn dleq_proove<T>(&self, mut t: T, p: &VRFInOut, kusama: bool) -> (VRFProof, VRFProofBatchable)
628 where
629 T: SigningTranscript,
630 {
631 t.proto_name(b"DLEQProof");
632 t.commit_point(b"vrf:h", p.input.as_compressed());
634 if !kusama { t.commit_point(b"vrf:pk", self.public.as_compressed()); }
635
636 let mut r = t.witness_scalar(b"proving\x000",&[&self.secret.nonce]);
638 let R = (&r * constants::RISTRETTO_BASEPOINT_TABLE).compress();
639 t.commit_point(b"vrf:R=g^r", &R);
640
641 let Hr = (r * p.input.as_point()).compress();
642 t.commit_point(b"vrf:h^r", &Hr);
643
644 if kusama { t.commit_point(b"vrf:pk", self.public.as_compressed()); }
645 t.commit_point(b"vrf:h^sk", p.output.as_compressed());
647
648 let c = t.challenge_scalar(b"prove"); let s = r - c * self.secret.key;
650
651 zeroize::Zeroize::zeroize(&mut r);
652
653 (VRFProof { c, s }, VRFProofBatchable { R, Hr, s })
654 }
655
656 pub fn vrf_sign<T>(&self, t: T) -> (VRFInOut, VRFProof, VRFProofBatchable)
665 where T: VRFSigningTranscript,
666 {
667 self.vrf_sign_extra(t,Transcript::new(b"VRF"))
668 }
670
671 pub fn vrf_sign_extra<T,E>(&self, t: T, extra: E) -> (VRFInOut, VRFProof, VRFProofBatchable)
674 where T: VRFSigningTranscript,
675 E: SigningTranscript,
676 {
677 let p = self.vrf_create_hash(t);
678 let (proof, proof_batchable) = self.dleq_proove(extra, &p, KUSAMA_VRF);
679 (p, proof, proof_batchable)
680 }
681
682
683 pub fn vrf_sign_after_check<T,F>(&self, t: T, mut check: F)
692 -> Option<(VRFInOut, VRFProof, VRFProofBatchable)>
693 where T: VRFSigningTranscript,
694 F: FnMut(&VRFInOut) -> bool,
695 {
696 self.vrf_sign_extra_after_check(t,
697 |io| if check(io) { Some(Transcript::new(b"VRF")) } else { None }
698 )
699 }
700
701 pub fn vrf_sign_extra_after_check<T,E,F>(&self, t: T, mut check: F)
705 -> Option<(VRFInOut, VRFProof, VRFProofBatchable)>
706 where T: VRFSigningTranscript,
707 E: SigningTranscript,
708 F: FnMut(&VRFInOut) -> Option<E>,
709 {
710 let p = self.vrf_create_hash(t);
711 let extra = check(&p) ?;
712 let (proof, proof_batchable) = self.dleq_proove(extra, &p, KUSAMA_VRF);
713 Some((p, proof, proof_batchable))
714 }
715
716 #[cfg(feature = "alloc")]
723 pub fn vrfs_sign<T, I>(&self, ts: I) -> (Box<[VRFInOut]>, VRFProof, VRFProofBatchable)
724 where
725 T: VRFSigningTranscript,
726 I: IntoIterator<Item = T>,
727 {
728 self.vrfs_sign_extra(ts, Transcript::new(b"VRF"))
729 }
730
731 #[cfg(feature = "alloc")]
738 pub fn vrfs_sign_extra<T,E,I>(&self, ts: I, extra: E) -> (Box<[VRFInOut]>, VRFProof, VRFProofBatchable)
739 where
740 T: VRFSigningTranscript,
741 E: SigningTranscript,
742 I: IntoIterator<Item = T>,
743 {
744 let ps = ts.into_iter()
745 .map(|t| self.vrf_create_hash(t))
746 .collect::<Vec<VRFInOut>>();
747 let p = self.public.vrfs_merge(&ps,true);
748 let (proof, proof_batchable) = self.dleq_proove(extra, &p, KUSAMA_VRF);
749 (ps.into_boxed_slice(), proof, proof_batchable)
750 }
751}
752
753impl PublicKey {
754 #[allow(non_snake_case)]
765 pub fn dleq_verify<T>(
766 &self,
767 mut t: T,
768 p: &VRFInOut,
769 proof: &VRFProof,
770 kusama: bool,
771 ) -> SignatureResult<VRFProofBatchable>
772 where
773 T: SigningTranscript,
774 {
775 t.proto_name(b"DLEQProof");
776 t.commit_point(b"vrf:h", p.input.as_compressed());
778 if !kusama { t.commit_point(b"vrf:pk", self.as_compressed()); }
779
780 let R = RistrettoPoint::vartime_double_scalar_mul_basepoint(
783 &proof.c,
784 self.as_point(),
785 &proof.s,
786 ).compress();
787 t.commit_point(b"vrf:R=g^r", &R);
788
789 #[cfg(not(feature = "alloc"))]
791 let Hr = (&proof.c * p.output.as_point()) + (&proof.s * p.input.as_point());
792
793 #[cfg(feature = "alloc")]
795 let Hr = RistrettoPoint::vartime_multiscalar_mul(
796 &[proof.c, proof.s],
797 &[*p.output.as_point(), *p.input.as_point()],
798 );
799
800 let Hr = Hr.compress();
801 t.commit_point(b"vrf:h^r", &Hr);
802
803 if kusama { t.commit_point(b"vrf:pk", self.as_compressed()); }
804 t.commit_point(b"vrf:h^sk", p.output.as_compressed());
806
807 let VRFProof { c, s } = *proof;
809 if c == t.challenge_scalar(b"prove") {
810 Ok(VRFProofBatchable { R, Hr, s }) } else {
812 Err(SignatureError::EquationFalse)
813 }
814 }
815
816 pub fn vrf_verify<T: VRFSigningTranscript>(
818 &self,
819 t: T,
820 out: &VRFPreOut,
821 proof: &VRFProof,
822 ) -> SignatureResult<(VRFInOut, VRFProofBatchable)> {
823 self.vrf_verify_extra(t,out,proof,Transcript::new(b"VRF"))
824 }
825
826 pub fn vrf_verify_extra<T,E>(
828 &self,
829 t: T,
830 out: &VRFPreOut,
831 proof: &VRFProof,
832 extra: E,
833 ) -> SignatureResult<(VRFInOut, VRFProofBatchable)>
834 where T: VRFSigningTranscript,
835 E: SigningTranscript,
836 {
837 let p = out.attach_input_hash(self,t)?;
838 let proof_batchable = self.dleq_verify(extra, &p, proof, KUSAMA_VRF)?;
839 Ok((p, proof_batchable))
840 }
841
842 #[cfg(feature = "alloc")]
844 pub fn vrfs_verify<T,I,O>(
845 &self,
846 transcripts: I,
847 outs: &[O],
848 proof: &VRFProof,
849 ) -> SignatureResult<(Box<[VRFInOut]>, VRFProofBatchable)>
850 where
851 T: VRFSigningTranscript,
852 I: IntoIterator<Item = T>,
853 O: Borrow<VRFPreOut>,
854 {
855 self.vrfs_verify_extra(transcripts,outs,proof,Transcript::new(b"VRF"))
856 }
857
858 #[cfg(feature = "alloc")]
860 pub fn vrfs_verify_extra<T,E,I,O>(
861 &self,
862 transcripts: I,
863 outs: &[O],
864 proof: &VRFProof,
865 extra: E,
866 ) -> SignatureResult<(Box<[VRFInOut]>, VRFProofBatchable)>
867 where
868 T: VRFSigningTranscript,
869 E: SigningTranscript,
870 I: IntoIterator<Item = T>,
871 O: Borrow<VRFPreOut>,
872 {
873 let mut ts = transcripts.into_iter();
874 let ps = ts.by_ref().zip(outs)
875 .map(|(t, out)| out.borrow().attach_input_hash(self,t))
876 .collect::<SignatureResult<Vec<VRFInOut>>>()?;
877 assert!(ts.next().is_none(), "Too few VRF outputs for VRF inputs.");
878 assert!(
879 ps.len() == outs.len(),
880 "Too few VRF inputs for VRF outputs."
881 );
882 let p = self.vrfs_merge(&ps[..],true);
883 let proof_batchable = self.dleq_verify(extra, &p, proof, KUSAMA_VRF)?;
884 Ok((ps.into_boxed_slice(), proof_batchable))
885 }
886}
887
888#[cfg(feature = "alloc")]
905#[allow(non_snake_case)]
906pub fn dleq_verify_batch(
907 ps: &[VRFInOut],
908 proofs: &[VRFProofBatchable],
909 public_keys: &[PublicKey],
910 kusama: bool,
911) -> SignatureResult<()> {
912 const ASSERT_MESSAGE: &str = "The number of messages/transcripts / input points, output points, proofs, and public keys must be equal.";
913 assert!(ps.len() == proofs.len(), "{}", ASSERT_MESSAGE);
914 assert!(proofs.len() == public_keys.len(), "{}", ASSERT_MESSAGE);
915
916 let mut csprng = {
919 let mut t = Transcript::new(b"VB-RNG");
920 for (pk,p) in public_keys.iter().zip(ps) {
921 t.commit_point(b"",pk.as_compressed());
922 p.commit(&mut t);
923 }
924 t.build_rng().finalize(&mut getrandom_or_panic())
925 };
926
927 let rnd_128bit_scalar = |_| {
931 let mut r = [0u8; 16];
932 csprng.fill_bytes(&mut r);
933 Scalar::from(u128::from_le_bytes(r))
934 };
935 let zz: Vec<Scalar> = proofs.iter().map(rnd_128bit_scalar).collect();
936
937 let z_s: Vec<Scalar> = zz.iter().zip(proofs)
938 .map(|(z, proof)| z * proof.s)
939 .collect();
940
941 let B_coefficient: Scalar = z_s.iter().sum();
943
944 let t0 = Transcript::new(b"VRF");
945 let z_c: Vec<Scalar> = zz.iter().enumerate()
946 .map( |(i, z)| z * proofs[i].shorten_dleq(t0.clone(), &public_keys[i], &ps[i], kusama).c )
947 .collect();
948
949 let mut b = RistrettoPoint::optional_multiscalar_mul(
951 zz.iter().map(|z| -z)
952 .chain(z_c.iter().cloned())
953 .chain(once(B_coefficient)),
954 proofs.iter().map(|proof| proof.R.decompress())
955 .chain(public_keys.iter().map(|pk| Some(*pk.as_point())))
956 .chain(once(Some(constants::RISTRETTO_BASEPOINT_POINT))),
957 ).map(|id| id.is_identity()).unwrap_or(false);
958
959 b &= RistrettoPoint::optional_multiscalar_mul(
961 zz.iter().map(|z| -z)
962 .chain(z_c)
963 .chain(z_s),
964 proofs.iter().map(|proof| proof.Hr.decompress())
965 .chain(ps.iter().map(|p| Some(*p.output.as_point())))
966 .chain(ps.iter().map(|p| Some(*p.input.as_point()))),
967 ).map(|id| id.is_identity()).unwrap_or(false);
968
969 if b { Ok(()) } else { Err(SignatureError::EquationFalse) }
970}
971
972#[cfg(feature = "alloc")]
976pub fn vrf_verify_batch<T, I>(
977 transcripts: I,
978 outs: &[VRFPreOut],
979 proofs: &[VRFProofBatchable],
980 publickeys: &[PublicKey],
981) -> SignatureResult<Box<[VRFInOut]>>
982where
983 T: VRFSigningTranscript,
984 I: IntoIterator<Item = T>,
985{
986 let mut ts = transcripts.into_iter();
987 let ps = ts.by_ref()
988 .zip(publickeys)
989 .zip(outs)
990 .map(|((t, pk), out)| out.attach_input_hash(pk,t))
991 .collect::<SignatureResult<Vec<VRFInOut>>>()?;
992 assert!(ts.next().is_none(), "Too few VRF outputs for VRF inputs.");
993 assert!(
994 ps.len() == outs.len(),
995 "Too few VRF inputs for VRF outputs."
996 );
997 if dleq_verify_batch(&ps[..], proofs, publickeys, KUSAMA_VRF).is_ok() {
998 Ok(ps.into_boxed_slice())
999 } else {
1000 Err(SignatureError::EquationFalse)
1001 }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006 #[cfg(feature = "alloc")]
1007 use alloc::vec::Vec;
1008
1009 use super::*;
1010
1011 #[cfg(feature = "getrandom")]
1012 #[test]
1013 fn vrf_single() {
1014 let mut csprng = rand_core::OsRng;
1015
1016 let keypair1 = Keypair::generate_with(&mut csprng);
1017
1018 let ctx = signing_context(b"yo!");
1019 let msg = b"meow";
1020 let (io1, proof1, proof1batchable) = keypair1.vrf_sign(ctx.bytes(msg));
1021 let out1 = &io1.to_preout();
1022 assert_eq!(
1023 proof1,
1024 proof1batchable
1025 .shorten_vrf(&keypair1.public, ctx.bytes(msg), &out1)
1026 .unwrap(),
1027 "Oops `shorten_vrf` failed"
1028 );
1029 let (io1too, proof1too) = keypair1.public.vrf_verify(ctx.bytes(msg), &out1, &proof1)
1030 .expect("Correct VRF verification failed!");
1031 assert_eq!(
1032 io1too, io1,
1033 "Output differs between signing and verification!"
1034 );
1035 assert_eq!(
1036 proof1batchable, proof1too,
1037 "VRF verification yielded incorrect batchable proof"
1038 );
1039 assert_eq!(
1040 keypair1.vrf_sign(ctx.bytes(msg)).0,
1041 io1,
1042 "Rerunning VRF gave different output"
1043 );
1044
1045 assert!(
1046 keypair1.public.vrf_verify(ctx.bytes(b"not meow"), &out1, &proof1).is_err(),
1047 "VRF verification with incorrect message passed!"
1048 );
1049
1050 let keypair2 = Keypair::generate_with(&mut csprng);
1051 assert!(
1052 keypair2.public.vrf_verify(ctx.bytes(msg), &out1, &proof1).is_err(),
1053 "VRF verification with incorrect signer passed!"
1054 );
1055 }
1056
1057 #[cfg(feature = "getrandom")]
1058 #[test]
1059 fn vrf_malleable() {
1060 let mut csprng = rand_core::OsRng;
1061
1062 let keypair1 = Keypair::generate_with(&mut csprng);
1063
1064 let ctx = signing_context(b"yo!");
1065 let msg = b"meow";
1066 let (io1, proof1, proof1batchable) = keypair1.vrf_sign(Malleable(ctx.bytes(msg)));
1067 let out1 = &io1.to_preout();
1068 assert_eq!(
1069 proof1,
1070 proof1batchable.shorten_vrf(&keypair1.public, Malleable(ctx.bytes(msg)), &out1).unwrap(),
1071 "Oops `shorten_vrf` failed"
1072 );
1073 let (io1too, proof1too) = keypair1
1074 .public.vrf_verify(Malleable(ctx.bytes(msg)), &out1, &proof1)
1075 .expect("Correct VRF verification failed!");
1076 assert_eq!(
1077 io1too, io1,
1078 "Output differs between signing and verification!"
1079 );
1080 assert_eq!(
1081 proof1batchable, proof1too,
1082 "VRF verification yielded incorrect batchable proof"
1083 );
1084 assert_eq!(
1085 keypair1.vrf_sign(Malleable(ctx.bytes(msg))).0,
1086 io1,
1087 "Rerunning VRF gave different output"
1088 );
1089 assert!(
1090 keypair1.public.vrf_verify(Malleable(ctx.bytes(b"not meow")), &out1, &proof1).is_err(),
1091 "VRF verification with incorrect message passed!"
1092 );
1093
1094 let keypair2 = Keypair::generate_with(&mut csprng);
1095 assert!(
1096 keypair2.public.vrf_verify(Malleable(ctx.bytes(msg)), &out1, &proof1).is_err(),
1097 "VRF verification with incorrect signer passed!"
1098 );
1099 let (io2, _proof2, _proof2batchable) = keypair2.vrf_sign(Malleable(ctx.bytes(msg)));
1100 let out2 = &io2.to_preout();
1101
1102 let t0 = Transcript::new(b"VRF");
1104 let io21 = keypair2.secret.vrf_create_from_compressed_point(out1).unwrap();
1105 let proofs21 = keypair2.dleq_proove(t0.clone(), &io21, KUSAMA_VRF);
1106 let io12 = keypair1.secret.vrf_create_from_compressed_point(out2).unwrap();
1107 let proofs12 = keypair1.dleq_proove(t0.clone(), &io12, KUSAMA_VRF);
1108 assert_eq!(io12.output, io21.output, "Sequential two-party VRF failed");
1109 assert_eq!(
1110 proofs21.0,
1111 proofs21.1.shorten_dleq(t0.clone(), &keypair2.public, &io21, KUSAMA_VRF),
1112 "Oops `shorten_dleq` failed"
1113 );
1114 assert_eq!(
1115 proofs12.0,
1116 proofs12.1.shorten_dleq(t0.clone(), &keypair1.public, &io12, KUSAMA_VRF),
1117 "Oops `shorten_dleq` failed"
1118 );
1119 assert!(keypair1
1120 .public
1121 .dleq_verify(t0.clone(), &io12, &proofs12.0, KUSAMA_VRF)
1122 .is_ok());
1123 assert!(keypair2
1124 .public
1125 .dleq_verify(t0.clone(), &io21, &proofs21.0, KUSAMA_VRF)
1126 .is_ok());
1127 }
1128
1129 #[cfg(feature = "alloc")]
1130 #[test]
1131 fn vrfs_merged_and_batched() {
1132 let mut csprng = rand_core::OsRng;
1133 let keypairs: Vec<Keypair> = (0..4)
1134 .map(|_| Keypair::generate_with(&mut csprng))
1135 .collect();
1136
1137 let ctx = signing_context(b"yo!");
1138 let messages: [&[u8; 4]; 2] = [b"meow", b"woof"];
1139 let ts = || messages.iter().map(|m| ctx.bytes(*m));
1140
1141 let ios_n_proofs = keypairs.iter().map(|k| k.vrfs_sign(ts())).collect::<Vec<(
1142 Box<[VRFInOut]>,
1143 VRFProof,
1144 VRFProofBatchable,
1145 )>>();
1146
1147 for (k, (ios, proof, proof_batchable)) in keypairs.iter().zip(&ios_n_proofs) {
1148 let outs = ios
1149 .iter()
1150 .map(|io| io.to_preout())
1151 .collect::<Vec<VRFPreOut>>();
1152 let (ios_too, proof_too) = k
1153 .public
1154 .vrfs_verify(ts(), &outs, &proof)
1155 .expect("Valid VRF output verification failed!");
1156 assert_eq!(
1157 ios_too, *ios,
1158 "Output differs between signing and verification!"
1159 );
1160 assert_eq!(
1161 proof_too, *proof_batchable,
1162 "Returning batchable proof failed!"
1163 );
1164 }
1165 for (k, (ios, proof, _proof_batchable)) in keypairs.iter().zip(&ios_n_proofs) {
1166 let outs = ios.iter()
1167 .rev()
1168 .map(|io| io.to_preout())
1169 .collect::<Vec<VRFPreOut>>();
1170 assert!(
1171 k.public.vrfs_verify(ts(), &outs, &proof).is_err(),
1172 "Incorrect VRF output verification passed!"
1173 );
1174 }
1175 for (k, (ios, proof, _proof_batchable)) in keypairs.iter().rev().zip(&ios_n_proofs) {
1176 let outs = ios.iter()
1177 .map(|io| io.to_preout())
1178 .collect::<Vec<VRFPreOut>>();
1179 assert!(
1180 k.public.vrfs_verify(ts(), &outs, &proof).is_err(),
1181 "VRF output verification by a different signer passed!"
1182 );
1183 }
1184
1185 let mut ios = keypairs.iter().enumerate()
1186 .map(|(i, keypair)| keypair.public.vrfs_merge(&ios_n_proofs[i].0,true))
1187 .collect::<Vec<VRFInOut>>();
1188
1189 let mut proofs = ios_n_proofs.iter()
1190 .map(|(_ios, _proof, proof_batchable)| proof_batchable.clone())
1191 .collect::<Vec<VRFProofBatchable>>();
1192
1193 let mut public_keys = keypairs.iter()
1194 .map(|keypair| keypair.public.clone())
1195 .collect::<Vec<PublicKey>>();
1196
1197 assert!(
1198 dleq_verify_batch(&ios, &proofs, &public_keys, KUSAMA_VRF).is_ok(),
1199 "Batch verification failed!"
1200 );
1201 proofs.reverse();
1202 assert!(
1203 dleq_verify_batch(&ios, &proofs, &public_keys, KUSAMA_VRF).is_err(),
1204 "Batch verification with incorrect proofs passed!"
1205 );
1206 proofs.reverse();
1207 public_keys.reverse();
1208 assert!(
1209 dleq_verify_batch(&ios, &proofs, &public_keys, KUSAMA_VRF).is_err(),
1210 "Batch verification with incorrect public keys passed!"
1211 );
1212 public_keys.reverse();
1213 ios.reverse();
1214 assert!(
1215 dleq_verify_batch(&ios, &proofs, &public_keys, KUSAMA_VRF).is_err(),
1216 "Batch verification with incorrect points passed!"
1217 );
1218 }
1219}