diff --git a/changelogs/unreleased/1041-schaeff b/changelogs/unreleased/1041-schaeff new file mode 100644 index 00000000..26a97864 --- /dev/null +++ b/changelogs/unreleased/1041-schaeff @@ -0,0 +1 @@ +Reduce compiler memory usage using iterators \ No newline at end of file diff --git a/zokrates_book/src/examples/rng_tutorial.md b/zokrates_book/src/examples/rng_tutorial.md index f4ce6adf..321e6e46 100644 --- a/zokrates_book/src/examples/rng_tutorial.md +++ b/zokrates_book/src/examples/rng_tutorial.md @@ -31,7 +31,7 @@ Create this file under the name `get_hash.zok`: Compile the program to a form that is usable for zero knowledge proofs. This command writes the binary to `get_hash`. You can see a textual representation, somewhat analogous to assembler -coming from a compiler, at `get_hash.ztf` enabled by the `--ztf` command line option. +coming from a compiler, at `get_hash.ztf` created by the `inspect` command. ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:10}} ``` diff --git a/zokrates_cli/examples/book/rng_tutorial/test.sh b/zokrates_cli/examples/book/rng_tutorial/test.sh index ba4cd113..56861771 100755 --- a/zokrates_cli/examples/book/rng_tutorial/test.sh +++ b/zokrates_cli/examples/book/rng_tutorial/test.sh @@ -7,7 +7,7 @@ function zokrates() { ZOKRATES_STDLIB=$stdlib $bin $* } -zokrates compile -i get_hash.zok -o get_hash --ztf +zokrates compile -i get_hash.zok -o get_hash && zokrates inspect -i get_hash zokrates compute-witness --verbose -i get_hash -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mkdir alice bob diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 5bd35a74..a437eef6 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -83,12 +83,6 @@ fn cli_compute>>( println!("Computing witness..."); let verbose = sub_matches.is_present("verbose"); - - // print deserialized flattened program if in verbose mode - // if verbose { - // println!("{}", ir_prog); - // } - let is_stdin = sub_matches.is_present("stdin"); let is_abi = sub_matches.is_present("abi"); diff --git a/zokrates_cli/src/ops/inspect.rs b/zokrates_cli/src/ops/inspect.rs index 1b4d5cd5..daf316b0 100644 --- a/zokrates_cli/src/ops/inspect.rs +++ b/zokrates_cli/src/ops/inspect.rs @@ -9,7 +9,7 @@ use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("inspect") - .about("Prints the compiled program in a human readable format") + .about("Outputs a compiled program to a file in a human readable format") .arg( Arg::with_name("input") .short("i") diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index d999999c..31d0e0e2 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -198,10 +198,6 @@ pub fn compile<'ast, T: Field, E: Into>( log::debug!("Flatten"); let program_flattened = FlattenerIterator::from_function_and_config(typed_ast.main, config); - // // constant propagation after call resolution - // log::debug!("Propagate flat program"); - // let program_flattened = program_flattened.propagate(); - // convert to ir log::debug!("Convert to IR"); let ir_prog = ir::from_flat::from_flat(program_flattened); diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index a96a5b1b..af96019c 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -635,6 +635,7 @@ pub fn unpack_to_bitwidth( let solver = Solver::bits(bit_width); + #[allow(clippy::needless_collect)] let outputs: Vec<_> = directive_outputs .iter() .enumerate() diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index c0666110..af65432a 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -1284,6 +1284,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { // Rename Parameters, assign them to values in call. Resolve complex expressions with definitions let params_flattened = params.into_iter().map(|e| e.get_field_unchecked()); + let return_values = (0..funct.return_count).map(FlatVariable::public); + for (concrete_argument, formal_argument) in params_flattened.zip(funct.arguments) { let new_var = self.define(concrete_argument, statements_flattened); replacement_map.insert(formal_argument.id, new_var); @@ -1329,17 +1331,10 @@ impl<'ast, T: Field> Flattener<'ast, T> { statements_flattened.extend(statements); - unimplemented!(); - - // match return_statements.pop().unwrap() { - // FlatStatement::Return(list) => list - // .expressions - // .into_iter() - // .map(|x| x.apply_substitution(&replacement_map)) - // .map(FlatUExpression::with_field) - // .collect(), - // _ => unreachable!(), - // } + return_values + .map(|x| FlatExpression::from(x).apply_substitution(&replacement_map)) + .map(FlatUExpression::with_field) + .collect() } /// Flattens an expression @@ -2368,6 +2363,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { ) { match stat { ZirStatement::Return(exprs) => { + #[allow(clippy::needless_collect)] + // clippy suggests to not collect here, but `statements_flattened` is borrowed in the iterator, + // so we cannot borrow again when extending let flat_expressions: Vec<_> = exprs .into_iter() .map(|expr| self.flatten_expression(statements_flattened, expr)) diff --git a/zokrates_core/src/ir/from_flat.rs b/zokrates_core/src/ir/from_flat.rs index 8a59bff6..640336b3 100644 --- a/zokrates_core/src/ir/from_flat.rs +++ b/zokrates_core/src/ir/from_flat.rs @@ -45,6 +45,10 @@ impl From> for LinComb { box FlatExpression::Identifier(v1), box FlatExpression::Number(n1), ) => LinComb::summand(n1, v1), + FlatExpression::Mult( + box FlatExpression::Number(n1), + box FlatExpression::Number(n2), + ) => LinComb::summand(n1 * n2, FlatVariable::one()), e => unreachable!("{}", e), } } diff --git a/zokrates_core/src/ir/serialize.rs b/zokrates_core/src/ir/serialize.rs index ee24ba14..9a5692b1 100644 --- a/zokrates_core/src/ir/serialize.rs +++ b/zokrates_core/src/ir/serialize.rs @@ -19,6 +19,13 @@ pub enum ProgEnum< Bw6_761Program(ProgIterator), } +type MemoryProgEnum = ProgEnum< + Vec>, + Vec>, + Vec>, + Vec>, +>; + impl< Bls12_381I: IntoIterator>, Bn128I: IntoIterator>, @@ -26,14 +33,7 @@ impl< Bw6_761I: IntoIterator>, > ProgEnum { - pub fn collect( - self, - ) -> ProgEnum< - Vec>, - Vec>, - Vec>, - Vec>, - > { + pub fn collect(self) -> MemoryProgEnum { match self { ProgEnum::Bls12_381Program(p) => ProgEnum::Bls12_381Program(p.collect()), ProgEnum::Bn128Program(p) => ProgEnum::Bn128Program(p.collect()), diff --git a/zokrates_core/src/proof_system/libsnark/gm17.rs b/zokrates_core/src/proof_system/libsnark/gm17.rs index 24b320ea..7ed7fa6b 100644 --- a/zokrates_core/src/proof_system/libsnark/gm17.rs +++ b/zokrates_core/src/proof_system/libsnark/gm17.rs @@ -204,7 +204,7 @@ mod tests { fn verify() { let program: Prog = Prog { arguments: vec![FlatParameter::private(FlatVariable::new(0))], - returns: vec![FlatVariable::public(0)], + return_count: 1, statements: vec![Statement::constraint( FlatVariable::new(0), FlatVariable::public(0), @@ -215,7 +215,7 @@ mod tests { let interpreter = Interpreter::default(); let witness = interpreter - .execute(&program, &vec![Bn128Field::from(42)]) + .execute(program.clone(), &vec![Bn128Field::from(42)]) .unwrap(); let proof = diff --git a/zokrates_core/src/proof_system/libsnark/pghr13.rs b/zokrates_core/src/proof_system/libsnark/pghr13.rs index cee611ec..6acb69c1 100644 --- a/zokrates_core/src/proof_system/libsnark/pghr13.rs +++ b/zokrates_core/src/proof_system/libsnark/pghr13.rs @@ -234,7 +234,7 @@ mod tests { fn verify() { let program: Prog = Prog { arguments: vec![FlatParameter::private(FlatVariable::new(0))], - returns: vec![FlatVariable::public(0)], + return_count: 1, statements: vec![Statement::constraint( FlatVariable::new(0), FlatVariable::public(0), @@ -245,7 +245,7 @@ mod tests { let interpreter = Interpreter::default(); let witness = interpreter - .execute(&program, &vec![Bn128Field::from(42)]) + .execute(program.clone(), &vec![Bn128Field::from(42)]) .unwrap(); let proof =