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

Refactor for basic constraints #48

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0ea19d7
add neg/add/mul backend interfaces
katat Apr 22, 2024
4d32ca7
impl neg constraint
katat Apr 22, 2024
ec3bf05
update asm
katat Apr 22, 2024
bb6b818
add span arg to basic constraint interface
katat Apr 22, 2024
b9797ee
move add of field constraint to kimchi backend
katat Apr 22, 2024
cce2669
move mul constraint of field to kimchi backend
katat Apr 22, 2024
3472824
refactor boolean constraints using basic constraints
katat Apr 22, 2024
7f1862d
add neg wrapper in field constraint, so as to be consistent.
katat Apr 22, 2024
02345e8
refactor sub constraint
katat Apr 22, 2024
654dda3
refactor if_else constraint
katat Apr 22, 2024
1dd5684
refactor equal_cells
katat Apr 22, 2024
eeaf71a
add backend interfaces for assert eq constraints
katat Apr 23, 2024
ba9233e
fix: under-constraint
katat Apr 23, 2024
e2ad54c
test: update asm
katat Apr 23, 2024
01b0ebf
rename constraint interface
katat Apr 23, 2024
76e43c9
refactor args for neg interface
katat Apr 23, 2024
70c8358
refactor args for add interface
katat Apr 23, 2024
314422c
refactor args for mul interface
katat Apr 23, 2024
7efa2ab
refactor check fn
katat Apr 23, 2024
4378fc1
refactor: and operation
katat Apr 23, 2024
bff163f
refactor: not operation
katat Apr 23, 2024
f5fe05e
add backend constraint for inputs and outputs
katat Apr 23, 2024
e4cd10f
revert test
katat Apr 23, 2024
4b004b2
fmt
katat Apr 23, 2024
cea6a71
move public_input_size to kimchi backend
katat Apr 24, 2024
a92fea9
move add_gate and add_generic_gate to kimchi backend
katat Apr 24, 2024
427f04e
outdated note
katat Apr 24, 2024
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
8 changes: 7 additions & 1 deletion examples/arithmetic.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@
DoubleGeneric<1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,0,0,-2>
(0,0) -> (1,1)
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1>
(0,0) -> (1,1) -> (3,0)
(1,0) -> (4,0)
(1,2) -> (2,0)
(3,2) -> (4,1)
(4,2) -> (5,0)
3 changes: 3 additions & 0 deletions examples/arithmetic.no
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
fn main(pub public_input: Field, private_input: Field) {
let xx = private_input + public_input;
assert_eq(xx, 2);

let yy = private_input - public_input;
assert_eq(yy, 0);
katat marked this conversation as resolved.
Show resolved Hide resolved
}
16 changes: 11 additions & 5 deletions examples/bool.asm
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
@ noname.0.7.0

DoubleGeneric<1>
DoubleGeneric<-1,0,0,1>
DoubleGeneric<-1,0,0,1>
DoubleGeneric<0,-1,-1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,-1,0,0,1>
DoubleGeneric<0,-1,0,0,1>
(0,0) -> (1,0) -> (1,1) -> (5,1)
(2,0) -> (2,1) -> (3,1)
(0,0) -> (1,0) -> (2,0) -> (8,1)
(1,2) -> (2,1)
(3,0) -> (4,0) -> (5,0)
(3,2) -> (4,1)
(5,2) -> (6,0)
(6,2) -> (7,1)
46 changes: 31 additions & 15 deletions examples/equals.asm
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@

