2022-01-27 13:53:10 -08:00
|
|
|
|
//! Chip implementations for the ECC gadgets.
|
|
|
|
|
|
2022-03-21 23:50:16 -07:00
|
|
|
|
use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints};
|
2021-06-13 06:06:34 -07:00
|
|
|
|
use crate::{
|
2022-05-08 19:54:04 -07:00
|
|
|
|
sinsemilla::primitives as sinsemilla,
|
2022-01-27 13:53:10 -08:00
|
|
|
|
utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions},
|
2021-06-13 06:06:34 -07:00
|
|
|
|
};
|
2021-06-11 21:32:31 -07:00
|
|
|
|
use arrayvec::ArrayVec;
|
2021-06-11 15:29:05 -07:00
|
|
|
|
|
2022-05-12 15:21:29 -07:00
|
|
|
|
use ff::PrimeField;
|
2021-06-11 15:29:05 -07:00
|
|
|
|
use group::prime::PrimeCurveAffine;
|
2022-01-27 15:28:02 -08:00
|
|
|
|
use halo2_proofs::{
|
2022-06-08 13:37:52 -07:00
|
|
|
|
circuit::{AssignedCell, Chip, Layouter, Value},
|
2022-05-12 15:21:29 -07:00
|
|
|
|
plonk::{Advice, Assigned, Column, ConstraintSystem, Error, Fixed},
|
2021-06-04 23:05:58 -07:00
|
|
|
|
};
|
2021-06-11 15:29:05 -07:00
|
|
|
|
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
2021-06-04 23:05:58 -07:00
|
|
|
|
|
2021-11-30 19:31:49 -08:00
|
|
|
|
use std::convert::TryInto;
|
|
|
|
|
|
2021-06-04 23:13:56 -07:00
|
|
|
|
pub(super) mod add;
|
2021-06-04 23:11:40 -07:00
|
|
|
|
pub(super) mod add_incomplete;
|
2022-01-26 16:22:30 -08:00
|
|
|
|
pub mod constants;
|
2021-06-04 23:17:43 -07:00
|
|
|
|
pub(super) mod mul;
|
2021-06-04 23:34:44 -07:00
|
|
|
|
pub(super) mod mul_fixed;
|
2021-06-04 23:08:51 -07:00
|
|
|
|
pub(super) mod witness_point;
|
2021-06-04 23:05:58 -07:00
|
|
|
|
|
2022-01-26 16:22:30 -08:00
|
|
|
|
pub use constants::*;
|
2021-08-19 21:21:46 -07:00
|
|
|
|
|
2022-05-10 08:24:00 -07:00
|
|
|
|
// Exposed for Sinsemilla.
|
|
|
|
|
pub(crate) use mul::incomplete::DoubleAndAdd;
|
|
|
|
|
|
2021-09-27 01:40:21 -07:00
|
|
|
|
/// A curve point represented in affine (x, y) coordinates, or the
|
|
|
|
|
/// identity represented as (0, 0).
|
|
|
|
|
/// Each coordinate is assigned to a cell.
|
2021-12-01 04:51:33 -08:00
|
|
|
|
#[derive(Clone, Debug)]
|
2021-06-11 15:29:05 -07:00
|
|
|
|
pub struct EccPoint {
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// x-coordinate
|
2022-05-12 15:21:29 -07:00
|
|
|
|
///
|
|
|
|
|
/// Stored as an `Assigned<F>` to enable batching inversions.
|
|
|
|
|
x: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// y-coordinate
|
2022-05-12 15:21:29 -07:00
|
|
|
|
///
|
|
|
|
|
/// Stored as an `Assigned<F>` to enable batching inversions.
|
|
|
|
|
y: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 15:29:05 -07:00
|
|
|
|
impl EccPoint {
|
2021-06-18 23:59:09 -07:00
|
|
|
|
/// Constructs a point from its coordinates, without checking they are on the curve.
|
|
|
|
|
///
|
2022-09-09 10:53:31 -07:00
|
|
|
|
/// This is an internal API that we only use where we know we have a valid curve point.
|
2022-01-27 13:53:10 -08:00
|
|
|
|
pub(crate) fn from_coordinates_unchecked(
|
2022-05-12 15:21:29 -07:00
|
|
|
|
x: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
|
|
|
|
y: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-06-18 23:59:09 -07:00
|
|
|
|
) -> Self {
|
|
|
|
|
EccPoint { x, y }
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// Returns the value of this curve point, if known.
|
2022-06-08 13:37:52 -07:00
|
|
|
|
pub fn point(&self) -> Value<pallas::Affine> {
|
|
|
|
|
self.x.value().zip(self.y.value()).map(|(x, y)| {
|
|
|
|
|
if x.is_zero_vartime() && y.is_zero_vartime() {
|
|
|
|
|
pallas::Affine::identity()
|
|
|
|
|
} else {
|
|
|
|
|
pallas::Affine::from_xy(x.evaluate(), y.evaluate()).unwrap()
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
2022-06-08 13:37:52 -07:00
|
|
|
|
})
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
2021-06-10 20:24:12 -07:00
|
|
|
|
/// The cell containing the affine short-Weierstrass x-coordinate,
|
|
|
|
|
/// or 0 for the zero point.
|
2021-12-01 18:51:46 -08:00
|
|
|
|
pub fn x(&self) -> AssignedCell<pallas::Base, pallas::Base> {
|
2022-05-12 15:21:29 -07:00
|
|
|
|
self.x.clone().evaluate()
|
2021-06-10 20:24:12 -07:00
|
|
|
|
}
|
|
|
|
|
/// The cell containing the affine short-Weierstrass y-coordinate,
|
|
|
|
|
/// or 0 for the zero point.
|
2021-12-01 18:51:46 -08:00
|
|
|
|
pub fn y(&self) -> AssignedCell<pallas::Base, pallas::Base> {
|
2022-05-12 15:21:29 -07:00
|
|
|
|
self.y.clone().evaluate()
|
2021-06-10 20:24:12 -07:00
|
|
|
|
}
|
2021-09-27 01:40:21 -07:00
|
|
|
|
|
2021-09-28 09:39:41 -07:00
|
|
|
|
#[cfg(test)]
|
2022-06-08 13:37:52 -07:00
|
|
|
|
fn is_identity(&self) -> Value<bool> {
|
2021-12-01 04:59:37 -08:00
|
|
|
|
self.x.value().map(|x| x.is_zero_vartime())
|
2021-09-27 01:40:21 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A non-identity point represented in affine (x, y) coordinates.
|
|
|
|
|
/// Each coordinate is assigned to a cell.
|
2021-12-01 04:51:33 -08:00
|
|
|
|
#[derive(Clone, Debug)]
|
2021-09-27 01:40:21 -07:00
|
|
|
|
pub struct NonIdentityEccPoint {
|
|
|
|
|
/// x-coordinate
|
2022-05-12 15:21:29 -07:00
|
|
|
|
///
|
|
|
|
|
/// Stored as an `Assigned<F>` to enable batching inversions.
|
|
|
|
|
x: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-09-27 01:40:21 -07:00
|
|
|
|
/// y-coordinate
|
2022-05-12 15:21:29 -07:00
|
|
|
|
///
|
|
|
|
|
/// Stored as an `Assigned<F>` to enable batching inversions.
|
|
|
|
|
y: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-09-27 01:40:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NonIdentityEccPoint {
|
|
|
|
|
/// Constructs a point from its coordinates, without checking they are on the curve.
|
|
|
|
|
///
|
|
|
|
|
/// This is an internal API that we only use where we know we have a valid non-identity
|
2022-09-09 10:53:31 -07:00
|
|
|
|
/// curve point.
|
2022-01-27 13:53:10 -08:00
|
|
|
|
pub(crate) fn from_coordinates_unchecked(
|
2022-05-12 15:21:29 -07:00
|
|
|
|
x: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
|
|
|
|
y: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
|
2021-09-27 01:40:21 -07:00
|
|
|
|
) -> Self {
|
|
|
|
|
NonIdentityEccPoint { x, y }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the value of this curve point, if known.
|
2022-06-08 13:37:52 -07:00
|
|
|
|
pub fn point(&self) -> Value<pallas::Affine> {
|
|
|
|
|
self.x.value().zip(self.y.value()).map(|(x, y)| {
|
|
|
|
|
assert!(!x.is_zero_vartime() && !y.is_zero_vartime());
|
|
|
|
|
pallas::Affine::from_xy(x.evaluate(), y.evaluate()).unwrap()
|
|
|
|
|
})
|
2021-09-27 01:40:21 -07:00
|
|
|
|
}
|
|
|
|
|
/// The cell containing the affine short-Weierstrass x-coordinate.
|
2021-12-01 18:51:46 -08:00
|
|
|
|
pub fn x(&self) -> AssignedCell<pallas::Base, pallas::Base> {
|
2022-05-12 15:21:29 -07:00
|
|
|
|
self.x.clone().evaluate()
|
2021-09-27 01:40:21 -07:00
|
|
|
|
}
|
|
|
|
|
/// The cell containing the affine short-Weierstrass y-coordinate.
|
2021-12-01 18:51:46 -08:00
|
|
|
|
pub fn y(&self) -> AssignedCell<pallas::Base, pallas::Base> {
|
2022-05-12 15:21:29 -07:00
|
|
|
|
self.y.clone().evaluate()
|
2021-09-27 01:40:21 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<NonIdentityEccPoint> for EccPoint {
|
|
|
|
|
fn from(non_id_point: NonIdentityEccPoint) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
x: non_id_point.x,
|
|
|
|
|
y: non_id_point.y,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 13:26:49 -07:00
|
|
|
|
/// Configuration for [`EccChip`].
|
2021-06-04 23:05:58 -07:00
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
|
#[allow(non_snake_case)]
|
2021-08-18 23:59:39 -07:00
|
|
|
|
pub struct EccConfig<FixedPoints: super::FixedPoints<pallas::Affine>> {
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// Advice columns needed by instructions in the ECC chip.
|
|
|
|
|
pub advices: [Column<Advice>; 10],
|
|
|
|
|
|
|
|
|
|
/// Incomplete addition
|
2021-11-30 10:29:52 -08:00
|
|
|
|
add_incomplete: add_incomplete::Config,
|
2021-06-13 06:06:34 -07:00
|
|
|
|
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// Complete addition
|
2021-11-30 10:41:02 -08:00
|
|
|
|
add: add::Config,
|
2021-06-13 06:06:34 -07:00
|
|
|
|
|
2021-11-30 12:41:57 -08:00
|
|
|
|
/// Variable-base scalar multiplication
|
|
|
|
|
mul: mul::Config,
|
2021-06-13 06:06:34 -07:00
|
|
|
|
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// Fixed-base full-width scalar multiplication
|
2021-08-18 23:59:39 -07:00
|
|
|
|
mul_fixed_full: mul_fixed::full_width::Config<FixedPoints>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
/// Fixed-base signed short scalar multiplication
|
2021-08-18 23:59:39 -07:00
|
|
|
|
mul_fixed_short: mul_fixed::short::Config<FixedPoints>,
|
2021-11-30 19:31:49 -08:00
|
|
|
|
/// Fixed-base mul using a base field element as a scalar
|
2021-08-18 23:59:39 -07:00
|
|
|
|
mul_fixed_base_field: mul_fixed::base_field_elem::Config<FixedPoints>,
|
2021-06-13 06:06:34 -07:00
|
|
|
|
|
2021-11-30 10:47:52 -08:00
|
|
|
|
/// Witness point
|
|
|
|
|
witness_point: witness_point::Config,
|
2021-06-19 04:08:46 -07:00
|
|
|
|
|
2021-07-09 17:50:07 -07:00
|
|
|
|
/// Lookup range check using 10-bit lookup table
|
2021-06-13 06:06:34 -07:00
|
|
|
|
pub lookup_config: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-26 16:22:30 -08:00
|
|
|
|
/// A trait representing the kind of scalar used with a particular `FixedPoint`.
|
|
|
|
|
///
|
|
|
|
|
/// This trait exists because of limitations around const generics.
|
2022-03-21 23:52:10 -07:00
|
|
|
|
pub trait FixedScalarKind {
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// The number of windows that this scalar kind requires.
|
2022-01-26 16:22:30 -08:00
|
|
|
|
const NUM_WINDOWS: usize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type marker representing a full-width scalar for use in fixed-base scalar
|
|
|
|
|
/// multiplication.
|
2022-01-27 13:53:10 -08:00
|
|
|
|
#[derive(Debug)]
|
2022-01-26 16:22:30 -08:00
|
|
|
|
pub enum FullScalar {}
|
2022-03-21 23:52:10 -07:00
|
|
|
|
impl FixedScalarKind for FullScalar {
|
2022-01-26 16:22:30 -08:00
|
|
|
|
const NUM_WINDOWS: usize = NUM_WINDOWS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type marker representing a signed 64-bit scalar for use in fixed-base scalar
|
|
|
|
|
/// multiplication.
|
2022-01-27 13:53:10 -08:00
|
|
|
|
#[derive(Debug)]
|
2022-01-26 16:22:30 -08:00
|
|
|
|
pub enum ShortScalar {}
|
2022-03-21 23:52:10 -07:00
|
|
|
|
impl FixedScalarKind for ShortScalar {
|
2022-01-26 16:22:30 -08:00
|
|
|
|
const NUM_WINDOWS: usize = NUM_WINDOWS_SHORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type marker representing a base field element being used as a scalar in fixed-base
|
|
|
|
|
/// scalar multiplication.
|
2022-01-27 13:53:10 -08:00
|
|
|
|
#[derive(Debug)]
|
2022-01-26 16:22:30 -08:00
|
|
|
|
pub enum BaseFieldElem {}
|
2022-03-21 23:52:10 -07:00
|
|
|
|
impl FixedScalarKind for BaseFieldElem {
|
2022-01-26 16:22:30 -08:00
|
|
|
|
const NUM_WINDOWS: usize = NUM_WINDOWS;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// Returns information about a fixed point that is required by [`EccChip`].
|
|
|
|
|
///
|
2022-03-21 23:52:10 -07:00
|
|
|
|
/// For each window required by `Self::FixedScalarKind`, $z$ is a field element such that for
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// each point $(x, y)$ in the window:
|
|
|
|
|
/// - $z + y = u^2$ (some square in the field); and
|
|
|
|
|
/// - $z - y$ is not a square.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
///
|
|
|
|
|
/// TODO: When associated consts can be used as const generics, introduce a
|
|
|
|
|
/// `const NUM_WINDOWS: usize` associated const, and return `NUM_WINDOWS`-sized
|
|
|
|
|
/// arrays instead of `Vec`s.
|
|
|
|
|
pub trait FixedPoint<C: CurveAffine>: std::fmt::Debug + Eq + Clone {
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// The kind of scalar that this fixed point can be multiplied by.
|
2022-03-21 23:52:10 -07:00
|
|
|
|
type FixedScalarKind: FixedScalarKind;
|
2022-01-26 16:22:30 -08:00
|
|
|
|
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// Returns the generator for this fixed point.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
fn generator(&self) -> C;
|
2022-01-27 13:53:10 -08:00
|
|
|
|
|
|
|
|
|
/// Returns the $u$ values for this fixed point.
|
2022-05-09 09:42:42 -07:00
|
|
|
|
fn u(&self) -> Vec<[<C::Base as PrimeField>::Repr; H]>;
|
2022-01-27 13:53:10 -08:00
|
|
|
|
|
|
|
|
|
/// Returns the $z$ value for this fixed point.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
fn z(&self) -> Vec<u64>;
|
2022-01-26 16:22:30 -08:00
|
|
|
|
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// Returns the Lagrange coefficients for this fixed point.
|
2022-01-26 16:22:30 -08:00
|
|
|
|
fn lagrange_coeffs(&self) -> Vec<[C::Base; H]> {
|
2022-03-21 23:52:10 -07:00
|
|
|
|
compute_lagrange_coeffs(self.generator(), Self::FixedScalarKind::NUM_WINDOWS)
|
2022-01-26 16:22:30 -08:00
|
|
|
|
}
|
2021-08-18 23:59:39 -07:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 13:26:49 -07:00
|
|
|
|
/// An [`EccInstructions`] chip that uses 10 advice columns.
|
2021-06-04 23:05:58 -07:00
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
2021-08-18 23:59:39 -07:00
|
|
|
|
pub struct EccChip<FixedPoints: super::FixedPoints<pallas::Affine>> {
|
|
|
|
|
config: EccConfig<FixedPoints>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 23:59:39 -07:00
|
|
|
|
impl<FixedPoints: super::FixedPoints<pallas::Affine>> Chip<pallas::Base> for EccChip<FixedPoints> {
|
|
|
|
|
type Config = EccConfig<FixedPoints>;
|
2021-06-04 23:05:58 -07:00
|
|
|
|
type Loaded = ();
|
|
|
|
|
|
|
|
|
|
fn config(&self) -> &Self::Config {
|
|
|
|
|
&self.config
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn loaded(&self) -> &Self::Loaded {
|
|
|
|
|
&()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 23:59:39 -07:00
|
|
|
|
impl<Fixed: super::FixedPoints<pallas::Affine>> UtilitiesInstructions<pallas::Base>
|
|
|
|
|
for EccChip<Fixed>
|
|
|
|
|
{
|
2021-12-01 18:51:46 -08:00
|
|
|
|
type Var = AssignedCell<pallas::Base, pallas::Base>;
|
2021-07-09 18:09:26 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 23:59:39 -07:00
|
|
|
|
impl<FixedPoints: super::FixedPoints<pallas::Affine>> EccChip<FixedPoints> {
|
2022-01-27 13:53:10 -08:00
|
|
|
|
/// Reconstructs this chip from the given config.
|
2021-06-11 15:29:05 -07:00
|
|
|
|
pub fn construct(config: <Self as Chip<pallas::Base>>::Config) -> Self {
|
2021-06-10 10:09:04 -07:00
|
|
|
|
Self { config }
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-15 04:52:15 -07:00
|
|
|
|
/// # Side effects
|
|
|
|
|
///
|
2021-07-22 07:14:34 -07:00
|
|
|
|
/// All columns in `advices` will be equality-enabled.
|
2021-06-04 23:05:58 -07:00
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
|
pub fn configure(
|
2021-06-11 15:29:05 -07:00
|
|
|
|
meta: &mut ConstraintSystem<pallas::Base>,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
advices: [Column<Advice>; 10],
|
2021-07-21 04:13:47 -07:00
|
|
|
|
lagrange_coeffs: [Column<Fixed>; 8],
|
2021-07-21 07:59:08 -07:00
|
|
|
|
range_check: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>,
|
2021-06-11 15:29:05 -07:00
|
|
|
|
) -> <Self as Chip<pallas::Base>>::Config {
|
2021-11-30 10:47:52 -08:00
|
|
|
|
// Create witness point gate
|
|
|
|
|
let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]);
|
2021-11-30 10:29:52 -08:00
|
|
|
|
// Create incomplete point addition gate
|
|
|
|
|
let add_incomplete =
|
|
|
|
|
add_incomplete::Config::configure(meta, advices[0], advices[1], advices[2], advices[3]);
|
2021-11-30 10:47:52 -08:00
|
|
|
|
|
2021-11-30 10:41:02 -08:00
|
|
|
|
// Create complete point addition gate
|
|
|
|
|
let add = add::Config::configure(
|
|
|
|
|
meta, advices[0], advices[1], advices[2], advices[3], advices[4], advices[5],
|
|
|
|
|
advices[6], advices[7], advices[8],
|
|
|
|
|
);
|
|
|
|
|
|
2021-11-30 12:41:57 -08:00
|
|
|
|
// Create variable-base scalar mul gates
|
|
|
|
|
let mul = mul::Config::configure(meta, add, range_check, advices);
|
2021-11-30 12:59:29 -08:00
|
|
|
|
|
2021-12-03 08:51:59 -08:00
|
|
|
|
// Create config that is shared across short, base-field, and full-width
|
|
|
|
|
// fixed-base scalar mul.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let mul_fixed = mul_fixed::Config::<FixedPoints>::configure(
|
2021-12-03 08:51:59 -08:00
|
|
|
|
meta,
|
|
|
|
|
lagrange_coeffs,
|
|
|
|
|
advices[4],
|
|
|
|
|
advices[5],
|
|
|
|
|
add,
|
|
|
|
|
add_incomplete,
|
|
|
|
|
);
|
|
|
|
|
|
2021-11-30 19:15:19 -08:00
|
|
|
|
// Create gate that is only used in full-width fixed-base scalar mul.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let mul_fixed_full =
|
|
|
|
|
mul_fixed::full_width::Config::<FixedPoints>::configure(meta, mul_fixed.clone());
|
2021-11-30 19:15:19 -08:00
|
|
|
|
|
2021-11-30 19:20:24 -08:00
|
|
|
|
// Create gate that is only used in short fixed-base scalar mul.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let mul_fixed_short =
|
|
|
|
|
mul_fixed::short::Config::<FixedPoints>::configure(meta, mul_fixed.clone());
|
2021-11-30 19:20:24 -08:00
|
|
|
|
|
2021-11-30 19:31:49 -08:00
|
|
|
|
// Create gate that is only used in fixed-base mul using a base field element.
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let mul_fixed_base_field = mul_fixed::base_field_elem::Config::<FixedPoints>::configure(
|
2021-11-30 19:31:49 -08:00
|
|
|
|
meta,
|
|
|
|
|
advices[6..9].try_into().unwrap(),
|
|
|
|
|
range_check,
|
|
|
|
|
mul_fixed,
|
|
|
|
|
);
|
|
|
|
|
|
2021-11-30 19:37:12 -08:00
|
|
|
|
EccConfig {
|
2021-06-04 23:05:58 -07:00
|
|
|
|
advices,
|
2021-11-30 10:29:52 -08:00
|
|
|
|
add_incomplete,
|
2021-11-30 10:41:02 -08:00
|
|
|
|
add,
|
2021-11-30 12:41:57 -08:00
|
|
|
|
mul,
|
2021-11-30 19:15:19 -08:00
|
|
|
|
mul_fixed_full,
|
2021-11-30 19:20:24 -08:00
|
|
|
|
mul_fixed_short,
|
2021-11-30 19:31:49 -08:00
|
|
|
|
mul_fixed_base_field,
|
2021-11-30 10:47:52 -08:00
|
|
|
|
witness_point,
|
2021-07-21 07:59:08 -07:00
|
|
|
|
lookup_config: range_check,
|
2021-11-30 19:37:12 -08:00
|
|
|
|
}
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 21:32:31 -07:00
|
|
|
|
/// A full-width scalar used for fixed-base scalar multiplication.
|
2021-06-18 02:41:13 -07:00
|
|
|
|
/// This is decomposed into 85 3-bit windows in little-endian order,
|
|
|
|
|
/// i.e. `windows` = [k_0, k_1, ..., k_84] (for a 255-bit scalar)
|
|
|
|
|
/// where `scalar = k_0 + k_1 * (2^3) + ... + k_84 * (2^3)^84` and
|
|
|
|
|
/// each `k_i` is in the range [0..2^3).
|
2021-06-11 21:32:31 -07:00
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct EccScalarFixed {
|
2022-06-08 13:37:52 -07:00
|
|
|
|
value: Value<pallas::Scalar>,
|
2022-05-08 22:18:05 -07:00
|
|
|
|
/// The circuit-assigned windows representing this scalar, or `None` if the scalar has
|
|
|
|
|
/// not been used yet.
|
|
|
|
|
windows: Option<ArrayVec<AssignedCell<pallas::Base, pallas::Base>, { NUM_WINDOWS }>>,
|
2021-06-11 21:32:31 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-07 18:16:59 -08:00
|
|
|
|
// TODO: Make V a `u64`
|
|
|
|
|
type MagnitudeCell = AssignedCell<pallas::Base, pallas::Base>;
|
|
|
|
|
// TODO: Make V an enum Sign { Positive, Negative }
|
|
|
|
|
type SignCell = AssignedCell<pallas::Base, pallas::Base>;
|
|
|
|
|
type MagnitudeSign = (MagnitudeCell, SignCell);
|
|
|
|
|
|
2021-06-11 21:32:31 -07:00
|
|
|
|
/// A signed short scalar used for fixed-base scalar multiplication.
|
2021-06-18 02:41:13 -07:00
|
|
|
|
/// A short scalar must have magnitude in the range [0..2^64), with
|
|
|
|
|
/// a sign of either 1 or -1.
|
2021-07-07 22:14:53 -07:00
|
|
|
|
/// This is decomposed into 3-bit windows in little-endian order
|
|
|
|
|
/// using a running sum `z`, where z_{i+1} = (z_i - a_i) / (2^3)
|
|
|
|
|
/// for element α = a_0 + (2^3) a_1 + ... + (2^{3(n-1)}) a_{n-1}.
|
|
|
|
|
/// Each `a_i` is in the range [0..2^3).
|
|
|
|
|
///
|
|
|
|
|
/// `windows` = [k_0, k_1, ..., k_21] (for a 64-bit magnitude)
|
2021-06-18 02:41:13 -07:00
|
|
|
|
/// where `scalar = k_0 + k_1 * (2^3) + ... + k_84 * (2^3)^84` and
|
|
|
|
|
/// each `k_i` is in the range [0..2^3).
|
|
|
|
|
/// k_21 must be a single bit, i.e. 0 or 1.
|
2021-06-11 21:32:31 -07:00
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct EccScalarFixedShort {
|
2021-12-07 18:16:59 -08:00
|
|
|
|
magnitude: MagnitudeCell,
|
|
|
|
|
sign: SignCell,
|
2022-05-08 22:18:05 -07:00
|
|
|
|
/// The circuit-assigned running sum constraining this signed short scalar, or `None`
|
|
|
|
|
/// if the scalar has not been used yet.
|
|
|
|
|
running_sum:
|
|
|
|
|
Option<ArrayVec<AssignedCell<pallas::Base, pallas::Base>, { NUM_WINDOWS_SHORT + 1 }>>,
|
2021-06-11 21:32:31 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-18 02:41:13 -07:00
|
|
|
|
/// A base field element used for fixed-base scalar multiplication.
|
|
|
|
|
/// This is decomposed into 3-bit windows in little-endian order
|
|
|
|
|
/// using a running sum `z`, where z_{i+1} = (z_i - a_i) / (2^3)
|
|
|
|
|
/// for element α = a_0 + (2^3) a_1 + ... + (2^{3(n-1)}) a_{n-1}.
|
|
|
|
|
/// Each `a_i` is in the range [0..2^3).
|
|
|
|
|
///
|
2021-07-24 08:54:54 -07:00
|
|
|
|
/// `running_sum` = [z_0, ..., z_85], where we expect z_85 = 0.
|
2021-07-03 01:49:15 -07:00
|
|
|
|
/// Since z_0 is initialized as the scalar α, we store it as
|
|
|
|
|
/// `base_field_elem`.
|
2021-06-18 02:41:13 -07:00
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
struct EccBaseFieldElemFixed {
|
2021-12-01 18:51:46 -08:00
|
|
|
|
base_field_elem: AssignedCell<pallas::Base, pallas::Base>,
|
2021-08-19 21:21:46 -07:00
|
|
|
|
running_sum: ArrayVec<AssignedCell<pallas::Base, pallas::Base>, { NUM_WINDOWS + 1 }>,
|
2021-06-18 02:41:13 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl EccBaseFieldElemFixed {
|
2022-09-09 10:57:37 -07:00
|
|
|
|
#![allow(dead_code)]
|
2021-12-01 18:51:46 -08:00
|
|
|
|
fn base_field_elem(&self) -> AssignedCell<pallas::Base, pallas::Base> {
|
2021-12-01 04:51:33 -08:00
|
|
|
|
self.base_field_elem.clone()
|
2021-06-18 02:41:13 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 00:20:16 -07:00
|
|
|
|
/// An enumeration of the possible types of scalars used in variable-base
|
|
|
|
|
/// multiplication.
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub enum ScalarVar {
|
|
|
|
|
/// An element of the elliptic curve's base field, that is used as a scalar
|
|
|
|
|
/// in variable-base scalar mul.
|
|
|
|
|
///
|
|
|
|
|
/// It is not true in general that a scalar field element fits in a curve's
|
|
|
|
|
/// base field, and in particular it is untrue for the Pallas curve, whose
|
|
|
|
|
/// scalar field `Fq` is larger than its base field `Fp`.
|
|
|
|
|
///
|
|
|
|
|
/// However, the only use of variable-base scalar mul in the Orchard protocol
|
|
|
|
|
/// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed
|
|
|
|
|
/// to be in the base field of the curve. (See non-normative notes in
|
2022-05-10 13:26:49 -07:00
|
|
|
|
/// [4.2.3 Orchard Key Components][orchardkeycomponents].)
|
|
|
|
|
///
|
|
|
|
|
/// [orchardkeycomponents]: https://zips.z.cash/protocol/protocol.pdf#orchardkeycomponents
|
2022-03-22 00:20:16 -07:00
|
|
|
|
BaseFieldElem(AssignedCell<pallas::Base, pallas::Base>),
|
|
|
|
|
/// A full-width scalar. This is unimplemented for halo2_gadgets v0.1.0.
|
|
|
|
|
FullWidth,
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 23:59:39 -07:00
|
|
|
|
impl<Fixed: FixedPoints<pallas::Affine>> EccInstructions<pallas::Affine> for EccChip<Fixed>
|
|
|
|
|
where
|
2022-01-26 16:22:30 -08:00
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::Base:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = BaseFieldElem>,
|
2022-01-26 16:22:30 -08:00
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::FullScalar:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = FullScalar>,
|
2022-01-26 16:22:30 -08:00
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::ShortScalar:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = ShortScalar>,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
{
|
2021-06-11 21:32:31 -07:00
|
|
|
|
type ScalarFixed = EccScalarFixed;
|
|
|
|
|
type ScalarFixedShort = EccScalarFixedShort;
|
2022-03-22 00:20:16 -07:00
|
|
|
|
type ScalarVar = ScalarVar;
|
2021-06-11 15:29:05 -07:00
|
|
|
|
type Point = EccPoint;
|
2021-09-27 01:44:43 -07:00
|
|
|
|
type NonIdentityPoint = NonIdentityEccPoint;
|
2021-12-01 18:51:46 -08:00
|
|
|
|
type X = AssignedCell<pallas::Base, pallas::Base>;
|
2021-08-18 23:59:39 -07:00
|
|
|
|
type FixedPoints = Fixed;
|
2021-06-04 23:05:58 -07:00
|
|
|
|
|
2021-06-13 06:26:30 -07:00
|
|
|
|
fn constrain_equal(
|
|
|
|
|
&self,
|
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
|
|
|
|
a: &Self::Point,
|
|
|
|
|
b: &Self::Point,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
layouter.assign_region(
|
|
|
|
|
|| "constrain equal",
|
|
|
|
|
|mut region| {
|
|
|
|
|
// Constrain x-coordinates
|
2021-07-15 04:52:15 -07:00
|
|
|
|
region.constrain_equal(a.x().cell(), b.x().cell())?;
|
2021-06-13 06:26:30 -07:00
|
|
|
|
// Constrain x-coordinates
|
2021-07-15 04:52:15 -07:00
|
|
|
|
region.constrain_equal(a.y().cell(), b.y().cell())
|
2021-06-13 06:26:30 -07:00
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 08:56:33 -07:00
|
|
|
|
fn witness_point(
|
|
|
|
|
&self,
|
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2022-06-08 13:37:52 -07:00
|
|
|
|
value: Value<pallas::Affine>,
|
2021-09-28 08:56:33 -07:00
|
|
|
|
) -> Result<Self::Point, Error> {
|
2021-11-30 10:47:52 -08:00
|
|
|
|
let config = self.config().witness_point;
|
2021-09-28 08:56:33 -07:00
|
|
|
|
layouter.assign_region(
|
|
|
|
|
|| "witness point",
|
|
|
|
|
|mut region| config.point(value, 0, &mut region),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 01:44:43 -07:00
|
|
|
|
fn witness_point_non_id(
|
|
|
|
|
&self,
|
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2022-06-08 13:37:52 -07:00
|
|
|
|
value: Value<pallas::Affine>,
|
2021-09-27 01:44:43 -07:00
|
|
|
|
) -> Result<Self::NonIdentityPoint, Error> {
|
2021-11-30 10:47:52 -08:00
|
|
|
|
let config = self.config().witness_point;
|
2021-09-27 01:44:43 -07:00
|
|
|
|
layouter.assign_region(
|
|
|
|
|
|| "witness non-identity point",
|
|
|
|
|
|mut region| config.point_non_id(value, 0, &mut region),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-21 21:35:29 -07:00
|
|
|
|
fn witness_scalar_var(
|
|
|
|
|
&self,
|
|
|
|
|
_layouter: &mut impl Layouter<pallas::Base>,
|
2022-06-08 13:37:52 -07:00
|
|
|
|
_value: Value<pallas::Scalar>,
|
2022-03-21 21:35:29 -07:00
|
|
|
|
) -> Result<Self::ScalarVar, Error> {
|
|
|
|
|
// This is unimplemented for halo2_gadgets v0.1.0.
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-08 22:18:05 -07:00
|
|
|
|
fn witness_scalar_fixed(
|
|
|
|
|
&self,
|
|
|
|
|
_layouter: &mut impl Layouter<pallas::Base>,
|
2022-06-08 13:37:52 -07:00
|
|
|
|
value: Value<pallas::Scalar>,
|
2022-05-08 22:18:05 -07:00
|
|
|
|
) -> Result<Self::ScalarFixed, Error> {
|
|
|
|
|
Ok(EccScalarFixed {
|
|
|
|
|
value,
|
|
|
|
|
// This chip uses lazy witnessing.
|
|
|
|
|
windows: None,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn scalar_fixed_from_signed_short(
|
|
|
|
|
&self,
|
|
|
|
|
_layouter: &mut impl Layouter<pallas::Base>,
|
|
|
|
|
(magnitude, sign): MagnitudeSign,
|
|
|
|
|
) -> Result<Self::ScalarFixedShort, Error> {
|
|
|
|
|
Ok(EccScalarFixedShort {
|
|
|
|
|
magnitude,
|
|
|
|
|
sign,
|
|
|
|
|
// This chip uses lazy constraining.
|
|
|
|
|
running_sum: None,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 01:44:43 -07:00
|
|
|
|
fn extract_p<Point: Into<Self::Point> + Clone>(point: &Point) -> Self::X {
|
|
|
|
|
let point: EccPoint = (point.clone()).into();
|
|
|
|
|
point.x()
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_incomplete(
|
|
|
|
|
&self,
|
2021-06-11 15:29:05 -07:00
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2021-09-27 01:44:43 -07:00
|
|
|
|
a: &Self::NonIdentityPoint,
|
|
|
|
|
b: &Self::NonIdentityPoint,
|
|
|
|
|
) -> Result<Self::NonIdentityPoint, Error> {
|
2021-11-30 10:29:52 -08:00
|
|
|
|
let config = self.config().add_incomplete;
|
2021-06-04 23:11:40 -07:00
|
|
|
|
layouter.assign_region(
|
|
|
|
|
|| "incomplete point addition",
|
|
|
|
|
|mut region| config.assign_region(a, b, 0, &mut region),
|
|
|
|
|
)
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 01:44:43 -07:00
|
|
|
|
fn add<A: Into<Self::Point> + Clone, B: Into<Self::Point> + Clone>(
|
2021-06-04 23:05:58 -07:00
|
|
|
|
&self,
|
2021-06-11 15:29:05 -07:00
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2021-09-27 01:44:43 -07:00
|
|
|
|
a: &A,
|
|
|
|
|
b: &B,
|
2021-06-04 23:05:58 -07:00
|
|
|
|
) -> Result<Self::Point, Error> {
|
2021-11-30 10:41:02 -08:00
|
|
|
|
let config = self.config().add;
|
2021-06-04 23:13:56 -07:00
|
|
|
|
layouter.assign_region(
|
|
|
|
|
|| "complete point addition",
|
2021-09-27 01:44:43 -07:00
|
|
|
|
|mut region| {
|
|
|
|
|
config.assign_region(&(a.clone()).into(), &(b.clone()).into(), 0, &mut region)
|
|
|
|
|
},
|
2021-06-04 23:13:56 -07:00
|
|
|
|
)
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mul(
|
|
|
|
|
&self,
|
2021-06-04 23:17:43 -07:00
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2022-03-21 21:35:06 -07:00
|
|
|
|
scalar: &Self::ScalarVar,
|
2021-09-27 01:44:43 -07:00
|
|
|
|
base: &Self::NonIdentityPoint,
|
2021-07-09 22:19:42 -07:00
|
|
|
|
) -> Result<(Self::Point, Self::ScalarVar), Error> {
|
2021-11-30 12:41:57 -08:00
|
|
|
|
let config = self.config().mul;
|
2022-03-22 00:20:16 -07:00
|
|
|
|
match scalar {
|
|
|
|
|
ScalarVar::BaseFieldElem(scalar) => config.assign(
|
|
|
|
|
layouter.namespace(|| "variable-base scalar mul"),
|
|
|
|
|
scalar.clone(),
|
|
|
|
|
base,
|
|
|
|
|
),
|
|
|
|
|
ScalarVar::FullWidth => {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mul_fixed(
|
|
|
|
|
&self,
|
2021-06-04 23:34:44 -07:00
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2022-05-08 22:18:05 -07:00
|
|
|
|
scalar: &Self::ScalarFixed,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
base: &<Self::FixedPoints as FixedPoints<pallas::Affine>>::FullScalar,
|
2021-07-09 22:19:42 -07:00
|
|
|
|
) -> Result<(Self::Point, Self::ScalarFixed), Error> {
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let config = self.config().mul_fixed_full.clone();
|
2021-07-06 20:26:32 -07:00
|
|
|
|
config.assign(
|
|
|
|
|
layouter.namespace(|| format!("fixed-base mul of {:?}", base)),
|
|
|
|
|
scalar,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
base,
|
2021-06-04 23:34:44 -07:00
|
|
|
|
)
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mul_fixed_short(
|
|
|
|
|
&self,
|
2021-06-04 23:34:44 -07:00
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2022-05-08 22:18:05 -07:00
|
|
|
|
scalar: &Self::ScalarFixedShort,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
base: &<Self::FixedPoints as FixedPoints<pallas::Affine>>::ShortScalar,
|
2021-07-09 22:19:42 -07:00
|
|
|
|
) -> Result<(Self::Point, Self::ScalarFixedShort), Error> {
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let config = self.config().mul_fixed_short.clone();
|
2021-07-06 20:26:32 -07:00
|
|
|
|
config.assign(
|
|
|
|
|
layouter.namespace(|| format!("short fixed-base mul of {:?}", base)),
|
2022-05-08 22:18:05 -07:00
|
|
|
|
scalar,
|
2021-07-06 20:26:32 -07:00
|
|
|
|
base,
|
2021-06-04 23:34:44 -07:00
|
|
|
|
)
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
2021-06-18 02:41:13 -07:00
|
|
|
|
|
|
|
|
|
fn mul_fixed_base_field_elem(
|
|
|
|
|
&self,
|
|
|
|
|
layouter: &mut impl Layouter<pallas::Base>,
|
2021-12-01 18:51:46 -08:00
|
|
|
|
base_field_elem: AssignedCell<pallas::Base, pallas::Base>,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
base: &<Self::FixedPoints as FixedPoints<pallas::Affine>>::Base,
|
2021-06-18 02:41:13 -07:00
|
|
|
|
) -> Result<Self::Point, Error> {
|
2021-08-18 23:59:39 -07:00
|
|
|
|
let config = self.config().mul_fixed_base_field.clone();
|
2021-07-06 20:26:32 -07:00
|
|
|
|
config.assign(
|
|
|
|
|
layouter.namespace(|| format!("base-field elem fixed-base mul of {:?}", base)),
|
|
|
|
|
base_field_elem,
|
2021-08-18 23:59:39 -07:00
|
|
|
|
base,
|
2021-06-18 02:41:13 -07:00
|
|
|
|
)
|
|
|
|
|
}
|
2021-06-04 23:05:58 -07:00
|
|
|
|
}
|
2022-03-21 23:50:16 -07:00
|
|
|
|
|
|
|
|
|
impl<Fixed: FixedPoints<pallas::Affine>> BaseFitsInScalarInstructions<pallas::Affine>
|
|
|
|
|
for EccChip<Fixed>
|
|
|
|
|
where
|
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::Base:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = BaseFieldElem>,
|
2022-03-21 23:50:16 -07:00
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::FullScalar:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = FullScalar>,
|
2022-03-21 23:50:16 -07:00
|
|
|
|
<Fixed as FixedPoints<pallas::Affine>>::ShortScalar:
|
2022-03-21 23:52:10 -07:00
|
|
|
|
FixedPoint<pallas::Affine, FixedScalarKind = ShortScalar>,
|
2022-03-21 23:50:16 -07:00
|
|
|
|
{
|
|
|
|
|
fn scalar_var_from_base(
|
|
|
|
|
&self,
|
|
|
|
|
_layouter: &mut impl Layouter<pallas::Base>,
|
|
|
|
|
base: &Self::Var,
|
|
|
|
|
) -> Result<Self::ScalarVar, Error> {
|
2022-03-22 00:20:16 -07:00
|
|
|
|
Ok(ScalarVar::BaseFieldElem(base.clone()))
|
2022-03-21 23:50:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|