1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +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 = [
"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)",
"zokrates_field 0.3.2",
]
[[package]]

View file

@ -57,8 +57,13 @@ impl<T: Field> Executable<T> for RustHelper {
RustHelper::Sha256Round => {
let i = &inputs[0..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);
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() {
let pos = import.pos();
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") {
match import.source.as_ref() {
"BELLMAN/sha256round" => {

View file

@ -3,16 +3,17 @@ use flat_absy::{FlatParameter, FlatVariable};
use helpers::{DirectiveStatement, Helper, RustHelper};
use reduce::Reduce;
use types::{Signature, Type};
use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint};
use zokrates_field::field::Field;
impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
fn from(c: zokrates_embed::Constraint<T>) -> FlatStatement<T> {
impl<T: Field> From<BellmanConstraint<T::BellmanEngine>> for FlatStatement<T> {
fn from(c: zokrates_embed::BellmanConstraint<T::BellmanEngine>) -> FlatStatement<T> {
let rhs_a = match c
.a
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val),
box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
@ -30,7 +31,7 @@ impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val),
box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
@ -48,7 +49,7 @@ impl<T: Field> From<zokrates_embed::Constraint<T>> for FlatStatement<T> {
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(val),
box FlatExpression::Number(T::from_bellman(val)),
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> {
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
@ -219,13 +221,6 @@ mod tests {
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();
prog.execute(&input).unwrap();

View file

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

View file

@ -1,15 +1,15 @@
use bellman::pairing::ff::Field;
use bellman::pairing::Engine;
use bellman::ConstraintSystem;
use bellman::{Index, LinearCombination, SynthesisError, Variable};
use sapling_crypto::circuit::boolean::{AllocatedBit, Boolean};
use sapling_crypto::circuit::sha256::sha256_compression_function;
use sapling_crypto::circuit::uint32::UInt32;
use zokrates_field::field::Field;
#[derive(Debug)]
struct BellmanR1CS<E: Engine> {
aux_count: usize,
constraints: Vec<BellmanConstraint<E>>,
pub struct BellmanR1CS<E: Engine> {
pub aux_count: usize,
pub constraints: Vec<BellmanConstraint<E>>,
}
impl<E: Engine> BellmanR1CS<E> {
@ -22,40 +22,29 @@ impl<E: Engine> BellmanR1CS<E> {
}
#[derive(Debug)]
struct BellmanWitness<E: Engine> {
pub struct BellmanWitness<E: Engine> {
pub values: Vec<E::Fr>,
}
#[derive(Debug, PartialEq)]
struct BellmanConstraint<E: Engine> {
pub struct BellmanConstraint<E: Engine> {
pub a: Vec<(usize, E::Fr)>,
pub b: Vec<(usize, E::Fr)>,
pub c: Vec<(usize, E::Fr)>,
}
#[derive(Debug, PartialEq)]
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>>(
fn sha256_round<E: Engine, CS: ConstraintSystem<E>>(
mut cs: CS,
input: Option<&Vec<T>>,
current_hash: Option<&Vec<T>>,
input: &Vec<Option<E::Fr>>,
current_hash: &Vec<Option<E::Fr>>,
) -> Result<(Vec<usize>, Vec<usize>, Vec<usize>), SynthesisError> {
let input_bits = (0..512)
.map(|i| {
AllocatedBit::alloc::<T::BellmanEngine, _>(
&mut cs.namespace(|| format!("input_{}", i)),
Some(input.as_ref().unwrap()[i] == T::from(1)),
let input_bits = input
.iter()
.enumerate()
.map(|(index, i)| {
AllocatedBit::alloc::<E, _>(
&mut cs.namespace(|| format!("input_{}", index)),
Some(*i == Some(<E::Fr as Field>::one())),
)
.unwrap()
})
@ -66,11 +55,13 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
.map(|i| Boolean::Is(i.clone()))
.collect::<Vec<_>>();
let current_hash_bits = (0..256)
.map(|i| {
AllocatedBit::alloc::<T::BellmanEngine, _>(
&mut cs.namespace(|| format!("current_hash_{}", i)),
Some(current_hash.as_ref().unwrap()[i] == T::from(1)),
let current_hash_bits = current_hash
.iter()
.enumerate()
.map(|(index, i)| {
AllocatedBit::alloc::<E, _>(
&mut cs.namespace(|| format!("current_hash_{}", index)),
Some(*i == Some(<E::Fr as Field>::one())),
)
.unwrap()
})
@ -88,8 +79,7 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
})
.collect::<Vec<_>>();
let res =
sha256_compression_function::<T::BellmanEngine, _>(&mut cs, &input, &current_hash).unwrap();
let res = sha256_compression_function::<E, _>(&mut cs, &input, &current_hash).unwrap();
let output_bits = res
.into_iter()
@ -100,59 +90,23 @@ fn sha256_round<T: Field, CS: ConstraintSystem<T::BellmanEngine>>(
Ok((
input_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.map(|b| var_to_index(b.get_variable()))
.collect(),
current_hash_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.map(|b| var_to_index(b.get_variable()))
.collect(),
output_bits
.into_iter()
.map(|b| BellmanR1CS::<T::BellmanEngine>::var_to_index(b.get_variable()))
.map(|b| var_to_index(b.get_variable()))
.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> {
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
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
@ -165,7 +119,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
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
F: FnOnce() -> Result<E::Fr, SynthesisError>,
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")
}
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
A: FnOnce() -> AR,
AR: Into<String>,
@ -185,7 +139,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
// do nothing
}
fn push_namespace<NR, N>(&mut self, _name_fn: N)
fn push_namespace<NR, N>(&mut self, _: N)
where
NR: Into<String>,
N: FnOnce() -> NR,
@ -205,7 +159,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanWitness<E> {
impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
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
F: FnOnce() -> Result<E::Fr, SynthesisError>,
A: FnOnce() -> AR,
@ -218,7 +172,7 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
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
F: FnOnce() -> Result<E::Fr, SynthesisError>,
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")
}
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
A: FnOnce() -> AR,
AR: Into<String>,
@ -242,29 +196,23 @@ impl<E: Engine> ConstraintSystem<E> for BellmanR1CS<E> {
let a = a
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
.collect();
let b = b
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
.collect();
let c = c
.as_ref()
.into_iter()
.map(|(variable, coefficient)| {
(BellmanR1CS::<E>::var_to_index(*variable), *coefficient)
})
.map(|(variable, coefficient)| (var_to_index(*variable), *coefficient))
.collect();
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
NR: Into<String>,
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 i0 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).unwrap());
let i1 = Boolean::Is(AllocatedBit::alloc::<T::BellmanEngine, _>(&mut cs, None).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();
let (input_bits, current_hash_bits, output_bits) =
sha256_round(&mut cs, &vec![None; 512], &vec![None; 256]).unwrap();
// 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)
}
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!(current_hash.len(), 256);
let mut cs = BellmanWitness {
values: vec![T::from(1).into_bellman()],
let mut cs: BellmanWitness<E> = BellmanWitness {
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 {
match v.get_unchecked() {
Index::Aux(i) => i + 1,
Index::Input(0) => 0,
_ => unreachable!(),
}
fn var_to_index(v: Variable) -> usize {
match v.get_unchecked() {
Index::Aux(i) => i + 1,
Index::Input(0) => 0,
_ => unreachable!(),
}
}
#[cfg(test)]
mod tests {
use super::*;
use zokrates_field::field::FieldPrime;
use bellman::pairing::bn256::{Bn256, Fr};
#[test]
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!(current_hash.len(), 256);
assert_eq!(output.len(), 256);
@ -365,45 +285,21 @@ mod tests {
#[test]
fn generate_witness() {
let witness = generate_sha256_round_witness(
&vec![FieldPrime::from(0); 512],
&vec![FieldPrime::from(0); 256],
);
let witness =
generate_sha256_round_witness::<Bn256>(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]);
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]
fn test_cs() {
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,
Some(&vec![FieldPrime::from(0); 512]),
Some(&vec![FieldPrime::from(1); 256]),
&vec![Some(Fr::zero()); 512],
&vec![Some(Fr::one()); 256],
)
.unwrap();