Skip to main content

sigma_proof_compiler/
equations.rs

1//
2// Symbolic
3//
4
5use 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
56//
57// SymScalar arithmetic operators
58//
59
60impl 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
158// SymPoint arithmetic operators
159impl 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
229// SymScalar * SymPoint -> SymPoint
230impl 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
258// Scalar * SymPoint -> SymPoint
259impl 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        // Test addition
298        let sum = &a + &b;
299        assert_eq!(sum.evaluate().unwrap(), Scalar::from(8u64));
300
301        // Test subtraction
302        let diff = &a - &b;
303        assert_eq!(diff.evaluate().unwrap(), Scalar::from(2u64));
304
305        // Test multiplication
306        let product = &a * &b;
307        assert_eq!(product.evaluate().unwrap(), Scalar::from(15u64));
308
309        // Test negation
310        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; // 2 * G
321        let point_c = scalar_3 * &point_a; // 3 * G
322
323        // Test point addition: (2*G) + (3*G) = 5*G
324        let sum = &point_b + &point_c;
325        let expected = Scalar::from(5u64) * RISTRETTO_BASEPOINT_POINT;
326        assert_eq!(sum.evaluate().unwrap(), expected);
327
328        // Test point subtraction: (3*G) - (2*G) = G
329        let diff = &point_c - &point_b;
330        assert_eq!(diff.evaluate().unwrap(), RISTRETTO_BASEPOINT_POINT);
331
332        // Test scalar multiplication with plain Scalar
333        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        // Test: (2 + 3) * G = 5 * G
345        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}