Skip to main content

tlsn_core/config/
prove.rs

1//! Proving configuration.
2
3use rangeset::{
4    iter::{FromRangeIterator, IntoRangeIterator},
5    set::RangeSet,
6};
7use serde::{Deserialize, Serialize};
8
9use crate::transcript::{Direction, Transcript, TranscriptCommitConfig, TranscriptCommitRequest};
10
11/// Configuration to prove information to the verifier.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ProveConfig {
14    server_identity: bool,
15    reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
16    transcript_commit: Option<TranscriptCommitConfig>,
17}
18
19impl ProveConfig {
20    /// Creates a new builder.
21    pub fn builder(transcript: &Transcript) -> ProveConfigBuilder<'_> {
22        ProveConfigBuilder::new(transcript)
23    }
24
25    /// Returns `true` if the server identity is to be proven.
26    pub fn server_identity(&self) -> bool {
27        self.server_identity
28    }
29
30    /// Returns the sent and received ranges of the transcript to be revealed,
31    /// respectively.
32    pub fn reveal(&self) -> Option<&(RangeSet<usize>, RangeSet<usize>)> {
33        self.reveal.as_ref()
34    }
35
36    /// Returns the transcript commitment configuration.
37    pub fn transcript_commit(&self) -> Option<&TranscriptCommitConfig> {
38        self.transcript_commit.as_ref()
39    }
40
41    /// Returns a request.
42    pub fn to_request(&self) -> ProveRequest {
43        ProveRequest {
44            server_identity: self.server_identity,
45            reveal: self.reveal.clone(),
46            transcript_commit: self
47                .transcript_commit
48                .clone()
49                .map(|config| config.to_request()),
50        }
51    }
52}
53
54/// Builder for [`ProveConfig`].
55#[derive(Debug)]
56pub struct ProveConfigBuilder<'a> {
57    transcript: &'a Transcript,
58    server_identity: bool,
59    reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
60    transcript_commit: Option<TranscriptCommitConfig>,
61}
62
63impl<'a> ProveConfigBuilder<'a> {
64    /// Creates a new builder.
65    pub fn new(transcript: &'a Transcript) -> Self {
66        Self {
67            transcript,
68            server_identity: false,
69            reveal: None,
70            transcript_commit: None,
71        }
72    }
73
74    /// Proves the server identity.
75    pub fn server_identity(&mut self) -> &mut Self {
76        self.server_identity = true;
77        self
78    }
79
80    /// Configures transcript commitments.
81    pub fn transcript_commit(&mut self, transcript_commit: TranscriptCommitConfig) -> &mut Self {
82        self.transcript_commit = Some(transcript_commit);
83        self
84    }
85
86    /// Reveals the given ranges of the transcript.
87    pub fn reveal(
88        &mut self,
89        direction: Direction,
90        ranges: impl IntoRangeIterator<usize>,
91    ) -> Result<&mut Self, ProveConfigError> {
92        self.reveal_inner(direction, RangeSet::from_range_iter(ranges))
93    }
94
95    fn reveal_inner(
96        &mut self,
97        direction: Direction,
98        idx: RangeSet<usize>,
99    ) -> Result<&mut Self, ProveConfigError> {
100        if idx.end().unwrap_or(0) > self.transcript.len_of_direction(direction) {
101            return Err(ProveConfigError(ErrorRepr::IndexOutOfBounds {
102                direction,
103                actual: idx.end().unwrap_or(0),
104                len: self.transcript.len_of_direction(direction),
105            }));
106        }
107
108        let (sent, recv) = self.reveal.get_or_insert_default();
109        match direction {
110            Direction::Sent => sent.union_mut(&idx),
111            Direction::Received => recv.union_mut(&idx),
112        }
113
114        Ok(self)
115    }
116
117    /// Reveals the given ranges of the sent data transcript.
118    pub fn reveal_sent(
119        &mut self,
120        ranges: impl IntoRangeIterator<usize>,
121    ) -> Result<&mut Self, ProveConfigError> {
122        self.reveal_inner(Direction::Sent, RangeSet::from_range_iter(ranges))
123    }
124
125    /// Reveals all of the sent data transcript.
126    pub fn reveal_sent_all(&mut self) -> Result<&mut Self, ProveConfigError> {
127        let len = self.transcript.len_of_direction(Direction::Sent);
128        let (sent, _) = self.reveal.get_or_insert_default();
129        sent.union_mut(0..len);
130        Ok(self)
131    }
132
133    /// Reveals the given ranges of the received data transcript.
134    pub fn reveal_recv(
135        &mut self,
136        ranges: impl IntoRangeIterator<usize>,
137    ) -> Result<&mut Self, ProveConfigError> {
138        self.reveal_inner(Direction::Received, RangeSet::from_range_iter(ranges))
139    }
140
141    /// Reveals all of the received data transcript.
142    pub fn reveal_recv_all(&mut self) -> Result<&mut Self, ProveConfigError> {
143        let len = self.transcript.len_of_direction(Direction::Received);
144        let (_, recv) = self.reveal.get_or_insert_default();
145        recv.union_mut(&(0..len));
146        Ok(self)
147    }
148
149    /// Builds the configuration.
150    pub fn build(self) -> Result<ProveConfig, ProveConfigError> {
151        Ok(ProveConfig {
152            server_identity: self.server_identity,
153            reveal: self.reveal,
154            transcript_commit: self.transcript_commit,
155        })
156    }
157}
158
159/// Request to prove statements about the connection.
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct ProveRequest {
162    server_identity: bool,
163    reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
164    transcript_commit: Option<TranscriptCommitRequest>,
165}
166
167impl ProveRequest {
168    /// Returns `true` if the server identity is to be proven.
169    pub fn server_identity(&self) -> bool {
170        self.server_identity
171    }
172
173    /// Returns the sent and received ranges of the transcript to be revealed,
174    /// respectively.
175    pub fn reveal(&self) -> Option<&(RangeSet<usize>, RangeSet<usize>)> {
176        self.reveal.as_ref()
177    }
178
179    /// Returns the transcript commitment configuration.
180    pub fn transcript_commit(&self) -> Option<&TranscriptCommitRequest> {
181        self.transcript_commit.as_ref()
182    }
183}
184
185/// Error for [`ProveConfig`].
186#[derive(Debug, thiserror::Error)]
187#[error(transparent)]
188pub struct ProveConfigError(#[from] ErrorRepr);
189
190#[derive(Debug, thiserror::Error)]
191enum ErrorRepr {
192    #[error("range is out of bounds of the transcript ({direction}): {actual} > {len}")]
193    IndexOutOfBounds {
194        direction: Direction,
195        actual: usize,
196        len: usize,
197    },
198}