use super::{CellValue, EccConfig, EccPoint, Var}; use halo2::{ arithmetic::CurveAffine, circuit::Region, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; #[derive(Clone, Debug)] pub struct Config { q_point: Selector, // x-coordinate pub x: Column, // y-coordinate pub y: Column, } impl From<&EccConfig> for Config { fn from(ecc_config: &EccConfig) -> Self { Self { q_point: ecc_config.q_point, x: ecc_config.advices[0], y: ecc_config.advices[1], } } } impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("witness point", |meta| { let q_point = meta.query_selector(self.q_point); let x = meta.query_advice(self.x, Rotation::cur()); let y = meta.query_advice(self.y, Rotation::cur()); // Check that y^2 = x^3 + b, where b = 5 in the Pallas equation vec![ q_point * (y.clone() * y - (x.clone() * x.clone() * x) - Expression::Constant(C::b())), ] }); } pub(super) fn assign_region( &self, value: Option, offset: usize, region: &mut Region<'_, C::Base>, ) -> Result, Error> { // Enable `q_point` selector self.q_point.enable(region, offset)?; let value = value.map(|value| value.coordinates().unwrap()); // Assign `x` value let x_val = value.map(|value| *value.x()); let x_var = region.assign_advice( || "x", self.x, offset, || x_val.ok_or(Error::SynthesisError), )?; // Assign `y` value let y_val = value.map(|value| *value.y()); let y_var = region.assign_advice( || "y", self.y, offset, || y_val.ok_or(Error::SynthesisError), )?; Ok(EccPoint { x: CellValue::::new(x_var, x_val), y: CellValue::::new(y_var, y_val), }) } }