DoubleGeneric<1>
DoubleGeneric<1>
DoubleGeneric<1,-1,-1>
DoubleGeneric<1,1,0,0,-1>
DoubleGeneric<0,0,0,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<0,-1,0,0,1>
DoubleGeneric<1,0,0,0,-3>
DoubleGeneric<1,-1,-1>
DoubleGeneric<1,1,0,0,-1>
DoubleGeneric<0,0,0,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<0,-1,0,0,1>
(0,0) -> (2,1) -> (8,1)
(1,0) -> (2,0)
(2,2) -> (4,1) -> (5,1)
(3,0) -> (5,2)
(3,1) -> (4,0) -> (6,1)
(7,0) -> (8,0)
(8,2) -> (10,1) -> (11,1)
(9,0) -> (11,2)
(9,1) -> (10,0) -> (12,1)
(0,0) -> (2,0) -> (12,0)
(1,0) -> (3,0)
(2,2) -> (3,1)
(3,2) -> (6,1) -> (7,1)
(4,0) -> (6,0) -> (10,1)
(4,2) -> (5,0)
(5,2) -> (8,0)
(7,2) -> (9,0)
(8,2) -> (9,1)
(11,0) -> (13,0)
(12,2) -> (13,1)
(13,2) -> (16,1) -> (17,1)
(14,0) -> (16,0) -> (20,1)
(14,2) -> (15,0)
(15,2) -> (18,0)
(17,2) -> (19,0)
(18,2) -> (19,1)
44 changes: 30 additions & 14 deletions examples/if_else.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,36 @@
DoubleGeneric<1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<1,0,0,0,-1>
DoubleGeneric<1,-1,-1>
DoubleGeneric<1,1,0,0,-1>
DoubleGeneric<0,0,0,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,0,-1,0,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,-1,-1>
DoubleGeneric<1,-1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<0,0,-1,1>
DoubleGeneric<1,0,1>
DoubleGeneric<1,1,-1>
DoubleGeneric<1,0,0,0,-2>
(0,0) -> (1,0) -> (3,1) -> (7,1) -> (8,1)
(1,2) -> (7,0)
(2,0) -> (3,0)
(3,2) -> (5,1) -> (6,1)
(4,0) -> (6,2)
(4,1) -> (5,0) -> (9,0)
(7,2) -> (9,1)
(8,0) -> (10,0)
(8,2) -> (9,2)
(0,0) -> (1,0) -> (3,0) -> (11,0) -> (13,0)
(1,2) -> (12,0)
(2,0) -> (4,0)
(3,2) -> (4,1)
(4,2) -> (7,1) -> (8,1)
(5,0) -> (7,0) -> (15,0)
(5,2) -> (6,0)
(6,2) -> (9,0)
(8,2) -> (10,0)
(9,2) -> (10,1)
(11,2) -> (12,1)
(12,2) -> (15,1)
(13,2) -> (14,1)
(14,0) -> (18,0)
(14,2) -> (16,0)
(15,2) -> (17,0)
(16,2) -> (17,1)
149 changes: 148 additions & 1 deletion src/backends/kimchi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
constants::Span,
error::{Error, ErrorKind, Result},
helpers::PrettyField,
var::{CellVar, Value, Var},
var::{CellVar, ConstOrCell, Value, Var},
witness::WitnessEnv,
};

Expand Down Expand Up @@ -546,4 +546,151 @@ impl Backend for KimchiVesta {

res
}

fn enforce_neg_constraint(
&mut self,
var: &crate::var::ConstOrCell<Self::Field>,
span: Span,
) -> crate::var::ConstOrCell<Self::Field> {
match var {
crate::var::ConstOrCell::Const(ff) => crate::var::ConstOrCell::Const(ff.neg()),
crate::var::ConstOrCell::Cell(var) => {
let zero = Self::Field::zero();
let one = Self::Field::one();

let neg_var = self.new_internal_var(
Value::LinearCombination(vec![(one.neg(), *var)], zero),
span,
);
self.add_generic_gate(
"constraint to validate a negation (`x + (-x) = 0`)",
vec![Some(*var), None, Some(neg_var)],
vec![one, zero, one],
span,
);

crate::var::ConstOrCell::Cell(neg_var)
}
}
}

