From 4d4605af1f31e80c9b933a7f75d09a5e11d84526 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 10 Nov 2021 11:50:25 -0800 Subject: [PATCH] merge --- src/gadgets/curve.rs | 32 ++++++++++++++++++++++++ src/gadgets/nonnative.rs | 54 ++++++++++++++++++++++++++++++++++++++-- src/iop/generator.rs | 5 ++++ src/iop/witness.rs | 6 +++++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/gadgets/curve.rs b/src/gadgets/curve.rs index 42bfd8a9..eeb966a5 100644 --- a/src/gadgets/curve.rs +++ b/src/gadgets/curve.rs @@ -59,6 +59,38 @@ impl, const D: usize> CircuitBuilder { y: neg_y, } } + + pub fn curve_double(&mut self, p: &AffinePointTarget) -> AffinePointTarget { + let AffinePointTarget { x, y } = p; + let double_y = self.add_nonnative(y, y); + let inv_double_y = self.inv_nonnative(&double_y); + let x_squared = self.mul_nonnative(x, x); + let double_x_squared = self.add_nonnative(&x_squared, &x_squared); + let triple_x_squared = self.add_nonnative(&double_x_squared, &x_squared); + + let a = self.constant_nonnative(C::A); + let triple_xx_a = self.add_nonnative(&triple_x_squared, &a); + let lambda = self.mul_nonnative(&triple_xx_a, &inv_double_y); + let lambda_squared = self.mul_nonnative(&lambda, &lambda); + let x_double = self.add_nonnative(x, x); + + let x3 = self.sub_nonnative(&lambda_squared, &x_double); + + let x_diff = self.sub_nonnative(x, &x3); + let lambda_x_diff = self.mul_nonnative(&lambda, &x_diff); + + let y3 = self.sub_nonnative(&lambda_x_diff, y); + + AffinePointTarget { x: x3, y: y3 } + } + + pub fn curve_add( + &mut self, + a: &AffinePointTarget, + b: &AffinePointTarget, + ) -> AffinePointTarget { + todo!() + } } mod tests { diff --git a/src/gadgets/nonnative.rs b/src/gadgets/nonnative.rs index bc090cd5..d6b20f14 100644 --- a/src/gadgets/nonnative.rs +++ b/src/gadgets/nonnative.rs @@ -5,6 +5,9 @@ use num::{BigUint, One}; use crate::field::field_types::RichField; use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gadgets::biguint::BigUintTarget; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::target::Target; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; pub struct NonNativeTarget { @@ -46,6 +49,7 @@ impl, const D: usize> CircuitBuilder { ) -> NonNativeTarget { let result = self.add_biguint(&a.value, &b.value); + // TODO: reduce add result with only one conditional subtraction self.reduce(&result) } @@ -84,8 +88,32 @@ impl, const D: usize> CircuitBuilder { self.mul_nonnative(&neg_one_ff, x) } - /// Returns `x % |FF|` as a `NonNativeTarget`. - fn reduce(&mut self, x: &BigUintTarget) -> NonNativeTarget { + pub fn inv_nonnative( + &mut self, + x: &ForeignFieldTarget, + ) -> ForeignFieldTarget { + let num_limbs = x.value.num_limbs(); + let inv_biguint = self.add_virtual_biguint_target(num_limbs); + let inv = ForeignFieldTarget:: { + value: inv_biguint, + _phantom: PhantomData, + }; + + self.add_simple_generator(NonNativeInverseGenerator:: { + x: x.clone(), + inv: inv.clone(), + _phantom: PhantomData, + }); + + let product = self.mul_nonnative(&x, &inv); + let one = self.constant_nonnative(FF::ONE); + self.connect_nonnative_reduced(&product, &one); + + inv + } + + /// Returns `x % |FF|` as a `ForeignFieldTarget`. + fn reduce(&mut self, x: &BigUintTarget) -> ForeignFieldTarget { let modulus = FF::order(); let order_target = self.constant_biguint(&modulus); let value = self.rem_biguint(x, &order_target); @@ -106,6 +134,28 @@ impl, const D: usize> CircuitBuilder { } } +#[derive(Debug)] +struct NonNativeInverseGenerator, const D: usize, FF: Field> { + x: ForeignFieldTarget, + inv: ForeignFieldTarget, + _phantom: PhantomData, +} + +impl, const D: usize, FF: Field> SimpleGenerator + for NonNativeInverseGenerator +{ + fn dependencies(&self) -> Vec { + self.x.value.limbs.iter().map(|&l| l.0).collect() + } + + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { + let x = witness.get_nonnative_target(self.x.clone()); + let inv = x.inverse(); + + out_buffer.set_nonnative_target(self.inv.clone(), inv); + } +} + #[cfg(test)] mod tests { use anyhow::Result; diff --git a/src/iop/generator.rs b/src/iop/generator.rs index ae973d7c..ff7f66e0 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -8,6 +8,7 @@ use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::{Field, RichField}; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; +use crate::gadgets::nonnative::ForeignFieldTarget; use crate::hash::hash_types::{HashOut, HashOutTarget}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -168,6 +169,10 @@ impl GeneratedValues { } } + pub fn set_nonnative_target(&mut self, target: ForeignFieldTarget, value: FF) { + self.set_biguint_target(target.value, value.to_biguint()) + } + pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { ht.elements .iter() diff --git a/src/iop/witness.rs b/src/iop/witness.rs index a773c1a9..d6f4fb59 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -6,6 +6,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gadgets::biguint::BigUintTarget; +use crate::gadgets::nonnative::ForeignFieldTarget; use crate::hash::hash_types::HashOutTarget; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; @@ -68,6 +69,11 @@ pub trait Witness { result } + fn get_nonnative_target(&self, target: ForeignFieldTarget) -> FF { + let val = self.get_biguint_target(target.value); + FF::from_biguint(val) + } + fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { HashOut { elements: self.get_targets(&ht.elements).try_into().unwrap(),