mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-11 18:23:09 +00:00
Fixed base works
This commit is contained in:
parent
ba5b1f7278
commit
6f3ca6a0bc
@ -1,7 +1,8 @@
|
||||
use itertools::Itertools;
|
||||
use num::BigUint;
|
||||
use plonky2_field::extension_field::Extendable;
|
||||
|
||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gadgets::curve::AffinePointTarget;
|
||||
use crate::gadgets::nonnative::NonNativeTarget;
|
||||
@ -70,18 +71,126 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// pub fn quad_curve_msm<C: Curve>(
|
||||
// &mut self,
|
||||
// points: [AffinePointTarget<C>; 4],
|
||||
// scalars: [NonNativeTarget<C::ScalarField>; 4],
|
||||
// ) -> AffinePointTarget<C> {
|
||||
// let limbs = scalars
|
||||
// .iter()
|
||||
// .map(|s| self.split_nonnative_to_bits(n))
|
||||
// .collect_vec();
|
||||
//
|
||||
// let hash_0 = KeccakHash::<32>::hash_no_pad(&[F::ZERO]);
|
||||
// let hash_0_scalar = C::ScalarField::from_biguint(BigUint::from_bytes_le(
|
||||
// &GenericHashOut::<F>::to_bytes(&hash_0),
|
||||
// ));
|
||||
// let rando = (CurveScalar(hash_0_scalar) * C::GENERATOR_PROJECTIVE).to_affine();
|
||||
// let rando_t = self.constant_affine_point(rando);
|
||||
// let neg_rando = self.constant_affine_point(-rando);
|
||||
//
|
||||
// let mut precomputation = vec![points[0].clone(); 16];
|
||||
// for i in 0..4 {
|
||||
// precomputation[1 << i] = points[i].clone();
|
||||
// for j in 1..1 << (i - 1) {}
|
||||
// }
|
||||
// let mut cur_p = rando_t.clone();
|
||||
// let mut cur_q = rando_t.clone();
|
||||
// for i in 0..4 {
|
||||
// precomputation[i] = cur_p.clone();
|
||||
// precomputation[4 * i] = cur_q.clone();
|
||||
// cur_p = self.curve_add(&cur_p, p);
|
||||
// cur_q = self.curve_add(&cur_q, q);
|
||||
// }
|
||||
// for i in 1..4 {
|
||||
// precomputation[i] = self.curve_add(&precomputation[i], &neg_rando);
|
||||
// precomputation[4 * i] = self.curve_add(&precomputation[4 * i], &neg_rando);
|
||||
// }
|
||||
// for i in 1..4 {
|
||||
// for j in 1..4 {
|
||||
// precomputation[i + 4 * j] =
|
||||
// self.curve_add(&precomputation[i], &precomputation[4 * j]);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let four = self.constant(F::from_canonical_usize(4));
|
||||
//
|
||||
// let zero = self.zero();
|
||||
// let mut result = rando_t;
|
||||
// for (limb_n, limb_m) in limbs_n.into_iter().zip(limbs_m).rev() {
|
||||
// result = self.curve_repeated_double(&result, 2);
|
||||
// let index = self.mul_add(four, limb_m, limb_n);
|
||||
// let r = self.random_access_curve_points(index, precomputation.clone());
|
||||
// let is_zero = self.is_equal(index, zero);
|
||||
// let should_add = self.not(is_zero);
|
||||
// result = self.curve_conditional_add(&result, &r, should_add);
|
||||
// }
|
||||
// let starting_point_multiplied =
|
||||
// (0..C::ScalarField::BITS).fold(rando, |acc, _| acc.double());
|
||||
// let to_add = self.constant_affine_point(-starting_point_multiplied);
|
||||
// result = self.curve_add(&result, &to_add);
|
||||
//
|
||||
// result
|
||||
// }
|
||||
|
||||
pub fn fixed_base_curve_mul<C: Curve>(
|
||||
&mut self,
|
||||
base: &AffinePoint<C>,
|
||||
scalar: &NonNativeTarget<C::ScalarField>,
|
||||
) -> AffinePointTarget<C> {
|
||||
let doubled_base = (0..scalar.value.limbs.len() * 8).scan(base.clone(), |acc, _| {
|
||||
let tmp = acc.clone();
|
||||
for _ in 0..4 {
|
||||
*acc = acc.double();
|
||||
}
|
||||
Some(tmp)
|
||||
});
|
||||
|
||||
let bits = self.split_nonnative_to_4_bit_limbs(scalar);
|
||||
|
||||
// let rando = (CurveScalar(C::ScalarField::rand()) * C::GENERATOR_PROJECTIVE).to_affine();
|
||||
let hash_0 = KeccakHash::<32>::hash_no_pad(&[F::ZERO]);
|
||||
let hash_0_scalar = C::ScalarField::from_biguint(BigUint::from_bytes_le(
|
||||
&GenericHashOut::<F>::to_bytes(&hash_0),
|
||||
));
|
||||
let rando = (CurveScalar(hash_0_scalar) * C::GENERATOR_PROJECTIVE).to_affine();
|
||||
let zero = self.zero();
|
||||
let mut result = self.constant_affine_point(rando.clone());
|
||||
for (limb, point) in bits.into_iter().zip(doubled_base) {
|
||||
let mul_point = (0..16)
|
||||
.scan(AffinePoint::ZERO, |acc, _| {
|
||||
let tmp = acc.clone();
|
||||
*acc = (point + *acc).to_affine();
|
||||
Some(tmp)
|
||||
})
|
||||
.map(|p| self.constant_affine_point(p))
|
||||
.collect::<Vec<_>>();
|
||||
let is_zero = self.is_equal(limb, zero);
|
||||
let should_add = self.not(is_zero);
|
||||
let r = self.random_access_curve_points(limb, mul_point);
|
||||
result = self.curve_conditional_add(&result, &r, should_add);
|
||||
}
|
||||
|
||||
let to_add = self.constant_affine_point(-rando);
|
||||
self.curve_add(&result, &to_add)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use num::BigUint;
|
||||
use plonky2_field::field_types::PrimeField;
|
||||
use plonky2_field::secp256k1_base::Secp256K1Base;
|
||||
use plonky2_field::secp256k1_scalar::Secp256K1Scalar;
|
||||
|
||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
||||
use crate::curve::secp256k1::Secp256K1;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::iop::witness::{PartialWitness, Witness};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
@ -168,4 +277,38 @@ mod tests {
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fixed_base() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let config = CircuitConfig::standard_ecc_config();
|
||||
|
||||
let mut pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let g = Secp256K1::GENERATOR_AFFINE;
|
||||
let n = Secp256K1Scalar::from_canonical_usize(10);
|
||||
let n = Secp256K1Scalar::rand();
|
||||
|
||||
let res = (CurveScalar(n) * g.to_projective()).to_affine();
|
||||
let res_expected = builder.constant_affine_point(res);
|
||||
builder.curve_assert_valid(&res_expected);
|
||||
|
||||
let n_target = builder.add_virtual_nonnative_target::<Secp256K1Scalar>();
|
||||
pw.set_biguint_target(&n_target.value, &n.to_canonical_biguint());
|
||||
|
||||
let res_target = builder.fixed_base_curve_mul(&g, &n_target);
|
||||
builder.curve_assert_valid(&res_target);
|
||||
|
||||
builder.connect_affine_point(&res_target, &res_expected);
|
||||
|
||||
dbg!(builder.num_gates());
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,12 +44,21 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
access_index: Target,
|
||||
v: Vec<AffinePointTarget<C>>,
|
||||
) -> AffinePointTarget<C> {
|
||||
let num_limbs = v[0].x.value.num_limbs();
|
||||
let num_limbs = C::BaseField::BITS / 32;
|
||||
let zero = self.zero_u32();
|
||||
let x_limbs: Vec<Vec<_>> = (0..num_limbs)
|
||||
.map(|i| v.iter().map(|p| p.x.value.limbs[i].0).collect())
|
||||
.map(|i| {
|
||||
v.iter()
|
||||
.map(|p| p.x.value.limbs.get(i).unwrap_or(&zero).0)
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let y_limbs: Vec<Vec<_>> = (0..num_limbs)
|
||||
.map(|i| v.iter().map(|p| p.y.value.limbs[i].0).collect())
|
||||
.map(|i| {
|
||||
v.iter()
|
||||
.map(|p| p.y.value.limbs.get(i).unwrap_or(&zero).0)
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let selected_x_limbs: Vec<_> = x_limbs
|
||||
|
||||
@ -19,6 +19,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.constant_nonnative(BETA)
|
||||
}
|
||||
|
||||
// TODO: Add decomposition check.
|
||||
pub fn decompose_secp256k1_scalar(
|
||||
&mut self,
|
||||
k: &NonNativeTarget<Secp256K1Scalar>,
|
||||
@ -59,12 +60,24 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
y: p.y.clone(),
|
||||
};
|
||||
|
||||
let part1 = self.curve_scalar_mul_windowed(p, &k1);
|
||||
let part1_neg = self.curve_conditional_neg(&part1, k1_neg);
|
||||
let part2 = self.curve_scalar_mul_windowed(&sp, &k2);
|
||||
let part2_neg = self.curve_conditional_neg(&part2, k2_neg);
|
||||
|
||||
self.curve_add(&part1_neg, &part2_neg)
|
||||
// let part1 = self.curve_scalar_mul_windowed(p, &k1);
|
||||
// let part1_neg = self.curve_conditional_neg(&part1, k1_neg);
|
||||
// let part2 = self.curve_scalar_mul_windowed(&sp, &k2);
|
||||
// let part2_neg = self.curve_conditional_neg(&part2, k2_neg);
|
||||
//
|
||||
// self.curve_add(&part1_neg, &part2_neg)
|
||||
// dbg!(k1.value.limbs.len());
|
||||
// dbg!(k2.value.limbs.len());
|
||||
let p_neg = self.curve_conditional_neg(&p, k1_neg);
|
||||
let sp_neg = self.curve_conditional_neg(&sp, k2_neg);
|
||||
// let yo = self.curve_scalar_mul_windowed(&p_neg, &k1);
|
||||
// let ya = self.curve_scalar_mul_windowed(&sp_neg, &k2);
|
||||
// dbg!(&yo);
|
||||
// dbg!(&ya);
|
||||
// self.connect_affine_point(&part1_neg, &yo);
|
||||
// self.connect_affine_point(&part2_neg, &ya);
|
||||
self.curve_msm(&p_neg, &sp_neg, &k1, &k2)
|
||||
// self.curve_add(&yo, &ya)
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +118,7 @@ mod tests {
|
||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||
use crate::curve::glv::glv_mul;
|
||||
use crate::curve::secp256k1::Secp256K1;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::iop::witness::{PartialWitness, Witness};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
@ -134,6 +147,43 @@ mod tests {
|
||||
let actual = builder.glv_mul(&randot, &scalar_target);
|
||||
builder.connect_affine_point(&expected, &actual);
|
||||
|
||||
dbg!(builder.num_gates());
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wtf() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let config = CircuitConfig::standard_ecc_config();
|
||||
|
||||
let mut pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let rando =
|
||||
(CurveScalar(Secp256K1Scalar::rand()) * Secp256K1::GENERATOR_PROJECTIVE).to_affine();
|
||||
let randot = builder.constant_affine_point(rando);
|
||||
|
||||
let scalar = Secp256K1Scalar::rand();
|
||||
let scalar_target = builder.constant_nonnative(scalar);
|
||||
|
||||
let tr = builder.add_virtual_bool_target();
|
||||
pw.set_bool_target(tr, false);
|
||||
|
||||
let randotneg = builder.curve_conditional_neg(&randot, tr);
|
||||
let y = builder.curve_scalar_mul_windowed(&randotneg, &scalar_target);
|
||||
|
||||
let yy = builder.curve_scalar_mul_windowed(&randot, &scalar_target);
|
||||
let yy = builder.curve_conditional_neg(&yy, tr);
|
||||
|
||||
builder.connect_affine_point(&y, &yy);
|
||||
|
||||
dbg!(builder.num_gates());
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
|
||||
marked_targets: Vec<MarkedTargets<D>>,
|
||||
|
||||
/// Generators used to generate the witness.
|
||||
generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
||||
pub generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
||||
|
||||
constants_to_targets: HashMap<F, Target>,
|
||||
targets_to_constants: HashMap<Target, F>,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user