This commit is contained in:
Nicholas Ward 2021-11-10 11:50:58 -08:00
parent a4b7772c34
commit dfad7708af
3 changed files with 48 additions and 13 deletions

View File

@ -160,9 +160,10 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
a: &BigUintTarget,
b: &BigUintTarget,
) -> (BigUintTarget, BigUintTarget) {
let num_limbs = a.limbs.len();
let div = self.add_virtual_biguint_target(num_limbs);
let rem = self.add_virtual_biguint_target(num_limbs);
let a_len = a.limbs.len();
let b_len = b.limbs.len();
let div = self.add_virtual_biguint_target(a_len - b_len + 1);
let rem = self.add_virtual_biguint_target(b_len);
self.add_simple_generator(BigUintDivRemGenerator::<F, D> {
a: a.clone(),

View File

@ -1,6 +1,6 @@
use crate::curve::curve_types::{AffinePoint, Curve};
use crate::field::extension_field::Extendable;
use crate::field::field_types::RichField;
use crate::field::field_types::{Field, RichField};
use crate::gadgets::nonnative::ForeignFieldTarget;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -60,7 +60,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
pub fn curve_double<C: Curve>(&mut self, p: &AffinePointTarget<C>) -> AffinePointTarget<C> {
pub fn curve_double<C: Curve>(
&mut self,
p: &AffinePointTarget<C>,
p_orig: AffinePoint<C>,
) -> AffinePointTarget<C> {
let AffinePointTarget { x, y } = p;
let double_y = self.add_nonnative(y, y);
let inv_double_y = self.inv_nonnative(&double_y);
@ -94,6 +98,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
mod tests {
use std::ops::Neg;
use anyhow::Result;
use crate::curve::curve_types::{AffinePoint, Curve};
@ -167,14 +173,19 @@ mod tests {
let mut builder = CircuitBuilder::<F, D>::new(config);
let g = Secp256K1::GENERATOR_AFFINE;
let neg_g = g.neg();
let g_target = builder.constant_affine_point(g);
let neg_g_target = builder.curve_neg(&g_target);
let double_g = builder.curve_double(&g_target);
let double_neg_g = builder.curve_double(&neg_g_target);
let double_g = g.double();
let double_g_other_target = builder.constant_affine_point(double_g);
builder.curve_assert_valid(&double_g_other_target);
builder.curve_assert_valid(&double_g);
builder.curve_assert_valid(&double_neg_g);
let double_g_target = builder.curve_double(&g_target, g);
let double_neg_g_target = builder.curve_double(&neg_g_target, neg_g);
builder.curve_assert_valid(&double_g_target);
builder.curve_assert_valid(&double_neg_g_target);
let data = builder.build();
let proof = data.prove(pw).unwrap();

View File

@ -81,6 +81,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
&mut self,
x: &NonNativeTarget<FF>,
) -> NonNativeTarget<FF> {
// TODO: zero - x would be more efficient but doesn't seem to work?
let neg_one = FF::order() - BigUint::one();
let neg_one_target = self.constant_biguint(&neg_one);
let neg_one_ff = self.biguint_to_nonnative(&neg_one_target);
@ -90,11 +91,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn inv_nonnative<FF: Field>(
&mut self,
x: &ForeignFieldTarget<FF>,
) -> ForeignFieldTarget<FF> {
x: &NonNativeTarget<FF>,
) -> NonNativeTarget<FF> {
let num_limbs = x.value.num_limbs();
let inv_biguint = self.add_virtual_biguint_target(num_limbs);
let inv = ForeignFieldTarget::<FF> {
let inv = NonNativeTarget::<FF> {
value: inv_biguint,
_phantom: PhantomData,
};
@ -107,7 +108,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let product = self.mul_nonnative(&x, &inv);
let one = self.constant_nonnative(FF::ONE);
self.connect_nonnative_reduced(&product, &one);
self.connect_nonnative(&product, &one);
inv
}
@ -264,4 +265,26 @@ mod tests {
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
#[test]
fn test_nonnative_inv() -> Result<()> {
type FF = Secp256K1Base;
let x_ff = FF::rand();
let inv_x_ff = x_ff.inverse();
type F = CrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, 4>::new(config);
let x = builder.constant_nonnative(x_ff);
let inv_x = builder.inv_nonnative(&x);
let inv_x_expected = builder.constant_nonnative(inv_x_ff);
builder.connect_nonnative(&inv_x, &inv_x_expected);
let data = builder.build();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
}