use core::marker::PhantomData;
use crate::{
constants::{GATE_WIDTH, N_MUL_SELECTORS},
gates::Gate,
};
use ark_ec::twisted_edwards::TECurveConfig as Config;
use ark_ff::PrimeField;
use derivative::Derivative;
#[inline]
fn edwards_coeff_d<P: Config>() -> P::BaseField {
P::COEFF_D
}
#[derive(Derivative)]
#[derivative(Clone(bound = "P: Config"))]
pub struct EdwardsCurveEquationGate<P: Config> {
pub(crate) _phantom: PhantomData<P>,
}
impl<F, P> Gate<F> for EdwardsCurveEquationGate<P>
where
F: PrimeField,
P: Config<BaseField = F>,
{
fn name(&self) -> &'static str {
"Curve Equation Gate"
}
fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
[-P::COEFF_A, -F::one()]
}
fn q_c(&self) -> F {
F::one()
}
fn q_ecc(&self) -> F {
edwards_coeff_d::<P>()
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = "P: Config"))]
pub struct CurvePointXAdditionGate<P: Config> {
pub(crate) _phantom: PhantomData<P>,
}
impl<F, P> Gate<F> for CurvePointXAdditionGate<P>
where
F: PrimeField,
P: Config<BaseField = F>,
{
fn name(&self) -> &'static str {
"Point Addition X-coordinate Gate"
}
fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
[F::one(), F::one()]
}
fn q_o(&self) -> F {
F::one()
}
fn q_ecc(&self) -> F {
let d: F = edwards_coeff_d::<P>();
-d
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = "P: Config"))]
pub struct CurvePointYAdditionGate<P: Config> {
pub(crate) _phantom: PhantomData<P>,
}
impl<F, P> Gate<F> for CurvePointYAdditionGate<P>
where
F: PrimeField,
P: Config<BaseField = F>,
{
fn name(&self) -> &'static str {
"Point Addition Y-coordinate Gate"
}
fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
[-P::COEFF_A, F::one()]
}
fn q_o(&self) -> F {
F::one()
}
fn q_ecc(&self) -> F {
edwards_coeff_d::<P>()
}
}
#[derive(Clone)]
pub struct QuaternaryPointSelectXGate<F: PrimeField> {
pub(crate) x1: F,
pub(crate) x2: F,
pub(crate) x3: F,
}
impl<F> Gate<F> for QuaternaryPointSelectXGate<F>
where
F: PrimeField,
{
fn name(&self) -> &'static str {
"4-ary Point Selection X-coordinate Gate"
}
fn q_lc(&self) -> [F; GATE_WIDTH] {
[self.x1, self.x2, F::zero(), F::zero()]
}
fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
[self.x3 - self.x2 - self.x1, F::zero()]
}
fn q_o(&self) -> F {
F::one()
}
}
#[derive(Clone)]
pub struct QuaternaryPointSelectYGate<F: PrimeField> {
pub(crate) y1: F,
pub(crate) y2: F,
pub(crate) y3: F,
}
impl<F> Gate<F> for QuaternaryPointSelectYGate<F>
where
F: PrimeField,
{
fn name(&self) -> &'static str {
"4-ary Point Selection Y-coordinate Gate"
}
fn q_lc(&self) -> [F; GATE_WIDTH] {
[self.y1 - F::one(), self.y2 - F::one(), F::zero(), F::zero()]
}
fn q_mul(&self) -> [F; N_MUL_SELECTORS] {
[self.y3 - self.y2 - self.y1 + F::one(), F::zero()]
}
fn q_c(&self) -> F {
F::one()
}
fn q_o(&self) -> F {
F::one()
}
}