test for split nonnative, and fixes

This commit is contained in:
Nicholas Ward 2022-02-10 11:18:47 -08:00
parent 53a2a92258
commit 67b7193e82
2 changed files with 97 additions and 2 deletions

View File

@ -230,7 +230,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let windows = self.split_nonnative_to_4_bit_limbs(n);
let m = C::ScalarField::BITS / WINDOW_SIZE;
for i in m..0 {
for i in (0..m).rev() {
result = self.curve_double(&result);
let window = windows[i];
@ -411,6 +411,38 @@ mod tests {
verify(proof, &data.verifier_only, &data.common)
}
#[test]
fn test_curve_mul_windowed() -> Result<()> {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_ecc_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
let g = Secp256K1::GENERATOR_AFFINE;
let five = Secp256K1Scalar::from_canonical_usize(5);
let neg_five = five.neg();
let neg_five_scalar = CurveScalar::<Secp256K1>(neg_five);
let neg_five_g = (neg_five_scalar * g.to_projective()).to_affine();
let neg_five_g_expected = builder.constant_affine_point(neg_five_g);
builder.curve_assert_valid(&neg_five_g_expected);
let g_target = builder.constant_affine_point(g);
let neg_five_target = builder.constant_nonnative(neg_five);
let neg_five_g_actual = builder.curve_scalar_mul_windowed(&g_target, &neg_five_target);
/*builder.curve_assert_valid(&neg_five_g_actual);
builder.connect_affine_point(&neg_five_g_expected, &neg_five_g_actual);*/
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
#[test]
#[ignore]
fn test_curve_random() -> Result<()> {

View File

@ -1,8 +1,11 @@
use std::marker::PhantomData;
use itertools::Itertools;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gadgets::biguint::BigUintTarget;
use crate::gadgets::nonnative::NonNativeTarget;
use crate::hash::hash_types::RichField;
use crate::iop::target::Target;
@ -10,7 +13,7 @@ use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn split_u32_to_4_bit_limbs(&mut self, val: U32Target) -> Vec<Target> {
let two_bit_limbs = self.split_le_base::<2>(val.0, 16);
let two_bit_limbs = self.split_le_base::<4>(val.0, 16);
let four = self.constant(F::from_canonical_usize(4));
let combined_limbs = two_bit_limbs
.iter()
@ -31,4 +34,64 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.flat_map(|&l| self.split_u32_to_4_bit_limbs(l))
.collect()
}
// Note: assumes its inputs are 4-bit limbs, and does not range-check.
pub fn recombine_nonnative_4_bit_limbs<FF: Field>(
&mut self,
limbs: Vec<Target>,
) -> NonNativeTarget<FF> {
let base = self.constant_u32(1 << 4);
let u32_limbs = limbs
.chunks(8)
.map(|chunk| {
let mut combined_chunk = self.zero_u32();
for i in (0..8).rev() {
let (low, _high) = self.mul_add_u32(combined_chunk, base, U32Target(chunk[i]));
combined_chunk = low;
}
combined_chunk
})
.collect();
NonNativeTarget {
value: BigUintTarget { limbs: u32_limbs },
_phantom: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use plonky2_field::field_types::Field;
use plonky2_field::secp256k1_scalar::Secp256K1Scalar;
use crate::gadgets::nonnative::NonNativeTarget;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::verifier::verify;
#[test]
fn test_split_nonnative() -> Result<()> {
type FF = Secp256K1Scalar;
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_ecc_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
let x = FF::rand();
let x_target = builder.constant_nonnative(x);
let split = builder.split_nonnative_to_4_bit_limbs(&x_target);
let combined: NonNativeTarget<Secp256K1Scalar> = builder.recombine_nonnative_4_bit_limbs(split);
builder.connect_nonnative(&x_target, &combined);
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
}