primitives/transcripts/
folklore.rs1use hybrid_array::Array;
2use rand::SeedableRng;
3use serde::{Deserialize, Serialize};
4use zeroize::Zeroize;
5
6use super::Transcript;
7use crate::{
8 constants::CollisionResistanceBytes,
9 hashing::{flatten_slices_with_length_prefixes, hash},
10 random::{BaseRng, Seed},
11 types::{identifiers::ProtocolInfo, SessionId},
12};
13
14#[derive(Clone, Default, Debug, Serialize, Deserialize, Zeroize)]
15pub struct FolkloreTranscript {
16 state: Array<u8, CollisionResistanceBytes>,
17}
18
19impl Transcript for FolkloreTranscript {
20 type Rng = BaseRng;
21
22 fn new(protocol_info: &'static ProtocolInfo, session_id: &SessionId) -> Self {
23 let state = hash(&[protocol_info.tag(), session_id.as_ref()]);
24 Self { state }
25 }
26
27 fn append_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], value: &T) {
28 self.state = hash(&[label, value.as_ref(), self.state.as_ref()]);
29 }
30
31 fn append_many_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]) {
32 let concatenated = flatten_slices_with_length_prefixes(values);
33 let values_len = (values.len() as u64).to_le_bytes();
34 self.state = hash(&[label, &concatenated, self.state.as_ref(), &values_len]);
35 }
36
37 fn extract(&mut self, label: &'static [u8]) -> Seed {
38 self.state = hash(&[label, self.state.as_ref()]);
39 *self.state.as_ref()
40 }
41
42 fn extract_rng(&mut self, label: &'static [u8]) -> Self::Rng {
43 self.state = hash(&[label, self.state.as_ref()]);
44 BaseRng::from_seed(self.state.into())
45 }
46}