clean, change signature to take arrays and return array
This commit is contained in:
parent
0aad524ab2
commit
ed252ad5f0
2 changed files with 95 additions and 95 deletions
|
@ -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
Loading…
Reference in a new issue