Skip to content

Commit

Permalink
consts moved into gate, static lookup for any table works
Browse files Browse the repository at this point in the history
  • Loading branch information
rebenkoy committed Nov 21, 2023
1 parent dc296c3 commit 6efaeec
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 127 deletions.
29 changes: 14 additions & 15 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct PolyOp<'closure, F: PrimeField>{
impl<'closure, F:PrimeField> PolyOp<'closure, F> {
pub fn new(d: usize, i: usize, o: usize, f: impl Fn(&[F], &[F]) -> Vec<F> + 'closure) -> Self {
let f = Rc::new(f);
check_poly(d, i, o, f.clone()).unwrap();
check_poly(d, i, o, f.clone(), &[]).unwrap();

Self { d, i, o, f }
}
Expand All @@ -41,7 +41,7 @@ impl<'closure, F: PrimeField> From<PolyOp<'closure, F>> for Gatebb<'closure, F>{
results.iter().zip(outputs.iter()).map(|(res, out)|*res-*out).collect()
};

Gatebb::new(d, i, o, Rc::new(f))
Gatebb::new(d, i, o, Rc::new(f), vec![])
}
}

Expand Down Expand Up @@ -249,7 +249,7 @@ where
output
}

fn apply_internal(&mut self, visibility: Visibility, round : usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>, constants: &[F]) -> Vec<Variable> {
fn apply_internal(&mut self, visibility: Visibility, round : usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>) -> Vec<Variable> {
assert!(round < self.ops.len(), "The round is too large.");

let op_index = self.ops[round].len();
Expand All @@ -270,40 +270,39 @@ where
let mut gate_io = input; // do not move input into new buffer
gate_io.extend(output.iter().cloned());

self.constrain(&gate_io, &constants, polyop.into());
self.constrain(&gate_io, polyop.into());

output
}

pub fn apply(&mut self, round: usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>, constants: &[F]) -> Vec<Variable> {
self.apply_internal(Visibility::Private, round, polyop, input, constants)
pub fn apply(&mut self, round: usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>) -> Vec<Variable> {
self.apply_internal(Visibility::Private, round, polyop, input)
}

pub fn apply_pub(&mut self, round : usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>, constants: &[F]) -> Vec<Variable> {
self.apply_internal(Visibility::Public, round, polyop, input, constants)
pub fn apply_pub(&mut self, round : usize, polyop: PolyOp<'circuit, F>, input: Vec<Variable>) -> Vec<Variable> {
self.apply_internal(Visibility::Public, round, polyop, input)
}

// TODO: pass input by value since we clone it down the stack either way
pub fn constrain(&mut self, input: &[Variable], constants: &[F], gate: G) {
pub fn constrain(&mut self, input: &[Variable], gate: G) {
println!("Using legacy unnamed constrains");
self._constrain(&input, &constants, gate)
self._constrain(&input, gate)
}

fn _constrain(&mut self, input: &[Variable], constants: &[F], gate: G) {
fn _constrain(&mut self, input: &[Variable], gate: G) {
assert!(gate.d() > 0, "Trying to constrain with gate of degree 0.");

let kind = if gate.d() == 1 { CommitKind::Zero } else { CommitKind::Group };
self.cs.constrain(kind, input, constants, gate);
self.cs.constrain(kind, input, gate);
}

pub fn constrain_with(
&mut self,
input: &[Variable],
constants: &[F],
gate_fetcher: &dyn Fn(&FrozenMap<String, Box<G>>) -> G
) {
let gate = gate_fetcher(&self.gate_registry);
self._constrain(&input, &constants, gate);
self._constrain(&input, gate);
}

pub fn load_pi(&'circuit mut self, round: usize, pi: ExternalValue<F>) -> Variable {
Expand Down Expand Up @@ -363,7 +362,7 @@ where
pub fn valid_witness(&self) -> () {
for constr in self.circuit.cs.iter_constraints() {
let input_values: Vec<_> = constr.inputs.iter().map(|&x| self.cs.getvar(x)).collect();
let result = constr.gate.exec(&input_values, &constr.constants);
let result = constr.gate.exec(&input_values);

assert!(result.iter().all(|&output| output == F::ZERO), "Constraint {:?} is not satisfied", constr);
}
Expand Down
11 changes: 5 additions & 6 deletions src/constraint_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ pub struct Variable {
#[derive(Debug, Clone)]
pub struct Constraint<'c, F: PrimeField, G: Gate<'c, F>>{
pub inputs: Vec<Variable>,
pub constants: Vec<F>,
pub gate: G,
_marker: PhantomData<&'c F>,
}
Expand Down Expand Up @@ -63,12 +62,12 @@ impl<'c, F: PrimeField, G: Gate<'c, F>> ConstraintGroup<'c, F, G> {
}
}

pub fn constrain(&mut self, inputs: &[Variable], constants: &[F], gate: G) {
pub fn constrain(&mut self, inputs: &[Variable], gate: G) {
assert!(gate.d() <= self.max_degree, "Constraint degree is too large for this group.");
assert!(gate.i() == inputs.len(), "Invalid amount of arguments supplied.");

self.num_rhs += gate.o();
self.entries.push(Constraint{inputs : inputs.to_vec(), constants: constants.to_vec(), gate, _marker : PhantomData});
self.entries.push(Constraint{inputs : inputs.to_vec(), gate, _marker : PhantomData});
}
}

Expand Down Expand Up @@ -114,7 +113,7 @@ pub trait CS<'c, F: PrimeField, G: Gate<'c, F>> {
self.alloc_in_round(self.last_round(), visibility, size)
}

fn constrain(&mut self, kind: CommitKind, inputs: &[Variable], constnts: &[F], gate: G);
fn constrain(&mut self, kind: CommitKind, inputs: &[Variable], gate: G);

fn extval(&mut self, size: usize) -> Vec<ExternalValue<F>>;
}
Expand Down Expand Up @@ -192,8 +191,8 @@ impl<'c, F: PrimeField, G: Gate<'c, F>> CS<'c, F, G> for ConstraintSystem<'c, F,
(prev..prev+size).into_iter().map(|index| Variable { visibility, round, index }).collect()
}

fn constrain(&mut self, kind: CommitKind, inputs: &[Variable], constants: &[F], gate: G) {
self.constraint_group(kind).constrain(inputs, constants, gate);
fn constrain(&mut self, kind: CommitKind, inputs: &[Variable], gate: G) {
self.constraint_group(kind).constrain(inputs, gate);
}

fn extval(&mut self, size: usize) -> Vec<ExternalValue<F>> {
Expand Down
2 changes: 1 addition & 1 deletion src/gadgets/arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ pub fn eq_gadget<'a, F: PrimeField+FieldUtils>(
a: Variable,
b: Variable,
) -> () {
circuit.constrain(&vec![a,b], &[], Gatebb::new(1, 2, 1, Rc::new(|args, _|vec![args[0]-args[1]])));
circuit.constrain(&vec![a,b], Gatebb::new(1, 2, 1, Rc::new(|args, _|vec![args[0]-args[1]]), vec![]));
}
10 changes: 5 additions & 5 deletions src/gadgets/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ pub fn bit_decomposition_gadget<'a, F: PrimeField+FieldUtils>(circuit: &mut Circ
vec![]
);

let bitcheck_gate = Gatebb::new(2, 1, 1, Rc::new(|args, _| bitcheck::<F>(args)));
let bitcheck_gate = Gatebb::new(2, 1, 1, Rc::new(|args, _| bitcheck::<F>(args)), vec![]);

for i in 0..num_bits-1 {
circuit.constrain(&vec![bits[i]], &[], bitcheck_gate.clone())
circuit.constrain(&vec![bits[i]], bitcheck_gate.clone())
}
circuit.constrain(&vec![bits[num_bits-1]], &[], bitcheck_gate);
circuit.constrain(&vec![bits[num_bits-1]], bitcheck_gate);

let decompcheck_gate = Gatebb::new(1, num_bits+1, 1, Rc::new(|args, _| decompcheck::<F>(args)));
let decompcheck_gate = Gatebb::new(1, num_bits+1, 1, Rc::new(|args, _| decompcheck::<F>(args)), vec![]);
let tmp : Vec<_> = repeat(input).take(1).chain(bits.iter().map(|x|*x)).collect();
circuit.constrain(&tmp, &[], decompcheck_gate);
circuit.constrain(&tmp, decompcheck_gate);

bits

Expand Down
35 changes: 19 additions & 16 deletions src/gadgets/ecmul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ impl<F: PrimeField+FieldUtils, C: CurveExt<Base=F>> EcAffinePoint<F, C> {
}

pub fn new<'a>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, x: Variable, y: Variable) -> Self{
circuit.constrain(&[x,y], &[], Gatebb::new(3, 2, 1, Rc::new(|args, _|{
let x = args[0];
let y = args[1];
circuit.constrain(&[x,y], Gatebb::new(
3, 2, 1,
Rc::new(|args, _|{
let x = args[0];
let y = args[1];

let a = C::a();
let b = C::b();
let a = C::a();
let b = C::b();

vec![x.cube() + a*x + b - y*y]
})));
vec![x.cube() + a*x + b - y*y]
}),
vec![],
));

Self::new_unchecked(x,y)
}
Expand Down Expand Up @@ -93,7 +97,6 @@ pub fn eclin_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(

circuit.constrain( // Constrain that they are on the same line
&pts,
&[],
Gatebb::new(
2,
6,
Expand All @@ -104,7 +107,8 @@ pub fn eclin_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
let c = args[4]-args[0];
let d = -args[5]-args[1];
vec![a*d - b*c]
})
}),
vec![],
)
);

