2021-06-04 23:08:51 -07:00
|
|
|
use super::{CellValue, EccConfig, EccPoint, Var};
|
|
|
|
|
2021-06-11 15:29:05 -07:00
|
|
|
use group::prime::PrimeCurveAffine;
|
|
|
|
|
2021-06-04 23:08:51 -07:00
|
|
|
use halo2::{
|
|
|
|
circuit::Region,
|
|
|
|
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
|
|
|
|
poly::Rotation,
|
|
|
|
};
|
2021-06-11 15:29:05 -07:00
|
|
|
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
2021-06-10 10:09:04 -07:00
|
|
|
|
2021-06-04 23:08:51 -07:00
|
|
|
#[derive(Clone, Debug)]
|
2021-06-11 15:29:05 -07:00
|
|
|
pub struct Config {
|
2021-06-04 23:08:51 -07:00
|
|
|
q_point: Selector,
|
|
|
|
// x-coordinate
|
|
|
|
pub x: Column<Advice>,
|
|
|
|
// y-coordinate
|
|
|
|
pub y: Column<Advice>,
|
|
|
|
}
|
|
|
|
|
2021-06-11 15:29:05 -07:00
|
|
|
impl From<&EccConfig> for Config {
|
|
|
|
fn from(ecc_config: &EccConfig) -> Self {
|
2021-06-04 23:08:51 -07:00
|
|
|
Self {
|
|
|
|
q_point: ecc_config.q_point,
|
|
|
|
x: ecc_config.advices[0],
|
|
|
|
y: ecc_config.advices[1],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 15:29:05 -07:00
|
|
|
impl Config {
|
|
|
|
pub(super) fn create_gate(&self, meta: &mut ConstraintSystem<pallas::Base>) {
|
2021-06-04 23:08:51 -07:00
|
|
|
meta.create_gate("witness point", |meta| {
|
2021-06-10 20:18:52 -07:00
|
|
|
// Check that either the point being witness is either:
|
|
|
|
// - the identity, which is mapped to (0, 0) in affine coordinates; or
|
|
|
|
// - a valid curve point y^2 = x^3 + b, where b = 5 in the Pallas equation
|
|
|
|
|
2021-06-04 23:08:51 -07:00
|
|
|
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());
|
|
|
|
|
2021-06-10 20:18:52 -07:00
|
|
|
// y^2 = x^3 + b
|
2021-06-13 09:19:21 -07:00
|
|
|
let curve_eqn = y.clone().square()
|
|
|
|
- (x.clone().square() * x.clone())
|
2021-06-11 15:29:05 -07:00
|
|
|
- Expression::Constant(pallas::Affine::b());
|
2021-06-10 20:18:52 -07:00
|
|
|
|
2021-06-04 23:08:51 -07:00
|
|
|
vec![
|
2021-06-10 20:18:52 -07:00
|
|
|
q_point.clone() * x * curve_eqn.clone(),
|
|
|
|
q_point * y * curve_eqn,
|
2021-06-04 23:08:51 -07:00
|
|
|
]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-10 10:09:04 -07:00
|
|
|
pub(super) fn assign_region(
|
2021-06-04 23:08:51 -07:00
|
|
|
&self,
|
2021-06-11 15:29:05 -07:00
|
|
|
value: Option<pallas::Affine>,
|
2021-06-04 23:08:51 -07:00
|
|
|
offset: usize,
|
2021-06-11 15:29:05 -07:00
|
|
|
region: &mut Region<'_, pallas::Base>,
|
|
|
|
) -> Result<EccPoint, Error> {
|
2021-06-04 23:08:51 -07:00
|
|
|
// Enable `q_point` selector
|
|
|
|
self.q_point.enable(region, offset)?;
|
|
|
|
|
2021-06-10 20:18:52 -07:00
|
|
|
let value = value.map(|value| {
|
|
|
|
// Map the identity to (0, 0).
|
2021-06-11 15:29:05 -07:00
|
|
|
if value == pallas::Affine::identity() {
|
|
|
|
(pallas::Base::zero(), pallas::Base::zero())
|
2021-06-10 20:18:52 -07:00
|
|
|
} else {
|
|
|
|
let value = value.coordinates().unwrap();
|
|
|
|
(*value.x(), *value.y())
|
|
|
|
}
|
|
|
|
});
|
2021-06-04 23:08:51 -07:00
|
|
|
|
|
|
|
// Assign `x` value
|
2021-06-10 20:18:52 -07:00
|
|
|
let x_val = value.map(|value| value.0);
|
2021-06-04 23:08:51 -07:00
|
|
|
let x_var = region.assign_advice(
|
|
|
|
|| "x",
|
|
|
|
self.x,
|
|
|
|
offset,
|
|
|
|
|| x_val.ok_or(Error::SynthesisError),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// Assign `y` value
|
2021-06-10 20:18:52 -07:00
|
|
|
let y_val = value.map(|value| value.1);
|
2021-06-04 23:08:51 -07:00
|
|
|
let y_var = region.assign_advice(
|
|
|
|
|| "y",
|
|
|
|
self.y,
|
|
|
|
offset,
|
|
|
|
|| y_val.ok_or(Error::SynthesisError),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(EccPoint {
|
2021-06-11 15:29:05 -07:00
|
|
|
x: CellValue::<pallas::Base>::new(x_var, x_val),
|
|
|
|
y: CellValue::<pallas::Base>::new(y_var, y_val),
|
2021-06-04 23:08:51 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|