primitives/transcripts/
protocol_transcript.rs

1use std::num::Wrapping;
2
3use crate::{
4    random::Seed,
5    transcripts::{AutoTranscript, FolkloreTranscript, Transcript},
6    types::{identifiers::ProtocolInfo, SessionId},
7};
8
9/// A transcript that appends a counter to each message. The counter starts at 0
10/// and increments by 1 with each appended message. This ensures that each message
11/// can be uniquely identified by its position in the transcript.
12#[derive(Debug, Clone)]
13pub struct ProtocolTranscript<T: Transcript = FolkloreTranscript> {
14    transcript: T,
15    counter: Wrapping<u64>,
16    protocol_tag: &'static [u8; 2],
17}
18
19impl<T: Transcript> Transcript for ProtocolTranscript<T> {
20    type Rng = T::Rng;
21    fn new(protocol_info: &'static ProtocolInfo, session_id: &SessionId) -> Self {
22        // Leak a protocol tag label to get a 'static reference
23        // This is acceptable since ProtocolInfo instances are static
24        let protocol_tag = Box::leak(Box::new(protocol_info.tag().to_le_bytes()));
25
26        Self {
27            transcript: T::new(protocol_info, session_id),
28            counter: Wrapping(0),
29            protocol_tag,
30        }
31    }
32
33    fn append_with<S: AsRef<[u8]>>(&mut self, label: &'static [u8], message: &S) {
34        let auto_label = self.next_label();
35        self.transcript
36            .append_many_with(label, &[auto_label.as_ref(), message.as_ref()]);
37    }
38
39    fn append_many_with<S: AsRef<[u8]>>(&mut self, label: &'static [u8], messages: &[S]) {
40        let auto_label = self.next_label();
41        let messages: Vec<&[u8]> = std::iter::once(auto_label.as_ref())
42            .chain(messages.iter().map(AsRef::as_ref))
43            .collect();
44        self.transcript.append_many_with(label, &messages);
45    }
46
47    fn extract(&mut self, label: &'static [u8]) -> Seed {
48        self.transcript.extract(label)
49    }
50
51    fn derive_rng(&mut self, label: &'static [u8]) -> T::Rng {
52        self.transcript.derive_rng(label)
53    }
54}
55
56impl<T: Transcript> AutoTranscript for ProtocolTranscript<T> {
57    type Label = [u8; 8];
58
59    #[inline]
60    fn get_current_label(&self) -> Self::Label {
61        self.counter.0.to_le_bytes()
62    }
63
64    #[inline]
65    fn next_label(&mut self) -> Self::Label {
66        self.counter += Wrapping(1);
67        self.get_current_label()
68    }
69
70    #[inline]
71    fn append<S: AsRef<[u8]>>(&mut self, message: &S) {
72        self.transcript.append_with(self.protocol_tag, message);
73    }
74
75    #[inline]
76    fn append_many<S: AsRef<[u8]>>(&mut self, messages: &[S]) {
77        self.transcript
78            .append_many_with(self.protocol_tag, messages);
79    }
80}