use hybrid_array::Array;
use rand::SeedableRng;
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
use super::Transcript;
use crate::{
constants::CollisionResistanceBytes,
hashing::{flatten_slices_with_length_prefixes, hash},
random::{BaseRng, Seed},
types::{identifiers::ProtocolInfo, SessionId},
};
#[derive(Clone, Default, Debug, Serialize, Deserialize, Zeroize)]
pub struct FolkloreTranscript {
state: Array<u8, CollisionResistanceBytes>,
}
impl Transcript for FolkloreTranscript {
type Rng = BaseRng;
fn new(protocol_info: &'static ProtocolInfo, session_id: &SessionId) -> Self {
let state = hash(&[protocol_info.tag(), session_id.as_ref()]);
Self { state }
}
fn append_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], value: &T) {
self.state = hash(&[label, value.as_ref(), self.state.as_ref()]);
}
fn append_many_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]) {
let concatenated = flatten_slices_with_length_prefixes(values);
let values_len = (values.len() as u64).to_le_bytes();
self.state = hash(&[label, &concatenated, self.state.as_ref(), &values_len]);
}
fn extract(&mut self, label: &'static [u8]) -> Seed {
self.state = hash(&[label, self.state.as_ref()]);
*self.state.as_ref()
}
fn extract_rng(&mut self, label: &'static [u8]) -> Self::Rng {
self.state = hash(&[label, self.state.as_ref()]);
BaseRng::from_seed(self.state.into())
}
}