Skip to content

Commit

Permalink
some progress
Browse files Browse the repository at this point in the history
  • Loading branch information
levs57 committed Nov 23, 2023
1 parent 40bfdf9 commit a607a9e
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 48 deletions.
6 changes: 3 additions & 3 deletions benches/bench_ecmul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use criterion::{Criterion, criterion_main, criterion_group, black_box};
use ff::Field;
use group::{Group, Curve};
use halo2::halo2curves::{bn256, grumpkin, CurveExt};
use protostar_works::{circuit::{ExternalValue, Circuit}, gate::{Gatebb, Gate}, gadgets::{ecmul::{EcAffinePoint, escalarmul_gadget_9}, nonzero_check::nonzero_gadget, input::input}, utils::poly_utils::bits_le, commitment::CkRound, witness::CSSystemCommit};
use protostar_works::{circuit::{ExternalValue, Circuit}, gate::{Gatebb, Gate}, gadgets::{ecmul::{EcAffinePoint, escalarmul_gadget_9}, nonzero_check::{Nonzeros}, input::input}, utils::poly_utils::bits_le, commitment::CkRound, witness::CSSystemCommit};
use rand_core::OsRng;

type F = bn256::Fr;
Expand Down Expand Up @@ -68,11 +68,11 @@ pub fn assemble_ecmul_circuit<'a>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, p
let pt = EcAffinePoint::<F,C>::new(circuit, x, y);
let sc = input(circuit, pi_sc_ext, 0);

let mut nonzeros = vec![];
let mut nonzeros = Nonzeros::new(9);

escalarmul_gadget_9(circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros);

nonzero_gadget(circuit, &nonzeros, 9);
nonzeros.finalize(circuit);
}

pub fn ecmul_pseudo_fold(c: &mut Criterion) {
Expand Down
39 changes: 31 additions & 8 deletions src/gadgets/arith.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
use std::rc::Rc;
use ff::PrimeField;
use gate_macro::make_gate;
use itertools::Itertools;
use crate::{circuit::{Circuit, Advice}, utils::field_precomp::FieldUtils, gate::Gatebb, constraint_system::Variable};
use elsa::FrozenMap;

pub fn eq_gadget<'a, F: PrimeField+FieldUtils>(
circuit: &mut Circuit<'a,F,Gatebb<'a,F>>,
a: Variable,
b: Variable,
) -> () {
circuit.constrain(&vec![a,b], Gatebb::new(1, 2, 1, Rc::new(|args, _|vec![args[0]-args[1]]), vec![]));
}

#[make_gate]
pub fn arith_gate<'c, F: PrimeField>(smul: F, sa: F, sb: F, sconst: F)->Gatebb<'c, F>{
Expand All @@ -26,6 +20,14 @@ pub fn arith_gate<'c, F: PrimeField>(smul: F, sa: F, sb: F, sconst: F)->Gatebb<'
}), vec![smul, sa, sb, sconst])
}

#[make_gate]
pub fn read_const_gate<'c, F: PrimeField>(c: F)->Gatebb<'c, F>{
Gatebb::new(1, 1, 1, Rc::new(|args, consts|{
let a = args[0];
let c = consts[0];
vec![a-c]
}), vec![c])
}
pub fn arith_gadget<'a, F: PrimeField+FieldUtils>(
circuit: &mut Circuit<'a,F,Gatebb<'a,F>>,
a: Variable,
Expand Down Expand Up @@ -62,4 +64,25 @@ pub fn mul_gadget<'a, F: PrimeField+FieldUtils> (
round: usize,
) -> Variable {
arith_gadget(circuit, a, b, F::ONE, F::ZERO, F::ZERO, F::ZERO, round)
}
}

pub fn eq_gadget<'a, F: PrimeField+FieldUtils>(
circuit: &mut Circuit<'a,F,Gatebb<'a,F>>,
a: Variable,
b: Variable,
) -> () {
let dummy = a;
circuit.constrain_with(&vec![a, dummy, b], &arith_gate(F::ZERO, F::ONE, F::ZERO, F::ZERO));
}


