1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

remove xor, remove field dep, clean

This commit is contained in:
schaeff 2019-04-02 14:24:33 +02:00
parent 9ad0040dec
commit 5b4da4c91c
6 changed files with 84 additions and 190 deletions

1
Cargo.lock generated
View file

@ -1246,7 +1246,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)", "bellman 0.2.0 (git+https://github.com/matterinc/bellman?tag=0.2.0)",
"sapling-crypto 0.0.4 (git+https://github.com/matterinc/sapling-crypto?tag=0.0.4)", "sapling-crypto 0.0.4 (git+https://github.com/matterinc/sapling-crypto?tag=0.0.4)",
"zokrates_field 0.3.2",
] ]
[[package]] [[package]]

View file

@ -57,8 +57,13 @@ impl<T: Field> Executable<T> for RustHelper {
RustHelper::Sha256Round => { RustHelper::Sha256Round => {
let i = &inputs[0..512]; let i = &inputs[0..512];
let h = &inputs[512..]; let h = &inputs[512..];
let i: Vec<_> = i.iter().map(|x| x.clone().into_bellman()).collect();
let h: Vec<_> = h.iter().map(|x| x.clone().into_bellman()).collect();
assert!(h.len() == 256); assert!(h.len() == 256);
Ok(generate_sha256_round_witness(i, h)) Ok(generate_sha256_round_witness::<T::BellmanEngine>(&i, &h)
.into_iter()
.map(|x| T::from_bellman(x))
.collect())
} }
} }
} }

View file

