diff --git a/src/circuit.rs b/src/circuit.rs index 5149a133..0dc8be33 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,2 +1,4 @@ +pub(crate) mod gadget; + #[derive(Debug)] pub struct Proof(Vec); diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs new file mode 100644 index 00000000..9e152918 --- /dev/null +++ b/src/circuit/gadget.rs @@ -0,0 +1 @@ +pub(crate) mod ecc; diff --git a/src/circuit/gadget/ecc.rs b/src/circuit/gadget/ecc.rs new file mode 100644 index 00000000..049c6b9e --- /dev/null +++ b/src/circuit/gadget/ecc.rs @@ -0,0 +1,140 @@ +//! Gadgets for elliptic curve operations. + +use std::fmt; + +use halo2::{ + arithmetic::CurveAffine, + circuit::{Chip, Layouter}, + plonk::Error, +}; + +/// Trait allowing circuit's fixed points to be enumerated. +pub trait FixedPoints: Clone + fmt::Debug {} + +/// The set of circuit instructions required to use the ECC gadgets. +pub trait EccInstructions: Chip { + /// Variable representing an element of the elliptic curve's scalar field. + type Scalar: Clone + fmt::Debug; + /// Variable representing an elliptic curve point. + type Point: Clone + fmt::Debug; + /// Variable representing the set of fixed bases in the circuit. + type FixedPoints: FixedPoints; + /// Variable representing a fixed elliptic curve point (constant in the circuit). + type FixedPoint: Clone + fmt::Debug; + + /// Witnesses the given scalar as a private input to the circuit. + fn witness_scalar( + layouter: &mut impl Layouter, + value: Option, + ) -> Result; + + /// Witnesses the given point as a private input to the circuit. + fn witness_point( + layouter: &mut impl Layouter, + value: Option, + ) -> Result; + + /// Gets a fixed point into the circuit. + fn get_fixed( + layouter: &mut impl Layouter, + fixed_points: Self::FixedPoints, + ) -> Result; + + /// Performs point addition, returning `a + b`. + fn add( + layouter: &mut impl Layouter, + a: &Self::Point, + b: &Self::Point, + ) -> Result; + + /// Performs point doubling, returning `[2] a`. + fn double(layouter: &mut impl Layouter, a: &Self::Point) -> Result; + + /// Performs variable-base scalar multiplication, returning `[scalar] base`. + fn mul( + layouter: &mut impl Layouter, + scalar: &Self::Scalar, + base: &Self::Point, + ) -> Result; + + /// Performs fixed-base scalar multiplication, returning `[scalar] base`. + fn mul_fixed( + layouter: &mut impl Layouter, + scalar: &Self::Scalar, + base: &Self::FixedPoint, + ) -> Result; +} + +/// An element of the given elliptic curve's scalar field. +#[derive(Debug)] +pub struct Scalar> { + inner: EccChip::Scalar, +} + +impl> Scalar { + /// Constructs a new point with the given value. + pub fn new( + mut layouter: impl Layouter, + value: Option, + ) -> Result { + EccChip::witness_scalar(&mut layouter, value).map(|inner| Scalar { inner }) + } +} + +/// An elliptic curve point over the given curve. +#[derive(Debug)] +pub struct Point> { + inner: EccChip::Point, +} + +impl> Point { + /// Constructs a new point with the given value. + pub fn new(mut layouter: impl Layouter, value: Option) -> Result { + EccChip::witness_point(&mut layouter, value).map(|inner| Point { inner }) + } + + /// Returns `self + other`. + pub fn add(&self, mut layouter: impl Layouter, other: &Self) -> Result { + EccChip::add(&mut layouter, &self.inner, &other.inner).map(|inner| Point { inner }) + } + + /// Returns `[2] self`. + pub fn double(&self, mut layouter: impl Layouter) -> Result { + EccChip::double(&mut layouter, &self.inner).map(|inner| Point { inner }) + } + + /// Returns `[by] self`. + pub fn mul( + &self, + mut layouter: impl Layouter, + by: &Scalar, + ) -> Result { + EccChip::mul(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner }) + } +} + +/// A constant elliptic curve point over the given curve, for which scalar multiplication +/// is more efficient. +#[derive(Debug)] +pub struct FixedPoint> { + inner: EccChip::FixedPoint, +} + +impl> FixedPoint { + /// Gets a reference to the specified fixed point in the circuit. + pub fn get( + mut layouter: impl Layouter, + point: EccChip::FixedPoints, + ) -> Result { + EccChip::get_fixed(&mut layouter, point).map(|inner| FixedPoint { inner }) + } + + /// Returns `[by] self`. + pub fn mul( + &self, + mut layouter: impl Layouter, + by: &Scalar, + ) -> Result, Error> { + EccChip::mul_fixed(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner }) + } +}