pub fn read_const_gadget<'a, F: PrimeField+FieldUtils>(
circuit: &mut Circuit<'a,F,Gatebb<'a,F>>,
c: F,
round: usize,
) -> Variable {
let advice = Advice::new(0, 1, move |_, _| vec![c]);
let v = circuit.advice(round, advice, vec![])[0];
circuit.constrain_with(&vec![v], &read_const_gate(c));
v
}
109 changes: 109 additions & 0 deletions src/gadgets/cyclefold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use ff::PrimeField;
use halo2::halo2curves::{CurveExt, CurveAffine};

use crate::{circuit::{ConstructedCircuit, Circuit, ExternalValue}, gate::Gatebb, utils::{field_precomp::FieldUtils, arith_helper::j2a}, gadgets::{arith::read_const_gadget, ecmul::EcAffinePoint, input::input}, folding::encode::Encoded, constraint_system::Variable};
use super::{ecmul::{escalarmul_gadget_9, eclin_gadget}, lookup::StaticLookup, nonzero_check::Nonzeros};

pub struct ConstructedCyclefoldCircuit<'circuit, F: PrimeField+FieldUtils>{
pub circuit: ConstructedCircuit<'circuit, F, Gatebb<'circuit, F>>,
pub pt_acc : (ExternalValue<F>, ExternalValue<F>),
pub pt_inc : (ExternalValue<F>, ExternalValue<F>),
pub pt_res : (ExternalValue<F>, ExternalValue<F>),
pub sc : ExternalValue<F>,
}


/// Constructs a circuit checking that PT_ACC + SC * PT_INC = PT_RES.
/// Might be incomplete for some offset points, so ensure that offset is generated randomly
/// in multi-prover case, this is a DoS vector - need to ensure that offset is chosen after
/// all the data is already committed.
/// Also, it will fail in case of the collision - i.e. if PT_ACC != SC*PT_INC != PT_RES condition
/// breaks. Avoid this (this never happens if scalar is chosen randomly).
pub fn construct_cyclefold_circuit<
'circuit,
F: PrimeField+FieldUtils,
F2: PrimeField+FieldUtils,
C: CurveExt<ScalarExt=F2, Base=F>
> (
offset_point: C,
) -> ConstructedCyclefoldCircuit<'circuit, F>{
let mut circuit = Circuit::<F, Gatebb<'circuit,F>>::new(10, 1);
let num_limbs = 41;
let a = offset_point;
let scale = (F2::from(9).pow([num_limbs as u64])-F2::ONE)*(F2::from(8).invert().unwrap());
let b = a*scale;

let a = j2a(a.jacobian_coordinates());
let b = j2a(b.jacobian_coordinates());

let var_a = (
read_const_gadget(&mut circuit, a.0, 0),
read_const_gadget(&mut circuit, a.1, 0)
);

let var_b = (
read_const_gadget(&mut circuit, b.0, 0),
read_const_gadget(&mut circuit, b.1, 0)
);

let pt_a = EcAffinePoint::<F, C>::new(&mut circuit, var_a.0, var_a.1);
let pt_b = EcAffinePoint::new(&mut circuit, var_b.0, var_b.1);

let mut nonzeros = Nonzeros::new(9);

let scalar_inp = circuit.ext_val(1)[0];
let sc = input(&mut circuit, scalar_inp, 0);

let pt_inc = circuit.ext_val(2);
let pt_inc = (pt_inc[0], pt_inc[1]);
let pt_inc_x = input(&mut circuit, pt_inc.0, 0);
let pt_inc_y = input(&mut circuit, pt_inc.1, 0);

let incoming_point = EcAffinePoint::new(&mut circuit, pt_inc_x, pt_inc_y);

let pt_acc = circuit.ext_val(2);
let pt_acc = (pt_acc[0], pt_acc[1]);
let pt_acc_x = input(&mut circuit, pt_acc.0, 0);
let pt_acc_y = input(&mut circuit, pt_acc.1, 0);

