1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

clean, change signature to take arrays and return array

This commit is contained in:
schaeff 2019-04-10 15:51:05 +02:00
parent 0aad524ab2
commit ed252ad5f0
2 changed files with 95 additions and 95 deletions

View file

@ -1,3 +1,4 @@
use bellman::pairing::ff::ScalarEngine;
use flat_absy::{FlatExpression, FlatExpressionList, FlatFunction, FlatStatement};
use flat_absy::{FlatParameter, FlatVariable};
use helpers::{DirectiveStatement, Helper, RustHelper};
@ -6,124 +7,123 @@ use types::{Signature, Type};
use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint};
use zokrates_field::field::Field;
// util to convert a vector of `(variable_id, coefficient)` to a flat_expression
fn flat_expression_from_vec<T: Field>(
v: Vec<(usize, <<T as Field>::BellmanEngine as ScalarEngine>::Fr)>,
) -> FlatExpression<T> {
match v
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
}
}
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(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
let rhs_b = match c
.b
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
let lhs = match c
.c
.into_iter()
.map(|(key, val)| {
FlatExpression::Mult(
box FlatExpression::Number(T::from_bellman(val)),
box FlatExpression::Identifier(FlatVariable::new(key)),
)
})
.reduce(|acc, e| FlatExpression::Add(box acc, box e))
{
Some(e @ FlatExpression::Mult(..)) => {
FlatExpression::Add(box FlatExpression::Number(T::zero()), box e)
} // the R1CS serializer only recognizes Add
Some(e) => e,
None => FlatExpression::Number(T::zero()),
};
let rhs_a = flat_expression_from_vec(c.a);
let rhs_b = flat_expression_from_vec(c.b);
let lhs = flat_expression_from_vec(c.c);
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
}
}
/// Returns a flat function which computes a sha256 round
///
/// # Remarks
///
/// The variables inside the function are set in this order:
/// - constraint system variables
/// - arguments
pub fn sha_round<T: Field>() -> FlatFunction<T> {
let (r1cs, input, current_hash, output) =
// Define iterators for all indices at hand
let (r1cs, input_indices, current_hash_indices, output_indices) =
generate_sha256_round_constraints::<T::BellmanEngine>();
// indices of the input
let input_indices = input_indices.into_iter();
// indices of the current hash
let current_hash_indices = current_hash_indices.into_iter();
// indices of the output
let output_indices = output_indices.into_iter();
let variable_count = r1cs.aux_count + 1; // auxiliary and ONE
// define the inputs with dummy variables: arguments to the function and to the directive
let input_variables: Vec<FlatVariable> = input
.iter()
.chain(current_hash.iter())
.map(|i| FlatVariable::new(i + variable_count))
.collect();
let arguments = input_variables
.iter()
// indices of the sha256round constraint system variables
let cs_indices = (0..variable_count).into_iter();
// indices of the arguments to the function
// apply an offset of `variable_count` to get the indice of our dummy `input` argument
let input_argument_indices = input_indices
.clone()
.into_iter()
.map(|i| i + variable_count);
// apply an offset of `variable_count` to get the indice of our dummy `current_hash` argument
let current_hash_argument_indices = current_hash_indices
.clone()
.into_iter()
.map(|i| i + variable_count);
// define the signature of the resulting function
let signature = Signature {
inputs: vec![
Type::FieldElementArray(input_indices.len()),
Type::FieldElementArray(current_hash_indices.len()),
],
outputs: vec![Type::FieldElementArray(output_indices.len())],
};
// define parameters to the function based on the variables
let arguments = input_argument_indices
.clone()
.chain(current_hash_argument_indices.clone())
.map(|i| FlatParameter {
id: i.clone(),
id: FlatVariable::new(i),
private: true,
})
.collect();
let inputs: Vec<FlatExpression<T>> = input_variables
.into_iter()
.map(|i| FlatExpression::Identifier(i))
.collect();
let input_binding_statements = // bind first variable to ~one
std::iter::once(FlatStatement::Condition(
// define a binding of the first variable in the constraint system to one
let one_binding_statement = FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(T::from(1)),
))
);
let input_binding_statements =
// bind input and current_hash to inputs
.chain(input.iter().chain(current_hash.iter()).map(|i| {
input_indices.clone().chain(current_hash_indices).zip(input_argument_indices.clone().chain(current_hash_argument_indices.clone())).map(|(cs_index, argument_index)| {
FlatStatement::Condition(
FlatVariable::new(*i).into(),
FlatVariable::new(i + variable_count).into(),
FlatVariable::new(cs_index).into(),
FlatVariable::new(argument_index).into(),
)
}));
});
// insert flattened statements to represent constraints
let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into());
// define the entire witness
let variables = (0..variable_count).map(|i| FlatVariable::new(i)).collect();
// define which subset of the witness is returned
let outputs: Vec<FlatExpression<T>> = output
.into_iter()
let outputs: Vec<FlatExpression<T>> = output_indices
.map(|o| FlatExpression::Identifier(FlatVariable::new(o)))
.collect();
let signature = Signature {
inputs: vec![Type::FieldElement; inputs.len()],
outputs: vec![Type::FieldElement; outputs.len()],
};
// insert a directive to set the witness based on the bellman gadget and inputs
let directive_statement = FlatStatement::Directive(DirectiveStatement {
outputs: variables,
inputs: inputs,
outputs: cs_indices.map(|i| FlatVariable::new(i)).collect(),
inputs: input_argument_indices
.chain(current_hash_argument_indices)
.map(|i| FlatVariable::new(i).into())
.collect(),
helper: Helper::Rust(RustHelper::Sha256Round),
});
@ -133,6 +133,7 @@ pub fn sha_round<T: Field>() -> FlatFunction<T> {
});
let statements = std::iter::once(directive_statement)
.chain(std::iter::once(one_binding_statement))
.chain(input_binding_statements)
.chain(constraint_statements)
.chain(std::iter::once(return_statement))
@ -159,8 +160,11 @@ mod tests {
assert_eq!(
compiled.signature,
Signature::new()
.inputs(vec![Type::FieldElement; 768])
.outputs(vec![Type::FieldElement; 256])
.inputs(vec![
Type::FieldElementArray(512),
Type::FieldElementArray(256)
])
.outputs(vec![Type::FieldElementArray(256)])
);
// function should have 768 inputs

File diff suppressed because one or more lines are too long