Expand All @@ -120,7 +124,6 @@ pub fn eclin_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
}
),
vec![pt1.x,pt2.x,pt3.x],
&[],
)[0]
);
}
Expand All @@ -137,7 +140,6 @@ pub fn ectangent_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
let pts = vec![pt1.x, pt1.y, pt2.x, pt2.y];
circuit.constrain( // Check that slope vector is collinear with vector from pt1 to [-pt2]
&pts,
&[],
Gatebb::new(
2,
4,
Expand All @@ -148,7 +150,8 @@ pub fn ectangent_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
let c = args[1].scale(2);
let d = args[0].square().scale(3);
vec![a*d - b*c]
})
}),
vec![],
)
);
nonzeros.push(
Expand All @@ -163,7 +166,6 @@ pub fn ectangent_gadget<'a, F: PrimeField+FieldUtils, C: CurveExt<Base=F>>(
}
),
vec![pt1.x,pt2.x],
&[],
)[0]
);
}
Expand Down Expand Up @@ -414,15 +416,16 @@ pub fn escalarmul_gadget_9<'a, F: PrimeField + FieldUtils, C: CurveExt<Base=F>>(
let (x1,y1,z1) = double_proj::<F,C>(a);
let (x2,y2,z2) = add_proj::<F,C>(b, (args[0], -args[1]));
vec![x2 - x1*q, y2 - y1*q, z2 - z1*q]
})
}),
vec![],
);