let accumulated_point = EcAffinePoint::new(&mut circuit, pt_acc_x, pt_acc_y);

let pt_res = circuit.ext_val(2);
let pt_res = (pt_res[0], pt_res[1]);

let pt_res_x = input(&mut circuit, pt_res.0, 0);
let pt_res_y = input(&mut circuit, pt_res.1, 0);

let result_point = EcAffinePoint::new(&mut circuit, pt_res_x, pt_res_y);


let prod = escalarmul_gadget_9 (
&mut circuit,
sc,
incoming_point,
num_limbs,
0,
pt_a,
pt_b,
&mut nonzeros
);
eclin_gadget(&mut circuit, prod, accumulated_point, result_point, &mut nonzeros, 0);
nonzeros.finalize(&mut circuit);

let circuit = circuit.finalize();

ConstructedCyclefoldCircuit { circuit, pt_acc, pt_inc, pt_res, sc : scalar_inp }
}

// pub struct Step<
// 'circuit,
// F : PrimeField,
// StepGadget : Fn(
// &mut Circuit<'circuit, F, Gatebb<'circuit, F>>,
// &mut StaticLookup<F>, // lookup arguments
// &mut Vec<Variable>, // nonzeros
// Vec<Variable> // inputs
// ) -> Vec<Variable>,
// > {

// }
11 changes: 6 additions & 5 deletions src/gadgets/ecmul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::circuit::{PolyOp, Advice};
use crate::{circuit::Circuit, constraint_system::Variable, gate::Gatebb};
use crate::utils::field_precomp::FieldUtils;

use super::nonzero_check::Nonzeros;
use super::range::{limb_decompose_gadget, choice_gadget};


