Skip to main content

primitives/transcripts/
folklore.rs

1use hybrid_array::Array;
2use rand::SeedableRng;
3use serde::{Deserialize, Serialize};
4use zeroize::Zeroize;
5
6use super::Transcript;
7use crate::{
8    constants::CollisionResistanceBytes,
9    hashing::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        // Create a vector of references to pass to hash
33        let mut elements: Vec<&[u8]> = Vec::with_capacity(2 + values.len());
34        elements.push(label);
35        elements.extend(values.iter().map(AsRef::as_ref));
36        elements.push(self.state.as_ref());
37
38        let values_len = values.len().to_be_bytes();
39        elements.push(&values_len);
40
41        self.state = hash(&elements);
42    }
43
44    fn extract(&mut self, label: &'static [u8]) -> Seed {
45        self.state = hash(&[label, self.state.as_ref()]);
46        *self.state.as_ref()
47    }
48
49    fn extract_rng(&mut self, label: &'static [u8]) -> Self::Rng {
50        self.state = hash(&[label, self.state.as_ref()]);
51        BaseRng::from_seed(self.state.into())
52    }
53}