@ -138,7 +138,7 @@ impl Importer {
for import in destination.imports.iter() { for import in destination.imports.iter() {
let pos = import.pos(); let pos = import.pos();
let import = &import.value; let import = &import.value;
// handle the case of special libsnark and packing imports // handle the case of special bellman and packing imports
if import.source.starts_with("BELLMAN") { if import.source.starts_with("BELLMAN") {
match import.source.as_ref() { match import.source.as_ref() {
"BELLMAN/sha256round" => { "BELLMAN/sha256round" => {

View file

@ -3,16 +3,17 @@ use flat_absy::{FlatParameter, FlatVariable};
use helpers::{DirectiveStatement, Helper, RustHelper}; use helpers::{DirectiveStatement, Helper, RustHelper};
use reduce::Reduce; use reduce::Reduce;
use types::{Signature, Type}; use types::{Signature, Type};
use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint};
use zokrates_field::field::Field; use zokrates_field::field::Field;
impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> { impl<T: Field> From<BellmanConstraint<T::BellmanEngine>> for FlatStatement<T> {
fn from(c: zokrates_embed::Constraint<T>) -> FlatStatement<T> { fn from(c: zokrates_embed::BellmanConstraint<T::BellmanEngine>) -> FlatStatement<T> {
let rhs_a = match c let rhs_a = match c
.a .a
.into_iter() .into_iter()
.map(|(key, val)| { .map(|(key, val)| {
FlatExpression::Mult( FlatExpression::Mult(
box FlatExpression::Number(val), box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)), box FlatExpression::Identifier(FlatVariable::new(key)),
) )
}) })
@ -30,7 +31,7 @@ impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
.into_iter() .into_iter()
.map(|(key, val)| { .map(|(key, val)| {
FlatExpression::Mult( FlatExpression::Mult(
box FlatExpression::Number(val), box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)), box FlatExpression::Identifier(FlatVariable::new(key)),
) )
}) })
@ -48,7 +49,7 @@ impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
.into_iter() .into_iter()
.map(|(key, val)| { .map(|(key, val)| {
FlatExpression::Mult( FlatExpression::Mult(
box FlatExpression::Number(val), box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)), box FlatExpression::Identifier(FlatVariable::new(key)),
) )
}) })
@ -66,7 +67,8 @@ impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
} }
pub fn sha_round<T: Field>() -> FlatFunction<T> { pub fn sha_round<T: Field>() -> FlatFunction<T> {
let (r1cs, input, current_hash, output) = zokrates_embed::generate_sha256_round_constraints(); let (r1cs, input, current_hash, output) =
generate_sha256_round_constraints::<T::BellmanEngine>();
let variable_count = r1cs.aux_count + 1; // auxiliary and ONE let variable_count = r1cs.aux_count + 1; // auxiliary and ONE
@ -219,13 +221,6 @@ mod tests {
private: vec![true; 768], private: vec![true; 768],
}; };
//use rand::Rng;
// let mut rng = rand::thread_rng();
// let input: Vec<_> = (0..768).map(|_| {
// rng.gen_range(0, 2)
// }).collect();
let input = (0..512).map(|_| 0).chain((0..256).map(|_| 1)).collect(); let input = (0..512).map(|_| 0).chain((0..256).map(|_| 1)).collect();
prog.execute(&input).unwrap(); prog.execute(&input).unwrap();

View file

@ -6,5 +6,4 @@ edition = "2018"
[dependencies] [dependencies]
sapling-crypto = { git = 'https://github.com/matterinc/sapling-crypto', tag = "0.0.4" } sapling-crypto = { git = 'https://github.com/matterinc/sapling-crypto', tag = "0.0.4" }
bellman = { git = 'https://github.com/matterinc/bellman', tag = "0.2.0" } bellman = { git = 'https://github.com/matterinc/bellman', tag = "0.2.0" }
zokrates_field = { path = "../zokrates_field" }

View file

@ -1,15 +1,15 @@
use bellman::pairing::ff::Field;
use bellman::pairing::Engine; use bellman::pairing::Engine;
use bellman::ConstraintSystem; use bellman::ConstraintSystem;
use bellman::{Index, LinearCombination, SynthesisError, Variable}; use bellman::{Index, LinearCombination, SynthesisError, Variable};
use sapling_crypto::circuit::boolean::{AllocatedBit, Boolean}; use sapling_crypto::circuit::boolean::{AllocatedBit, Boolean};
use sapling_crypto::circuit::sha256::sha256_compression_function; use sapling_crypto::circuit::sha256::sha256_compression_function;
use sapling_crypto::circuit::uint32::UInt32; use sapling_crypto::circuit::uint32::UInt32;
use zokrates_field::field::Field;
#[derive(Debug)] #[derive(Debug)]
struct BellmanR1CS<E: Engine> { pub struct BellmanR1CS<E: Engine> {
aux_count: usize, pub aux_count: usize,
constraints: Vec<BellmanConstraint<E>>, pub constraints: Vec<BellmanConstraint<E>>,
} }
impl<E: Engine> BellmanR1CS<E> { impl<E: Engine> BellmanR1CS<E> {
@ -22,40 +22,29 @@ impl<E: Engine> BellmanR1CS<E> {
} }
#[derive(Debug)] #[derive(Debug)]
struct BellmanWitness<E: Engine> { pub struct BellmanWitness<E: Engine> {
pub values: Vec<E::Fr>, pub values: Vec<E::Fr>,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct BellmanConstraint<E: Engine> { pub struct BellmanConstraint<E: Engine> {
pub a: Vec<(usize, E::Fr)>, pub a: Vec<(usize, E::Fr)>,
pub b: Vec<(usize, E::Fr)>, pub b: Vec<(usize, E::Fr)>,
pub c: Vec<(usize, E::Fr)>, pub c: Vec<(usize, E::Fr)>,
} }
#[derive(Debug, PartialEq)] fn sha256_round<E: Engine, CS: ConstraintSystem<E>>(
pub struct Constraint<T: Field> {
pub a: Vec<(usize, T)>,
pub b: Vec<(usize, T)>,
pub c: Vec<(usize, T)>,
}
#[derive(Debug)]
pub struct R1CS<T: Field> {
pub aux_count: usize,
pub constraints: Vec<Constraint<T>>,
}
fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
mut cs: CS, mut cs: CS,
input: Option<&Vec<T>>, input: &Vec<Option<E::Fr>>,
current_hash: Option<&Vec<T>>, current_hash: &Vec<Option<E::Fr>>,
) -> Result<(Vec<usize>, Vec<usize>, Vec<usize>), SynthesisError> { ) -> Result<(Vec<usize>, Vec<usize>, Vec<usize>), SynthesisError> {
let input_bits = (0..512) let input_bits = input
.map(|i| { .iter()
AllocatedBit::alloc::<T::BellmanEngine, _>( .enumerate()
&mut cs.namespace(|| format!("input_{}", i)), .map(|(index, i)| {
Some(input.as_ref().unwrap()[i] == T::from(1)), AllocatedBit::alloc::<E, _>(
&mut cs.namespace(|| format!("input_{}", index)),
Some(*i == Some(<E::Fr as Field>::one())),
) )
.unwrap() .unwrap()
}) })
@ -66,11 +55,13 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
.map(|i| Boolean::Is(i.clone())) .map(|i| Boolean::Is(i.clone()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let current_hash_bits = (0..256) let current_hash_bits = current_hash
.map(|i| { .iter()
AllocatedBit::alloc::<T::BellmanEngine, _>( .enumerate()
&mut cs.namespace(|| format!("current_hash_{}", i)), .map(|(index, i)| {
Some(current_hash.as_ref().unwrap()[i] == T::from(1)), AllocatedBit::alloc::<E, _>(
&mut cs.namespace(|| format!("current_hash_{}", index)),
Some(*i == Some(<E::Fr as Field>::one())),
) )
.unwrap() .unwrap()
}) })
@ -88,8 +79,7 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let res = let res = sha256_compression_function::<E, _>(&mut cs, &input, &current_hash).unwrap();
sha256_compression_function::<T::BellmanEngine, _>(&mut cs, &input, &current_hash).unwrap();
let output_bits = res let output_bits = res
.into_iter() .into_iter()
@ -100,59 +90,23 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
Ok(( Ok((
input_bits input_bits
.into_iter() .into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable())) .map(|b| var_to_index(b.get_variable()))
.collect(), .collect(),
current_hash_bits current_hash_bits
.into_iter() .into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable())) .map(|b| var_to_index(b.get_variable()))
.collect(), .collect(),
output_bits output_bits
.into_iter() .into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable())) .map(|b| var_to_index(b.get_variable()))
.collect(), .collect(),
)) ))
} }
impl<T: Field> R1CS<T> {
fn from_bellman(cs: BellmanR1CS<T::BellmanEngine>) -> Self {
R1CS {
aux_count: cs.aux_count,
constraints: cs
.constraints
.into_iter()
.map(|c| Constraint::from_bellman(c))
.collect(),
}
}
}
impl<T: Field> Constraint<T> {
fn from_bellman(cs: BellmanConstraint<T::BellmanEngine>) -> Self {
let res = Constraint {
a: cs
.a
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
b: cs
.b
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
c: cs
.c
.into_iter()
.map(|(variable, coefficient)| (variable, T::from_bellman(coefficient)))
.collect(),
};
res
}
}
impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> { impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
type Root = Self; type Root = Self;
fn alloc<F, A, AR>(&mut self, _annotation: A, f: F) -> Result<Variable, SynthesisError> fn alloc<F, A, AR>(&mut self, _: A, f: F) -> Result<Variable, SynthesisError>
where where
F: FnOnce() -> Result<E::Fr, SynthesisError>, F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR, A: FnOnce() -> AR,
@ -165,7 +119,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
Ok(var) Ok(var)
} }
fn alloc_input<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError> fn alloc_input<F, A, AR>(&mut self, _: A, _: F) -> Result<Variable, SynthesisError>
where where
F: FnOnce() -> Result<E::Fr, SynthesisError>, F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR, A: FnOnce() -> AR,
@ -174,7 +128,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
unreachable!("Bellman helpers are not allowed to allocate public variables") unreachable!("Bellman helpers are not allowed to allocate public variables")
} }
fn enforce<A, AR, LA, LB, LC>(&mut self, _annotation: A, _a: LA, _b: LB, _c: LC) fn enforce<A, AR, LA, LB, LC>(&mut self, _: A, _: LA, _: LB, _: LC)
where where
A: FnOnce() -> AR, A: FnOnce() -> AR,
AR: Into<String>, AR: Into<String>,
@ -185,7 +139,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
// do nothing // do nothing
} }
fn push_namespace<NR, N>(&mut self, _name_fn: N) fn push_namespace<NR, N>(&mut self, _: N)
where where
NR: Into<String>, NR: Into<String>,
N: FnOnce() -> NR, N: FnOnce() -> NR,
@ -205,7 +159,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> { impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
type Root = Self; type Root = Self;
fn alloc<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError> fn alloc<F, A, AR>(&mut self, _: A, _: F) -> Result<Variable, SynthesisError>
where where
F: FnOnce() -> Result<E::Fr, SynthesisError>, F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR, A: FnOnce() -> AR,
@ -218,7 +172,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
Ok(var) Ok(var)
} }
fn alloc_input<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError> fn alloc_input<F, A, AR>(&mut self, _: A, _: F) -> Result<Variable, SynthesisError>
where where
F: FnOnce() -> Result<E::Fr, SynthesisError>, F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR, A: FnOnce() -> AR,
@ -227,7 +181,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
unreachable!("Bellman helpers are not allowed to allocate public variables") unreachable!("Bellman helpers are not allowed to allocate public variables")
} }
fn enforce<A, AR, LA, LB, LC>(&mut self, _annotation: A, a: LA, b: LB, c: LC) fn enforce<A, AR, LA, LB, LC>(&mut self, _: A, a: LA, b: LB, c: LC)
where where
A: FnOnce() -> AR, A: FnOnce() -> AR,
AR: Into<String>, AR: Into<String>,
@ -242,29 +196,23 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
let a = a let a = a
.as_ref() .as_ref()
.into_iter() .into_iter()
.map(|(variable, coefficient)| { .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect(); .collect();
let b = b let b = b
.as_ref() .as_ref()
.into_iter() .into_iter()
.map(|(variable, coefficient)| { .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect(); .collect();
let c = c let c = c
.as_ref() .as_ref()
.into_iter() .into_iter()
.map(|(variable, coefficient)| { .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.collect(); .collect();
self.constraints.push(BellmanConstraint { a, b, c }); self.constraints.push(BellmanConstraint { a, b, c });
} }
fn push_namespace<NR, N>(&mut self, _name_fn: N) fn push_namespace<NR, N>(&mut self, _: N)
where where
NR: Into<String>, NR: Into<String>,
N: FnOnce() -> NR, N: FnOnce() -> NR,
@ -281,83 +229,55 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
} }
} }
pub fn generate_xor_constraints<T: Field>() -> (R1CS<T>, usize) { pub fn generate_sha256_round_constraints<E: Engine>(
) -> (BellmanR1CS<E>, Vec<usize>, Vec<usize>, Vec<usize>) {
let mut cs = BellmanR1CS::new(); let mut cs = BellmanR1CS::new();
let i0 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).unwrap()); let (input_bits, current_hash_bits, output_bits) =
let i1 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).unwrap()); sha256_round(&mut cs, &vec![None; 512], &vec![None; 256]).unwrap();
let res = Boolean::xor(&mut cs, &i0, &i1).unwrap();
let res =
BellmanR1CS::<T::BellmanEngine>::var_to_index(res.get_variable().unwrap().get_variable());
let cs = R1CS::from_bellman(cs);
(cs, res)
}
pub fn generate_xor_witness<T: Field>(i1: bool, i2: bool) -> Vec<T> {
let mut cs = BellmanWitness {
values: vec![T::from(1).into_bellman()],
};
let i0 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, Some(i1)).unwrap());
let i1 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, Some(i2)).unwrap());
Boolean::xor(&mut cs, &i0, &i1).unwrap();
cs.values.into_iter().map(|v| T::from_bellman(v)).collect()
}
pub fn generate_sha256_round_constraints<T: Field>() -> (R1CS<T>, Vec<usize>, Vec<usize>, Vec<usize>)
{
let mut cs = BellmanR1CS::new();
let (input_bits, current_hash_bits, output_bits) = sha256_round::<T, _>(
&mut cs,
Some(&vec![T::from(0); 512]),
Some(&vec![T::from(0); 256]),
)
.unwrap();
// res is now the allocated bits for input, current_hash and sha256_output // res is now the allocated bits for input, current_hash and sha256_output
let cs = R1CS::<T>::from_bellman(cs);
(cs, input_bits, current_hash_bits, output_bits) (cs, input_bits, current_hash_bits, output_bits)
} }
pub fn generate_sha256_round_witness<T: Field>(input: &[T], current_hash: &[T]) -> Vec<T> { pub fn generate_sha256_round_witness<E: Engine>(
input: &[E::Fr],
current_hash: &[E::Fr],
) -> Vec<E::Fr> {
assert_eq!(input.len(), 512); assert_eq!(input.len(), 512);
assert_eq!(current_hash.len(), 256); assert_eq!(current_hash.len(), 256);
let mut cs = BellmanWitness { let mut cs: BellmanWitness<E> = BellmanWitness {
values: vec![T::from(1).into_bellman()], values: vec![<E::Fr as Field>::one()],
}; };
sha256_round(&mut cs, Some(&input.to_vec()), Some(&current_hash.to_vec())).unwrap(); sha256_round(
&mut cs,
&input.iter().map(|x| Some(x.clone())).collect(),
&current_hash.iter().map(|x| Some(x.clone())).collect(),
)
.unwrap();
cs.values.into_iter().map(|v| T::from_bellman(v)).collect() cs.values
} }
impl<E: Engine> BellmanR1CS<E> { fn var_to_index(v: Variable) -> usize {
fn var_to_index(v: Variable) -> usize { match v.get_unchecked() {
match v.get_unchecked() { Index::Aux(i) => i + 1,
Index::Aux(i) => i + 1, Index::Input(0) => 0,
Index::Input(0) => 0, _ => unreachable!(),
_ => unreachable!(),
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use zokrates_field::field::FieldPrime; use bellman::pairing::bn256::{Bn256, Fr};
#[test] #[test]
fn generate_constraints() { fn generate_constraints() {
let (_c, input, current_hash, output) = generate_sha256_round_constraints::<FieldPrime>(); let (_c, input, current_hash, output) = generate_sha256_round_constraints::<Bn256>();
assert_eq!(input.len(), 512); assert_eq!(input.len(), 512);
assert_eq!(current_hash.len(), 256); assert_eq!(current_hash.len(), 256);
assert_eq!(output.len(), 256); assert_eq!(output.len(), 256);
@ -365,45 +285,21 @@ mod tests {
#[test] #[test]
fn generate_witness() { fn generate_witness() {
let witness = generate_sha256_round_witness( let witness =
&vec![FieldPrime::from(0); 512], generate_sha256_round_witness::<Bn256>(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]);
&vec![FieldPrime::from(0); 256],
);
assert_eq!(witness.len(), 26935); assert_eq!(witness.len(), 26935);
} }
#[test]
fn xor() {
let (_, indice) = generate_xor_constraints::<FieldPrime>();
assert_eq!(
FieldPrime::from(0),
generate_xor_witness::<FieldPrime>(true, true)[indice]
);
assert_eq!(
FieldPrime::from(1),
generate_xor_witness::<FieldPrime>(true, false)[indice]
);
assert_eq!(
FieldPrime::from(1),
generate_xor_witness::<FieldPrime>(false, true)[indice]
);
assert_eq!(
FieldPrime::from(0),
generate_xor_witness::<FieldPrime>(false, false)[indice]
);
}
#[test] #[test]
fn test_cs() { fn test_cs() {
use sapling_crypto::circuit::test::TestConstraintSystem; use sapling_crypto::circuit::test::TestConstraintSystem;
let mut cs = TestConstraintSystem::new(); let mut cs: TestConstraintSystem<Bn256> = TestConstraintSystem::new();
let _ = sha256_round::<FieldPrime, _>( let _ = sha256_round(
&mut cs, &mut cs,
Some(&vec![FieldPrime::from(0); 512]), &vec![Some(Fr::zero()); 512],
Some(&vec![FieldPrime::from(1); 256]), &vec![Some(Fr::one()); 256],
) )
.unwrap(); .unwrap();