patch unconstrained cast
This commit is contained in:
parent
57ed8adb1d
commit
6ecc2c9885
7 changed files with 24 additions and 189 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -796,7 +796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_cli"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -804,14 +804,14 @@ dependencies = [
|
|||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zokrates_core 0.3.5",
|
||||
"zokrates_core 0.3.6",
|
||||
"zokrates_field 0.3.2",
|
||||
"zokrates_fs_resolver 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zokrates_core"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
dependencies = [
|
||||
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_cli"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>", "Thibaut Schaeffer <thibaut@schaeff.fr>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates.git"
|
||||
edition = "2018"
|
||||
|
|
|
@ -42,7 +42,7 @@ fn cli() -> Result<(), String> {
|
|||
// cli specification using clap library
|
||||
let matches = App::new("ZoKrates")
|
||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||
.version("0.4.1")
|
||||
.version("0.4.2")
|
||||
.author("Jacob Eberhardt, Thibaut Schaeffer, Dennis Kuhnert")
|
||||
.about("Supports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.\n'I know that I show nothing!'")
|
||||
.subcommand(SubCommand::with_name("compile")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_core"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
use zokrates_field::field::Field;
|
||||
|
||||
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Debug)]
|
||||
pub struct Constraints<T: Field> {
|
||||
pub constraints: Vec<Constraint<T>>,
|
||||
}
|
||||
|
||||
impl<T: Field> Constraints<T> {
|
||||
pub fn none() -> Constraints<T> {
|
||||
Constraints {
|
||||
constraints: vec![],
|
||||
}
|
||||
}
|
||||
pub fn boolean() -> Constraints<T> {
|
||||
Constraints {
|
||||
constraints: vec![Constraint {
|
||||
a: box [T::from(1)],
|
||||
b: box [T::from(1)],
|
||||
c: box [T::from(1)],
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Debug)]
|
||||
pub struct Constraint<T: Field> {
|
||||
pub a: Box<[T]>,
|
||||
pub b: Box<[T]>,
|
||||
pub c: Box<[T]>,
|
||||
}
|
|
@ -3,8 +3,6 @@ use flat_absy::flat_parameter::FlatParameter;
|
|||
use flat_absy::flat_variable::FlatVariable;
|
||||
use flat_absy::*;
|
||||
use helpers::{DirectiveStatement, Helper};
|
||||
use reduce::Reduce;
|
||||
use types::constraints::Constraint;
|
||||
use types::signature::Signature;
|
||||
use types::Type;
|
||||
use zokrates_field::field::Field;
|
||||
|
@ -167,94 +165,24 @@ pub fn cast<T: Field>(from: &Type, to: &Type) -> FlatFunction<T> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let directive_inputs = (0..from.get_primitive_count())
|
||||
let binding_inputs: Vec<_> = (0..from.get_primitive_count())
|
||||
.map(|index| use_variable(&mut bijection, format!("i{}", index), &mut counter))
|
||||
.collect();
|
||||
let directive_outputs: Vec<FlatVariable> = (0..to.get_primitive_count())
|
||||
let binding_outputs: Vec<FlatVariable> = (0..to.get_primitive_count())
|
||||
.map(|index| use_variable(&mut bijection, format!("o{}", index), &mut counter))
|
||||
.collect();
|
||||
|
||||
let constraints = to.get_constraints::<T>().constraints;
|
||||
|
||||
let intermediate_variables = match constraints.len() {
|
||||
0 => vec![],
|
||||
_ => constraints[0]
|
||||
.a
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(_, index)| use_variable(&mut bijection, format!("inter{}", index), &mut counter))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let conditions: Vec<FlatStatement<T>> = to
|
||||
.get_constraints()
|
||||
.constraints
|
||||
let outputs = binding_outputs
|
||||
.iter()
|
||||
.map(|constraint: &Constraint<T>| {
|
||||
let rhs_a = match constraint
|
||||
.a
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(key, val)| {
|
||||
FlatExpression::Mult(
|
||||
box FlatExpression::Number(val.clone()),
|
||||
box FlatExpression::Identifier(intermediate_variables[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 constraint
|
||||
.b
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(key, val)| {
|
||||
FlatExpression::Mult(
|
||||
box FlatExpression::Number(val.clone()),
|
||||
box FlatExpression::Identifier(intermediate_variables[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 constraint
|
||||
.c
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(key, val)| {
|
||||
FlatExpression::Mult(
|
||||
box FlatExpression::Number(val.clone()),
|
||||
box FlatExpression::Identifier(intermediate_variables[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()),
|
||||
};
|
||||
|
||||
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
|
||||
})
|
||||
.map(|o| FlatExpression::Identifier(o.clone()))
|
||||
.collect();
|
||||
|
||||
let helper = match (from, to) {
|
||||
(Type::Boolean, Type::FieldElement) => Helper::identity(),
|
||||
(Type::FieldElement, Type::Boolean) => Helper::identity(),
|
||||
let bindings: Vec<_> = match (from, to) {
|
||||
(Type::Boolean, Type::FieldElement) => binding_outputs
|
||||
.into_iter()
|
||||
.zip(binding_inputs.into_iter())
|
||||
.map(|(o, i)| FlatStatement::Definition(o, i.into()))
|
||||
.collect(),
|
||||
_ => panic!(format!("can't cast {} to {}", from, to)),
|
||||
};
|
||||
|
||||
|
@ -263,26 +191,13 @@ pub fn cast<T: Field>(from: &Type, to: &Type) -> FlatFunction<T> {
|
|||
outputs: vec![to.clone()],
|
||||
};
|
||||
|
||||
let outputs = directive_outputs
|
||||
.iter()
|
||||
.map(|o| FlatExpression::Identifier(o.clone()))
|
||||
let statements = bindings
|
||||
.into_iter()
|
||||
.chain(std::iter::once(FlatStatement::Return(FlatExpressionList {
|
||||
expressions: outputs,
|
||||
})))
|
||||
.collect();
|
||||
|
||||
let mut statements = conditions;
|
||||
|
||||
statements.insert(
|
||||
0,
|
||||
FlatStatement::Directive(DirectiveStatement::new(
|
||||
directive_outputs,
|
||||
helper,
|
||||
directive_inputs,
|
||||
)),
|
||||
);
|
||||
|
||||
statements.push(FlatStatement::Return(FlatExpressionList {
|
||||
expressions: outputs,
|
||||
}));
|
||||
|
||||
FlatFunction {
|
||||
id: format!("_{}_to_{}", from, to),
|
||||
arguments,
|
||||
|
@ -300,48 +215,19 @@ mod tests {
|
|||
mod cast {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn field_to_bool() {
|
||||
let f2b: FlatFunction<FieldPrime> = cast(&Type::FieldElement, &Type::Boolean);
|
||||
assert_eq!(f2b.id, String::from("_field_to_bool"));
|
||||
assert_eq!(
|
||||
f2b.arguments,
|
||||
vec![FlatParameter::private(FlatVariable::new(0))]
|
||||
);
|
||||
assert_eq!(f2b.statements.len(), 3); // 1 directive, 1 constraint, 1 return
|
||||
assert_eq!(
|
||||
f2b.statements[0],
|
||||
FlatStatement::Directive(DirectiveStatement::new(
|
||||
vec![FlatVariable::new(1)],
|
||||
Helper::identity(),
|
||||
vec![FlatVariable::new(0)]
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
f2b.statements[2],
|
||||
FlatStatement::Return(FlatExpressionList {
|
||||
expressions: vec![FlatExpression::Identifier(FlatVariable::new(1))]
|
||||
})
|
||||
);
|
||||
assert_eq!(f2b.signature.outputs.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bool_to_field() {
|
||||
let b2f: FlatFunction<FieldPrime> = cast(&Type::Boolean, &Type::FieldElement);
|
||||
println!("{}", b2f);
|
||||
assert_eq!(b2f.id, String::from("_bool_to_field"));
|
||||
assert_eq!(
|
||||
b2f.arguments,
|
||||
vec![FlatParameter::private(FlatVariable::new(0))]
|
||||
);
|
||||
assert_eq!(b2f.statements.len(), 2); // 1 directive, 1 return
|
||||
assert_eq!(b2f.statements.len(), 2); // 1 definition, 1 return
|
||||
assert_eq!(
|
||||
b2f.statements[0],
|
||||
FlatStatement::Directive(DirectiveStatement::new(
|
||||
vec![FlatVariable::new(1)],
|
||||
Helper::identity(),
|
||||
vec![FlatVariable::new(0)]
|
||||
))
|
||||
FlatStatement::Definition(FlatVariable::new(1), FlatVariable::new(0).into())
|
||||
);
|
||||
assert_eq!(
|
||||
b2f.statements[1],
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use std::fmt;
|
||||
use types::constraints::Constraints;
|
||||
pub use types::signature::Signature;
|
||||
use zokrates_field::field::Field;
|
||||
|
||||
mod constraints;
|
||||
pub mod conversions;
|
||||
mod signature;
|
||||
|
||||
|
@ -35,14 +32,6 @@ impl fmt::Debug for Type {
|
|||
}
|
||||
|
||||
impl Type {
|
||||
fn get_constraints<T: Field>(&self) -> Constraints<T> {
|
||||
match self {
|
||||
Type::FieldElement => Constraints::none(),
|
||||
Type::Boolean => Constraints::boolean(),
|
||||
Type::FieldElementArray(_) => Type::FieldElement.get_constraints(),
|
||||
}
|
||||
}
|
||||
|
||||
// the number of field elements the type maps to
|
||||
pub fn get_primitive_count(&self) -> usize {
|
||||
match self {
|
||||
|
@ -64,21 +53,11 @@ impl Type {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use zokrates_field::field::FieldPrime;
|
||||
|
||||
#[test]
|
||||
fn array() {
|
||||
let t = Type::FieldElementArray(42);
|
||||
assert_eq!(t.get_primitive_count(), 42);
|
||||
assert_eq!(t.get_constraints::<FieldPrime>(), Constraints::none());
|
||||
assert_eq!(t.to_slug(), "f[42]");
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn array_of_arrays() {
|
||||
// let t = Type::FieldElementArray(42, box Type::FieldElementArray(33, box Type::Boolean));
|
||||
// assert_eq!(t.get_primitive_count(), 1);
|
||||
// assert_eq!(t.get_constraints::<FieldPrime>(), Constraints::boolean());
|
||||
// assert_eq!(t.to_slug(), "[]");
|
||||
// }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue