mirror of https://github.com/zcash/halo2.git
ecc::chip.rs: Use concrete pallas::Affine for Chip impl.
The EccInstructions trait is still generic over C: CurveAffine; however, the EccChip implementation is specific to the pasta curves.
This commit is contained in:
parent
aec7a7f850
commit
e259bb3846
|
@ -378,30 +378,24 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ff::PrimeFieldBits;
|
||||
use group::{Curve, Group};
|
||||
use group::{prime::PrimeCurveAffine, Curve, Group};
|
||||
|
||||
use halo2::{
|
||||
arithmetic::CurveAffine,
|
||||
circuit::{layouter::SingleChipLayouter, Layouter},
|
||||
dev::MockProver,
|
||||
pasta::pallas,
|
||||
plonk::{Assignment, Circuit, ConstraintSystem, Error},
|
||||
};
|
||||
use pasta_curves::pallas;
|
||||
|
||||
use super::chip::{EccChip, EccConfig};
|
||||
|
||||
struct MyCircuit<C: CurveAffine> {
|
||||
_marker: std::marker::PhantomData<C>,
|
||||
}
|
||||
struct MyCircuit {}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<C: CurveAffine> Circuit<C::Base> for MyCircuit<C>
|
||||
where
|
||||
C::Scalar: PrimeFieldBits,
|
||||
{
|
||||
type Config = EccConfig<C>;
|
||||
impl Circuit<pallas::Base> for MyCircuit {
|
||||
type Config = EccConfig;
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<C::Base>) -> Self::Config {
|
||||
fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
|
||||
let advices = [
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
|
@ -422,25 +416,25 @@ mod tests {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
EccChip::<C>::configure(meta, advices, perm)
|
||||
EccChip::configure(meta, advices, perm)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
cs: &mut impl Assignment<C::Base>,
|
||||
cs: &mut impl Assignment<pallas::Base>,
|
||||
config: Self::Config,
|
||||
) -> Result<(), Error> {
|
||||
let mut layouter = SingleChipLayouter::new(cs)?;
|
||||
let chip = EccChip::construct(config);
|
||||
|
||||
// Generate a random point P
|
||||
let p_val = C::CurveExt::random(rand::rngs::OsRng).to_affine(); // P
|
||||
let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P
|
||||
let p = super::Point::new(chip.clone(), layouter.namespace(|| "P"), Some(p_val))?;
|
||||
let p_neg = -p_val;
|
||||
let p_neg = super::Point::new(chip.clone(), layouter.namespace(|| "-P"), Some(p_neg))?;
|
||||
|
||||
// Generate a random point Q
|
||||
let q_val = C::CurveExt::random(rand::rngs::OsRng).to_affine(); // Q
|
||||
let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q
|
||||
let q = super::Point::new(chip.clone(), layouter.namespace(|| "Q"), Some(q_val))?;
|
||||
|
||||
// Make sure P and Q are not the same point.
|
||||
|
@ -451,7 +445,7 @@ mod tests {
|
|||
super::Point::new(
|
||||
chip.clone(),
|
||||
layouter.namespace(|| "identity"),
|
||||
Some(C::identity()),
|
||||
Some(pallas::Affine::identity()),
|
||||
)?
|
||||
};
|
||||
|
||||
|
@ -487,9 +481,7 @@ mod tests {
|
|||
#[test]
|
||||
fn ecc() {
|
||||
let k = 5;
|
||||
let circuit = MyCircuit::<pallas::Affine> {
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
let circuit = MyCircuit {};
|
||||
let prover = MockProver::run(k, &circuit, vec![]).unwrap();
|
||||
assert_eq!(prover.verify(), Ok(()))
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use super::EccInstructions;
|
||||
use crate::circuit::gadget::utilities::{copy, CellValue, Var};
|
||||
use crate::constants;
|
||||
use ff::{Field, PrimeFieldBits};
|
||||
|
||||
use group::prime::PrimeCurveAffine;
|
||||
use halo2::{
|
||||
arithmetic::CurveAffine,
|
||||
circuit::{Chip, Layouter},
|
||||
plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Permutation, Selector},
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
pub(super) mod add;
|
||||
pub(super) mod add_incomplete;
|
||||
|
@ -19,22 +19,22 @@ pub(super) mod witness_point;
|
|||
/// A curve point represented in affine (x, y) coordinates. Each coordinate is
|
||||
/// assigned to a cell.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EccPoint<C: CurveAffine> {
|
||||
pub struct EccPoint {
|
||||
/// x-coordinate
|
||||
x: CellValue<C::Base>,
|
||||
x: CellValue<pallas::Base>,
|
||||
/// y-coordinate
|
||||
y: CellValue<C::Base>,
|
||||
y: CellValue<pallas::Base>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> EccPoint<C> {
|
||||
impl EccPoint {
|
||||
/// Returns the value of this curve point, if known.
|
||||
pub fn point(&self) -> Option<C> {
|
||||
pub fn point(&self) -> Option<pallas::Affine> {
|
||||
match (self.x.value(), self.y.value()) {
|
||||
(Some(x), Some(y)) => {
|
||||
if x == C::Base::zero() && y == C::Base::zero() {
|
||||
Some(C::identity())
|
||||
if x == pallas::Base::zero() && y == pallas::Base::zero() {
|
||||
Some(pallas::Affine::identity())
|
||||
} else {
|
||||
Some(C::from_xy(x, y).unwrap())
|
||||
Some(pallas::Affine::from_xy(x, y).unwrap())
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
|
@ -42,12 +42,12 @@ impl<C: CurveAffine> EccPoint<C> {
|
|||
}
|
||||
/// The cell containing the affine short-Weierstrass x-coordinate,
|
||||
/// or 0 for the zero point.
|
||||
pub fn x(&self) -> CellValue<C::Base> {
|
||||
pub fn x(&self) -> CellValue<pallas::Base> {
|
||||
self.x
|
||||
}
|
||||
/// The cell containing the affine short-Weierstrass y-coordinate,
|
||||
/// or 0 for the zero point.
|
||||
pub fn y(&self) -> CellValue<C::Base> {
|
||||
pub fn y(&self) -> CellValue<pallas::Base> {
|
||||
self.y
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ impl<C: CurveAffine> EccPoint<C> {
|
|||
/// Configuration for the ECC chip
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct EccConfig<C: CurveAffine> {
|
||||
pub struct EccConfig {
|
||||
/// Advice columns needed by instructions in the ECC chip.
|
||||
pub advices: [Column<Advice>; 10],
|
||||
|
||||
|
@ -88,17 +88,16 @@ pub struct EccConfig<C: CurveAffine> {
|
|||
pub q_scalar_fixed_short: Selector,
|
||||
/// Permutation
|
||||
pub perm: Permutation,
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
/// A chip implementing EccInstructions
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct EccChip<C: CurveAffine> {
|
||||
config: EccConfig<C>,
|
||||
pub struct EccChip {
|
||||
config: EccConfig,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> Chip<C::Base> for EccChip<C> {
|
||||
type Config = EccConfig<C>;
|
||||
impl Chip<pallas::Base> for EccChip {
|
||||
type Config = EccConfig;
|
||||
type Loaded = ();
|
||||
|
||||
fn config(&self) -> &Self::Config {
|
||||
|
@ -110,21 +109,18 @@ impl<C: CurveAffine> Chip<C::Base> for EccChip<C> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> EccChip<C>
|
||||
where
|
||||
C::Scalar: PrimeFieldBits,
|
||||
{
|
||||
pub fn construct(config: <Self as Chip<C::Base>>::Config) -> Self {
|
||||
impl EccChip {
|
||||
pub fn construct(config: <Self as Chip<pallas::Base>>::Config) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn configure(
|
||||
meta: &mut ConstraintSystem<C::Base>,
|
||||
meta: &mut ConstraintSystem<pallas::Base>,
|
||||
advices: [Column<Advice>; 10],
|
||||
perm: Permutation,
|
||||
) -> <Self as Chip<C::Base>>::Config {
|
||||
let config = EccConfig::<C> {
|
||||
) -> <Self as Chip<pallas::Base>>::Config {
|
||||
let config = EccConfig {
|
||||
advices,
|
||||
lagrange_coeffs: [
|
||||
meta.fixed_column(),
|
||||
|
@ -149,24 +145,23 @@ where
|
|||
q_scalar_fixed: meta.selector(),
|
||||
q_scalar_fixed_short: meta.selector(),
|
||||
perm,
|
||||
_marker: PhantomData,
|
||||
};
|
||||
|
||||
// Create witness point gate
|
||||
{
|
||||
let config: witness_point::Config<C> = (&config).into();
|
||||
let config: witness_point::Config = (&config).into();
|
||||
config.create_gate(meta);
|
||||
}
|
||||
|
||||
// Create incomplete point addition gate
|
||||
{
|
||||
let config: add_incomplete::Config<C> = (&config).into();
|
||||
let config: add_incomplete::Config = (&config).into();
|
||||
config.create_gate(meta);
|
||||
}
|
||||
|
||||
// Create complete point addition gate
|
||||
{
|
||||
let add_config: add::Config<C> = (&config).into();
|
||||
let add_config: add::Config = (&config).into();
|
||||
add_config.create_gate(meta);
|
||||
}
|
||||
|
||||
|
@ -174,48 +169,45 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> EccInstructions<C> for EccChip<C>
|
||||
where
|
||||
C::Scalar: PrimeFieldBits,
|
||||
{
|
||||
impl EccInstructions<pallas::Affine> for EccChip {
|
||||
type ScalarFixed = (); // TODO
|
||||
type ScalarFixedShort = (); // TODO
|
||||
type ScalarVar = (); // TODO
|
||||
type Point = EccPoint<C>;
|
||||
type X = CellValue<C::Base>;
|
||||
type Point = EccPoint;
|
||||
type X = CellValue<pallas::Base>;
|
||||
type FixedPoints = (); // TODO
|
||||
type FixedPointsShort = (); // TODO
|
||||
|
||||
fn witness_scalar_var(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_value: Option<C::Base>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_value: Option<pallas::Base>,
|
||||
) -> Result<Self::ScalarVar, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn witness_scalar_fixed(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_value: Option<C::Scalar>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_value: Option<pallas::Scalar>,
|
||||
) -> Result<Self::ScalarFixed, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn witness_scalar_fixed_short(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_value: Option<C::Scalar>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_value: Option<pallas::Scalar>,
|
||||
) -> Result<Self::ScalarFixedShort, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn witness_point(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<C::Base>,
|
||||
value: Option<C>,
|
||||
layouter: &mut impl Layouter<pallas::Base>,
|
||||
value: Option<pallas::Affine>,
|
||||
) -> Result<Self::Point, Error> {
|
||||
let config: witness_point::Config<C> = self.config().into();
|
||||
let config: witness_point::Config = self.config().into();
|
||||
layouter.assign_region(
|
||||
|| "witness point",
|
||||
|mut region| config.assign_region(value, 0, &mut region),
|
||||
|
@ -228,11 +220,11 @@ where
|
|||
|
||||
fn add_incomplete(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<C::Base>,
|
||||
layouter: &mut impl Layouter<pallas::Base>,
|
||||
a: &Self::Point,
|
||||
b: &Self::Point,
|
||||
) -> Result<Self::Point, Error> {
|
||||
let config: add_incomplete::Config<C> = self.config().into();
|
||||
let config: add_incomplete::Config = self.config().into();
|
||||
layouter.assign_region(
|
||||
|| "incomplete point addition",
|
||||
|mut region| config.assign_region(a, b, 0, &mut region),
|
||||
|
@ -241,11 +233,11 @@ where
|
|||
|
||||
fn add(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<C::Base>,
|
||||
layouter: &mut impl Layouter<pallas::Base>,
|
||||
a: &Self::Point,
|
||||
b: &Self::Point,
|
||||
) -> Result<Self::Point, Error> {
|
||||
let config: add::Config<C> = self.config().into();
|
||||
let config: add::Config = self.config().into();
|
||||
layouter.assign_region(
|
||||
|| "complete point addition",
|
||||
|mut region| config.assign_region(a, b, 0, &mut region),
|
||||
|
@ -254,7 +246,7 @@ where
|
|||
|
||||
fn mul(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_scalar: &Self::ScalarVar,
|
||||
_base: &Self::Point,
|
||||
) -> Result<Self::Point, Error> {
|
||||
|
@ -263,7 +255,7 @@ where
|
|||
|
||||
fn mul_fixed(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_scalar: &Self::ScalarFixed,
|
||||
_base: &Self::FixedPoints,
|
||||
) -> Result<Self::Point, Error> {
|
||||
|
@ -272,7 +264,7 @@ where
|
|||
|
||||
fn mul_fixed_short(
|
||||
&self,
|
||||
_layouter: &mut impl Layouter<C::Base>,
|
||||
_layouter: &mut impl Layouter<pallas::Base>,
|
||||
_scalar: &Self::ScalarFixedShort,
|
||||
_base: &Self::FixedPointsShort,
|
||||
) -> Result<Self::Point, Error> {
|
||||
|
|
|
@ -3,15 +3,16 @@ use std::array;
|
|||
use super::{copy, CellValue, EccConfig, EccPoint, Var};
|
||||
use ff::Field;
|
||||
use halo2::{
|
||||
arithmetic::{BatchInvert, CurveAffine, FieldExt},
|
||||
arithmetic::BatchInvert,
|
||||
circuit::Region,
|
||||
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Permutation, Selector},
|
||||
poly::Rotation,
|
||||
};
|
||||
use std::{collections::HashSet, marker::PhantomData};
|
||||
use pasta_curves::{arithmetic::FieldExt, pallas};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config<C: CurveAffine> {
|
||||
pub struct Config {
|
||||
q_add: Selector,
|
||||
// lambda
|
||||
lambda: Column<Advice>,
|
||||
|
@ -33,11 +34,10 @@ pub struct Config<C: CurveAffine> {
|
|||
delta: Column<Advice>,
|
||||
// Permutation
|
||||
perm: Permutation,
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> From<&EccConfig<C>> for Config<C> {
|
||||
fn from(ecc_config: &EccConfig<C>) -> Self {
|
||||
impl From<&EccConfig> for Config {
|
||||
fn from(ecc_config: &EccConfig) -> Self {
|
||||
Self {
|
||||
q_add: ecc_config.q_add,
|
||||
x_p: ecc_config.advices[0],
|
||||
|
@ -50,12 +50,11 @@ impl<C: CurveAffine> From<&EccConfig<C>> for Config<C> {
|
|||
gamma: ecc_config.advices[7],
|
||||
delta: ecc_config.advices[8],
|
||||
perm: ecc_config.perm.clone(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> Config<C> {
|
||||
impl Config {
|
||||
pub(crate) fn advice_columns(&self) -> HashSet<Column<Advice>> {
|
||||
core::array::IntoIter::new([
|
||||
self.x_p,
|
||||
|
@ -71,7 +70,7 @@ impl<C: CurveAffine> Config<C> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn create_gate(&self, meta: &mut ConstraintSystem<C::Base>) {
|
||||
pub(crate) fn create_gate(&self, meta: &mut ConstraintSystem<pallas::Base>) {
|
||||
meta.create_gate("complete addition gates", |meta| {
|
||||
let q_add = meta.query_selector(self.q_add);
|
||||
let x_p = meta.query_advice(self.x_p, Rotation::cur());
|
||||
|
@ -102,9 +101,9 @@ impl<C: CurveAffine> Config<C> {
|
|||
let if_delta = (y_q.clone() + y_p.clone()) * delta;
|
||||
|
||||
// Useful constants
|
||||
let one = Expression::Constant(C::Base::one());
|
||||
let two = Expression::Constant(C::Base::from_u64(2));
|
||||
let three = Expression::Constant(C::Base::from_u64(3));
|
||||
let one = Expression::Constant(pallas::Base::one());
|
||||
let two = Expression::Constant(pallas::Base::from_u64(2));
|
||||
let three = Expression::Constant(pallas::Base::from_u64(3));
|
||||
|
||||
// (x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p)) = 0
|
||||
let poly1 = {
|
||||
|
@ -199,11 +198,11 @@ impl<C: CurveAffine> Config<C> {
|
|||
|
||||
pub(super) fn assign_region(
|
||||
&self,
|
||||
p: &EccPoint<C>,
|
||||
q: &EccPoint<C>,
|
||||
p: &EccPoint,
|
||||
q: &EccPoint,
|
||||
offset: usize,
|
||||
region: &mut Region<'_, C::Base>,
|
||||
) -> Result<EccPoint<C>, Error> {
|
||||
region: &mut Region<'_, pallas::Base>,
|
||||
) -> Result<EccPoint, Error> {
|
||||
// Enable `q_add` selector
|
||||
self.q_add.enable(region, offset)?;
|
||||
|
||||
|
@ -281,7 +280,7 @@ impl<C: CurveAffine> Config<C> {
|
|||
if x_q == x_p {
|
||||
delta.ok_or(Error::SynthesisError)
|
||||
} else {
|
||||
Ok(C::Base::zero())
|
||||
Ok(pallas::Base::zero())
|
||||
}
|
||||
},
|
||||
)?;
|
||||
|
@ -300,15 +299,15 @@ impl<C: CurveAffine> Config<C> {
|
|||
// know that x_q != x_p in this branch.
|
||||
(y_q - y_p) * alpha
|
||||
} else {
|
||||
if y_p != C::Base::zero() {
|
||||
if y_p != pallas::Base::zero() {
|
||||
// 3(x_p)^2
|
||||
let three_x_p_sq = C::Base::from_u64(3) * x_p * x_p;
|
||||
let three_x_p_sq = pallas::Base::from_u64(3) * x_p * x_p;
|
||||
// 1 / 2(y_p)
|
||||
let inv_two_y_p = y_p.invert().unwrap() * C::Base::TWO_INV;
|
||||
let inv_two_y_p = y_p.invert().unwrap() * pallas::Base::TWO_INV;
|
||||
// λ = 3(x_p)^2 / 2(y_p)
|
||||
three_x_p_sq * inv_two_y_p
|
||||
} else {
|
||||
C::Base::zero()
|
||||
pallas::Base::zero()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -326,15 +325,15 @@ impl<C: CurveAffine> Config<C> {
|
|||
.zip(y_q)
|
||||
.zip(lambda)
|
||||
.map(|((((x_p, y_p), x_q), y_q), lambda)| {
|
||||
if x_p == C::Base::zero() {
|
||||
if x_p == pallas::Base::zero() {
|
||||
// 0 + Q = Q
|
||||
x_q
|
||||
} else if x_q == C::Base::zero() {
|
||||
} else if x_q == pallas::Base::zero() {
|
||||
// P + 0 = P
|
||||
x_p
|
||||
} else if (x_q == x_p) && (y_q == -y_p) {
|
||||
// P + (-P) maps to (0,0)
|
||||
C::Base::zero()
|
||||
pallas::Base::zero()
|
||||
} else {
|
||||
// x_r = λ^2 - x_p - x_q
|
||||
lambda * lambda - x_p - x_q
|
||||
|
@ -350,15 +349,15 @@ impl<C: CurveAffine> Config<C> {
|
|||
// Assign y_r
|
||||
let y_r = x_p.zip(y_p).zip(x_q).zip(y_q).zip(x_r).zip(lambda).map(
|
||||
|(((((x_p, y_p), x_q), y_q), x_r), lambda)| {
|
||||
if x_p == C::Base::zero() {
|
||||
if x_p == pallas::Base::zero() {
|
||||
// 0 + Q = Q
|
||||
y_q
|
||||
} else if x_q == C::Base::zero() {
|
||||
} else if x_q == pallas::Base::zero() {
|
||||
// P + 0 = P
|
||||
y_p
|
||||
} else if (x_q == x_p) && (y_q == -y_p) {
|
||||
// P + (-P) maps to (0,0)
|
||||
C::Base::zero()
|
||||
pallas::Base::zero()
|
||||
} else {
|
||||
// y_r = λ(x_p - x_r) - y_p
|
||||
lambda * (x_p - x_r) - y_p
|
||||
|
@ -372,9 +371,9 @@ impl<C: CurveAffine> Config<C> {
|
|||
|| y_r.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
let result = EccPoint::<C> {
|
||||
x: CellValue::<C::Base>::new(x_r_cell, x_r),
|
||||
y: CellValue::<C::Base>::new(y_r_cell, y_r),
|
||||
let result = EccPoint {
|
||||
x: CellValue::<pallas::Base>::new(x_r_cell, x_r),
|
||||
y: CellValue::<pallas::Base>::new(y_r_cell, y_r),
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -398,25 +397,22 @@ impl<C: CurveAffine> Config<C> {
|
|||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use group::Curve;
|
||||
use halo2::{
|
||||
arithmetic::{CurveAffine, CurveExt},
|
||||
circuit::Layouter,
|
||||
plonk::Error,
|
||||
};
|
||||
use group::{prime::PrimeCurveAffine, Curve};
|
||||
use halo2::{circuit::Layouter, plonk::Error};
|
||||
use pasta_curves::{arithmetic::CurveExt, pallas};
|
||||
|
||||
use crate::circuit::gadget::ecc::{EccInstructions, Point};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn test_add<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Eq + std::fmt::Debug>(
|
||||
pub fn test_add<EccChip: EccInstructions<pallas::Affine> + Clone + Eq + std::fmt::Debug>(
|
||||
chip: EccChip,
|
||||
mut layouter: impl Layouter<C::Base>,
|
||||
zero: &Point<C, EccChip>,
|
||||
p_val: C,
|
||||
p: &Point<C, EccChip>,
|
||||
q_val: C,
|
||||
q: &Point<C, EccChip>,
|
||||
p_neg: &Point<C, EccChip>,
|
||||
mut layouter: impl Layouter<pallas::Base>,
|
||||
zero: &Point<pallas::Affine, EccChip>,
|
||||
p_val: pallas::Affine,
|
||||
p: &Point<pallas::Affine, EccChip>,
|
||||
q_val: pallas::Affine,
|
||||
q: &Point<pallas::Affine, EccChip>,
|
||||
p_neg: &Point<pallas::Affine, EccChip>,
|
||||
) -> Result<(), Error> {
|
||||
// Make sure P and Q are not the same point.
|
||||
assert_ne!(p_val, q_val);
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
use std::{array, marker::PhantomData};
|
||||
use std::array;
|
||||
|
||||
use super::{copy, CellValue, EccConfig, EccPoint, Var};
|
||||
use ff::Field;
|
||||
use group::Curve;
|
||||
use halo2::{
|
||||
arithmetic::CurveAffine,
|
||||
circuit::Region,
|
||||
plonk::{Advice, Column, ConstraintSystem, Error, Permutation, Selector},
|
||||
poly::Rotation,
|
||||
};
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config<C: CurveAffine> {
|
||||
pub struct Config {
|
||||
q_add_incomplete: Selector,
|
||||
// x-coordinate of P in P + Q = R
|
||||
pub x_p: Column<Advice>,
|
||||
|
@ -23,11 +22,10 @@ pub struct Config<C: CurveAffine> {
|
|||
pub y_qr: Column<Advice>,
|
||||
// Permutation
|
||||
perm: Permutation,
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> From<&EccConfig<C>> for Config<C> {
|
||||
fn from(ecc_config: &EccConfig<C>) -> Self {
|
||||
impl From<&EccConfig> for Config {
|
||||
fn from(ecc_config: &EccConfig) -> Self {
|
||||
Self {
|
||||
q_add_incomplete: ecc_config.q_add_incomplete,
|
||||
x_p: ecc_config.advices[0],
|
||||
|
@ -35,13 +33,12 @@ impl<C: CurveAffine> From<&EccConfig<C>> for Config<C> {
|
|||
x_qr: ecc_config.advices[2],
|
||||
y_qr: ecc_config.advices[3],
|
||||
perm: ecc_config.perm.clone(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> Config<C> {
|
||||
pub(super) fn create_gate(&self, meta: &mut ConstraintSystem<C::Base>) {
|
||||
impl Config {
|
||||
pub(super) fn create_gate(&self, meta: &mut ConstraintSystem<pallas::Base>) {
|
||||
meta.create_gate("incomplete addition gates", |meta| {
|
||||
let q_add_incomplete = meta.query_selector(self.q_add_incomplete);
|
||||
let x_p = meta.query_advice(self.x_p, Rotation::cur());
|
||||
|
@ -68,11 +65,11 @@ impl<C: CurveAffine> Config<C> {
|
|||
|
||||
pub(super) fn assign_region(
|
||||
&self,
|
||||
p: &EccPoint<C>,
|
||||
q: &EccPoint<C>,
|
||||
p: &EccPoint,
|
||||
q: &EccPoint,
|
||||
offset: usize,
|
||||
region: &mut Region<'_, C::Base>,
|
||||
) -> Result<EccPoint<C>, Error> {
|
||||
region: &mut Region<'_, pallas::Base>,
|
||||
) -> Result<EccPoint, Error> {
|
||||
// Enable `q_add_incomplete` selector
|
||||
self.q_add_incomplete.enable(region, offset)?;
|
||||
|
||||
|
@ -84,9 +81,9 @@ impl<C: CurveAffine> Config<C> {
|
|||
.zip(y_q)
|
||||
.map(|(((x_p, y_p), x_q), y_q)| {
|
||||
// P is point at infinity
|
||||
if (x_p == C::Base::zero() && y_p == C::Base::zero())
|
||||
if (x_p == pallas::Base::zero() && y_p == pallas::Base::zero())
|
||||
// Q is point at infinity
|
||||
|| (x_q == C::Base::zero() && y_q == C::Base::zero())
|
||||
|| (x_q == pallas::Base::zero() && y_q == pallas::Base::zero())
|
||||
// x_p = x_q
|
||||
|| (x_p == x_q)
|
||||
{
|
||||
|
@ -135,9 +132,9 @@ impl<C: CurveAffine> Config<C> {
|
|||
|| y_r.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
let result = EccPoint::<C> {
|
||||
x: CellValue::<C::Base>::new(x_r_var, x_r),
|
||||
y: CellValue::<C::Base>::new(y_r_var, y_r),
|
||||
let result = EccPoint {
|
||||
x: CellValue::<pallas::Base>::new(x_r_var, x_r),
|
||||
y: CellValue::<pallas::Base>::new(y_r_var, y_r),
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
|
|
|
@ -1,38 +1,35 @@
|
|||
use super::{CellValue, EccConfig, EccPoint, Var};
|
||||
|
||||
use ff::Field;
|
||||
use group::prime::PrimeCurveAffine;
|
||||
|
||||
use halo2::{
|
||||
arithmetic::CurveAffine,
|
||||
circuit::Region,
|
||||
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
|
||||
poly::Rotation,
|
||||
};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config<C: CurveAffine> {
|
||||
pub struct Config {
|
||||
q_point: Selector,
|
||||
// x-coordinate
|
||||
pub x: Column<Advice>,
|
||||
// y-coordinate
|
||||
pub y: Column<Advice>,
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> From<&EccConfig<C>> for Config<C> {
|
||||
fn from(ecc_config: &EccConfig<C>) -> Self {
|
||||
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],
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> Config<C> {
|
||||
pub(super) fn create_gate(&self, meta: &mut ConstraintSystem<C::Base>) {
|
||||
impl Config {
|
||||
pub(super) fn create_gate(&self, meta: &mut ConstraintSystem<pallas::Base>) {
|
||||
meta.create_gate("witness point", |meta| {
|
||||
// Check that either the point being witness is either:
|
||||
// - the identity, which is mapped to (0, 0) in affine coordinates; or
|
||||
|
@ -45,7 +42,7 @@ impl<C: CurveAffine> Config<C> {
|
|||
// y^2 = x^3 + b
|
||||
let curve_eqn = y.clone() * y.clone()
|
||||
- (x.clone() * x.clone() * x.clone())
|
||||
- Expression::Constant(C::b());
|
||||
- Expression::Constant(pallas::Affine::b());
|
||||
|
||||
vec![
|
||||
q_point.clone() * x * curve_eqn.clone(),
|
||||
|
@ -56,17 +53,17 @@ impl<C: CurveAffine> Config<C> {
|
|||
|
||||
pub(super) fn assign_region(
|
||||
&self,
|
||||
value: Option<C>,
|
||||
value: Option<pallas::Affine>,
|
||||
offset: usize,
|
||||
region: &mut Region<'_, C::Base>,
|
||||
) -> Result<EccPoint<C>, Error> {
|
||||
region: &mut Region<'_, pallas::Base>,
|
||||
) -> Result<EccPoint, Error> {
|
||||
// Enable `q_point` selector
|
||||
self.q_point.enable(region, offset)?;
|
||||
|
||||
let value = value.map(|value| {
|
||||
// Map the identity to (0, 0).
|
||||
if value == C::identity() {
|
||||
(C::Base::zero(), C::Base::zero())
|
||||
if value == pallas::Affine::identity() {
|
||||
(pallas::Base::zero(), pallas::Base::zero())
|
||||
} else {
|
||||
let value = value.coordinates().unwrap();
|
||||
(*value.x(), *value.y())
|
||||
|
@ -92,8 +89,8 @@ impl<C: CurveAffine> Config<C> {
|
|||
)?;
|
||||
|
||||
Ok(EccPoint {
|
||||
x: CellValue::<C::Base>::new(x_var, x_val),
|
||||
y: CellValue::<C::Base>::new(y_var, y_val),
|
||||
x: CellValue::<pallas::Base>::new(x_var, x_val),
|
||||
y: CellValue::<pallas::Base>::new(y_var, y_val),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue