Skip to content

Commit

Permalink
Directly use constants from Orchard in chip
Browse files Browse the repository at this point in the history
We can generalise this in a later iteration to remove Orchard-specific
assumptions.
  • Loading branch information
therealyingtong committed Mar 31, 2021
1 parent d78e1e6 commit da969be
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 126 deletions.
81 changes: 13 additions & 68 deletions src/circuit/gadget/ecc/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ impl<F: FieldExt> CellValue<F> {
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct EccConfig {
// Width of windows used in fixed-base scalar multiplication
window_width: usize,
// Number of bits for which we use complete addition (in variable-base scalar multiplication)
complete_bits: usize,
// Number of bits in a short signed scalar
short_signed_bits: usize,

// Advice column for scalar decomposition into bits
bits: Column<Advice>,
// Witness u = (y + z).sqrt(), used in fixed-base scalar multiplication
Expand All @@ -69,7 +62,7 @@ pub struct EccConfig {
// [alpha, beta, gamma, delta] inverses used in complete addition
add_complete_inv: [Column<Advice>; 4],
// Coefficients of interpolation polynomials for x-coordinates (used in fixed-base scalar multiplication)
lagrange_coeffs: [Column<Fixed>; 8],
lagrange_coeffs: [Column<Fixed>; constants::H],
// Fixed z such that y + z = u^2 some square, and -y + z is a non-square. (Used in fixed-base scalar multiplication)
fixed_z: Column<Fixed>,

Expand Down Expand Up @@ -109,9 +102,6 @@ pub struct EccChip<C: CurveAffine> {
impl<C: CurveAffine> EccChip<C> {
fn configure(
meta: &mut ConstraintSystem<C::Base>,
window_width: usize,
complete_bits: usize,
short_signed_bits: usize,
bits: Column<Advice>,
u: Column<Advice>,
A: (Column<Advice>, Column<Advice>),
Expand All @@ -120,8 +110,6 @@ impl<C: CurveAffine> EccChip<C> {
add_complete_bool: [Column<Advice>; 4],
add_complete_inv: [Column<Advice>; 4],
) -> EccConfig {
let number_base = 1 << window_width;

let q_add = meta.selector();
let q_add_complete = meta.selector();
let q_double = meta.selector();
Expand Down Expand Up @@ -171,7 +159,7 @@ impl<C: CurveAffine> EccChip<C> {
{
let q_scalar_fixed = meta.query_selector(q_scalar_fixed, Rotation::cur());
let k = meta.query_advice(bits, Rotation::cur());
witness_scalar_fixed::create_gate::<C>(meta, number_base, q_scalar_fixed, k);
witness_scalar_fixed::create_gate::<C>(meta, q_scalar_fixed, k);
}

// Create witness scalar_fixed_short gate
Expand Down Expand Up @@ -260,17 +248,7 @@ impl<C: CurveAffine> EccChip<C> {
let u = meta.query_advice(u, Rotation::cur());
let z = meta.query_fixed(fixed_z, Rotation::cur());

mul_fixed::create_gate::<C>(
meta,
number_base,
lagrange_coeffs,
q_mul_fixed,
x_p,
y_p,
k,
u,
z,
);
mul_fixed::create_gate::<C>(meta, lagrange_coeffs, q_mul_fixed, x_p, y_p, k, u, z);
}

// Create fixed-base short signed scalar mul gate
Expand Down Expand Up @@ -310,9 +288,6 @@ impl<C: CurveAffine> EccChip<C> {
}

EccConfig {
window_width,
complete_bits,
short_signed_bits,
bits,
u,
A,
Expand Down Expand Up @@ -345,8 +320,8 @@ impl<C: CurveAffine> EccChip<C> {
pub struct EccLoaded<C: CurveAffine> {
lagrange_coeffs: BTreeMap<OrchardFixedBases<C>, Vec<Vec<C::Base>>>,
lagrange_coeffs_short: BTreeMap<OrchardFixedBases<C>, Vec<Vec<C::Base>>>,
z: BTreeMap<OrchardFixedBases<C>, [u64; 85]>,
z_short: BTreeMap<OrchardFixedBases<C>, [u64; 22]>,
z: BTreeMap<OrchardFixedBases<C>, [u64; constants::NUM_WINDOWS]>,
z_short: BTreeMap<OrchardFixedBases<C>, [u64; constants::NUM_WINDOWS_SHORT]>,
u: BTreeMap<OrchardFixedBases<C>, Vec<Vec<C::Base>>>,
u_short: BTreeMap<OrchardFixedBases<C>, Vec<Vec<C::Base>>>,
}
Expand All @@ -360,11 +335,11 @@ impl<C: CurveAffine> EccLoaded<C> {
self.lagrange_coeffs_short.get(&point).cloned()
}

fn z(&self, point: OrchardFixedBases<C>) -> Option<[u64; 85]> {
fn z(&self, point: OrchardFixedBases<C>) -> Option<[u64; constants::NUM_WINDOWS]> {
self.z.get(&point).cloned()
}

fn z_short(&self, point: OrchardFixedBases<C>) -> Option<[u64; 22]> {
fn z_short(&self, point: OrchardFixedBases<C>) -> Option<[u64; constants::NUM_WINDOWS_SHORT]> {
self.z_short.get(&point).cloned()
}

Expand Down Expand Up @@ -533,8 +508,8 @@ pub struct EccFixedPoint<C: CurveAffine> {
fixed_point: OrchardFixedBases<C>,
lagrange_coeffs: Option<Vec<Vec<C::Base>>>,
lagrange_coeffs_short: Option<Vec<Vec<C::Base>>>,
z: Option<[u64; 85]>,
z_short: Option<[u64; 22]>,
z: Option<[u64; constants::NUM_WINDOWS]>,
z_short: Option<[u64; constants::NUM_WINDOWS_SHORT]>,
u: Option<Vec<Vec<C::Base>>>,
u_short: Option<Vec<Vec<C::Base>>>,
}
Expand Down Expand Up @@ -593,13 +568,7 @@ impl<C: CurveAffine> EccInstructions<C> for EccChip<C> {
let scalar = layouter.assign_region(
|| "witness scalar for fixed-base mul",
|mut region| {
witness_scalar_fixed_short::assign_region(
value,
constants::L_VALUE,
0,
&mut region,
config.clone(),
)
witness_scalar_fixed_short::assign_region(value, 0, &mut region, config.clone())
},
)?;

Expand Down Expand Up @@ -710,20 +679,10 @@ impl<C: CurveAffine> EccInstructions<C> for EccChip<C> {
base: &Self::FixedPoint,
) -> Result<Self::Point, Error> {
let config = layouter.config().clone();
let num_windows = C::Scalar::NUM_BITS / config.window_width as u32;

let point = layouter.assign_region(
|| format!("Multiply {:?}", base.fixed_point),
|mut region| {
mul_fixed::assign_region(
scalar,
base,
0,
&mut region,
config.clone(),
num_windows as usize,
)
},
|mut region| mul_fixed::assign_region(scalar, base, 0, &mut region, config.clone()),
)?;

Ok(point)
Expand All @@ -736,21 +695,10 @@ impl<C: CurveAffine> EccInstructions<C> for EccChip<C> {
) -> Result<Self::Point, Error> {
let config = layouter.config().clone();

// CEIL(l_value / window_width)
let num_windows =
(config.short_signed_bits + config.window_width - 1) / config.window_width;

let point = layouter.assign_region(
|| format!("Multiply {:?}", base.fixed_point),
|mut region| {
mul_fixed_short::assign_region(
scalar,
base,
0,
&mut region,
config.clone(),
num_windows as usize,
)
mul_fixed_short::assign_region(scalar, base, 0, &mut region, config.clone())
},
)?;

Expand All @@ -760,7 +708,7 @@ impl<C: CurveAffine> EccInstructions<C> for EccChip<C> {

#[cfg(test)]
mod tests {
use crate::constants::{self, FIXED_BASE_WINDOW_SIZE, L_VALUE, NUM_COMPLETE_BITS};
use crate::constants;
use group::{Curve, Group};
use halo2::{
arithmetic::{CurveAffine, FieldExt},
Expand Down Expand Up @@ -802,9 +750,6 @@ mod tests {

EccChip::<C>::configure(
meta,
FIXED_BASE_WINDOW_SIZE,
NUM_COMPLETE_BITS,
L_VALUE,
bits,
u,
A,
Expand Down
37 changes: 21 additions & 16 deletions src/circuit/gadget/ecc/chip/mul_fixed.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::super::EccInstructions;
use super::{add, util, witness_point, EccChip, EccPoint};
use crate::constants;

use group::Curve;
use halo2::{
Expand All @@ -11,8 +12,7 @@ use halo2::{

pub(super) fn create_gate<C: CurveAffine>(
meta: &mut ConstraintSystem<C::Base>,
number_base: usize,
lagrange_coeffs: [Column<Fixed>; 8],
lagrange_coeffs: [Column<Fixed>; constants::H],
q_mul_fixed: Expression<C::Base>,
x_p: Expression<C::Base>,
y_p: Expression<C::Base>,
Expand All @@ -22,7 +22,7 @@ pub(super) fn create_gate<C: CurveAffine>(
) {
// Check interpolation of x-coordinate
meta.create_gate("fixed-base scalar mul (x)", |meta| {
let k_pow: Vec<Expression<C::Base>> = (0..number_base)
let k_pow: Vec<Expression<C::Base>> = (0..constants::H)
.map(|pow| {
(0..pow).fold(Expression::Constant(C::Base::one()), |acc, _| {
acc * k.clone()
Expand Down Expand Up @@ -50,14 +50,13 @@ pub(super) fn assign_region<C: CurveAffine>(
offset: usize,
region: &mut Region<'_, EccChip<C>>,
config: <EccChip<C> as Chip>::Config,
num_windows: usize,
) -> Result<EccPoint<C::Base>, Error> {
// Assign fixed columns for given fixed base
for w in 0..num_windows {
for w in 0..constants::NUM_WINDOWS {
// Enable `q_mul_fixed` selector
config.q_mul_fixed.enable(region, w + offset)?;

for k in 0..(1 << config.window_width) {
for k in 0..(constants::H) {
// Assign x-coordinate Lagrange interpolation coefficients
region.assign_fixed(
|| {
Expand Down Expand Up @@ -126,7 +125,7 @@ pub(super) fn assign_region<C: CurveAffine>(
.collect::<Vec<_>>();

// This is 2^w, where w is the window width
let number_base = C::Scalar::from_u64(1u64 << config.window_width);
let h = C::Scalar::from_u64(constants::H as u64);

// Process the least significant window outside the for loop
let mul_b = k[0].map(|k_0| b * (k_0 + C::Scalar::one()));
Expand Down Expand Up @@ -175,7 +174,7 @@ pub(super) fn assign_region<C: CurveAffine>(
let w = w + 1;

// Compute [(k_w + 1) ⋅ 8^w]B
let mul_b = k.map(|k| b * (k + C::Scalar::one()) * number_base.pow(&[w as u64, 0, 0, 0]));
let mul_b = k.map(|k| b * (k + C::Scalar::one()) * h.pow(&[w as u64, 0, 0, 0]));
let mul_b = witness_point::assign_region(
mul_b.map(|point| point.to_affine()),
offset + w,
Expand All @@ -192,17 +191,17 @@ pub(super) fn assign_region<C: CurveAffine>(
}

// Process most significant window outside the for loop
let offset_sum = (0..(num_windows - 1)).fold(C::ScalarExt::zero(), |acc, w| {
acc + number_base.pow(&[w as u64, 0, 0, 0])
let offset_sum = (0..(constants::NUM_WINDOWS - 1)).fold(C::ScalarExt::zero(), |acc, w| {
acc + h.pow(&[w as u64, 0, 0, 0])
});

// `scalar = [k * 8^84 - offset_sum]`, where `offset_sum = \sum_{j = 0}^{83} 8^j`.
let scalar = k[k.len() - 1]
.map(|k| k * number_base.pow(&[(num_windows - 1) as u64, 0, 0, 0]) - offset_sum);
.map(|k| k * h.pow(&[(constants::NUM_WINDOWS - 1) as u64, 0, 0, 0]) - offset_sum);
let mul_b = scalar.map(|scalar| b * scalar);
let mul_b = witness_point::assign_region(
mul_b.map(|point| point.to_affine()),
offset + num_windows - 1,
offset + constants::NUM_WINDOWS - 1,
region,
config.clone(),
)?;
Expand All @@ -212,16 +211,22 @@ pub(super) fn assign_region<C: CurveAffine>(
let u_val = base
.u
.as_ref()
.zip(k_usize[num_windows - 1])
.map(|(u, k)| u[num_windows - 1][k]);
.zip(k_usize[constants::NUM_WINDOWS - 1])
.map(|(u, k)| u[constants::NUM_WINDOWS - 1][k]);
region.assign_advice(
|| "u",
config.u,
offset + num_windows - 1,
offset + constants::NUM_WINDOWS - 1,
|| u_val.ok_or(Error::SynthesisError),
)?;
}

// Add to the cumulative sum and return the final result as `[scalar]B`.
add::assign_region(&mul_b, &sum, offset + num_windows - 1, region, config)
add::assign_region(
&mul_b,
&sum,
offset + constants::NUM_WINDOWS - 1,
region,
config,
)
}
Loading

0 comments on commit da969be

Please sign in to comment.