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:
therealyingtong 2021-06-12 06:29:05 +08:00
parent aec7a7f850
commit e259bb3846
5 changed files with 130 additions and 156 deletions

View File

@ -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(()))
}

View File

@ -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> {

View File

@ -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_qy_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);

View File

@ -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)

View File

@ -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),
})
}
}