fn enforce_add_constraint(
&mut self,
lhs: &crate::var::ConstOrCell<Self::Field>,
rhs: &crate::var::ConstOrCell<Self::Field>,
span: Span,
) -> crate::var::ConstOrCell<Self::Field> {
let zero = Self::Field::zero();
let one = Self::Field::one();

match (lhs, rhs) {
// 2 constants
(ConstOrCell::Const(lhs), ConstOrCell::Const(rhs)) => {
ConstOrCell::Const(*lhs + *rhs)
}

// const and a var
(ConstOrCell::Const(cst), ConstOrCell::Cell(cvar))
| (ConstOrCell::Cell(cvar), ConstOrCell::Const(cst)) => {
// if the constant is zero, we can ignore this gate
if cst.is_zero() {
return ConstOrCell::Cell(*cvar);
}

// create a new variable to store the result
let res = self
.new_internal_var(Value::LinearCombination(vec![(one, *cvar)], *cst), span);

// create a gate to store the result
// TODO: we should use an add_generic function that takes advantage of the double generic gate
self.add_generic_gate(
"add a constant with a variable",
vec![Some(*cvar), None, Some(res)],
vec![one, zero, one.neg(), zero, *cst],
span,
);

ConstOrCell::Cell(res)
}
(ConstOrCell::Cell(lhs), ConstOrCell::Cell(rhs)) => {
// create a new variable to store the result
let res = self.new_internal_var(
Value::LinearCombination(
vec![(Self::Field::one(), *lhs), (Self::Field::one(), *rhs)],
Self::Field::zero(),
),
span,
);

// create a gate to store the result
self.add_generic_gate(
"add two variables together",
vec![Some(*lhs), Some(*rhs), Some(res)],
vec![Self::Field::one(), Self::Field::one(), Self::Field::one().neg()],
span,
);

ConstOrCell::Cell(res)
}
}
}

fn enforce_mul_constraint(
&mut self,
lhs: &crate::var::ConstOrCell<Self::Field>,
rhs: &crate::var::ConstOrCell<Self::Field>,
span: Span,
) -> crate::var::ConstOrCell<Self::Field> {
let zero = Self::Field::zero();
let one = Self::Field::one();

match (lhs, rhs) {
// 2 constants
(ConstOrCell::Const(lhs), ConstOrCell::Const(rhs)) => ConstOrCell::Const(*lhs * *rhs),

// const and a var
(ConstOrCell::Const(cst), ConstOrCell::Cell(cvar))
| (ConstOrCell::Cell(cvar), ConstOrCell::Const(cst)) => {
// if the constant is zero, we can ignore this gate
if cst.is_zero() {
let zero = self.add_constant(
Some("encoding zero for the result of 0 * var"),
Self::Field::zero(),
span,
);
return ConstOrCell::Cell(zero);
}

// create a new variable to store the result
let res = self.new_internal_var(Value::Scale(*cst, *cvar), span);

// create a gate to store the result
// TODO: we should use an add_generic function that takes advantage of the double generic gate
self.add_generic_gate(
"add a constant with a variable",
vec![Some(*cvar), None, Some(res)],
vec![*cst, zero, one.neg(), zero, *cst],
span,
);

ConstOrCell::Cell(res)
}

// everything is a var
(ConstOrCell::Cell(lhs), ConstOrCell::Cell(rhs)) => {
// create a new variable to store the result
let res = self.new_internal_var(Value::Mul(*lhs, *rhs), span);

// create a gate to store the result
self.add_generic_gate(
"add two variables together",
vec![Some(*lhs), Some(*rhs), Some(res)],
vec![zero, zero, one.neg(), one],
span,
);

ConstOrCell::Cell(res)
}
}
}
}
25 changes: 24 additions & 1 deletion src/backends/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
error::{Error, ErrorKind, Result},
helpers::PrettyField,
imports::FnHandle,
var::{CellVar, Value, Var},
var::{CellVar, ConstOrCell, Value, Var},
witness::WitnessEnv,
};

Expand All @@ -35,6 +35,29 @@ pub trait Backend: Clone {
/// It increments the variable index for look up later.
fn new_internal_var(&mut self, val: Value<Self>, span: Span) -> CellVar;

/// basic constraint negation
fn enforce_neg_constraint(
&mut self,
var: &ConstOrCell<Self::Field>,
span: Span,
) -> ConstOrCell<Self::Field>;

/// basic constraint addition
fn enforce_add_constraint(
&mut self,
lhs: &ConstOrCell<Self::Field>,
rhs: &ConstOrCell<Self::Field>,
span: Span,
) -> ConstOrCell<Self::Field>;

/// basic constraint multiplication
fn enforce_mul_constraint(
&mut self,
lhs: &ConstOrCell<Self::Field>,
rhs: &ConstOrCell<Self::Field>,
span: Span,
) -> ConstOrCell<Self::Field>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call these neg, add, and mul as they might not create a constraint eventually.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also as I hint later, I think they should not receive ConstOrCell but CellVar instead

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It now uses CellVar at the backend layer


/// This should be called only when you want to constrain a constant for real.
/// Gates that handle constants should always make sure to call this function when they want them constrained.
fn add_constant(
Expand Down
Loading
Loading