Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consts moved into gate, static lookup for any table works #9

Merged
merged 1 commit into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading