Skip to content

Commit

Permalink
mul::overflow.rs: Overflow check in variable-base scalar mul
Browse files Browse the repository at this point in the history
  • Loading branch information
therealyingtong committed Jun 14, 2021
1 parent 37045dc commit 80e9dc5
Show file tree
Hide file tree
Showing 10 changed files with 752 additions and 254 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ rustdoc-args = [ "--html-in-header", "katex-header.html" ]
[dependencies]
aes = "0.6"
arrayvec = "0.7.0"
bigint = "4"
bitvec = "0.22"
blake2b_simd = "0.5"
ff = "0.10"
Expand Down
9 changes: 7 additions & 2 deletions src/circuit/gadget/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,14 +427,15 @@ mod tests {
meta.advice_column(),
];

let lookup_table = meta.fixed_column();
let perm = meta.permutation(
&advices
.iter()
.map(|advice| (*advice).into())
.collect::<Vec<_>>(),
);

EccChip::configure(meta, advices, perm)
EccChip::configure(meta, advices, lookup_table, perm)
}

fn synthesize(
Expand All @@ -443,7 +444,11 @@ mod tests {
config: Self::Config,
) -> Result<(), Error> {
let mut layouter = SingleChipLayouter::new(cs)?;
let chip = EccChip::construct(config);
let chip = EccChip::construct(config.clone());

// Load 10-bit lookup table. In the Action circuit, this will be
// provided by the Sinsemilla chip.
config.lookup_config.load(&mut layouter)?;

// Generate a random point P
let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P
Expand Down
70 changes: 58 additions & 12 deletions src/circuit/gadget/ecc/chip.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use super::EccInstructions;
use crate::circuit::gadget::utilities::{copy, CellValue, Var};
use crate::constants::{self, OrchardFixedBasesFull, ValueCommitV};
use crate::{
circuit::gadget::utilities::{
copy, lookup_range_check::LookupRangeCheckConfig, CellValue, Var,
},
constants::{self, OrchardFixedBasesFull, ValueCommitV},
primitives::sinsemilla,
};
use arrayvec::ArrayVec;

use group::prime::PrimeCurveAffine;
Expand Down Expand Up @@ -67,8 +72,10 @@ pub struct EccConfig {

/// Incomplete addition
pub q_add_incomplete: Selector,

/// Complete addition
pub q_add: Selector,

/// Variable-base scalar multiplication (hi half)
pub q_mul_hi: Selector,
/// Variable-base scalar multiplication (lo half)
Expand All @@ -78,19 +85,31 @@ pub struct EccConfig {
/// Selector used in scalar decomposition for variable-base scalar mul
pub q_init_z: Selector,
/// Variable-base scalar multiplication (final scalar)
pub q_mul_complete: Selector,
pub q_mul_z: Selector,
/// Variable-base scalar multiplication (overflow check)
pub q_mul_overflow: Selector,
// Fixed column to constrain s_{120..=125} of s = alpha + k_{254} * 2^127
pub q_three_bit: Selector,
// Fixed column to constrain s_{126} of s = alpha + k_{254} * 2^127
pub q_one_bit: Selector,

/// Fixed-base full-width scalar multiplication
pub q_mul_fixed: Selector,

/// Fixed-base signed short scalar multiplication
pub q_mul_fixed_short: Selector,

/// Witness point
pub q_point: Selector,
/// Witness full-width scalar for fixed-base scalar mul
pub q_scalar_fixed: Selector,
/// Witness signed short scalar for full-width fixed-base scalar mul
pub q_scalar_fixed_short: Selector,

/// Permutation
pub perm: Permutation,
/// 10-bit lookup
pub lookup_config: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>,
}

/// A chip implementing EccInstructions
Expand Down Expand Up @@ -121,8 +140,19 @@ impl EccChip {
pub fn configure(
meta: &mut ConstraintSystem<pallas::Base>,
advices: [Column<Advice>; 10],
lookup_table: Column<Fixed>,
perm: Permutation,
) -> <Self as Chip<pallas::Base>>::Config {
let decompose_s_lookup = meta.fixed_column();

let lookup_config = LookupRangeCheckConfig::configure(
meta,
decompose_s_lookup,
advices[9],
lookup_table,
perm.clone(),
);

let config = EccConfig {
advices,
lagrange_coeffs: [
Expand All @@ -142,13 +172,17 @@ impl EccChip {
q_mul_lo: meta.selector(),
q_mul_decompose_var: meta.selector(),
q_init_z: meta.selector(),
q_mul_complete: meta.selector(),
q_mul_z: meta.selector(),
q_mul_overflow: meta.selector(),
q_three_bit: meta.selector(),
q_one_bit: meta.selector(),
q_mul_fixed: meta.selector(),
q_mul_fixed_short: meta.selector(),
q_point: meta.selector(),
q_scalar_fixed: meta.selector(),
q_scalar_fixed_short: meta.selector(),
perm,
lookup_config,
};

// Create witness point gate
Expand Down Expand Up @@ -182,13 +216,13 @@ impl EccChip {
config.create_gate(meta);
}

// Create witness scalar_fixed gate that only apploes to short scalars
// Create witness scalar_fixed gate that only applies to short scalars
{
let config: witness_scalar_fixed::short::Config = (&config).into();
config.create_gate(meta);
}

// Create fixed-base scalar mul gate that os used in both full-width
// Create fixed-base scalar mul gate that is used in both full-width
// and short multiplication.
{
let mul_fixed_config: mul_fixed::Config<{ constants::NUM_WINDOWS }> = (&config).into();
Expand All @@ -206,6 +240,17 @@ impl EccChip {
}
}

/// A base-field element used as the scalar in variable-base scalar multiplication.
#[derive(Copy, Clone, Debug)]
pub struct EccScalarVar(CellValue<pallas::Base>);
impl std::ops::Deref for EccScalarVar {
type Target = CellValue<pallas::Base>;

fn deref(&self) -> &CellValue<pallas::Base> {
&self.0
}
}

/// A full-width scalar used for fixed-base scalar multiplication.
/// This is decomposed in chunks of `window_width` bits in little-endian order.
/// For example, if `window_width` = 3, we will have [k_0, k_1, ..., k_n]
Expand All @@ -232,7 +277,7 @@ pub struct EccScalarFixedShort {
impl EccInstructions<pallas::Affine> for EccChip {
type ScalarFixed = EccScalarFixed;
type ScalarFixedShort = EccScalarFixedShort;
type ScalarVar = CellValue<pallas::Base>;
type ScalarVar = EccScalarVar;
type Point = EccPoint;
type X = CellValue<pallas::Base>;
type FixedPoints = OrchardFixedBasesFull;
Expand Down Expand Up @@ -266,12 +311,12 @@ impl EccInstructions<pallas::Affine> for EccChip {
|| "Witness scalar for variable-base mul",
|mut region| {
let cell = region.assign_advice(
|| "Witness scalar var",
|| "witness scalar var",
config.advices[0],
0,
|| value.ok_or(Error::SynthesisError),
)?;
Ok(CellValue::new(cell, value))
Ok(EccScalarVar(CellValue::new(cell, value)))
},
)
}
Expand Down Expand Up @@ -349,9 +394,10 @@ impl EccInstructions<pallas::Affine> for EccChip {
base: &Self::Point,
) -> Result<Self::Point, Error> {
let config: mul::Config = self.config().into();
layouter.assign_region(
|| "variable-base scalar mul",
|mut region| config.assign_region(scalar, base, 0, &mut region),
config.assign(
layouter.namespace(|| "variable-base scalar mul"),
*scalar,
base,
)
}

Expand Down
Loading

0 comments on commit 80e9dc5

Please sign in to comment.