1use super::concat;
7use crate::{Entropy, TicketId, simple::TrancheIndex};
8use ark_vrf::{
9 reexports::ark_serialize::{CanonicalDeserialize, CanonicalSerialize},
10 suites::bandersnatch::{self, AffinePoint, Secret as SecretImpl},
11};
12use codec::{Decode, Encode, MaxEncodedLen};
13use jam_types::{AnyVec, OpaqueBandersnatchPublic, TicketAttempt};
14
15pub use ark_vrf::Error;
16
17const SCALAR_SERIALIZED_SIZE: usize = 32;
18const POINT_SERIALIZED_SIZE: usize = 32;
19
20pub const PUBLIC_SERIALIZED_SIZE: usize = POINT_SERIALIZED_SIZE;
21pub const PREOUT_SERIALIZED_SIZE: usize = POINT_SERIALIZED_SIZE;
22
23const ERR_MSG: &str = "object length is constant and checked by test; qed";
24
25type Seed = [u8; SCALAR_SERIALIZED_SIZE];
27
28#[derive(Clone, Copy, PartialEq, Eq, Hash, Encode, Decode, MaxEncodedLen, Default)]
30pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]);
31
32impl Public {
33 pub fn is_valid(&self) -> bool {
34 AffinePoint::deserialize_compressed_unchecked(&self.0[..]).is_ok()
35 }
36}
37
38impl std::fmt::Debug for Public {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{:?}", AnyVec(self.0.to_vec()))
41 }
42}
43
44impl std::fmt::Display for Public {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{}", AnyVec(self.0.to_vec()))
47 }
48}
49
50impl From<OpaqueBandersnatchPublic> for Public {
51 fn from(opaque: OpaqueBandersnatchPublic) -> Self {
52 Self(opaque.0)
53 }
54}
55impl From<Public> for OpaqueBandersnatchPublic {
56 fn from(public: Public) -> Self {
57 Self(public.0)
58 }
59}
60
61#[derive(Clone)]
63pub struct Secret(SecretImpl);
64
65impl Secret {
66 pub fn new(rng: &mut impl rand::CryptoRng) -> Self {
68 Self::from_seed(rand::Rng::random(rng))
69 }
70
71 pub fn from_seed(seed: Seed) -> Self {
73 Self(SecretImpl::from_seed(&seed))
74 }
75
76 pub fn public(&self) -> Public {
78 let public = self.0.public();
79 let mut raw = [0; PUBLIC_SERIALIZED_SIZE];
80 public.serialize_compressed(raw.as_mut_slice()).expect(ERR_MSG);
81 Public(raw)
82 }
83
84 pub fn generate() -> Self {
86 Self::new(&mut rand::rng())
87 }
88}
89
90pub enum Message {
92 TicketSeal(Entropy, TicketAttempt),
94 FallbackSeal(Entropy),
96 Entropy(TicketId),
98 AuditInitial(Entropy),
100 AuditSubsequent(Entropy, jam_types::WorkReportHash, TrancheIndex),
102}
103
104impl Message {
105 pub fn using_encoded<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
107 match self {
108 Self::TicketSeal(entropy, attempt) =>
109 f(concat(&mut [0; 15 + 32 + 1], &[b"jam_ticket_seal", &entropy.0, &[*attempt]])),
110 Self::FallbackSeal(entropy) =>
111 f(concat(&mut [0; 17 + 32], &[b"jam_fallback_seal", &entropy.0])),
112 Self::Entropy(ticket_id) =>
113 f(concat(&mut [0; 11 + 32], &[b"jam_entropy", &ticket_id.0])),
114 Self::AuditInitial(entropy_source) =>
115 f(concat(&mut [0; 9 + 32], &[b"jam_audit", &entropy_source.0])),
116 Self::AuditSubsequent(entropy_source, report, index) => f(concat(
117 &mut [0; 9 + 64 + 1],
118 &[b"jam_audit", &entropy_source.0, &report.0, &[*index]],
119 )),
120 }
121 }
122}
123
124#[inline(always)]
126fn vrf_input(message: &Message) -> bandersnatch::Input {
127 message
128 .using_encoded(|enc| bandersnatch::Input::new(enc).expect("Elligator2 H2C is infallible"))
129}
130
131pub mod vrf {
133 use super::*;
134 use ark_vrf::ietf::{Prover, Verifier};
135 use codec::ConstEncodedLen;
136
137 pub(crate) const PROOF_SERIALIZED_SIZE: usize = 64;
138 pub const SIGNATURE_SERIALIZED_SIZE: usize = PREOUT_SERIALIZED_SIZE + PROOF_SERIALIZED_SIZE;
139
140 #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
142 pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]);
143
144 impl ConstEncodedLen for Signature {}
145
146 impl Signature {
147 pub fn vrf_output(&self) -> Entropy {
149 bandersnatch::Output::deserialize_compressed_unchecked(
150 &self.0[..PREOUT_SERIALIZED_SIZE],
151 )
152 .map(|p| {
153 let mut raw = [0u8; 32];
154 raw.copy_from_slice(&p.hash()[..32]);
155 Entropy(raw)
156 })
157 .unwrap_or_default()
158 }
159
160 pub fn vrf_verify(
162 &self,
163 message: &Message,
164 aux_data: &[u8],
165 public: &Public,
166 ) -> Result<(), Error> {
167 public.vrf_verify(message, aux_data, self)
168 }
169 }
170
171 impl Secret {
172 pub fn vrf_sign(&self, message: &Message, aux_data: &[u8]) -> Signature {
176 let input = vrf_input(message);
177 let output = self.0.output(input);
178 let proof = self.0.prove(input, output, aux_data);
179 let mut raw = [0_u8; SIGNATURE_SERIALIZED_SIZE];
180 output.serialize_compressed(&mut raw[..PREOUT_SERIALIZED_SIZE]).expect(ERR_MSG);
181 proof.serialize_compressed(&mut raw[PREOUT_SERIALIZED_SIZE..]).expect(ERR_MSG);
182 Signature(raw)
183 }
184
185 pub fn vrf_output(&self, message: &Message) -> Entropy {
187 let input = vrf_input(message);
188 let hash = self.0.output(input).hash();
189 let mut raw = [0u8; 32];
190 raw.copy_from_slice(&hash[..32]);
191 Entropy(raw)
192 }
193 }
194
195 impl Public {
196 pub fn vrf_verify(
198 &self,
199 message: &Message,
200 aux_data: &[u8],
201 signature: &Signature,
202 ) -> Result<(), Error> {
203 let public = bandersnatch::Public::deserialize_compressed_unchecked(self.0.as_ref())
204 .map_err(|_| Error::InvalidData)?;
205 let output = bandersnatch::Output::deserialize_compressed_unchecked(
206 &signature.0[..PREOUT_SERIALIZED_SIZE],
207 )
208 .map_err(|_| Error::InvalidData)?;
209 let proof = bandersnatch::IetfProof::deserialize_compressed_unchecked(
210 &signature.0[PREOUT_SERIALIZED_SIZE..],
211 )
212 .map_err(|_| Error::InvalidData)?;
213 let input = vrf_input(message);
214 public.verify(input, output, aux_data, &proof)
215 }
216 }
217
218 impl AsRef<[u8]> for Public {
219 fn as_ref(&self) -> &[u8] {
220 &self.0
221 }
222 }
223}
224
225pub mod ring_vrf {
226 use super::*;
227 use ark_vrf::ring::{Prover, Verifier};
228 pub use bandersnatch::{RingBatchItem, RingBatchVerifier, RingProver, RingVerifier};
229 use bandersnatch::{RingCommitment as RingCommitmentImpl, RingProofParams};
230
231 pub const RING_COMMITMENT_SERIALIZED_SIZE: usize = 144;
232
233 pub const RING_PROOF_SERIALIZED_SIZE: usize = 752;
234
235 pub const RING_SIGNATURE_SERIALIZED_SIZE: usize =
236 PREOUT_SERIALIZED_SIZE + RING_PROOF_SERIALIZED_SIZE;
237
238 #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, MaxEncodedLen)]
239 pub struct RingCommitment(pub [u8; RING_COMMITMENT_SERIALIZED_SIZE]);
240
241 #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
243 pub struct Signature(pub [u8; RING_SIGNATURE_SERIALIZED_SIZE]);
244
245 impl Signature {
246 pub fn ring_vrf_verify(
251 &self,
252 message: &Message,
253 aux_data: &[u8],
254 verifier: &RingVerifier,
255 ) -> Result<(), Error> {
256 let output = bandersnatch::Output::deserialize_compressed_unchecked(
257 &self.0[..PREOUT_SERIALIZED_SIZE],
258 )
259 .map_err(|_| Error::InvalidData)?;
260 let proof = bandersnatch::RingProof::deserialize_compressed_unchecked(
261 &self.0[PREOUT_SERIALIZED_SIZE..],
262 )
263 .map_err(|_| Error::InvalidData)?;
264 let input = vrf_input(message);
265 bandersnatch::Public::verify(input, output, aux_data, &proof, verifier)
266 }
267
268 pub fn ring_vrf_prepare(
274 &self,
275 message: &Message,
276 aux_data: &[u8],
277 batch_verifier: &RingBatchVerifier,
278 ) -> Result<RingBatchItem, Error> {
279 let output = bandersnatch::Output::deserialize_compressed_unchecked(
280 &self.0[..PREOUT_SERIALIZED_SIZE],
281 )
282 .map_err(|_| Error::InvalidData)?;
283 let proof = bandersnatch::RingProof::deserialize_compressed_unchecked(
284 &self.0[PREOUT_SERIALIZED_SIZE..],
285 )
286 .map_err(|_| Error::InvalidData)?;
287 let input = vrf_input(message);
288 Ok(batch_verifier.prepare(input, output, aux_data, &proof))
289 }
290
291 pub fn vrf_output(&self) -> Entropy {
293 bandersnatch::Output::deserialize_compressed_unchecked(
294 &self.0[..PREOUT_SERIALIZED_SIZE],
295 )
296 .map(|p| {
297 let mut raw = [0u8; 32];
298 raw.copy_from_slice(&p.hash()[..32]);
299 Entropy(raw)
300 })
301 .unwrap_or_default()
302 }
303 }
304
305 impl Secret {
306 pub fn ring_vrf_sign(
310 &self,
311 message: &Message,
312 aux_data: &[u8],
313 prover: &RingProver,
314 ) -> Signature {
315 let input = vrf_input(message);
316 let output = self.0.output(input);
317 let proof = self.0.prove(input, output, aux_data, prover);
318 let mut raw = [0_u8; RING_SIGNATURE_SERIALIZED_SIZE];
319 output.serialize_compressed(&mut raw[..PREOUT_SERIALIZED_SIZE]).expect(ERR_MSG);
320 proof.serialize_compressed(&mut raw[PREOUT_SERIALIZED_SIZE..]).expect(ERR_MSG);
321 Signature(raw)
322 }
323 }
324
325 #[derive(Clone)]
327 pub struct RingContext;
328
329 impl RingContext {
330 pub fn params() -> &'static RingProofParams {
338 use std::sync::OnceLock;
339 static PARAMS: OnceLock<RingProofParams> = OnceLock::new();
340 PARAMS.get_or_init(|| {
341 use bandersnatch::PcsParams;
342 let buf = include_bytes!(concat!(
344 env!("CARGO_MANIFEST_DIR"),
345 "/data/zcash-srs-2-11-uncompressed.bin"
346 ));
347 let pcs_params = PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..])
348 .expect("Error deserializing PcsParam");
349 RingProofParams::from_pcs_params(jam_types::max_val_count() as usize, pcs_params)
350 .expect("Error constructing RingProofParams from PcsParams")
351 })
352 }
353
354 pub fn prover(public_keys: &[Public], public_index: usize) -> RingProver {
358 let params = Self::params();
359 let pks = public_to_affine(public_keys);
360 let prover_key = params.prover_key(&pks);
361 params.prover(prover_key, public_index)
362 }
363
364 pub fn verifier(public_keys: &[Public]) -> RingVerifier {
368 let params = Self::params();
369 let pks = public_to_affine(public_keys);
370 let verifier_key = params.verifier_key(&pks);
371 params.verifier(verifier_key)
372 }
373
374 pub fn commitment(public_keys: &[Public]) -> RingCommitment {
378 let params = Self::params();
379 let pks = public_to_affine(public_keys);
380 let verifier_key = params.verifier_key(&pks);
381 let commitment = verifier_key.commitment();
382 let mut raw = [0; RING_COMMITMENT_SERIALIZED_SIZE];
383 commitment.serialize_compressed(&mut raw[..]).expect(ERR_MSG);
384 RingCommitment(raw)
385 }
386
387 pub fn verifier_from_commitment(commitment: RingCommitment) -> Result<RingVerifier, Error> {
389 let params = Self::params();
390 let mut raw = &commitment.0[..];
391 let commitment = RingCommitmentImpl::deserialize_compressed_unchecked(&mut raw)
392 .map_err(|_| Error::InvalidData)?;
393 let verifier_key = params.verifier_key_from_commitment(commitment);
394 Ok(params.verifier(verifier_key))
395 }
396 }
397
398 #[inline(always)]
403 fn public_to_affine(pks: &[Public]) -> Vec<AffinePoint> {
404 pks.iter()
405 .map(|pk| {
406 AffinePoint::deserialize_compressed_unchecked(&pk.0[..])
407 .unwrap_or(RingProofParams::padding_point())
408 })
409 .collect()
410 }
411}
412
413#[cfg(all(test, feature = "full-test-suite"))]
414mod tests {
415 #![allow(clippy::unwrap_used)]
416 use super::{ring_vrf::*, vrf::*, *};
417 use crate::NewNull;
418 use ring_vrf::RING_COMMITMENT_SERIALIZED_SIZE;
419
420 const SEED_SERIALIZED_SIZE: usize = 32;
421 const RING_KEYSET_SIZE: usize = 1023;
422
423 const DEV_SEED: [u8; SEED_SERIALIZED_SIZE] = [0xcb; SEED_SERIALIZED_SIZE];
424
425 #[allow(dead_code)]
426 fn serialize<T: CanonicalSerialize>(obj: &T) -> Vec<u8> {
427 let mut buf = Vec::new();
428 obj.serialize_compressed(&mut buf).unwrap();
429 buf
430 }
431
432 #[test]
433 fn backend_assumptions_check() {
434 use ark_vrf::reexports::ark_std;
435 use bandersnatch::RingProofParams;
436 const EXPECTED_DOMAIN_OVERHEAD: usize = 257;
437
438 let ctx = RingProofParams::from_seed(RING_KEYSET_SIZE, [0; 32]);
439
440 let expected_domain_size = 1 << ark_std::log2(RING_KEYSET_SIZE + EXPECTED_DOMAIN_OVERHEAD);
441 assert_eq!(ctx.max_ring_size(), expected_domain_size - EXPECTED_DOMAIN_OVERHEAD);
442
443 let pks: Vec<_> =
444 (0..16).map(|i| SecretImpl::from_seed(&[i as u8; 32]).public().0).collect();
445
446 let secret = SecretImpl::from_seed(&[0u8; 32]);
447
448 let public = secret.public();
449 assert_eq!(public.compressed_size(), PUBLIC_SERIALIZED_SIZE);
450
451 let input = vrf_input(&Message::FallbackSeal(Default::default()));
452 let output = secret.output(input);
453 assert_eq!(output.compressed_size(), PREOUT_SERIALIZED_SIZE);
454
455 let prover_key = ctx.prover_key(&pks);
456 let prover = ctx.prover(prover_key, 0);
457
458 let verifier_key = ctx.verifier_key(&pks);
459 let commitment = verifier_key.commitment();
460 assert_eq!(commitment.compressed_size(), RING_COMMITMENT_SERIALIZED_SIZE);
461
462 let ietf_proof = {
463 use ark_vrf::ietf::Prover;
464 secret.prove(input, output, [])
465 };
466 assert_eq!(ietf_proof.compressed_size(), PROOF_SERIALIZED_SIZE);
467
468 let ring_proof = {
469 use ark_vrf::ring::Prover;
470 secret.prove(input, output, [], &prover)
471 };
472 assert_eq!(ring_proof.compressed_size(), RING_PROOF_SERIALIZED_SIZE);
473
474 let padding_raw = [
477 0x92, 0xca, 0x79, 0xe6, 0x1d, 0xd9, 0x0c, 0x15, 0x73, 0xa8, 0x69, 0x3f, 0x19, 0x9b,
478 0xf6, 0xe1, 0xe8, 0x68, 0x35, 0xcc, 0x71, 0x5c, 0xdc, 0xf9, 0x3f, 0x5e, 0xf2, 0x22,
479 0x56, 0x00, 0x23, 0xaa,
480 ];
481 let padding_point = AffinePoint::deserialize_compressed(&padding_raw[..]).unwrap();
482 assert_eq!(RingProofParams::padding_point(), padding_point);
483 }
484
485 fn encode_decode<T: Encode + Decode + PartialEq + std::fmt::Debug>(expected_len: usize) {
486 let obj = T::new_null();
487 let buf = obj.encode();
488 assert_eq!(buf.len(), expected_len);
489 let dec = T::decode(&mut buf.as_slice()).unwrap();
490 assert_eq!(obj, dec);
491 }
492
493 #[test]
494 fn codec_works() {
495 encode_decode::<Public>(PUBLIC_SERIALIZED_SIZE);
496 encode_decode::<vrf::Signature>(SIGNATURE_SERIALIZED_SIZE);
497 encode_decode::<ring_vrf::Signature>(RING_SIGNATURE_SERIALIZED_SIZE);
498 }
499
500 #[test]
501 fn vrf_sign_verify() {
502 let secret = Secret::from_seed(DEV_SEED);
503 let public = secret.public();
504
505 let input = Message::FallbackSeal(Default::default());
506 let ad = b"data";
507
508 let signature = secret.vrf_sign(&input, ad);
509
510 assert!(public.vrf_verify(&input, ad, &signature).is_ok());
511
512 assert!(public.vrf_verify(&input, b"bad", &signature).is_err());
514
515 assert!(
517 public
518 .vrf_verify(&Message::FallbackSeal([1; 32].into()), ad, &signature)
519 .is_err()
520 );
521 }
522
523 #[test]
524 fn vrf_output_hash_matches() {
525 let secret = Secret::from_seed(DEV_SEED);
526
527 let input = Message::FallbackSeal(Default::default());
528 let signature = secret.vrf_sign(&input, b"data");
529
530 let output1 = secret.vrf_output(&input);
531 let output2 = signature.vrf_output();
532 assert_eq!(output1, output2);
533 }
534
535 #[test]
536 fn ring_vrf_sign_verify() {
537 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
538 assert!(pks.len() <= RING_KEYSET_SIZE);
539
540 let secret = Secret::from_seed(DEV_SEED);
541
542 let input = Message::FallbackSeal(Default::default());
543 let ad = b"data";
544
545 let prover_index = 3;
547 pks[prover_index] = secret.public();
548
549 let prover = RingContext::prover(&pks, prover_index);
550 let signature = secret.ring_vrf_sign(&input, ad, &prover);
551
552 let verifier = RingContext::verifier(&pks);
553 assert!(signature.ring_vrf_verify(&input, ad, &verifier).is_ok());
554
555 assert!(signature.ring_vrf_verify(&input, b"bad", &verifier).is_err());
557
558 assert!(
560 signature
561 .ring_vrf_verify(&Message::FallbackSeal([1; 32].into()), ad, &verifier)
562 .is_err()
563 );
564 }
565
566 #[test]
567 fn ring_vrf_sign_verify_with_out_of_ring_key() {
568 let pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
569 let secret = Secret::from_seed(DEV_SEED);
570
571 let input = Message::FallbackSeal(Default::default());
572 let ad = b"data";
573
574 let prover = RingContext::prover(&pks, 0);
576 let signature = secret.ring_vrf_sign(&input, ad, &prover);
577
578 let verifier = RingContext::verifier(&pks);
579 assert!(signature.ring_vrf_verify(&input, ad, &verifier).is_err());
580 }
581
582 #[test]
583 fn ring_vrf_batch_verify() {
584 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
585 assert!(pks.len() <= RING_KEYSET_SIZE);
586
587 let secrets = [
588 Secret::from_seed(DEV_SEED),
589 Secret::from_seed([0xab; SEED_SERIALIZED_SIZE]),
590 Secret::from_seed([0xcd; SEED_SERIALIZED_SIZE]),
591 ];
592 let indices = [3, 7, 12];
593 for (i, secret) in secrets.iter().enumerate() {
594 pks[indices[i]] = secret.public();
595 }
596
597 let messages = [
598 Message::FallbackSeal(Default::default()),
599 Message::FallbackSeal([1; 32].into()),
600 Message::FallbackSeal([2; 32].into()),
601 ];
602 let ad = b"data";
603
604 let signatures: Vec<_> = secrets
605 .iter()
606 .enumerate()
607 .map(|(i, secret)| {
608 let prover = RingContext::prover(&pks, indices[i]);
609 secret.ring_vrf_sign(&messages[i], ad, &prover)
610 })
611 .collect();
612
613 let verifier = RingContext::verifier(&pks);
615 let mut batch = RingBatchVerifier::new(verifier);
616 for (i, sig) in signatures.iter().enumerate() {
617 let item = sig.ring_vrf_prepare(&messages[i], ad, &batch).unwrap();
618 batch.push_prepared(item);
619 }
620 assert!(batch.verify().is_ok());
621
622 let verifier = RingContext::verifier(&pks);
624 let mut batch = RingBatchVerifier::new(verifier);
625 for (i, sig) in signatures.iter().enumerate() {
626 let msg = if i == 2 { &messages[0] } else { &messages[i] };
627 let item = sig.ring_vrf_prepare(msg, ad, &batch).unwrap();
628 batch.push_prepared(item);
629 }
630 assert!(batch.verify().is_err());
631 }
632
633 #[test]
634 fn ring_vrf_make_bytes_matches() {
635 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
636 assert!(pks.len() <= RING_KEYSET_SIZE);
637
638 let secret = Secret::from_seed(DEV_SEED);
639
640 let prover_index = 3;
642 pks[prover_index] = secret.public();
643
644 let input = Message::FallbackSeal(Default::default());
645
646 let prover = RingContext::prover(&pks, prover_index);
647 let signature = secret.ring_vrf_sign(&input, b"data", &prover);
648
649 let output1 = secret.vrf_output(&input);
650 let output2 = signature.vrf_output();
651 assert_eq!(output1, output2);
652 }
653}