1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

use variable as function output, avoid substituting outputs

This commit is contained in:
schaeff 2019-02-06 14:51:13 +01:00
commit 87ddcdcc55
12 changed files with 65 additions and 71 deletions

16
Cargo.lock generated
View file

@ -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)",
]

View file

View file

@ -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"

View file

@ -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")

View file

@ -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"

View file

@ -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

View file

@ -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
}

View file

@ -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());

View file

@ -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> {

View file

@ -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();

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_field"
version = "0.3.1"
version = "0.3.2"
authors = ["Guillaume Ballet <gballet@gmail.com>"]
edition = "2018"

View file

@ -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"