nonnative neg

This commit is contained in:
Nicholas Ward 2021-11-02 12:42:42 -07:00
parent e838096940
commit c861c10a5b
2 changed files with 36 additions and 11 deletions

View File

@ -30,7 +30,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let limb_values = value.to_u32_digits();
let limbs = limb_values
.iter()
.map(|l| self.constant(F::from_canonical_u32(l)))
.map(|&l| U32Target(self.constant(F::from_canonical_u32(l))))
.collect();
BigUintTarget { limbs }

View File

@ -1,8 +1,9 @@
use std::marker::PhantomData;
use num::{BigUint, One};
use crate::field::field_types::RichField;
use crate::field::{extension_field::Extendable, field_types::Field};
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gadgets::biguint::BigUintTarget;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -12,15 +13,6 @@ pub struct ForeignFieldTarget<FF: Field> {
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn order_u32_limbs<FF: Field>(&mut self) -> Vec<U32Target> {
let modulus = FF::order();
let limbs = modulus.to_u32_digits();
limbs
.iter()
.map(|&limb| self.constant_u32(F::from_canonical_u32(limb)))
.collect()
}
pub fn biguint_to_ff<FF: Field>(&mut self, x: &BigUintTarget) -> ForeignFieldTarget<FF> {
ForeignFieldTarget {
value: x.clone(),
@ -84,6 +76,17 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.reduce(&result)
}
pub fn neg_nonnative<FF: Field>(
&mut self,
x: &ForeignFieldTarget<FF>,
) -> ForeignFieldTarget<FF> {
let neg_one = FF::order() - BigUint::one();
let neg_one_target = self.constant_biguint(&neg_one);
let neg_one_ff = self.biguint_to_ff(&neg_one_target);
self.mul_nonnative(&neg_one_ff, x)
}
/// Returns `x % |FF|` as a `ForeignFieldTarget`.
fn reduce<FF: Field>(&mut self, x: &BigUintTarget) -> ForeignFieldTarget<FF> {
let modulus = FF::order();
@ -188,4 +191,26 @@ mod tests {
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
#[test]
fn test_nonnative_neg() -> Result<()> {
type FF = Secp256K1Base;
let x_ff = FF::rand();
let neg_x_ff = -x_ff;
type F = CrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, 4>::new(config);
let x = builder.constant_ff(x_ff);
let neg_x = builder.neg_nonnative(&x);
let neg_x_expected = builder.constant_ff(neg_x_ff);
builder.connect_ff_reduced(&neg_x, &neg_x_expected);
let data = builder.build();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
}