feature: sketch ecc add

This commit is contained in:
Xin Gao
2021-11-20 12:36:26 +08:00
parent 5d1e4a37ae
commit fa11f3b09d
7 changed files with 517 additions and 39 deletions

View File

@@ -13,6 +13,7 @@ num-bigint = { version = "0.4", features = ["rand"] }
num-integer = "0.1"
num-traits = "0.2"
rand = "0.8"
group = "0.11"
[dev-dependencies]

View File

@@ -1,40 +1,315 @@
use crate::rns::Integer;
use crate::circuit::main_gate::{MainGateConfig};
use super::{integer::IntegerConfig, AssignedInteger};
use halo2::arithmetic::CurveAffine;
use halo2::circuit::Region;
use super::{AssignedCondition, AssignedInteger};
use super::main_gate::{MainGate, MainGateInstructions};
use super::integer::{IntegerConfig, IntegerChip, IntegerInstructions};
use halo2::arithmetic::{FieldExt, CurveAffine};
use halo2::circuit::{Region, Layouter};
use halo2::plonk::Error;
use std::marker::PhantomData;
use crate::NUMBER_OF_LIMBS;
mod base_field_ecc;
mod external_ecc;
pub struct Point<C: CurveAffine> {
x: Integer<C::ScalarExt>,
y: Integer<C::ScalarExt>,
// Ecc operation mods
mod add;
/* Emulate CurveAffine point undert field F */
#[derive(Default, Clone, Debug)]
pub struct Point<C: CurveAffine, F:FieldExt> {
x: Integer<F>,
y: Integer<F>,
_marker: PhantomData<C::Base>
}
impl<C: CurveAffine> Point<C> {
fn new(x: Integer<C::ScalarExt>, y: Integer<C::ScalarExt>) -> Self {
Point { x, y }
impl<C: CurveAffine, F:FieldExt> Point<C, F> {
fn new(x: Integer<F>, y: Integer<F>) -> Self {
Point { x, y, _marker:PhantomData }
}
}
pub struct AssignedPoint<C: CurveAffine> {
x: AssignedInteger<C::ScalarExt>,
y: AssignedInteger<C::ScalarExt>,
pub struct AssignedPoint<C: CurveAffine, F:FieldExt > {
x: AssignedInteger<F>,
y: AssignedInteger<F>,
// indicate whether the poinit is the identity point of curve or not
z: AssignedCondition<F>,
_marker: PhantomData<C::Base>
}
impl<C: CurveAffine, F:FieldExt> AssignedPoint<C, F> {
pub fn new(
x:AssignedInteger<F>,
y:AssignedInteger<F>,
z:AssignedCondition<F>
) -> AssignedPoint<C,F> {
AssignedPoint{ x, y, z, _marker:PhantomData }
}
pub fn is_identity(&self) -> AssignedCondition<F> {
self.z.clone()
}
}
/// Linear combination term
pub enum Term<C: CurveAffine> {
Assigned(AssignedPoint<C>, C::ScalarExt),
Unassigned(Option<Point<C>>, C::ScalarExt),
pub enum Term<C: CurveAffine, F:FieldExt> {
Assigned(AssignedPoint<C, F>, F),
Unassigned(Option<Point<C, F>>, F),
}
#[derive(Clone, Debug)]
pub struct EccConfig {
integer_chip_config: IntegerConfig,
integer_gate_config: MainGateConfig,
}
pub struct EccChip {
config: IntegerConfig,
// we need template arg C to extract curve constants including a and b
pub struct EccChip<C: CurveAffine, F: FieldExt> {
config: EccConfig,
integer_chip: IntegerChip<C::Base, F>,
// We need to assign following integers based on constants of curve C
a: AssignedInteger<F>,
b: AssignedInteger<F>,
}
/* Now moved to external_ecc
impl<C: CurveAffine, F:FieldExt> EccInstruction<C, F> for EccChip<C, F> {
fn assign_point(&self, region: &mut Region<'_, F>, point: Point<C,F>, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
let x = self.integer_chip.assign_integer(region, Some(point.x.clone()), offset)?.clone();
let y = self.integer_chip.assign_integer(region, Some(point.y.clone()), offset)?.clone();
let z = self.integer_gate().assign_bit(region, Some(F::zero()), offset)?.clone();
Ok(AssignedPoint::new(x,y,z))
}
fn assert_is_on_curve(&self, region: &mut Region<'_, F>, point: AssignedPoint<C,F>, offset: &mut usize) -> Result<(), Error> {
unimplemented!();
}
fn assert_equal(
&self,
region: &mut Region<'_, F>,
p0: &AssignedPoint<C,F>,
p1: &AssignedPoint<C,F>,
offset: &mut usize,
) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
fn add(&self, region: &mut Region<'_, F>, p0: &AssignedPoint<C,F>, p1: &AssignedPoint<C,F>, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
self._add(region, p0, p1, offset)
}
fn double(&self, region: &mut Region<'_, F>, p: AssignedPoint<C,F>, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
fn mul_var(&self, region: &mut Region<'_, F>, p: AssignedPoint<C,F>, e: F, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
fn mul_fix(&self, region: &mut Region<'_, F>, p: C, e: F, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
fn multi_exp(&self, region: &mut Region<'_, F>, terms: Vec<Term<C, F>>, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
fn combine(&self, region: &mut Region<'_, F>, terms: Vec<Term<C, F>>, u: F, offset: &mut usize) -> Result<AssignedPoint<C,F>, Error> {
unimplemented!();
}
}
*/
impl<C: CurveAffine, F: FieldExt> EccChip<C, F> {
fn new(
layouter: &mut impl Layouter<F>,
config: EccConfig,
integer_chip: IntegerChip<C::Base, F>
) -> Result<Self, Error> {
let ca = Integer::<F>::from_bytes_le(
&C::a().to_bytes(),
NUMBER_OF_LIMBS,
integer_chip.rns.bit_len_limb
);
let cb = Integer::<F>::from_bytes_le(
&C::b().to_bytes(),
NUMBER_OF_LIMBS,
integer_chip.rns.bit_len_limb
);
let (a, b) = {
let mut a: Option<AssignedInteger<F>> = None;
let mut b: Option<AssignedInteger<F>> = None;
layouter.assign_region(
|| "region 0",
|mut region| {
let offset = &mut 0;
a = Some (integer_chip.assign_integer(&mut region, Some(ca.clone()), offset)?);
b = Some (integer_chip.assign_integer(&mut region, Some(cb.clone()), offset)?);
Ok(())
},
)?;
(a.unwrap(), b.unwrap())
};
Ok(EccChip {config, integer_chip, a, b})
}
}
impl<C: CurveAffine, F:FieldExt> EccChip<C, F> {
fn integer_gate(&self) -> MainGate<F> {
let main_gate_config = self.config.integer_gate_config.clone();
MainGate::<F>::new(main_gate_config)
}
}
#[cfg(test)]
mod tests {
use halo2::arithmetic::{CurveAffine, FieldExt, Field};
use super::{IntegerChip, IntegerConfig, IntegerInstructions};
use crate::circuit::AssignedValue;
use crate::circuit::main_gate::{MainGate, MainGateConfig, MainGateInstructions};
use crate::circuit::range::{RangeChip, RangeInstructions, RangeConfig};
use crate::circuit::ecc::{Point, EccChip, EccInstruction, EccConfig};
use crate::rns::{Integer, Limb, Rns};
use halo2::circuit::{Layouter, SimpleFloorPlanner};
use halo2::dev::MockProver;
use halo2::plonk::{Circuit, ConstraintSystem, Error};
use group::{Curve, prime::PrimeCurveAffine};
use crate::NUMBER_OF_LIMBS;
#[derive(Clone, Debug)]
struct TestCircuitConfig {
integer_gate_config: MainGateConfig,
integer_chip_config: IntegerConfig,
ecc_chip_config: EccConfig,
range_config: RangeConfig,
}
impl TestCircuitConfig {
fn overflow_bit_lengths() -> Vec<usize> {
vec![2, 3]
}
}
#[derive(Default, Clone, Debug)]
struct TestEcc<C: CurveAffine, N: FieldExt> {
x: Point<C, N>,
y: Point<C, N>,
z: Point<C, N>,
rns: Rns<C::Base, N>,
}
impl<C: CurveAffine, N: FieldExt> Circuit<N> for TestEcc<C, N> {
type Config = TestCircuitConfig;
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
Self::default()
}
fn configure(meta: &mut ConstraintSystem<N>) -> Self::Config {
let integer_gate_config = MainGate::<N>::configure(meta);
let overflow_bit_lengths = TestCircuitConfig::overflow_bit_lengths();
let range_config = RangeChip::<N>::configure(meta, &integer_gate_config, overflow_bit_lengths);
let integer_chip_config = IntegerChip::<C::Base, N>::configure(meta, &range_config, &integer_gate_config);
let ecc_chip_config = EccConfig {
integer_gate_config: integer_gate_config.clone(),
integer_chip_config: integer_chip_config.clone()
};
TestCircuitConfig {
range_config,
integer_chip_config,
integer_gate_config,
ecc_chip_config,
}
}
fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<N>) -> Result<(), Error> {
let integer_chip = IntegerChip::<C::Base, N>::new(config.integer_chip_config.clone(), self.rns.clone());
let ecc_chip = EccChip::<C, N>::new(&mut layouter, config.ecc_chip_config, integer_chip)?;
let offset = &mut 0;
layouter.assign_region(
|| "region 0",
|mut region| {
let px = ecc_chip.assign_point(&mut region, self.x.clone(), offset)?;
let py = ecc_chip.assign_point(&mut region, self.y.clone(), offset)?;
let pz = ecc_chip.assign_point(&mut region, self.z.clone(), offset)?;
let r = ecc_chip.add(&mut region, &px, &py, offset)?;
ecc_chip.assert_equal(&mut region, &r, &pz, offset)?;
Ok(())
},
)?;
let range_chip = RangeChip::<N>::new(config.range_config, self.rns.bit_len_lookup);
#[cfg(not(feature = "no_lookup"))]
range_chip.load_limb_range_table(&mut layouter)?;
#[cfg(not(feature = "no_lookup"))]
range_chip.load_overflow_range_tables(&mut layouter)?;
Ok(())
}
}
#[test]
fn test_ecc_add_circuit() {
use halo2::pasta::EpAffine as C;
use halo2::pasta::Fq as Native;
let bit_len_limb = 64;
let rns_base = Rns::<<C as CurveAffine>::Base, Native>::construct(bit_len_limb);
let rns_scalar = Rns::<<C as CurveAffine>::ScalarExt, Native>::construct(bit_len_limb);
#[cfg(not(feature = "no_lookup"))]
let k: u32 = (rns_base.bit_len_lookup + 1) as u32;
#[cfg(feature = "no_lookup")]
let k: u32 = 8;
let sk = <C as CurveAffine>::ScalarExt::rand();
let generator = <C as PrimeCurveAffine> :: generator();
let pk = generator * sk;
let pbase = //<C as PrimeCurveAffine> :: generator()
pk
.to_affine()
.coordinates()
.unwrap();
let x = {
let x = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.x().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
let y = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.y().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
Point::new(x, y)
};
let y = {
let x = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.x().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
let y = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.y().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
Point::new(x, y)
};
let z = {
let x = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.x().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
let y = Integer::<<C as CurveAffine>::ScalarExt>::from_bytes_le(
&pbase.y().to_bytes(), NUMBER_OF_LIMBS, bit_len_limb);
Point::new(x, y)
};
let circuit = TestEcc::<C, Native> {
x: x,
y: y,
z: z,
rns: rns_base.clone(),
};
let prover = match MockProver::run(k, &circuit, vec![]) {
Ok(prover) => prover,
Err(e) => panic!("{:#?}", e),
};
assert_eq!(prover.verify(), Ok(()));
}
}

136
src/circuit/ecc/add.rs Normal file
View File

@@ -0,0 +1,136 @@
use super::EccChip;
use super::{AssignedPoint};
use super::super::integer::{IntegerConfig, IntegerChip, IntegerInstructions};
use crate::circuit::main_gate::{MainGateConfig, MainGateInstructions};
use crate::circuit::{AssignedInteger, AssignedLimb, AssignedCondition};
use halo2::arithmetic::{CurveAffine, FieldExt};
use halo2::circuit::Region;
use halo2::plonk::Error;
impl<C: CurveAffine, F: FieldExt> EccChip<C, F> {
fn curvature(
&self,
region: &mut Region<'_, F>,
a: &AssignedPoint<C,F>,
offset: &mut usize
) -> Result <AssignedInteger<F>, Error> {
// (3 * a.x^2 + self.a) / 2 * a.y
let cst3 = {
let rns3 = self.integer_chip.rns.new_from_big(3u32.into());
&self.integer_chip.assign_integer(region, Some(rns3), offset)?
};
let cst2 = {
let rns2 = self.integer_chip.rns.new_from_big(2u32.into());
&self.integer_chip.assign_integer(region, Some(rns2), offset)?
};
let xsqm = {
let xsq = self.integer_chip.mul(region, &a.x, &a.x, offset)?;
self.integer_chip.mul(region, &xsq, cst3, offset)?
};
let curvature = {
let numerator = self.integer_chip.add(region, &xsqm, &self.a, offset)?;
let denominator = self.integer_chip.mul(region, &a.y, cst2, offset)?;
let (lambda, _) = self.integer_chip.div(region,
&numerator,
&denominator,
offset
)?;
lambda
};
Ok(curvature)
}
fn lambda(
&self,
region: &mut Region<'_, F>,
a: &AssignedPoint<C,F>,
b: &AssignedPoint<C,F>,
offset: &mut usize
) -> Result<(AssignedInteger<F>, AssignedCondition<F>), Error> {
let integer_gate = self.integer_gate();
let numerator = self.integer_chip.sub(region, &a.y, &b.y, offset)?;
let (_, eqy_cond) = self.integer_chip.invert(region, &numerator, offset)?;
let (lambda_neq, eqx_cond) = {
let denominator = self.integer_chip.sub(region, &a.x, &b.x, offset)?;
self.integer_chip.div(region, &numerator, &denominator, offset)?
};
// When eqx_cond == 1, we calculated the tangent curvature
let lambda_eq = self.curvature(region, a, offset)?;
let lambda = self.integer_chip.cond_select(region, &lambda_neq, &lambda_eq, &eqx_cond, offset)?;
// eqx_cond == 1 and eqy_cond == 0 means tangent is infinity
let not_eqy_cond = integer_gate.cond_not(region, &eqy_cond, offset)?;
let zero_cond = integer_gate.cond_and(region,
&not_eqy_cond,
&eqx_cond,
offset,
)?;
Ok((lambda, zero_cond))
}
/* We use affine coordinates since invert cost almost the same as mul in
* halo circuts gates while projective coordinates involves more multiplication
* than affine coordinates.
* Thus coordinate z in point is used as an indicator of whether the point is
* identity(infinity) or not.
*/
pub(crate) fn _add(
&self,
region: &mut Region<'_, F>,
a: &AssignedPoint<C,F>,
b: &AssignedPoint<C,F>,
offset: &mut usize
) -> Result<AssignedPoint<C,F>, Error> {
let integer_gate = self.integer_gate();
let (lambda, zero_cond) = self.lambda(region, a, b, offset)?;
let lambda_square = self.integer_chip._square(region, &lambda, offset)?;
// cx = λ^2 - a.x - b.x
let sqsub = self.integer_chip._sub(region, &lambda_square, &a.x, offset)?;
let cx = self.integer_chip._sub(
region,
&sqsub,
&b.x,
offset
)?;
// cy = λ(a.x - c.x) - a.y
let xsub = self.integer_chip._sub(region, &a.x, &cx, offset)?;
let yi = self.integer_chip._mul(
region,
&lambda,
&xsub,
offset,
)?;
let cy = self.integer_chip._sub(region, &yi, &a.y, offset)?;
let cx_sel = self.integer_chip.cond_select(region,
&b.x,
&cx,
&a.is_identity(),
offset
)?;
let p = AssignedPoint::new(cx, cy, zero_cond);
/* Now combine the calculation using the following cond table
* a.is_identity() -> b
* b.is_identity() -> a
* zero_cond -> self.identity()
* otherwise -> p
*/
let id_sel = integer_gate.cond_or(
region,
&a.is_identity(),
&b.is_identity(),
offset
)?;
Ok(p)
}
}

View File

@@ -1,60 +1,63 @@
use crate::circuit::AssignedInteger;
use halo2::arithmetic::CurveAffine;
use halo2::arithmetic::{FieldExt, CurveAffine};
use halo2::circuit::Region;
use halo2::plonk::Error;
use super::{AssignedPoint, EccChip, Point};
pub trait ExternalEccInstruction<Native: CurveAffine, External: CurveAffine> {
fn assign_point(&self, region: &mut Region<'_, Native::ScalarExt>, point: Point<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error>;
pub trait ExternalEccInstruction<External: CurveAffine, Native: FieldExt> {
fn assign_point(&self, region: &mut Region<'_, Native>, point: Point<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error>;
fn assert_is_on_curve(&self, region: &mut Region<'_, Native::ScalarExt>, point: AssignedPoint<External>, offset: &mut usize) -> Result<(), Error>;
fn assert_is_on_curve(&self, region: &mut Region<'_, Native>, point: AssignedPoint<External>, offset: &mut usize) -> Result<(), Error>;
fn assert_equal(
&self,
region: &mut Region<'_, Native::ScalarExt>,
p0: AssignedPoint<External>,
p1: AssignedPoint<External>,
region: &mut Region<'_, Native>,
p0: AssignedPoint<External, Native>,
p1: AssignedPoint<External, Native>,
offset: &mut usize,
) -> Result<(), Error>;
fn add(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p0: AssignedPoint<External>,
p1: AssignedPoint<External>,
offset: &mut usize,
) -> Result<AssignedPoint<External>, Error>;
fn double(&self, region: &mut Region<'_, Native::ScalarExt>, p: AssignedPoint<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error>;
fn double(&self, region: &mut Region<'_, Native>, p: AssignedPoint<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error>;
fn mul_var(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p: AssignedPoint<External>,
e: AssignedInteger<External::ScalarExt>,
offset: &mut usize,
) -> Result<AssignedPoint<External>, Error>;
fn mul_fix(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p: Point<External>,
e: AssignedInteger<External::ScalarExt>,
offset: &mut usize,
) -> Result<AssignedPoint<External>, Error>;
}
impl<Native: CurveAffine, External: CurveAffine> ExternalEccInstruction<Native, External> for EccChip {
fn assign_point(&self, region: &mut Region<'_, Native::ScalarExt>, point: Point<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error> {
unimplemented!();
impl<External: CurveAffine, Native: FieldExt> ExternalEccInstruction<External, Native> for EccChip {
fn assign_point(&self, region: &mut Region<'_, Native>, point: Point<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error> {
let x = self.integer_chip.assign_integer(region, Some(point.x.clone()), offset)?.clone();
let y = self.integer_chip.assign_integer(region, Some(point.y.clone()), offset)?.clone();
let z = self.integer_gate().assign_bit(region, Some(F::zero()), offset)?.clone();
Ok(AssignedPoint::new(x,y,z))
}
fn assert_is_on_curve(&self, region: &mut Region<'_, Native::ScalarExt>, point: AssignedPoint<External>, offset: &mut usize) -> Result<(), Error> {
fn assert_is_on_curve(&self, region: &mut Region<'_, Native>, point: AssignedPoint<External>, offset: &mut usize) -> Result<(), Error> {
unimplemented!();
}
fn assert_equal(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p0: AssignedPoint<External>,
p1: AssignedPoint<External>,
offset: &mut usize,
@@ -64,7 +67,7 @@ impl<Native: CurveAffine, External: CurveAffine> ExternalEccInstruction<Native,
fn add(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p0: AssignedPoint<External>,
p1: AssignedPoint<External>,
offset: &mut usize,
@@ -72,13 +75,13 @@ impl<Native: CurveAffine, External: CurveAffine> ExternalEccInstruction<Native,
unimplemented!();
}
fn double(&self, region: &mut Region<'_, Native::ScalarExt>, p: AssignedPoint<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error> {
fn double(&self, region: &mut Region<'_, Native>, p: AssignedPoint<External>, offset: &mut usize) -> Result<AssignedPoint<External>, Error> {
unimplemented!();
}
fn mul_var(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p: AssignedPoint<External>,
e: AssignedInteger<External::ScalarExt>,
offset: &mut usize,
@@ -88,7 +91,7 @@ impl<Native: CurveAffine, External: CurveAffine> ExternalEccInstruction<Native,
fn mul_fix(
&self,
region: &mut Region<'_, Native::ScalarExt>,
region: &mut Region<'_, Native>,
p: Point<External>,
e: AssignedInteger<External::ScalarExt>,
offset: &mut usize,
@@ -96,3 +99,5 @@ impl<Native: CurveAffine, External: CurveAffine> ExternalEccInstruction<Native,
unimplemented!();
}
}

View File

@@ -29,10 +29,10 @@ pub struct IntegerConfig {
pub struct IntegerChip<Wrong: FieldExt, Native: FieldExt> {
config: IntegerConfig,
rns: Rns<Wrong, Native>,
pub rns: Rns<Wrong, Native>,
}
trait IntegerInstructions<N: FieldExt> {
pub trait IntegerInstructions<N: FieldExt> {
fn assign_integer(&self, region: &mut Region<'_, N>, integer: Option<Integer<N>>, offset: &mut usize) -> Result<AssignedInteger<N>, Error>;
fn range_assign_integer(
&self,

View File

@@ -111,6 +111,29 @@ pub trait MainGateInstructions<F: FieldExt> {
fn one_or_one(&self, region: &mut Region<'_, F>, a: impl Assigned<F>, b: impl Assigned<F>, offset: &mut usize) -> Result<(), Error>;
fn cond_or(
&self,
region: &mut Region<'_, F>,
c1: &AssignedCondition<F>,
c2: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error>;
fn cond_and(
&self,
region: &mut Region<'_, F>,
c1: &AssignedCondition<F>,
c2: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error>;
fn cond_not(
&self,
region: &mut Region<'_, F>,
c: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error>;
fn cond_select(
&self,
region: &mut Region<'_, F>,
@@ -522,6 +545,38 @@ impl<F: FieldExt> MainGateInstructions<F> for MainGate<F> {
Ok(is_zero)
}
fn cond_or(
&self,
region: &mut Region<'_, F>,
c1: &AssignedCondition<F>,
c2: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error> {
unimplemented!();
}
fn cond_and(
&self,
region: &mut Region<'_, F>,
c1: &AssignedCondition<F>,
c2: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error> {
unimplemented!();
}
fn cond_not(
&self,
region: &mut Region<'_, F>,
c: &AssignedCondition<F>,
offset: &mut usize,
) -> Result<AssignedCondition<F>, Error> {
unimplemented!();
}
fn cond_select(
&self,
region: &mut Region<'_, F>,

View File

@@ -490,6 +490,12 @@ impl<F: FieldExt> Integer<F> {
Self { limbs }
}
pub fn from_bytes_le(e: &[u8], number_of_limbs: usize, bit_len: usize) -> Self {
let x = num_bigint::BigUint::from_bytes_le(e);
Self::from_big(x, number_of_limbs, bit_len)
}
pub fn limbs(&self) -> Vec<F> {
self.limbs.iter().map(|limb| limb.fe()).collect()
}