use pairing::{ Engine, Field, PrimeField }; use bellman::{ SynthesisError, ConstraintSystem, LinearCombination, Variable }; pub struct MultiEq>{ cs: CS, ops: usize, bits_used: usize, lhs: LinearCombination, rhs: LinearCombination, } impl> MultiEq { pub fn new(cs: CS) -> Self { MultiEq { cs: cs, ops: 0, bits_used: 0, lhs: LinearCombination::zero(), rhs: LinearCombination::zero() } } fn accumulate(&mut self) { let ops = self.ops; let lhs = self.lhs.clone(); let rhs = self.rhs.clone(); self.cs.enforce( || format!("multieq {}", ops), |_| lhs, |lc| lc + CS::one(), |_| rhs ); self.lhs = LinearCombination::zero(); self.rhs = LinearCombination::zero(); self.bits_used = 0; self.ops += 1; } pub fn enforce_equal( &mut self, num_bits: usize, lhs: &LinearCombination, rhs: &LinearCombination ) { // Check if we will exceed the capacity if (E::Fr::CAPACITY as usize) <= (self.bits_used + num_bits) { self.accumulate(); } assert!((E::Fr::CAPACITY as usize) > (self.bits_used + num_bits)); let coeff = E::Fr::from_str("2").unwrap().pow(&[self.bits_used as u64]); self.lhs = self.lhs.clone() + (coeff, lhs); self.rhs = self.rhs.clone() + (coeff, rhs); self.bits_used += num_bits; } } impl> Drop for MultiEq { fn drop(&mut self) { if self.bits_used > 0 { self.accumulate(); } } } impl> ConstraintSystem for MultiEq { type Root = Self; fn one() -> Variable { CS::one() } fn alloc( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { self.cs.alloc(annotation, f) } fn alloc_input( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { self.cs.alloc_input(annotation, f) } fn enforce( &mut self, annotation: A, a: LA, b: LB, c: LC ) where A: FnOnce() -> AR, AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination { self.cs.enforce(annotation, a, b, c) } fn push_namespace(&mut self, name_fn: N) where NR: Into, N: FnOnce() -> NR { self.cs.get_root().push_namespace(name_fn) } fn pop_namespace(&mut self) { self.cs.get_root().pop_namespace() } fn get_root(&mut self) -> &mut Self::Root { self } }