Expand Down Expand Up @@ -90,7 +91,7 @@ pub fn eclin_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
pt1: EcAffinePoint<F,C>,
pt2: EcAffinePoint<F,C>,
pt3: EcAffinePoint<F,C>,
nonzeros: &mut Vec<Variable>,
nonzeros: &mut Nonzeros,
round: usize
) -> () {
let pts = vec![pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y];
Expand Down Expand Up @@ -134,7 +135,7 @@ pub fn ectangent_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
circuit: &mut Circuit<'a, F, Gatebb<'a, F>>,
pt1: EcAffinePoint<F,C>,
pt2: EcAffinePoint<F,C>,
nonzeros: &mut Vec<Variable>,
nonzeros: &mut Nonzeros,
round: usize
) -> () {
let pts = vec![pt1.x, pt1.y, pt2.x, pt2.y];
Expand Down Expand Up @@ -177,7 +178,7 @@ pub fn ecadd_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
circuit: &mut Circuit<'a, F, Gatebb<'a, F>>,
pt1: EcAffinePoint<F,C>,
pt2: EcAffinePoint<F,C>,
nonzeros: &mut Vec<Variable>,
nonzeros: &mut Nonzeros,
round: usize
) -> EcAffinePoint<F,C>{
let tmp = circuit.advice(
Expand Down Expand Up @@ -205,7 +206,7 @@ pub fn ecadd_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
pub fn ecdouble_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
circuit: &mut Circuit<'a, F, Gatebb<'a, F>>,
pt: EcAffinePoint<F,C>,
nonzeros: &mut Vec<Variable>,
nonzeros: &mut Nonzeros,
round: usize
) -> EcAffinePoint<F,C>{
let tmp = circuit.advice(
Expand Down Expand Up @@ -240,7 +241,7 @@ pub fn escalarmul_gadget_9<'a, F: PrimeField + FieldUtils, C: CurveExt<Base=F>>(
round: usize,
a: EcAffinePoint<F,C>,
b: EcAffinePoint<F,C>,
nonzeros: &mut Vec<Variable>,
nonzeros: &mut Nonzeros,
) -> EcAffinePoint<F, C> {
// The algorithm:
// We compute a, pt+a, 2pt+a, ..., 8pt+a
Expand Down
4 changes: 2 additions & 2 deletions src/gadgets/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ mod test {
#[test]
fn random() {
type F = bn256::Fr;
let indexes = 0..TEST_LEN;
let indices = 0..TEST_LEN;
let range = 16;

let table = (0..range).map(|_| F::random(OsRng)).collect_vec();
Expand All @@ -613,7 +613,7 @@ mod test {
let mut instance = constructed.spawn();

test_values.into_iter().map(|val| instance.set_ext(val, table[(OsRng.next_u64() % range as u64) as usize])).last();
for i in indexes {
for i in indices {
instance.execute(i);
}
let challenge = F::random(OsRng);
Expand Down
3 changes: 2 additions & 1 deletion src/gadgets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pub mod running_prod;
pub mod nonzero_check;
pub mod lookup;
pub mod input;
pub mod arith;
pub mod arith;
pub mod cyclefold;
20 changes: 19 additions & 1 deletion src/gadgets/nonzero_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,28 @@ use crate::{utils::field_precomp::FieldUtils, circuit::{Circuit, Advice}, gate::
use super::running_prod::prod_run_gadget;
use crate::gatelib::nonzero_check;

pub struct Nonzeros {
entries: Vec<Variable>,
rate: usize,
}

impl Nonzeros {
pub fn new(rate: usize) -> Self {
Self {entries : vec![], rate}
}

pub fn push(&mut self, v: Variable) {
self.entries.push(v);
}

pub fn finalize<'a, F: PrimeField+FieldUtils>(self, circuit: &mut Circuit<'a, F, Gatebb<'a, F>>) {
nonzero_gadget(circuit, &self.entries, self.rate);
}
}

/// Checks that the array of variables is nonzero.
/// Rate = amount of elements processed in a single chunk.
pub fn nonzero_gadget<'a, F: PrimeField + FieldUtils> (circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, input: &[Variable], rate: usize) -> () {
fn nonzero_gadget<'a, F: PrimeField + FieldUtils> (circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, input: &[Variable], rate: usize) -> () {
let mut round = 0;
for v in input {
round = max(
Expand Down
7 changes: 4 additions & 3 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod tests {
VarSmall,
choice_gadget
},
nonzero_check::nonzero_gadget, input::input
nonzero_check::Nonzeros, input::input
}, folding::poseidon::Poseidon
};
use ff::{PrimeField, Field};
Expand Down Expand Up @@ -406,12 +406,12 @@ mod tests {
let pt = EcAffinePoint::<F,C>::new(&mut circuit, x, y);
let sc = input(&mut circuit, pi_sc_ext, 0);

let mut nonzeros = vec![];
let mut nonzeros = Nonzeros::new(9);
let num_limbs = 81;

let scmul = escalarmul_gadget_9(&mut circuit, sc, pt, num_limbs, 0, a, b, &mut nonzeros);

nonzero_gadget(&mut circuit, &nonzeros, 9);
nonzeros.finalize(&mut circuit);
let constructed = circuit.finalize();
let mut instance = constructed.spawn();

Expand All @@ -427,6 +427,7 @@ mod tests {
instance.set_ext(pi_b_ext.1, pi_b.y);

let pi_pt = C::random(OsRng).to_affine();

instance.set_ext(pi_pt_ext.0, pi_pt.x);
instance.set_ext(pi_pt_ext.1, pi_pt.y);

Expand Down
8 changes: 8 additions & 0 deletions src/utils/arith_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ pub fn ev<F:PrimeField>(poly: &Vec<F>, x: F) -> F {
ret += poly[l-i-1];
}
ret
}

/// Converts jacobian to affine.
pub fn j2a<F: PrimeField>(pt: (F,F,F)) -> (F,F) {
let zi = pt.2.invert().unwrap();
let zisq = zi.square();
let zicb = zisq*zi;
(pt.0 * zisq, pt.1 * zicb)
}
Loading

0 comments on commit a607a9e

Please sign in to comment.