primitives/transcripts/
merlin.rs1use hybrid_array::Array;
2pub use merlin::Transcript as MerlinTranscript;
3use rand::SeedableRng;
4use rand_chacha::ChaCha12Rng as ChachaRng;
5use typenum::Unsigned;
6
7use super::{Transcript, TranscriptRng};
8use crate::{constants::CollisionResistanceBytes, hashing::flatten_slices, types::SessionId};
9
10impl Transcript for MerlinTranscript {
11 fn new(label: &'static [u8]) -> Self {
12 merlin::Transcript::new(label)
13 }
14
15 fn new_with_session_id(label: &'static [u8], session_id: &SessionId) -> Self {
16 let mut t = merlin::Transcript::new(label);
17 t.append_message(b"session_id", session_id.as_ref());
18 t
19 }
20
21 fn append<T: AsRef<[u8]>>(&mut self, label: &'static [u8], message: &T) {
22 self.append_message(label, message.as_ref());
23 }
24
25 fn append_many<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]) {
26 let concatenated = flatten_slices(values);
27 self.append_message(label, &concatenated);
28 }
29
30 fn extract<T: AsMut<[u8]>>(&mut self, label: &'static [u8], dest: &mut T) {
31 self.challenge_bytes(label, dest.as_mut());
32 }
33}
34
35impl TranscriptRng for MerlinTranscript {
36 type Rng = merlin::TranscriptRng;
37 fn rng(&mut self, label: &'static [u8]) -> Self::Rng {
38 let mut seed: Array<u8, CollisionResistanceBytes> =
39 Array([0u8; CollisionResistanceBytes::USIZE]);
40 self.extract(label, &mut seed);
41 self.build_rng()
42 .finalize(&mut ChachaRng::from_seed(seed.into()))
43 }
44}