Skip to content

Commit

Permalink
Merge pull request privacy-scaling-explorations#143 from input-output…
Browse files Browse the repository at this point in the history
…-hk/dev-feature/97-gen-vbsm

Generalize vbsm part of Ecc Chip

This is the variable-base scalar-mul (vbsm) part of the SOW task of generalizing the Ecc Chip to Pluto.

This builds on top of privacy-scaling-explorations#124: that issue generalized the algorithm, while keeping the curve fixed to Pallas, and this PR generalizes the curves supported.

The goal of this issue is to generalize vbsm to arbitrary curves over fields of "arbitrary" bit-width: we can make restrictions as needed, but at minimum need to support Pluto, Eris, Pallas, and Vesta. In practice, the assumptions amount to the base and scalar fields having the same bit-width, and (simplified) both field moduli having a zero-bit in the second-to-highest-order position. See the Halo2 book chapter as updated in this PR for details.
  • Loading branch information
ntc2 authored Mar 15, 2024
2 parents 7a13a02 + 785afa6 commit 0b712a1
Show file tree
Hide file tree
Showing 13 changed files with 847 additions and 463 deletions.
134 changes: 65 additions & 69 deletions book/src/design/gadgets/ecc/var-base-scalar-mul.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions halo2_gadgets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ goldenfile = "1.5.2"
[dev-dependencies]
criterion = { version = "0.3", features = ["html_reports"] }
proptest = "1.0.0"
seq-macro = "0.3.5"

[target.'cfg(unix)'.dev-dependencies]
pprof = { version = "0.8", features = ["criterion", "flamegraph"] } # MSRV 1.56
Expand Down
2 changes: 1 addition & 1 deletion halo2_gadgets/benches/ecc_circuits/scalar_mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct ScalarMulCircuitSmall {}

#[derive(Debug, Clone)]
pub struct BenchBaseScalarMulSmall {
mul: configs::MulVarBaseConfig,
mul: configs::MulVarBaseConfig<pallas::Affine>,
// Need this here to fill our the table
lookup: LookupRangeCheckConfig<pallas::Base, 10>,
advices: [Column<Advice>; 10],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def loop_checks(p, q):
The conditions are:
- alpha + t_q always fits in the same bit-width as p and q.
- the maximum number of incomplete addition rounds we can perform is n-2,
for n the bit-width of the fields.
for n+1 the bit-width of the fields.
"""
n = q.nbits() - 1
tq = q - 2^n
Expand Down
4 changes: 2 additions & 2 deletions halo2_gadgets/src/ecc/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,13 @@ pub struct EccConfig<FixedPoints: super::FixedPoints<pallas::Affine>> {
add_incomplete: add_incomplete::Config<pallas::Affine>,

/// Complete addition
add: add::Config,
add: add::Config<pallas::Affine>,

/// Non-identity point doubling
double: double::Config<pallas::Affine>,

/// Variable-base scalar multiplication
mul: mul::Config,
mul: mul::Config<pallas::Affine>,

/// Fixed-base full-width scalar multiplication
mul_fixed_full: mul_fixed::full_width::Config<FixedPoints>,
Expand Down
32 changes: 17 additions & 15 deletions halo2_gadgets/src/ecc/chip/add.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
//! Complete addition.
use super::EccPoint;
use super::{mul::VbsmCurve, EccPoint};
use ff::PrimeField;
use halo2_proofs::{
circuit::Region,
plonk::{Advice, Assigned, Column, ConstraintSystem, Constraints, Error, Expression, Selector},
poly::Rotation,
};
use halo2curves::pasta::pallas;

use std::collections::HashSet;

/// Configuration for complete ECC point addition
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Config {
pub struct Config<C: VbsmCurve> {
q_add: Selector,
// lambda
lambda: Column<Advice>,
Expand All @@ -31,13 +31,14 @@ pub struct Config {
gamma: Column<Advice>,
// δ = inv0(y_p + y_q) if x_q = x_p, 0 otherwise
delta: Column<Advice>,
_marker: std::marker::PhantomData<C>,
}

impl Config {
impl<C: VbsmCurve> Config<C> {
/// Build a [`Config`] for complete point addition
#[allow(clippy::too_many_arguments)]
pub fn configure(
meta: &mut ConstraintSystem<pallas::Base>,
meta: &mut ConstraintSystem<C::Base>,
x_p: Column<Advice>,
y_p: Column<Advice>,
x_qr: Column<Advice>,
Expand All @@ -64,6 +65,7 @@ impl Config {
beta,
gamma,
delta,
_marker: std::marker::PhantomData,
};

config.create_gate(meta);
Expand Down Expand Up @@ -91,7 +93,7 @@ impl Config {
[self.x_qr, self.y_qr].into_iter().collect()
}

fn create_gate(&self, meta: &mut ConstraintSystem<pallas::Base>) {
fn create_gate(&self, meta: &mut ConstraintSystem<C::Base>) {
// https://p.z.cash/halo2-0.1:ecc-complete-addition
meta.create_gate("complete addition", |meta| {
let q_add = meta.query_selector(self.q_add);
Expand Down Expand Up @@ -129,9 +131,9 @@ impl Config {
let if_delta = y_q_plus_y_p.clone() * delta;

// Useful constants
let one = Expression::Constant(pallas::Base::one());
let two = Expression::Constant(pallas::Base::from(2));
let three = Expression::Constant(pallas::Base::from(3));
let one = Expression::Constant(C::Base::from(1));
let two = Expression::Constant(C::Base::from(2));
let three = Expression::Constant(C::Base::from(3));

// (x_q − x_p)⋅((x_q − x_p)⋅λ − (y_q−y_p)) = 0
let poly1 = {
Expand Down Expand Up @@ -212,11 +214,11 @@ impl Config {
/// Return the complete addition of `p` and `q`.
pub(super) fn assign_region(
&self,
p: &EccPoint<pallas::Affine>,
q: &EccPoint<pallas::Affine>,
p: &EccPoint<C>,
q: &EccPoint<C>,
offset: usize,
region: &mut Region<'_, pallas::Base>,
) -> Result<EccPoint<pallas::Affine>, Error> {
region: &mut Region<'_, C::Base>,
) -> Result<EccPoint<C>, Error> {
// Enable `q_add` selector
self.q_add.enable(region, offset)?;

Expand Down Expand Up @@ -273,9 +275,9 @@ impl Config {
} else {
if !y_p.is_zero_vartime() {
// 3(x_p)^2
let three_x_p_sq = x_p.square() * pallas::Base::from(3);
let three_x_p_sq = x_p.square() * C::Base::from(3);
// 1 / 2(y_p)
let inv_two_y_p = y_p.invert() * pallas::Base::TWO_INV;
let inv_two_y_p = y_p.invert() * C::Base::TWO_INV;
// λ = 3(x_p)^2 / 2(y_p)
three_x_p_sq * inv_two_y_p
} else {
Expand Down
Loading

0 comments on commit 0b712a1

Please sign in to comment.