for i in 0..num_limbs-1 {
let input = vec![pt_acc[i].x, pt_acc[i].y, pt_x3[i].x, pt_x3[i].y, scale3[i]];
circuit.constrain(&input, &[], triple_check.clone());
circuit.constrain(&input, triple_check.clone());
nonzeros.push(scale3[i]);
let input = vec![pt_x3[i].x, pt_x3[i].y, pt_x9[i].x, pt_x9[i].y, scale9[i]];
circuit.constrain(&input, &[], triple_check.clone());
circuit.constrain(&input, triple_check.clone());
nonzeros.push(scale9[i]);

eclin_gadget(circuit,
Expand Down
10 changes: 5 additions & 5 deletions src/gadgets/lc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@ pub fn sum_arr<F: PrimeField+FieldUtils>(args: &[F]) -> F {
pub fn lc_constr<'a, F: PrimeField+FieldUtils>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, coeffs:&'a [F], vars: &[Variable]) -> () {
assert_eq!(coeffs.len(), vars.len());
let l = vars.len();
let gate = Gatebb::new(1, l, 1, Rc::new(|args, _|{vec![inner_prod(coeffs, args)]})); // NO MOVE HERE!!
circuit.constrain(vars, &[], gate);
let gate = Gatebb::new(1, l, 1, Rc::new(|args, _|{vec![inner_prod(coeffs, args)]}), vec![]); // NO MOVE HERE!!
circuit.constrain(vars, gate);
}

pub fn qc<'a, F: PrimeField+FieldUtils>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, a: &[Variable], b: &[Variable], round: usize) -> Variable {
assert_eq!(a.len(), b.len());
let l = a.len();
let poly = PolyOp::new(2, 2*l, 1, |args, _| split_and_ip::<F>(args));
let args : Vec<_> = a.iter().chain(b.iter()).map(|x|*x).collect();
circuit.apply(round, poly, args, &[])[0]
circuit.apply(round, poly, args)[0]
}

pub fn lc<'a, F: PrimeField+FieldUtils>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, coeffs:&'a [F], vars: &[Variable], round: usize) -> Variable {
assert_eq!(coeffs.len(), vars.len());
let l = vars.len();
let poly = PolyOp::new(1, l, 1, |args, _|{vec![inner_prod(coeffs, args)]}); // NO MOVE HERE!!
circuit.apply(round, poly, vars.to_vec(), &[])[0]
circuit.apply(round, poly, vars.to_vec())[0]
}

pub fn sum_gadget<'a, F: PrimeField+FieldUtils>(circuit: &mut Circuit<'a, F, Gatebb<'a, F>>, vars: &[Variable], round: usize) -> Variable {
let l = vars.len();
let poly = PolyOp::new(1, l, 1, |arr, _|vec![sum_arr(arr)]);
circuit.apply(round, poly, vars.to_vec(), &[])[0]
circuit.apply(round, poly, vars.to_vec())[0]
}
Loading

0 comments on commit 6efaeec

Please sign in to comment.