diff --git a/src/gadgets/arithmetic_u32.rs b/src/gadgets/arithmetic_u32.rs index 213cdffe..489a9d5b 100644 --- a/src/gadgets/arithmetic_u32.rs +++ b/src/gadgets/arithmetic_u32.rs @@ -6,7 +6,7 @@ use crate::gates::arithmetic_u32::{U32ArithmeticGate, NUM_U32_ARITHMETIC_OPS}; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -pub struct U32Target(Target); +pub struct U32Target(pub Target); impl, const D: usize> CircuitBuilder { pub fn add_virtual_u32_target(&self) -> U32Target { diff --git a/src/gadgets/nonnative.rs b/src/gadgets/nonnative.rs index 6da8ab5e..cf232632 100644 --- a/src/gadgets/nonnative.rs +++ b/src/gadgets/nonnative.rs @@ -13,19 +13,23 @@ use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bimap::bimap_from_lists; - -pub struct NonNativeTarget { - /// The modulus of the field F' being represented. - modulus: BigUint, + +pub struct ForeignFieldTarget { /// These F elements are assumed to contain 32-bit values. limbs: Vec, + _phantom: PhantomData, } impl, const D: usize> CircuitBuilder { - pub fn add_nonnative(&mut self, a: NonNativeTarget, b: NonNativeTarget) -> NonNativeTarget { - let modulus = a.modulus; + pub fn order_u32_limbs(&self) -> Vec { + let modulus = FF::order(); + let limbs = modulus.to_u32_digits(); + limbs.iter().map(|&limb| self.constant_u32(F::from_canonical_u32(limb))).collect() + } + + // Add two `ForeignFieldTarget`s, which we assume are both normalized. + pub fn add_nonnative(&mut self, a: ForeignFieldTarget, b: ForeignFieldTarget) -> ForeignFieldTarget { let num_limbs = a.limbs.len(); - debug_assert!(b.modulus == modulus); debug_assert!(b.limbs.len() == num_limbs); let mut combined_limbs = self.add_virtual_u32_targets(num_limbs + 1); @@ -36,21 +40,21 @@ impl, const D: usize> CircuitBuilder { } combined_limbs[num_limbs] = carry; - let reduced_limbs = self.reduce_add_result(combined_limbs, modulus); - NonNativeTarget { - modulus, + let reduced_limbs = self.reduce_add_result::(combined_limbs); + ForeignFieldTarget { limbs: reduced_limbs, + _phantom: PhantomData, } } - pub fn reduce_add_result(&mut self, limbs: Vec, modulus: BigUint) -> Vec { + pub fn reduce_add_result(&mut self, limbs: Vec) -> Vec { + let modulus = FF::order(); + todo!() } - pub fn mul_nonnative(&mut self, a: NonNativeTarget, b: NonNativeTarget) -> NonNativeTarget { - let modulus = a.modulus; + pub fn mul_nonnative(&mut self, a: ForeignFieldTarget, b: ForeignFieldTarget) -> ForeignFieldTarget { let num_limbs = a.limbs.len(); - debug_assert!(b.modulus == modulus); debug_assert!(b.limbs.len() == num_limbs); let mut combined_limbs = self.add_virtual_targets(2 * num_limbs - 1); @@ -61,15 +65,15 @@ impl, const D: usize> CircuitBuilder { } } - let reduced_limbs = self.reduce_mul_result(combined_limbs, modulus); + let reduced_limbs = self.reduce_mul_result::(combined_limbs); - NonNativeTarget { - modulus, + ForeignFieldTarget { limbs: reduced_limbs, + _phantom: PhantomData, } } - pub fn reduce_mul_result(&mut self, limbs: Vec, modulus: BigUint) -> Vec { + pub fn reduce_mul_result(&mut self, limbs: Vec) -> Vec { todo!() } } diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 4879d144..019bc71e 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -13,6 +13,7 @@ use crate::field::field_types::{Field, RichField}; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::{FriConfig, FriParams}; use crate::gadgets::arithmetic_extension::ArithmeticOperation; +use crate::gadgets::arithmetic_u32::U32Target; use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::gates::constant::ConstantGate; use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate}; @@ -349,6 +350,11 @@ impl, const D: usize> CircuitBuilder { } } + /// Returns a U32Target for the value `c`, which is assumed to be at most 32 bits. + pub fn constant_u32(&mut self, c: F) -> U32Target { + U32Target(self.constant(c)) + } + /// If the given target is a constant (i.e. it was created by the `constant(F)` method), returns /// its constant value. Otherwise, returns `None`. pub fn target_as_constant(&self, target: Target) -> Option {