jf_relation/gates/
ecc.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the Jellyfish library.
3
4// You should have received a copy of the MIT License
5// along with the Jellyfish library. If not, see <https://mit-license.org/>.
6
7//! Implementation of ECC related gates
8
9use core::marker::PhantomData;
10
11use crate::{
12    constants::{GATE_WIDTH, N_MUL_SELECTORS},
13    gates::Gate,
14};
15use ark_ec::twisted_edwards::TECurveConfig as Config;
16use ark_ff::PrimeField;
17use derive_where::derive_where;
18
19#[inline]
20fn edwards_coeff_d<P: Config>() -> P::BaseField {
21    P::COEFF_D
22}
23
24/// A gate for checking a point conforming the twisted Edwards curve equation
25#[derive_where(Clone; P: Config)]
26pub struct EdwardsCurveEquationGate<P: Config> {
27    pub(crate) _phantom: PhantomData<P>,
28}
29
30impl<F, P> Gate<F> for EdwardsCurveEquationGate<P>
31where
32    F: PrimeField,
33    P: Config<BaseField = F>,
34{
35    fn name(&self) -> &'static str {
36        "Curve Equation Gate"
37    }
38    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
39        // edwards equation: ax^2 + y^2 =1 + dx^2y^2
40        // for ed_on_bn curves, we have a = 1
41        // for ed_on_bls curves, we have a = -1
42        [-P::COEFF_A, -F::one()]
43    }
44    fn q_c(&self) -> F {
45        F::one()
46    }
47    fn q_ecc(&self) -> F {
48        edwards_coeff_d::<P>()
49    }
50}
51
52/// A gate for point addition on x-coordinate between two Curve Points
53#[derive_where(Clone; P: Config)]
54pub struct CurvePointXAdditionGate<P: Config> {
55    pub(crate) _phantom: PhantomData<P>,
56}
57
58impl<F, P> Gate<F> for CurvePointXAdditionGate<P>
59where
60    F: PrimeField,
61    P: Config<BaseField = F>,
62{
63    fn name(&self) -> &'static str {
64        "Point Addition X-coordinate Gate"
65    }
66    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
67        [F::one(), F::one()]
68    }
69    fn q_o(&self) -> F {
70        F::one()
71    }
72    fn q_ecc(&self) -> F {
73        let d: F = edwards_coeff_d::<P>();
74        -d
75    }
76}
77
78/// A gate for point addition on y-coordinate between two Curve Points
79#[derive_where(Clone; P: Config)]
80pub struct CurvePointYAdditionGate<P: Config> {
81    pub(crate) _phantom: PhantomData<P>,
82}
83
84impl<F, P> Gate<F> for CurvePointYAdditionGate<P>
85where
86    F: PrimeField,
87    P: Config<BaseField = F>,
88{
89    fn name(&self) -> &'static str {
90        "Point Addition Y-coordinate Gate"
91    }
92    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
93        [-P::COEFF_A, F::one()]
94    }
95    fn q_o(&self) -> F {
96        F::one()
97    }
98    fn q_ecc(&self) -> F {
99        edwards_coeff_d::<P>()
100    }
101}
102
103/// A point selection gate on x-coordinate for conditional selection among 4
104/// point candidates
105/// P0 is default neutral point, P1, P2, P3 are public constants
106#[derive(Clone)]
107pub struct QuaternaryPointSelectXGate<F: PrimeField> {
108    pub(crate) x1: F,
109    pub(crate) x2: F,
110    pub(crate) x3: F,
111}
112
113impl<F> Gate<F> for QuaternaryPointSelectXGate<F>
114where
115    F: PrimeField,
116{
117    fn name(&self) -> &'static str {
118        "4-ary Point Selection X-coordinate Gate"
119    }
120    fn q_lc(&self) -> [F; GATE_WIDTH] {
121        [self.x1, self.x2, F::zero(), F::zero()]
122    }
123    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
124        [self.x3 - self.x2 - self.x1, F::zero()]
125    }
126    fn q_o(&self) -> F {
127        F::one()
128    }
129}
130
131/// A point selection gate on y-coordinate for conditional selection among 4
132/// point candidates
133/// P0 is default neutral point, P1, P2, P3 are public constants
134#[derive(Clone)]
135pub struct QuaternaryPointSelectYGate<F: PrimeField> {
136    pub(crate) y1: F,
137    pub(crate) y2: F,
138    pub(crate) y3: F,
139}
140
141impl<F> Gate<F> for QuaternaryPointSelectYGate<F>
142where
143    F: PrimeField,
144{
145    fn name(&self) -> &'static str {
146        "4-ary Point Selection Y-coordinate Gate"
147    }
148    fn q_lc(&self) -> [F; GATE_WIDTH] {
149        [self.y1 - F::one(), self.y2 - F::one(), F::zero(), F::zero()]
150    }
151    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
152        [self.y3 - self.y2 - self.y1 + F::one(), F::zero()]
153    }
154    fn q_c(&self) -> F {
155        F::one()
156    }
157    fn q_o(&self) -> F {
158        F::one()
159    }
160}