dory_pcs/backends/arkworks/
blake2b_transcript.rs1#![allow(missing_docs)]
4#![allow(clippy::missing_errors_doc)]
5#![allow(clippy::missing_panics_doc)]
6
7use crate::primitives::arithmetic::{Group, PairingCurve};
8use crate::primitives::serialization::Compress;
9use crate::primitives::transcript::Transcript;
10use crate::primitives::DorySerialize;
11use ark_ff::{BigInteger, PrimeField};
12use ark_serialize::CanonicalSerialize;
13use blake2::Blake2b512;
14use digest::{Digest, Output};
15use std::marker::PhantomData;
16
17#[derive(Clone)]
18pub struct Blake2bTranscript<E: PairingCurve> {
19 hasher: Blake2b512,
20 _phantom: PhantomData<E>,
21}
22
23impl<E: PairingCurve> Blake2bTranscript<E> {
24 pub fn new(domain_label: &[u8]) -> Self {
25 let mut hasher = Blake2b512::default();
26 hasher.update(domain_label);
27 Self {
28 hasher,
29 _phantom: PhantomData,
30 }
31 }
32
33 pub fn append_bytes_impl(&mut self, label: &[u8], bytes: &[u8]) {
34 self.hasher.update(label);
35 self.hasher.update((bytes.len() as u64).to_le_bytes());
36 self.hasher.update(bytes);
37 }
38
39 pub fn append_field_impl<F: PrimeField>(&mut self, label: &[u8], x: &F) {
40 self.append_bytes_impl(label, &x.into_bigint().to_bytes_le());
41 }
42
43 pub fn append_group_impl<G: CanonicalSerialize>(&mut self, label: &[u8], g: &G) {
44 let mut bytes = Vec::new();
45 g.serialize_compressed(&mut bytes)
46 .expect("Serialization should not fail");
47 self.append_bytes_impl(label, &bytes);
48 }
49
50 pub fn challenge_scalar_impl<F: PrimeField>(&mut self, label: &[u8]) -> F {
51 self.hasher.update(label);
52
53 let h = self.hasher.clone();
54 let digest: Output<Blake2b512> = h.finalize();
55
56 let repr = digest.to_vec();
57 let fe = F::from_le_bytes_mod_order(&repr);
58
59 if fe.is_zero() {
60 panic!("Challenge scalar cannot be zero")
61 }
62
63 self.hasher.update(&repr);
64
65 fe
66 }
67
68 pub fn reset_impl(&mut self, domain_label: &[u8]) {
69 let mut hasher = Blake2b512::default();
70 hasher.update(domain_label);
71 self.hasher = hasher;
72 self._phantom = PhantomData;
73 }
74}
75
76impl Transcript for Blake2bTranscript<crate::backends::arkworks::BN254> {
77 type Curve = crate::backends::arkworks::BN254;
78
79 fn append_bytes(&mut self, label: &[u8], bytes: &[u8]) {
80 self.append_bytes_impl(label, bytes);
81 }
82
83 fn append_field(
84 &mut self,
85 label: &[u8],
86 x: &<<crate::backends::arkworks::BN254 as PairingCurve>::G1 as Group>::Scalar,
87 ) {
88 self.append_field_impl(label, &x.0);
89 }
90
91 fn append_group<G: Group + DorySerialize>(&mut self, label: &[u8], g: &G) {
92 let mut bytes: Vec<u8> = Vec::new();
93 g.serialize_with_mode(&mut bytes, Compress::Yes)
94 .expect("DorySerialize should not fail");
95 self.append_bytes_impl(label, &bytes);
96 }
97
98 fn append_serde<S: DorySerialize>(&mut self, label: &[u8], s: &S) {
99 let mut bytes: Vec<u8> = Vec::new();
100 s.serialize_with_mode(&mut bytes, Compress::Yes)
101 .expect("DorySerialize should not fail");
102 self.append_bytes_impl(label, &bytes);
103 }
104
105 fn challenge_scalar(&mut self, label: &[u8]) -> crate::backends::arkworks::ArkFr {
106 use crate::backends::arkworks::ArkFr;
107 ArkFr(self.challenge_scalar_impl(label))
108 }
109
110 fn reset(&mut self, domain_label: &[u8]) {
111 self.reset_impl(domain_label);
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use crate::backends::arkworks::BN254;
119
120 #[test]
121 fn transcript_consistency() {
122 let mut t1: Blake2bTranscript<BN254> = Blake2bTranscript::new(b"demo");
123 let mut t2: Blake2bTranscript<BN254> = Blake2bTranscript::new(b"demo");
124
125 t1.append_bytes(b"m", b"hello");
127 t2.append_bytes(b"m", b"hello");
128
129 let c1 = t1.challenge_scalar(b"x");
130 let c2 = t2.challenge_scalar(b"x");
131
132 assert_eq!(c1, c2);
133 }
134
135 #[test]
136 fn transcript_different_messages() {
137 let mut t1: Blake2bTranscript<BN254> = Blake2bTranscript::new(b"demo");
138 let mut t2: Blake2bTranscript<BN254> = Blake2bTranscript::new(b"demo");
139
140 t1.append_bytes(b"m", b"hello");
141 t2.append_bytes(b"m", b"world");
142
143 let c1 = t1.challenge_scalar(b"x");
144 let c2 = t2.challenge_scalar(b"x");
145
146 assert_ne!(c1, c2);
147 }
148}