1pub mod traits;
2
3use crate::traits::{ConstTranscribable, GenTranscribable, Transcript};
4use crypto_primitives::{ConstIntSemiring, PrimeField};
5use zinc_primality::PrimalityTest;
6use zinc_utils::add;
7
8#[derive(Debug, Clone)]
12pub struct Blake3Transcript {
13 hasher: blake3::Hasher,
15}
16
17impl Default for Blake3Transcript {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl Blake3Transcript {
24 pub fn new() -> Self {
25 Self {
26 hasher: blake3::Hasher::new(),
27 }
28 }
29
30 #[allow(clippy::arithmetic_side_effects)]
36 fn fill_with_random_bytes(&mut self, buf: &mut [u8]) {
37 self.hasher.finalize_xof().fill(buf);
38 }
39
40 fn gen_random<R: ConstTranscribable>(&mut self, buf: &mut [u8]) -> R {
41 self.fill_with_random_bytes(buf);
42 self.absorb_inner(buf);
43 R::read_transcription_bytes_exact(buf)
44 }
45}
46
47impl Transcript for Blake3Transcript {
48 fn get_challenge<T: ConstTranscribable>(&mut self) -> T {
49 let mut buf = vec![0u8; T::NUM_BYTES];
50 self.fill_with_random_bytes(&mut buf);
51 self.hasher.update(&[0x12]);
52 self.hasher.update(&buf);
53 self.hasher.update(&[0x34]);
54 T::read_transcription_bytes_exact(&buf)
55 }
56
57 #[allow(clippy::arithmetic_side_effects)]
58 fn get_prime<R: ConstIntSemiring + ConstTranscribable, T: PrimalityTest<R>>(&mut self) -> R {
59 let buf = &mut vec![0u8; R::NUM_BYTES];
60 loop {
61 let mut prime_candidate: R = self.gen_random(buf);
62 if prime_candidate.is_zero() {
63 continue;
64 }
65 if prime_candidate.is_even() {
66 prime_candidate -= R::ONE;
67 }
68 if T::is_probably_prime(&prime_candidate) {
69 return prime_candidate;
70 }
71 }
72 }
73
74 fn absorb_inner(&mut self, v: &[u8]) {
75 self.hasher.update(v);
76 }
77}
78
79pub fn read_field_cfg<F>(bytes: &[u8]) -> F::Config
80where
81 F: PrimeField,
82 F::Modulus: ConstTranscribable,
83{
84 let mod_size = F::Modulus::NUM_BYTES;
85 let modulus = F::Modulus::read_transcription_bytes_exact(&bytes[..mod_size]);
86 F::make_cfg(&modulus).expect("valid field modulus in proof transcription")
87}
88
89pub fn read_field_vec_with_cfg<F>(bytes: &[u8], field_cfg: &F::Config) -> Vec<F>
90where
91 F: PrimeField,
92 F::Inner: ConstTranscribable,
93{
94 let inner_size = F::Inner::NUM_BYTES;
95 bytes
96 .chunks_exact(inner_size)
97 .map(F::Inner::read_transcription_bytes_exact)
98 .map(|inner| F::new_unchecked_with_cfg(inner, field_cfg))
99 .collect()
100}
101
102pub fn append_field_cfg<'a, F>(buf: &'a mut [u8], modulus: &F::Modulus) -> &'a mut [u8]
103where
104 F: PrimeField,
105 F::Modulus: ConstTranscribable,
106{
107 let mod_size = F::Modulus::NUM_BYTES;
108 let (buf, rest) = buf.split_at_mut(mod_size);
109 modulus.write_transcription_bytes_exact(buf);
110 rest
111}
112
113pub fn append_field_vec_inner<'a, F>(buf: &'a mut [u8], slice: &[F]) -> &'a mut [u8]
114where
115 F: PrimeField,
116 F::Inner: ConstTranscribable,
117{
118 let inner_size = F::Inner::NUM_BYTES;
119 let mut offset = 0;
120 for elem in slice {
121 let offset_end = add!(offset, inner_size);
122 elem.inner()
123 .write_transcription_bytes_exact(&mut buf[offset..offset_end]);
124 offset = offset_end;
125 }
126 &mut buf[offset..]
127}