1use curve25519_dalek::{RistrettoPoint, Scalar};
6use std::ops::{Add, Mul, Neg, Sub};
7
8use crate::errors::SigmaProofError;
9
10#[derive(Clone)]
11pub enum SymScalar {
12 Const(Scalar),
13 Var(Option<Scalar>),
14 Add(Box<SymScalar>, Box<SymScalar>),
15 Sub(Box<SymScalar>, Box<SymScalar>),
16 Neg(Box<SymScalar>),
17 Mul(Box<SymScalar>, Box<SymScalar>),
18}
19
20impl SymScalar {
21 pub fn evaluate(&self) -> Result<Scalar, SigmaProofError> {
22 match self {
23 SymScalar::Const(s) => Ok(*s),
24 SymScalar::Var(s) => s.ok_or(SigmaProofError::UninstantiatedScalar),
25 SymScalar::Add(s1, s2) => Ok(s1.evaluate()? + s2.evaluate()?),
26 SymScalar::Sub(s1, s2) => Ok(s1.evaluate()? - s2.evaluate()?),
27 SymScalar::Neg(s) => Ok(-s.evaluate()?),
28 SymScalar::Mul(s1, s2) => Ok(s1.evaluate()? * s2.evaluate()?),
29 }
30 }
31}
32
33#[derive(Clone)]
34pub enum SymPoint {
35 Const(RistrettoPoint),
36 Var(Option<RistrettoPoint>),
37 Add(Box<SymPoint>, Box<SymPoint>),
38 Sub(Box<SymPoint>, Box<SymPoint>),
39 Neg(Box<SymPoint>),
40 Scale(Box<SymScalar>, Box<SymPoint>),
41}
42
43impl SymPoint {
44 pub fn evaluate(&self) -> Result<RistrettoPoint, SigmaProofError> {
45 match self {
46 SymPoint::Const(p) => Ok(p.clone()),
47 SymPoint::Var(p) => p.ok_or(SigmaProofError::UninstantiatedPoint),
48 SymPoint::Add(p1, p2) => Ok(p1.evaluate()? + p2.evaluate()?),
49 SymPoint::Sub(p1, p2) => Ok(p1.evaluate()? - p2.evaluate()?),
50 SymPoint::Neg(p) => Ok(-p.evaluate()?),
51 SymPoint::Scale(s, p) => Ok(s.evaluate()? * p.evaluate()?),
52 }
53 }
54}
55
56impl Add for SymScalar {
61 type Output = SymScalar;
62 fn add(self, rhs: SymScalar) -> SymScalar {
63 SymScalar::Add(Box::new(self), Box::new(rhs))
64 }
65}
66
67impl Add<&SymScalar> for SymScalar {
68 type Output = SymScalar;
69 fn add(self, rhs: &SymScalar) -> SymScalar {
70 SymScalar::Add(Box::new(self), Box::new(rhs.clone()))
71 }
72}
73
74impl Add<SymScalar> for &SymScalar {
75 type Output = SymScalar;
76 fn add(self, rhs: SymScalar) -> SymScalar {
77 SymScalar::Add(Box::new(self.clone()), Box::new(rhs))
78 }
79}
80
81impl Add<&SymScalar> for &SymScalar {
82 type Output = SymScalar;
83 fn add(self, rhs: &SymScalar) -> SymScalar {
84 SymScalar::Add(Box::new(self.clone()), Box::new(rhs.clone()))
85 }
86}
87
88impl Sub for SymScalar {
89 type Output = SymScalar;
90 fn sub(self, rhs: SymScalar) -> SymScalar {
91 SymScalar::Sub(Box::new(self), Box::new(rhs))
92 }
93}
94
95impl Sub<&SymScalar> for SymScalar {
96 type Output = SymScalar;
97 fn sub(self, rhs: &SymScalar) -> SymScalar {
98 SymScalar::Sub(Box::new(self), Box::new(rhs.clone()))
99 }
100}
101
102impl Sub<SymScalar> for &SymScalar {
103 type Output = SymScalar;
104 fn sub(self, rhs: SymScalar) -> SymScalar {
105 SymScalar::Sub(Box::new(self.clone()), Box::new(rhs))
106 }
107}
108
109impl Sub<&SymScalar> for &SymScalar {
110 type Output = SymScalar;
111 fn sub(self, rhs: &SymScalar) -> SymScalar {
112 SymScalar::Sub(Box::new(self.clone()), Box::new(rhs.clone()))
113 }
114}
115
116impl Mul for SymScalar {
117 type Output = SymScalar;
118 fn mul(self, rhs: SymScalar) -> SymScalar {
119 SymScalar::Mul(Box::new(self), Box::new(rhs))
120 }
121}
122
123impl Mul<&SymScalar> for SymScalar {
124 type Output = SymScalar;
125 fn mul(self, rhs: &SymScalar) -> SymScalar {
126 SymScalar::Mul(Box::new(self), Box::new(rhs.clone()))
127 }
128}
129
130impl Mul<SymScalar> for &SymScalar {
131 type Output = SymScalar;
132 fn mul(self, rhs: SymScalar) -> SymScalar {
133 SymScalar::Mul(Box::new(self.clone()), Box::new(rhs))
134 }
135}
136
137impl Mul<&SymScalar> for &SymScalar {
138 type Output = SymScalar;
139 fn mul(self, rhs: &SymScalar) -> SymScalar {
140 SymScalar::Mul(Box::new(self.clone()), Box::new(rhs.clone()))
141 }
142}
143
144impl Neg for SymScalar {
145 type Output = SymScalar;
146 fn neg(self) -> SymScalar {
147 SymScalar::Neg(Box::new(self))
148 }
149}
150
151impl Neg for &SymScalar {
152 type Output = SymScalar;
153 fn neg(self) -> SymScalar {
154 SymScalar::Neg(Box::new(self.clone()))
155 }
156}
157
158impl Add for SymPoint {
160 type Output = SymPoint;
161 fn add(self, rhs: SymPoint) -> SymPoint {
162 SymPoint::Add(Box::new(self), Box::new(rhs))
163 }
164}
165
166impl Add<&SymPoint> for SymPoint {
167 type Output = SymPoint;
168 fn add(self, rhs: &SymPoint) -> SymPoint {
169 SymPoint::Add(Box::new(self), Box::new(rhs.clone()))
170 }
171}
172
173impl Add<SymPoint> for &SymPoint {
174 type Output = SymPoint;
175 fn add(self, rhs: SymPoint) -> SymPoint {
176 SymPoint::Add(Box::new(self.clone()), Box::new(rhs))
177 }
178}
179
180impl Add<&SymPoint> for &SymPoint {
181 type Output = SymPoint;
182 fn add(self, rhs: &SymPoint) -> SymPoint {
183 SymPoint::Add(Box::new(self.clone()), Box::new(rhs.clone()))
184 }
185}
186
187impl Sub for SymPoint {
188 type Output = SymPoint;
189 fn sub(self, rhs: SymPoint) -> SymPoint {
190 SymPoint::Sub(Box::new(self), Box::new(rhs))
191 }
192}
193
194impl Sub<&SymPoint> for SymPoint {
195 type Output = SymPoint;
196 fn sub(self, rhs: &SymPoint) -> SymPoint {
197 SymPoint::Sub(Box::new(self), Box::new(rhs.clone()))
198 }
199}
200
201impl Sub<SymPoint> for &SymPoint {
202 type Output = SymPoint;
203 fn sub(self, rhs: SymPoint) -> SymPoint {
204 SymPoint::Sub(Box::new(self.clone()), Box::new(rhs))
205 }
206}
207
208impl Sub<&SymPoint> for &SymPoint {
209 type Output = SymPoint;
210 fn sub(self, rhs: &SymPoint) -> SymPoint {
211 SymPoint::Sub(Box::new(self.clone()), Box::new(rhs.clone()))
212 }
213}
214
215impl Neg for SymPoint {
216 type Output = SymPoint;
217 fn neg(self) -> SymPoint {
218 SymPoint::Neg(Box::new(self))
219 }
220}
221
222impl Neg for &SymPoint {
223 type Output = SymPoint;
224 fn neg(self) -> SymPoint {
225 SymPoint::Neg(Box::new(self.clone()))
226 }
227}
228
229impl Mul<SymPoint> for SymScalar {
231 type Output = SymPoint;
232 fn mul(self, rhs: SymPoint) -> SymPoint {
233 SymPoint::Scale(Box::new(self), Box::new(rhs))
234 }
235}
236
237impl Mul<&SymPoint> for SymScalar {
238 type Output = SymPoint;
239 fn mul(self, rhs: &SymPoint) -> SymPoint {
240 SymPoint::Scale(Box::new(self), Box::new(rhs.clone()))
241 }
242}
243
244impl Mul<SymPoint> for &SymScalar {
245 type Output = SymPoint;
246 fn mul(self, rhs: SymPoint) -> SymPoint {
247 SymPoint::Scale(Box::new(self.clone()), Box::new(rhs))
248 }
249}
250
251impl Mul<&SymPoint> for &SymScalar {
252 type Output = SymPoint;
253 fn mul(self, rhs: &SymPoint) -> SymPoint {
254 SymPoint::Scale(Box::new(self.clone()), Box::new(rhs.clone()))
255 }
256}
257
258impl Mul<SymPoint> for Scalar {
260 type Output = SymPoint;
261 fn mul(self, rhs: SymPoint) -> SymPoint {
262 SymPoint::Scale(Box::new(SymScalar::Const(self)), Box::new(rhs))
263 }
264}
265
266impl Mul<&SymPoint> for Scalar {
267 type Output = SymPoint;
268 fn mul(self, rhs: &SymPoint) -> SymPoint {
269 SymPoint::Scale(Box::new(SymScalar::Const(self)), Box::new(rhs.clone()))
270 }
271}
272
273impl Mul<SymPoint> for &Scalar {
274 type Output = SymPoint;
275 fn mul(self, rhs: SymPoint) -> SymPoint {
276 SymPoint::Scale(Box::new(SymScalar::Const(*self)), Box::new(rhs))
277 }
278}
279
280impl Mul<&SymPoint> for &Scalar {
281 type Output = SymPoint;
282 fn mul(self, rhs: &SymPoint) -> SymPoint {
283 SymPoint::Scale(Box::new(SymScalar::Const(*self)), Box::new(rhs.clone()))
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use super::*;
290 use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
291
292 #[test]
293 fn test_symscalar_operators() {
294 let a = SymScalar::Const(Scalar::from(5u64));
295 let b = SymScalar::Const(Scalar::from(3u64));
296
297 let sum = &a + &b;
299 assert_eq!(sum.evaluate().unwrap(), Scalar::from(8u64));
300
301 let diff = &a - &b;
303 assert_eq!(diff.evaluate().unwrap(), Scalar::from(2u64));
304
305 let product = &a * &b;
307 assert_eq!(product.evaluate().unwrap(), Scalar::from(15u64));
308
309 let neg_a = -&a;
311 assert_eq!(neg_a.evaluate().unwrap(), -Scalar::from(5u64));
312 }
313
314 #[test]
315 fn test_sympoint_operators() {
316 let scalar_2 = SymScalar::Const(Scalar::from(2u64));
317 let scalar_3 = SymScalar::Const(Scalar::from(3u64));
318
319 let point_a = SymPoint::Const(RISTRETTO_BASEPOINT_POINT);
320 let point_b = scalar_2 * &point_a; let point_c = scalar_3 * &point_a; let sum = &point_b + &point_c;
325 let expected = Scalar::from(5u64) * RISTRETTO_BASEPOINT_POINT;
326 assert_eq!(sum.evaluate().unwrap(), expected);
327
328 let diff = &point_c - &point_b;
330 assert_eq!(diff.evaluate().unwrap(), RISTRETTO_BASEPOINT_POINT);
331
332 let scaled = Scalar::from(4u64) * &point_a;
334 let expected_scaled = Scalar::from(4u64) * RISTRETTO_BASEPOINT_POINT;
335 assert_eq!(scaled.evaluate().unwrap(), expected_scaled);
336 }
337
338 #[test]
339 fn test_mixed_operations() {
340 let a = SymScalar::Const(Scalar::from(2u64));
341 let b = SymScalar::Const(Scalar::from(3u64));
342 let point = SymPoint::Const(RISTRETTO_BASEPOINT_POINT);
343
344 let scalar_sum = &a + &b;
346 let result = scalar_sum * &point;
347 let expected = Scalar::from(5u64) * RISTRETTO_BASEPOINT_POINT;
348 assert_eq!(result.evaluate().unwrap(), expected);
349 }
350}