1use crate::error::{Error, Result};
7use curve25519_dalek::ristretto::RistrettoPoint;
8use curve25519_dalek::scalar::Scalar;
9
10pub trait Commitment: Clone + Send + Sync {
12 fn to_bytes(&self) -> Vec<u8>;
13 fn from_bytes(bytes: &[u8]) -> Result<Self>
14 where
15 Self: Sized;
16}
17
18pub trait Challenge: Clone + Send + Sync {
20 fn to_bytes(&self) -> Vec<u8>;
21 fn from_bytes(bytes: &[u8]) -> Result<Self>
22 where
23 Self: Sized;
24}
25
26pub trait Response: Clone + Send + Sync {
28 fn to_bytes(&self) -> Vec<u8>;
29 fn from_bytes(bytes: &[u8]) -> Result<Self>
30 where
31 Self: Sized;
32}
33
34pub trait SigmaProtocol {
41 type Statement: Clone + Send + Sync;
43 type Witness: Clone + Send + Sync;
45 type Commitment: Commitment;
47 type Challenge: Challenge;
49 type Response: Response;
51
52 fn prover_commit(
56 statement: &Self::Statement,
57 witness: &Self::Witness,
58 ) -> (Self::Commitment, Vec<u8>);
59
60 fn prover_response(
64 statement: &Self::Statement,
65 witness: &Self::Witness,
66 state: &[u8],
67 challenge: &Self::Challenge,
68 ) -> Result<Self::Response>;
69
70 fn verifier(
74 statement: &Self::Statement,
75 commitment: &Self::Commitment,
76 challenge: &Self::Challenge,
77 response: &Self::Response,
78 ) -> Result<()>;
79}
80
81#[derive(Clone, Debug)]
83pub struct ScalarChallenge(pub Scalar);
84
85impl Challenge for ScalarChallenge {
86 fn to_bytes(&self) -> Vec<u8> {
87 self.0.to_bytes().to_vec()
88 }
89
90 fn from_bytes(bytes: &[u8]) -> Result<Self> {
91 if bytes.len() != 32 {
92 return Err(Error::InvalidChallenge);
93 }
94 let mut array = [0u8; 32];
95 array.copy_from_slice(bytes);
96
97 Ok(ScalarChallenge(Scalar::from_bytes_mod_order(array)))
99 }
100}
101
102#[derive(Clone, Debug)]
104pub struct PointCommitment(pub RistrettoPoint);
105
106impl Commitment for PointCommitment {
107 fn to_bytes(&self) -> Vec<u8> {
108 self.0.compress().to_bytes().to_vec()
109 }
110
111 fn from_bytes(bytes: &[u8]) -> Result<Self> {
112 if bytes.len() != 32 {
113 return Err(Error::InvalidCommitment);
114 }
115 let mut array = [0u8; 32];
116 array.copy_from_slice(bytes);
117
118 let compressed = curve25519_dalek::ristretto::CompressedRistretto::from_slice(&array)
119 .map_err(|_| Error::InvalidCommitment)?;
120
121 compressed
122 .decompress()
123 .map(PointCommitment)
124 .ok_or(Error::InvalidPoint)
125 }
126}
127
128#[derive(Clone, Debug)]
130pub struct ScalarResponse(pub Scalar);
131
132impl Response for ScalarResponse {
133 fn to_bytes(&self) -> Vec<u8> {
134 self.0.to_bytes().to_vec()
135 }
136
137 fn from_bytes(bytes: &[u8]) -> Result<Self> {
138 if bytes.len() != 32 {
139 return Err(Error::InvalidResponse);
140 }
141 let mut array = [0u8; 32];
142 array.copy_from_slice(bytes);
143
144 let scalar_option = Scalar::from_canonical_bytes(array);
145
146 if scalar_option.is_some().unwrap_u8() == 1 {
147 Ok(ScalarResponse(scalar_option.unwrap()))
148 } else {
149 Err(Error::InvalidScalar)
150 }
151 }
152}
153
154#[derive(Clone, Debug)]
156pub struct MultiPointCommitment(pub Vec<RistrettoPoint>);
157
158impl Commitment for MultiPointCommitment {
159 fn to_bytes(&self) -> Vec<u8> {
160 let mut bytes = Vec::with_capacity(self.0.len() * 32 + 4);
161 bytes.extend_from_slice(&(self.0.len() as u32).to_le_bytes());
162
163 for point in &self.0 {
164 bytes.extend_from_slice(&point.compress().to_bytes());
165 }
166
167 bytes
168 }
169
170 fn from_bytes(bytes: &[u8]) -> Result<Self> {
171 if bytes.len() < 4 {
172 return Err(Error::InvalidCommitment);
173 }
174
175 let len = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as usize;
176
177 if bytes.len() != 4 + len * 32 {
178 return Err(Error::InvalidCommitment);
179 }
180
181 let mut points = Vec::with_capacity(len);
182 for i in 0..len {
183 let start = 4 + i * 32;
184 let end = start + 32;
185 let compressed =
186 curve25519_dalek::ristretto::CompressedRistretto::from_slice(&bytes[start..end])
187 .map_err(|_| Error::InvalidCommitment)?;
188
189 let point = compressed.decompress().ok_or(Error::InvalidPoint)?;
190 points.push(point);
191 }
192
193 Ok(MultiPointCommitment(points))
194 }
195}
196
197#[derive(Clone, Debug)]
199pub struct MultiScalarResponse(pub Vec<Scalar>);
200
201impl Response for MultiScalarResponse {
202 fn to_bytes(&self) -> Vec<u8> {
203 let mut bytes = Vec::with_capacity(self.0.len() * 32 + 4);
204 bytes.extend_from_slice(&(self.0.len() as u32).to_le_bytes());
205
206 for scalar in &self.0 {
207 bytes.extend_from_slice(&scalar.to_bytes());
208 }
209
210 bytes
211 }
212
213 fn from_bytes(bytes: &[u8]) -> Result<Self> {
214 if bytes.len() < 4 {
215 return Err(Error::InvalidResponse);
216 }
217
218 let len = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as usize;
219
220 if bytes.len() != 4 + len * 32 {
221 return Err(Error::InvalidResponse);
222 }
223
224 let mut scalars = Vec::with_capacity(len);
225 for i in 0..len {
226 let start = 4 + i * 32;
227 let end = start + 32;
228 let mut array = [0u8; 32];
229 array.copy_from_slice(&bytes[start..end]);
230
231 let scalar_option = Scalar::from_canonical_bytes(array);
232
233 let scalar = if scalar_option.is_some().unwrap_u8() == 1 {
234 scalar_option.unwrap()
235 } else {
236 return Err(Error::InvalidScalar);
237 };
238 scalars.push(scalar);
239 }
240
241 Ok(MultiScalarResponse(scalars))
242 }
243}