use variable as function output, avoid substituting outputs
This commit is contained in:
commit
87ddcdcc55
12 changed files with 65 additions and 71 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -796,7 +796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_cli"
|
||||
version = "0.3.3"
|
||||
version = "0.4.0"
|
||||
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.3",
|
||||
"zokrates_field 0.3.1",
|
||||
"zokrates_fs_resolver 0.3.2",
|
||||
"zokrates_core 0.3.4",
|
||||
"zokrates_field 0.3.2",
|
||||
"zokrates_fs_resolver 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zokrates_core"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
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)",
|
||||
|
@ -832,12 +832,12 @@ dependencies = [
|
|||
"serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zokrates_field 0.3.1",
|
||||
"zokrates_field 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zokrates_field"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
dependencies = [
|
||||
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -851,7 +851,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_fs_resolver"
|
||||
version = "0.3.2"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_cli"
|
||||
version = "0.3.3"
|
||||
version = "0.4.0"
|
||||
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"
|
||||
|
@ -15,7 +15,7 @@ bincode = "0.8.0"
|
|||
regex = "0.2"
|
||||
zokrates_field = { version = "0.3", path = "../zokrates_field" }
|
||||
zokrates_core = { version = "0.3", path = "../zokrates_core" }
|
||||
zokrates_fs_resolver = { version = "0.3", path = "../zokrates_fs_resolver"}
|
||||
zokrates_fs_resolver = { version = "0.4", path = "../zokrates_fs_resolver"}
|
||||
|
||||
[dev-dependencies]
|
||||
glob = "0.2.11"
|
||||
|
|
|
@ -42,7 +42,7 @@ fn cli() -> Result<(), String> {
|
|||
// cli specification using clap library
|
||||
let matches = App::new("ZoKrates")
|
||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||
.version("0.3.3")
|
||||
.version("0.4.0")
|
||||
.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.3"
|
||||
version = "0.3.4"
|
||||
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -27,10 +27,6 @@ impl FlatVariable {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.id < 0
|
||||
}
|
||||
|
||||
pub fn id(&self) -> usize {
|
||||
assert!(self.id > 0);
|
||||
(self.id as usize) - 1
|
||||
|
|
|
@ -100,7 +100,7 @@ pub fn fold_function<T: Field, F: Folder<T>>(f: &mut F, fun: Function<T>) -> Fun
|
|||
returns: fun
|
||||
.returns
|
||||
.into_iter()
|
||||
.map(|e| f.fold_quadratic_combination(e))
|
||||
.map(|v| f.fold_variable(v))
|
||||
.collect(),
|
||||
..fun
|
||||
}
|
||||
|
|
|
@ -19,8 +19,9 @@ impl<T: Field> From<FlatFunction<T>> for Function<T> {
|
|||
id: flat_function.id,
|
||||
arguments: flat_function.arguments.into_iter().map(|p| p.id).collect(),
|
||||
returns: return_expressions
|
||||
.into_iter()
|
||||
.map(|e| QuadComb::from_flat_expression(e))
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, _)| FlatVariable::public(index))
|
||||
.collect(),
|
||||
statements: flat_function
|
||||
.statements
|
||||
|
@ -29,6 +30,17 @@ impl<T: Field> From<FlatFunction<T>> for Function<T> {
|
|||
FlatStatement::Return(..) => None,
|
||||
s => Some(s.into()),
|
||||
})
|
||||
.chain(
|
||||
return_expressions
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, expression)| {
|
||||
Statement::Constraint(
|
||||
expression.into(),
|
||||
FlatVariable::public(index).into(),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
@ -46,44 +58,12 @@ impl<T: Field> From<FlatProg<T>> for Prog<T> {
|
|||
// get the interface of the program, ie which inputs are private and public
|
||||
let private = main.arguments.iter().map(|p| p.private).collect();
|
||||
|
||||
// convert the main function to this IR for functions
|
||||
let main: Function<T> = main.into();
|
||||
let main = main.into();
|
||||
|
||||
// contrary to other functions, we need to make sure that return values are identifiers, so we define new (public) variables
|
||||
let definitions =
|
||||
main.returns.iter().enumerate().map(|(index, e)| {
|
||||
Statement::Constraint(e.clone(), FlatVariable::public(index).into())
|
||||
});
|
||||
|
||||
// update the main function with the extra definition statements and replace the return values
|
||||
let main = Function {
|
||||
returns: (0..main.returns.len())
|
||||
.map(|i| QuadComb::from_flat_expression(FlatVariable::public(i)))
|
||||
.collect(),
|
||||
statements: main.statements.into_iter().chain(definitions).collect(),
|
||||
..main
|
||||
};
|
||||
|
||||
let main = Function::from(main);
|
||||
Prog { private, main }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> QuadComb<T> {
|
||||
fn from_flat_expression<U: Into<FlatExpression<T>>>(flat_expression: U) -> QuadComb<T> {
|
||||
let flat_expression = flat_expression.into();
|
||||
match flat_expression.is_linear() {
|
||||
true => LinComb::from(flat_expression).into(),
|
||||
false => match flat_expression {
|
||||
FlatExpression::Mult(box e1, box e2) => {
|
||||
QuadComb::from_linear_combinations(e1.into(), e2.into())
|
||||
}
|
||||
e => unimplemented!("{}", e),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> From<FlatExpression<T>> for LinComb<T> {
|
||||
fn from(flat_expression: FlatExpression<T>) -> LinComb<T> {
|
||||
assert!(flat_expression.is_linear());
|
||||
|
|
|
@ -74,7 +74,7 @@ pub struct Function<T: Field> {
|
|||
pub id: String,
|
||||
pub statements: Vec<Statement<T>>,
|
||||
pub arguments: Vec<FlatVariable>,
|
||||
pub returns: Vec<QuadComb<T>>,
|
||||
pub returns: Vec<FlatVariable>,
|
||||
}
|
||||
|
||||
impl<T: Field> fmt::Display for Function<T> {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// ```
|
||||
|
||||
use flat_absy::flat_variable::FlatVariable;
|
||||
use ir::folder::Folder;
|
||||
use ir::folder::{fold_function, Folder};
|
||||
use ir::LinComb;
|
||||
use ir::*;
|
||||
use num::Zero;
|
||||
|
@ -47,7 +47,7 @@ impl<T: Field> Folder<T> for RedefinitionOptimizer<T> {
|
|||
Some(l) => match lin.try_summand() {
|
||||
// right side must be a single variable
|
||||
Some((variable, coefficient)) => {
|
||||
match variable.is_public() || variable == &FlatVariable::one() {
|
||||
match variable == &FlatVariable::one() {
|
||||
// variable must not be public nor ~ONE
|
||||
false => match self.substitution.get(variable) {
|
||||
Some(_) => None,
|
||||
|
@ -97,6 +97,15 @@ impl<T: Field> Folder<T> for RedefinitionOptimizer<T> {
|
|||
self.substitution.insert(a.clone(), a.clone().into());
|
||||
a
|
||||
}
|
||||
|
||||
fn fold_function(&mut self, fun: Function<T>) -> Function<T> {
|
||||
self.substitution.drain();
|
||||
|
||||
self.substitution
|
||||
.extend(fun.returns.iter().map(|x| (x.clone(), x.clone().into())));
|
||||
|
||||
fold_function(self, fun)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -125,8 +134,8 @@ mod tests {
|
|||
let optimized: Function<FieldPrime> = Function {
|
||||
id: "foo".to_string(),
|
||||
arguments: vec![x],
|
||||
statements: vec![],
|
||||
returns: vec![x.into()],
|
||||
statements: vec![Statement::definition(z, x)],
|
||||
returns: vec![z],
|
||||
};
|
||||
|
||||
let mut optimizer = RedefinitionOptimizer::new();
|
||||
|
@ -165,8 +174,8 @@ mod tests {
|
|||
let optimized: Function<FieldPrime> = Function {
|
||||
id: "foo".to_string(),
|
||||
arguments: vec![x],
|
||||
statements: vec![Statement::constraint(x, x)],
|
||||
returns: vec![x.into()],
|
||||
statements: vec![Statement::definition(z, x), Statement::constraint(z, x)],
|
||||
returns: vec![z.into()],
|
||||
};
|
||||
|
||||
let mut optimizer = RedefinitionOptimizer::new();
|
||||
|
@ -202,14 +211,17 @@ mod tests {
|
|||
Statement::definition(z, y),
|
||||
Statement::definition(w, t),
|
||||
],
|
||||
returns: vec![z.into(), w.into()],
|
||||
returns: vec![z, w],
|
||||
};
|
||||
|
||||
let optimized: Function<FieldPrime> = Function {
|
||||
id: "foo".to_string(),
|
||||
arguments: vec![x],
|
||||
statements: vec![],
|
||||
returns: vec![x.into(), FieldPrime::from(1).into()],
|
||||
statements: vec![
|
||||
Statement::definition(z, x),
|
||||
Statement::definition(w, FieldPrime::from(1)),
|
||||
],
|
||||
returns: vec![z, w],
|
||||
};
|
||||
|
||||
let mut optimizer = RedefinitionOptimizer::new();
|
||||
|
@ -224,7 +236,8 @@ mod tests {
|
|||
// b = a + x + y
|
||||
// c = b + x + y
|
||||
// 2*c == 6*x + 6*y
|
||||
// return a + b + c
|
||||
// r = a + b + c
|
||||
// return r
|
||||
|
||||
// ->
|
||||
|
||||
|
@ -237,6 +250,7 @@ mod tests {
|
|||
let a = FlatVariable::new(2);
|
||||
let b = FlatVariable::new(3);
|
||||
let c = FlatVariable::new(4);
|
||||
let r = FlatVariable::new(5);
|
||||
|
||||
let f: Function<FieldPrime> = Function {
|
||||
id: "foo".to_string(),
|
||||
|
@ -249,18 +263,22 @@ mod tests {
|
|||
LinComb::summand(2, c),
|
||||
LinComb::summand(6, x) + LinComb::summand(6, y),
|
||||
),
|
||||
Statement::definition(r, LinComb::from(a) + LinComb::from(b) + LinComb::from(c)),
|
||||
],
|
||||
returns: vec![(LinComb::from(a) + LinComb::from(b) + LinComb::from(c)).into()],
|
||||
returns: vec![r],
|
||||
};
|
||||
|
||||
let optimized: Function<FieldPrime> = Function {
|
||||
id: "foo".to_string(),
|
||||
arguments: vec![x, y],
|
||||
statements: vec![Statement::constraint(
|
||||
LinComb::summand(6, x) + LinComb::summand(6, y),
|
||||
LinComb::summand(6, x) + LinComb::summand(6, y),
|
||||
)],
|
||||
returns: vec![(LinComb::summand(6, x) + LinComb::summand(6, y)).into()],
|
||||
statements: vec![
|
||||
Statement::constraint(
|
||||
LinComb::summand(6, x) + LinComb::summand(6, y),
|
||||
LinComb::summand(6, x) + LinComb::summand(6, y),
|
||||
),
|
||||
Statement::definition(r, LinComb::summand(6, x) + LinComb::summand(6, y)),
|
||||
],
|
||||
returns: vec![r],
|
||||
};
|
||||
|
||||
let mut optimizer = RedefinitionOptimizer::new();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_field"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
authors = ["Guillaume Ballet <gballet@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_fs_resolver"
|
||||
version = "0.3.2"
|
||||
version = "0.4.0"
|
||||
authors = ["Thibaut Schaeffer <thibaut@schaeff.fr>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates.git"
|
||||
|
||||
|
|
Loading…
Reference in a new issue