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 derivative::Derivative;
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(Derivative)]
26#[derivative(Clone(bound = "P: Config"))]
27pub struct EdwardsCurveEquationGate<P: Config> {
28    pub(crate) _phantom: PhantomData<P>,
29}
30
31impl<F, P> Gate<F> for EdwardsCurveEquationGate<P>
32where
33    F: PrimeField,
34    P: Config<BaseField = F>,
35{
36    fn name(&self) -> &'static str {
37        "Curve Equation Gate"
38    }
39    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
40        // edwards equation: ax^2 + y^2 =1 + dx^2y^2
41        // for ed_on_bn curves, we have a = 1
42        // for ed_on_bls curves, we have a = -1
43        [-P::COEFF_A, -F::one()]
44    }
45    fn q_c(&self) -> F {
46        F::one()
47    }
48    fn q_ecc(&self) -> F {
49        edwards_coeff_d::<P>()
50    }
51}
52
53/// A gate for point addition on x-coordinate between two Curve Points
54#[derive(Derivative)]
55#[derivative(Clone(bound = "P: Config"))]
56pub struct CurvePointXAdditionGate<P: Config> {
57    pub(crate) _phantom: PhantomData<P>,
58}
59
60impl<F, P> Gate<F> for CurvePointXAdditionGate<P>
61where
62    F: PrimeField,
63    P: Config<BaseField = F>,
64{
65    fn name(&self) -> &'static str {
66        "Point Addition X-coordinate Gate"
67    }
68    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
69        [F::one(), F::one()]
70    }
71    fn q_o(&self) -> F {
72        F::one()
73    }
74    fn q_ecc(&self) -> F {
75        let d: F = edwards_coeff_d::<P>();
76        -d
77    }
78}
79
80/// A gate for point addition on y-coordinate between two Curve Points
81#[derive(Derivative)]
82#[derivative(Clone(bound = "P: Config"))]
83pub struct CurvePointYAdditionGate<P: Config> {
84    pub(crate) _phantom: PhantomData<P>,
85}
86
87impl<F, P> Gate<F> for CurvePointYAdditionGate<P>
88where
89    F: PrimeField,
90    P: Config<BaseField = F>,
91{
92    fn name(&self) -> &'static str {
93        "Point Addition Y-coordinate Gate"
94    }
95    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
96        [-P::COEFF_A, F::one()]
97    }
98    fn q_o(&self) -> F {
99        F::one()
100    }
101    fn q_ecc(&self) -> F {
102        edwards_coeff_d::<P>()
103    }
104}
105
106/// A point selection gate on x-coordinate for conditional selection among 4
107/// point candidates
108/// P0 is default neutral point, P1, P2, P3 are public constants
109#[derive(Clone)]
110pub struct QuaternaryPointSelectXGate<F: PrimeField> {
111    pub(crate) x1: F,
112    pub(crate) x2: F,
113    pub(crate) x3: F,
114}
115
116impl<F> Gate<F> for QuaternaryPointSelectXGate<F>
117where
118    F: PrimeField,
119{
120    fn name(&self) -> &'static str {
121        "4-ary Point Selection X-coordinate Gate"
122    }
123    fn q_lc(&self) -> [F; GATE_WIDTH] {
124        [self.x1, self.x2, F::zero(), F::zero()]
125    }
126    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
127        [self.x3 - self.x2 - self.x1, F::zero()]
128    }
129    fn q_o(&self) -> F {
130        F::one()
131    }
132}
133
134/// A point selection gate on y-coordinate for conditional selection among 4
135/// point candidates
136/// P0 is default neutral point, P1, P2, P3 are public constants
137#[derive(Clone)]
138pub struct QuaternaryPointSelectYGate<F: PrimeField> {
139    pub(crate) y1: F,
140    pub(crate) y2: F,
141    pub(crate) y3: F,
142}
143
144impl<F> Gate<F> for QuaternaryPointSelectYGate<F>
145where
146    F: PrimeField,
147{
148    fn name(&self) -> &'static str {
149        "4-ary Point Selection Y-coordinate Gate"
150    }
151    fn q_lc(&self) -> [F; GATE_WIDTH] {
152        [self.y1 - F::one(), self.y2 - F::one(), F::zero(), F::zero()]
153    }
154    fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
155        [self.y3 - self.y2 - self.y1 + F::one(), F::zero()]
156    }
157    fn q_c(&self) -> F {
158        F::one()
159    }
160    fn q_o(&self) -> F {
161        F::one()
162    }
163}