Implement raw constraints for Bit
This commit is contained in:
parent
506ef75e3c
commit
ececc2b60b
78
src/bit.rs
78
src/bit.rs
@ -214,14 +214,68 @@ fn resolve(a: &Var, b: &Var, op: Op) -> Var {
|
|||||||
vals.set_output(0, op.val(a, b));
|
vals.set_output(0, op.val(a, b));
|
||||||
}, |i, o, cs| {
|
}, |i, o, cs| {
|
||||||
cs.push(match op {
|
cs.push(match op {
|
||||||
And => Constraint::And(i[0].index(), i[1].index(), o[0].index()),
|
// a * b = c
|
||||||
Nand => Constraint::Nand(i[0].index(), i[1].index(), o[0].index()),
|
And => Constraint(vec![(FieldT::one(), i[0].clone())],
|
||||||
Xor => Constraint::Xor(i[0].index(), i[1].index(), o[0].index()),
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
Xnor => Constraint::Xnor(i[0].index(), i[1].index(), o[0].index()),
|
vec![(FieldT::one(), o[0].clone())]
|
||||||
Nor => Constraint::Nor(i[0].index(), i[1].index(), o[0].index()),
|
),
|
||||||
Or => Constraint::Or(i[0].index(), i[1].index(), o[0].index()),
|
// a * b = 1 - c
|
||||||
MaterialNonimplication => Constraint::MaterialNonimplication(i[0].index(), i[1].index(), o[0].index()),
|
Nand => Constraint(vec![(FieldT::one(), i[0].clone())],
|
||||||
MaterialImplication => Constraint::MaterialImplication(i[0].index(), i[1].index(), o[0].index())
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
|
vec![(FieldT::one(), Var::one()),
|
||||||
|
(-FieldT::one(), o[0].clone())
|
||||||
|
]
|
||||||
|
),
|
||||||
|
// 2a * b = a + b - c
|
||||||
|
Xor => Constraint(vec![(FieldT::from(2), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
|
vec![(FieldT::one(), i[0].clone()),
|
||||||
|
(FieldT::one(), i[1].clone()),
|
||||||
|
(-FieldT::one(), o[0].clone())
|
||||||
|
]
|
||||||
|
),
|
||||||
|
// 2a * b = a + b + c - 1
|
||||||
|
Xnor => Constraint(vec![(FieldT::from(2), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
|
vec![
|
||||||
|
(FieldT::one(), i[0].clone()),
|
||||||
|
(FieldT::one(), i[1].clone()),
|
||||||
|
(FieldT::one(), o[0].clone()),
|
||||||
|
(-FieldT::one(), Var::one())
|
||||||
|
]
|
||||||
|
),
|
||||||
|
// a * (1 - b) = c
|
||||||
|
MaterialNonimplication => Constraint(vec![(FieldT::one(), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), Var::one()),
|
||||||
|
(-FieldT::one(), i[1].clone())
|
||||||
|
],
|
||||||
|
vec![(FieldT::one(), o[0].clone())]
|
||||||
|
),
|
||||||
|
// a * b = a + c - 1
|
||||||
|
MaterialImplication => Constraint(vec![(FieldT::one(), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
|
vec![(FieldT::one(), i[0].clone()),
|
||||||
|
(FieldT::one(), o[0].clone()),
|
||||||
|
(-FieldT::one(), Var::one())
|
||||||
|
]
|
||||||
|
),
|
||||||
|
// (1 - a) * (1 - b) = c
|
||||||
|
Nor => Constraint(vec![(FieldT::one(), Var::one()),
|
||||||
|
(-FieldT::one(), i[0].clone())
|
||||||
|
],
|
||||||
|
vec![(FieldT::one(), Var::one()),
|
||||||
|
(-FieldT::one(), i[1].clone())
|
||||||
|
],
|
||||||
|
vec![(FieldT::one(), o[0].clone())]
|
||||||
|
),
|
||||||
|
// a * b = a + b - c
|
||||||
|
Or => Constraint(vec![(FieldT::one(), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), i[1].clone())],
|
||||||
|
vec![(FieldT::one(), i[0].clone()),
|
||||||
|
(FieldT::one(), i[1].clone()),
|
||||||
|
(-FieldT::one(), o[0].clone())
|
||||||
|
]
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
vec![o[0]]
|
vec![o[0]]
|
||||||
@ -263,7 +317,13 @@ impl Bit {
|
|||||||
|
|
||||||
pub fn new(v: &Var) -> Bit {
|
pub fn new(v: &Var) -> Bit {
|
||||||
Is(gadget(&[v], 0, |_| {}, |i, o, cs| {
|
Is(gadget(&[v], 0, |_| {}, |i, o, cs| {
|
||||||
cs.push(Constraint::Bitness(i[0].index()));
|
// boolean constraint:
|
||||||
|
// (1 - a) * a = 0
|
||||||
|
cs.push(Constraint(vec![(FieldT::one(), Var::one()),
|
||||||
|
(-FieldT::one(), i[0].clone())],
|
||||||
|
vec![(FieldT::one(), i[0].clone())],
|
||||||
|
vec![(FieldT::zero(), Var::one())]
|
||||||
|
));
|
||||||
|
|
||||||
vec![i[0]]
|
vec![i[0]]
|
||||||
}).remove(0))
|
}).remove(0))
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use tinysnark::FieldT;
|
use tinysnark::FieldT;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::fmt;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
pub type WitnessMap = BTreeMap<usize, Vec<(Vec<usize>, Vec<usize>, Rc<Fn(&mut VariableView) + 'static>)>>;
|
pub type WitnessMap = BTreeMap<usize, Vec<(Vec<usize>, Vec<usize>, Rc<Fn(&mut VariableView) + 'static>)>>;
|
||||||
@ -41,33 +40,7 @@ pub fn witness_field_elements(vars: &mut [FieldT], witness_map: &WitnessMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Constraint {
|
pub struct Constraint(pub Vec<(FieldT, Var)>, pub Vec<(FieldT, Var)>, pub Vec<(FieldT, Var)>);
|
||||||
Bitness(Rc<Cell<usize>>),
|
|
||||||
And(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
Nand(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
Xor(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
Xnor(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
MaterialNonimplication(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
MaterialImplication(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
Nor(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>),
|
|
||||||
Or(Rc<Cell<usize>>, Rc<Cell<usize>>, Rc<Cell<usize>>)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Constraint {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", match *self {
|
|
||||||
Constraint::Bitness(ref b) => format!("bitness: {}", b.get()),
|
|
||||||
Constraint::And(ref a, ref b, ref c) => format!("{} = {} AND {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::Nand(ref a, ref b, ref c) => format!("{} = {} NAND {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::Xor(ref a, ref b, ref c) => format!("{} = {} XOR {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::Xnor(ref a, ref b, ref c) => format!("{} = {} XNOR {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::MaterialNonimplication(ref a, ref b, ref c) => format!("{} = {} ↛ {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::MaterialImplication(ref a, ref b, ref c) => format!("{} = {} <-> {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::Nor(ref a, ref b, ref c) => format!("{} = {} NOR {}", c.get(), a.get(), b.get()),
|
|
||||||
Constraint::Or(ref a, ref b, ref c) => format!("{} = {} OR {}", c.get(), a.get(), b.get())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Gadget {
|
struct Gadget {
|
||||||
inputs: Vec<Var>,
|
inputs: Vec<Var>,
|
||||||
@ -122,6 +95,13 @@ impl Var {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn one() -> Var {
|
||||||
|
Var {
|
||||||
|
index: Rc::new(Cell::new(0)),
|
||||||
|
gadget: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// make this not public or unsafe too
|
// make this not public or unsafe too
|
||||||
pub fn index(&self) -> Rc<Cell<usize>> {
|
pub fn index(&self) -> Rc<Cell<usize>> {
|
||||||
self.index.clone()
|
self.index.clone()
|
||||||
|
Loading…
Reference in New Issue
Block a user