diff --git a/plonky2/src/curve/curve_types.rs b/plonky2/src/curve/curve_types.rs index b7ee34e6..9599f6fe 100644 --- a/plonky2/src/curve/curve_types.rs +++ b/plonky2/src/curve/curve_types.rs @@ -259,3 +259,11 @@ impl Neg for ProjectivePoint { ProjectivePoint { x, y: -y, z } } } + +pub fn base_to_scalar(x: C::BaseField) -> C::ScalarField { + C::ScalarField::from_biguint(x.to_biguint()) +} + +pub fn scalar_to_base(x: C::ScalarField) -> C::BaseField { + C::BaseField::from_biguint(x.to_biguint()) +} diff --git a/plonky2/src/curve/ecdsa.rs b/plonky2/src/curve/ecdsa.rs index cce83d4c..f708a827 100644 --- a/plonky2/src/curve/ecdsa.rs +++ b/plonky2/src/curve/ecdsa.rs @@ -1,7 +1,7 @@ use itertools::{unfold, Itertools}; use num::BigUint; -use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar}; +use crate::curve::curve_types::{base_to_scalar, AffinePoint, Curve, CurveScalar}; use crate::field::field_types::Field; use crate::hash::hash_types::RichField; use crate::hash::hashing::{hash_n_to_m, PlonkyPermutation}; @@ -15,14 +15,6 @@ pub struct ECDSASignature { pub struct ECDSASecretKey(pub C::ScalarField); pub struct ECDSAPublicKey(pub AffinePoint); -pub fn base_to_scalar(x: C::BaseField) -> C::ScalarField { - C::ScalarField::from_biguint(x.to_biguint()) -} - -pub fn scalar_to_base(x: C::ScalarField) -> C::BaseField { - C::BaseField::from_biguint(x.to_biguint()) -} - pub fn hash_to_bits>(x: F, num_bits: usize) -> Vec { let hashed = hash_n_to_m::(&vec![x], 1, true)[0]; diff --git a/plonky2/src/gadgets/arithmetic_u32.rs b/plonky2/src/gadgets/arithmetic_u32.rs index 8da01dc1..f57c1db5 100644 --- a/plonky2/src/gadgets/arithmetic_u32.rs +++ b/plonky2/src/gadgets/arithmetic_u32.rs @@ -196,24 +196,6 @@ impl, const D: usize> CircuitBuilder { (output_result, output_borrow) } - - pub fn split_to_u32(&mut self, x: Target) -> (U32Target, U32Target) { - let low = self.add_virtual_u32_target(); - let high = self.add_virtual_u32_target(); - - let base = self.constant(F::from_canonical_u64(1u64 << 32)); - let combined = self.mul_add(high.0, base, low.0); - self.connect(x, combined); - - self.add_simple_generator(SplitToU32Generator:: { - x: x.clone(), - low: low.clone(), - high: high.clone(), - _phantom: PhantomData, - }); - - (low, high) - } } #[derive(Debug)] @@ -235,7 +217,7 @@ impl, const D: usize> SimpleGenerator let x = witness.get_target(self.x.clone()); let x_u64 = x.to_canonical_u64(); let low = x_u64 as u32; - let high: u32 = (x_u64 >> 32).try_into().unwrap(); + let high = (x_u64 >> 32) as u32; out_buffer.set_u32_target(self.low.clone(), low); out_buffer.set_u32_target(self.high.clone(), high); diff --git a/plonky2/src/gadgets/biguint.rs b/plonky2/src/gadgets/biguint.rs index 51cfcc06..15c2a630 100644 --- a/plonky2/src/gadgets/biguint.rs +++ b/plonky2/src/gadgets/biguint.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use num::{BigUint, FromPrimitive, Integer, Zero}; +use num::{BigUint, Integer, Zero}; use plonky2_field::extension_field::Extendable; use crate::gadgets::arithmetic_u32::U32Target; @@ -27,14 +27,7 @@ impl BigUintTarget { impl, const D: usize> CircuitBuilder { pub fn constant_biguint(&mut self, value: &BigUint) -> BigUintTarget { - let base = BigUint::from_u64(1 << 32).unwrap(); - let mut limb_values = Vec::new(); - let mut current = value.clone(); - while current > BigUint::zero() { - let (div, rem) = current.div_rem(&base); - current = div; - limb_values.push(rem.to_u64_digits()[0] as u32); - } + let limb_values = value.to_u32_digits(); let limbs = limb_values.iter().map(|&l| self.constant_u32(l)).collect(); BigUintTarget { limbs } @@ -167,11 +160,10 @@ impl, const D: usize> CircuitBuilder { let t = b.target; BigUintTarget { - limbs: a - .limbs - .iter() - .map(|l| U32Target(self.mul(l.0, t))) - .collect(), + limbs: a.limbs + .iter() + .map(|&l| U32Target(self.mul(l.0, t))) + .collect(), } } diff --git a/plonky2/src/gadgets/curve.rs b/plonky2/src/gadgets/curve.rs index 92f45242..d16aaefa 100644 --- a/plonky2/src/gadgets/curve.rs +++ b/plonky2/src/gadgets/curve.rs @@ -135,7 +135,7 @@ impl, const D: usize> CircuitBuilder { for &bit in bits.iter() { let not_bit = self.not(bit); - + let result_plus_2_i_p = self.curve_add(&result, &two_i_times_p); let new_x_if_bit = self.mul_nonnative_by_bool(&result_plus_2_i_p.x, bit); @@ -321,6 +321,7 @@ mod tests { builder.connect_affine_point(&neg_five_g_expected, &neg_five_g_actual); + println!("NUM GATES: {}", builder.num_gates()); let data = builder.build::(); let proof = data.prove(pw).unwrap(); diff --git a/plonky2/src/gadgets/nonnative.rs b/plonky2/src/gadgets/nonnative.rs index 998ce628..b513abbb 100644 --- a/plonky2/src/gadgets/nonnative.rs +++ b/plonky2/src/gadgets/nonnative.rs @@ -93,17 +93,8 @@ impl, const D: usize> CircuitBuilder { a: &NonNativeTarget, b: BoolTarget, ) -> NonNativeTarget { - let t = b.target; - NonNativeTarget { - value: BigUintTarget { - limbs: a - .value - .limbs - .iter() - .map(|l| U32Target(self.mul(l.0, t))) - .collect(), - }, + value: self.mul_biguint_by_bool(&a.value, b), _phantom: PhantomData, } } diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index 93f7277c..def09473 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -138,7 +138,7 @@ impl, const D: usize> Gate for ArithmeticExte ); g }) - .collect::>() + .collect() } fn num_wires(&self) -> usize { diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index bef21a97..dc03e296 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -425,10 +425,7 @@ mod tests { v1.append(&mut output_limbs_f); } - v0.iter() - .chain(v1.iter()) - .map(|&x| x.into()) - .collect::>() + v0.iter().chain(v1.iter()).map(|&x| x.into()).collect() } let mut rng = rand::thread_rng(); diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 9a119b1d..424ecb5b 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -658,7 +658,7 @@ mod tests { v.append(&mut intermediate_values); v.append(&mut msd_bits); - v.iter().map(|&x| x.into()).collect::>() + v.iter().map(|&x| x.into()).collect() }; let mut rng = rand::thread_rng(); diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 9d3d6e3f..46c42113 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -343,7 +343,7 @@ mod tests { for i in 0..coeffs.len() { v.extend(coeffs.coeffs[i].0); } - v.iter().map(|&x| x.into()).collect::>() + v.iter().map(|&x| x.into()).collect() } // Get a working row for InterpolationGate. diff --git a/plonky2/src/gates/mul_biguint_bool.rs b/plonky2/src/gates/mul_biguint_bool.rs deleted file mode 100644 index 2fca84e1..00000000 --- a/plonky2/src/gates/mul_biguint_bool.rs +++ /dev/null @@ -1,241 +0,0 @@ -use std::marker::PhantomData; - -use plonky2_field::extension_field::Extendable; - -use crate::gates::gate::Gate; -use crate::gates::util::StridedConstraintConsumer; -use crate::hash::hash_types::RichField; -use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; -use crate::iop::target::Target; -use crate::iop::wire::Wire; -use crate::iop::witness::{PartitionWitness, Witness}; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; - -/// A gate to perform a basic mul-add on 32-bit values (we assume they are range-checked beforehand). -#[derive(Copy, Clone, Debug)] -pub struct MulBiguintBoolGate, const D: usize> { - pub num_limbs: usize, - _phantom: PhantomData, -} - -impl, const D: usize> MulBiguintBoolGate { - pub fn new(num_limbs: usize) -> Self { - Self { - num_limbs, - _phantom: PhantomData, - } - } - - pub fn wire_ith_input_limb(&self, i: usize) -> usize { - debug_assert!(i < self.num_limbs); - i - } - pub fn wire_input_bool(&self) -> usize { - self.num_limbs - } - pub fn wire_ith_output_limb(&self, i: usize) -> usize { - debug_assert!(i < self.num_limbs); - self.num_limbs + 1 + i - } -} - -impl, const D: usize> Gate for MulBiguintBoolGate { - fn id(&self) -> String { - format!("{:?}", self) - } - - fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let mut constraints = Vec::with_capacity(self.num_constraints()); - - let input_bool = vars.local_wires[self.wire_input_bool()]; - for i in 0..self.num_limbs { - let input_i = vars.local_wires[self.wire_ith_input_limb(i)]; - let output_i = vars.local_wires[self.wire_ith_output_limb(i)]; - - constraints.push(input_i * input_bool - output_i); - } - - constraints - } - - fn eval_unfiltered_base_one( - &self, - vars: EvaluationVarsBase, - mut yield_constr: StridedConstraintConsumer, - ) { - let input_bool = vars.local_wires[self.wire_input_bool()]; - for i in 0..self.num_limbs { - let input_i = vars.local_wires[self.wire_ith_input_limb(i)]; - let output_i = vars.local_wires[self.wire_ith_output_limb(i)]; - - yield_constr.one(input_i * input_bool - output_i); - } - } - - fn eval_unfiltered_recursively( - &self, - builder: &mut CircuitBuilder, - vars: EvaluationTargets, - ) -> Vec> { - let mut constraints = Vec::with_capacity(self.num_constraints()); - - let input_bool = vars.local_wires[self.wire_input_bool()]; - for i in 0..self.num_limbs { - let input_i = vars.local_wires[self.wire_ith_input_limb(i)]; - let output_i = vars.local_wires[self.wire_ith_output_limb(i)]; - - constraints.push(builder.mul_sub_extension(input_i, input_bool, output_i)); - } - - constraints - } - - fn generators( - &self, - gate_index: usize, - _local_constants: &[F], - ) -> Vec>> { - let gen = MulBiguintBoolGenerator { - gate: *self, - gate_index, - _phantom: PhantomData, - }; - vec![Box::new(gen.adapter())] - } - - fn num_wires(&self) -> usize { - self.num_limbs * 2 + 1 - } - - fn num_constants(&self) -> usize { - 0 - } - - fn degree(&self) -> usize { - 2 - } - - fn num_constraints(&self) -> usize { - self.num_limbs - } -} - -#[derive(Clone, Debug)] -struct MulBiguintBoolGenerator, const D: usize> { - gate: MulBiguintBoolGate, - gate_index: usize, - _phantom: PhantomData, -} - -impl, const D: usize> SimpleGenerator - for MulBiguintBoolGenerator -{ - fn dependencies(&self) -> Vec { - let local_target = |input| Target::wire(self.gate_index, input); - - (0..self.gate.num_limbs) - .map(|i| local_target(self.gate.wire_ith_input_limb(i))) - .chain([local_target(self.gate.wire_input_bool())]) - .collect() - } - - fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let local_wire = |input| Wire { - gate: self.gate_index, - input, - }; - - let get_local_wire = |input| witness.get_wire(local_wire(input)); - - let input_bool = get_local_wire(self.gate.wire_input_bool()); - for i in 0..self.gate.num_limbs { - let input_limb = get_local_wire(self.gate.wire_ith_input_limb(i)); - let output_wire = local_wire(self.gate.wire_ith_output_limb(i)); - let output_limb = input_limb * input_bool; - out_buffer.set_wire(output_wire, output_limb); - } - } -} - -#[cfg(test)] -mod tests { - use std::marker::PhantomData; - - use anyhow::Result; - use plonky2_field::field_types::Field; - use plonky2_field::goldilocks_field::GoldilocksField; - use rand::Rng; - - use crate::gates::gate::Gate; - use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; - use crate::gates::mul_biguint_bool::MulBiguintBoolGate; - use crate::hash::hash_types::HashOut; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::vars::EvaluationVars; - - #[test] - fn low_degree() { - test_low_degree::(MulBiguintBoolGate:: { - num_limbs: 8, - _phantom: PhantomData, - }) - } - - #[test] - fn eval_fns() -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - test_eval_fns::(MulBiguintBoolGate:: { - num_limbs: 8, - _phantom: PhantomData, - }) - } - - #[test] - fn test_gate_constraint() { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - type FF = >::FE; - const NUM_LIMBS: usize = 8; - - fn get_wires(input_limbs: Vec, input_bool: bool) -> Vec { - let output_limbs = input_limbs - .iter() - .map(|&l| if input_bool { l } else { F::ZERO }); - - input_limbs - .iter() - .cloned() - .chain([F::from_bool(input_bool)]) - .chain(output_limbs) - .map(|x| x.into()) - .collect() - } - - let mut rng = rand::thread_rng(); - let input_limbs: Vec<_> = (0..NUM_LIMBS) - .map(|_| F::from_canonical_u64(rng.gen())) - .collect(); - let input_bool: bool = rng.gen(); - - let gate = MulBiguintBoolGate:: { - num_limbs: NUM_LIMBS, - _phantom: PhantomData, - }; - - let vars = EvaluationVars { - local_constants: &[], - local_wires: &get_wires(input_limbs, input_bool), - public_inputs_hash: &HashOut::rand(), - }; - - assert!( - gate.eval_unfiltered(vars).iter().all(|x| x.is_zero()), - "Gate constraints are not satisfied." - ); - } -} diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index c5271a60..583f9a6e 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -432,7 +432,7 @@ mod tests { v.push(F::from_bool(switch)); } - v.iter().map(|&x| x.into()).collect::>() + v.iter().map(|&x| x.into()).collect() } let first_inputs: Vec> = (0..num_copies).map(|_| F::rand_vec(CHUNK_SIZE)).collect();