diff --git a/changelogs/unreleased/1353-dark64 b/changelogs/unreleased/1353-dark64 new file mode 100644 index 000000000..bc47506cc --- /dev/null +++ b/changelogs/unreleased/1353-dark64 @@ -0,0 +1 @@ +Remove expensive and buggy branch isolation \ No newline at end of file diff --git a/zokrates_analysis/src/branch_isolator.rs b/zokrates_analysis/src/branch_isolator.rs deleted file mode 100644 index 6b6789ec6..000000000 --- a/zokrates_analysis/src/branch_isolator.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Isolate branches means making sure that any branch is enclosed in a block. -// This is important, because we want any statement resulting from inlining any branch to be isolated from the coller, so that its panics can be conditional to the branch being logically run - -// `if c then a else b fi` becomes `if c then { a } else { b } fi`, and down the line any statements resulting from trating `a` and `b` can be safely kept inside the respective blocks. - -use zokrates_ast::common::{Fold, WithSpan}; -use zokrates_ast::typed::folder::*; -use zokrates_ast::typed::*; -use zokrates_field::Field; - -pub struct Isolator; - -impl Isolator { - pub fn isolate(p: TypedProgram) -> TypedProgram { - let mut isolator = Isolator; - isolator.fold_program(p) - } -} - -impl<'ast, T: Field> Folder<'ast, T> for Isolator { - fn fold_conditional_expression< - E: Expr<'ast, T> + Block<'ast, T> + Fold + Conditional<'ast, T>, - >( - &mut self, - _: &E::Ty, - e: ConditionalExpression<'ast, T, E>, - ) -> ConditionalOrExpression<'ast, T, E> { - let span = e.get_span(); - - let consequence_span = e.consequence.get_span(); - let alternative_span = e.alternative.get_span(); - - ConditionalOrExpression::Conditional( - ConditionalExpression::new( - self.fold_boolean_expression(*e.condition), - E::block(vec![], e.consequence.fold(self)).span(consequence_span), - E::block(vec![], e.alternative.fold(self)).span(alternative_span), - e.kind, - ) - .span(span), - ) - } -} diff --git a/zokrates_analysis/src/lib.rs b/zokrates_analysis/src/lib.rs index 2cf0c24fc..bd3efa097 100644 --- a/zokrates_analysis/src/lib.rs +++ b/zokrates_analysis/src/lib.rs @@ -6,7 +6,6 @@ mod assembly_transformer; mod boolean_array_comparator; -mod branch_isolator; mod condition_redefiner; mod constant_argument_checker; mod constant_resolver; @@ -25,7 +24,6 @@ mod variable_write_remover; mod zir_propagation; use self::boolean_array_comparator::BooleanArrayComparator; -use self::branch_isolator::Isolator; use self::condition_redefiner::ConditionRedefiner; use self::constant_argument_checker::ConstantArgumentChecker; use self::flatten_complex_types::Flattener; @@ -132,17 +130,6 @@ pub fn analyse<'ast, T: Field>( let r = ConstantResolver::inline(p); log::trace!("\n{}", r); - // isolate branches - let r = if config.isolate_branches { - log::debug!("Static analyser: Isolate branches"); - let r = Isolator::isolate(r); - log::trace!("\n{}", r); - r - } else { - log::debug!("Static analyser: Branch isolation skipped"); - r - }; - // include logs let r = if config.debug { log::debug!("Static analyser: Include logs"); diff --git a/zokrates_ast/src/ir/mod.rs b/zokrates_ast/src/ir/mod.rs index 46c99b13f..7118c6f6e 100644 --- a/zokrates_ast/src/ir/mod.rs +++ b/zokrates_ast/src/ir/mod.rs @@ -74,7 +74,7 @@ impl fmt::Display for ConstraintStatement { self.error .as_ref() .map(|e| format!(" // {}", e)) - .unwrap_or_else(|| "".to_string()) + .unwrap_or_default() ) } } diff --git a/zokrates_ast/src/lib.rs b/zokrates_ast/src/lib.rs index 084173f84..bf97b93f6 100644 --- a/zokrates_ast/src/lib.rs +++ b/zokrates_ast/src/lib.rs @@ -1,3 +1,6 @@ +// see https://github.com/mcarton/rust-derivative/issues/115 +#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)] + pub mod common; pub mod flat; pub mod ir; diff --git a/zokrates_ast/src/untyped/mod.rs b/zokrates_ast/src/untyped/mod.rs index c0f77ea64..46fa1e10f 100644 --- a/zokrates_ast/src/untyped/mod.rs +++ b/zokrates_ast/src/untyped/mod.rs @@ -543,11 +543,8 @@ impl<'ast> fmt::Display for Range<'ast> { self.from .as_ref() .map(|e| e.to_string()) - .unwrap_or_else(|| "".to_string()), - self.to - .as_ref() - .map(|e| e.to_string()) - .unwrap_or_else(|| "".to_string()) + .unwrap_or_default(), + self.to.as_ref().map(|e| e.to_string()).unwrap_or_default() ) } } diff --git a/zokrates_book/src/language/control_flow.md b/zokrates_book/src/language/control_flow.md index 6e7929cc1..2a50e2f83 100644 --- a/zokrates_book/src/language/control_flow.md +++ b/zokrates_book/src/language/control_flow.md @@ -47,9 +47,8 @@ Now the two caveats: ```zokrates {{#include ../../../zokrates_cli/examples/book/conditional_panic.zok}} ``` -The experimental flag `--branch-isolation` can be activated in the CLI in order to restrict any unsatisfied constraint to make the execution fail only if it is in a logically executed branch. This way, the execution of the program above will always succeed. ->The reason for these caveats is that the program is compiled down to an arithmetic circuit. This construct does not support jumping to a branch depending on a condition as you could do on traditional architectures. Instead, all branches are inlined as if they were printed on a circuit board. The `branch-isolation` feature comes with overhead for each assertion in each branch, and this overhead compounds when deeply nesting conditionals. +>The reason for these caveats is that the program is compiled down to an arithmetic circuit. This construct does not support jumping to a branch depending on a condition as you could do on traditional architectures. Instead, all branches are inlined as if they were printed on a circuit board. ### For loops diff --git a/zokrates_cli/src/ops/check.rs b/zokrates_cli/src/ops/check.rs index c2cada4d6..1172f0307 100644 --- a/zokrates_cli/src/ops/check.rs +++ b/zokrates_cli/src/ops/check.rs @@ -44,11 +44,6 @@ pub fn subcommand() -> App<'static, 'static> { .possible_values(cli_constants::CURVES) .default_value(BN128), ) - .arg(Arg::with_name("isolate-branches") - .long("isolate-branches") - .help("Isolate the execution of branches: a panic in a branch only makes the program panic if this branch is being logically executed") - .required(false) - ) } pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { @@ -94,17 +89,13 @@ fn cli_check(sub_matches: &ArgMatches) -> Result<(), String> { )), }?; - let config = - CompileConfig::default().isolate_branches(sub_matches.is_present("isolate-branches")); - + let config = CompileConfig::default(); let resolver = FileSystemResolver::with_stdlib_root(stdlib_path); + check::(source, path, Some(&resolver), &config).map_err(|e| { format!( "Check failed:\n\n{}", - e.0.iter() - .map(|e| fmt_error(e)) - .collect::>() - .join("\n\n") + e.0.iter().map(fmt_error).collect::>().join("\n\n") ) })?; diff --git a/zokrates_cli/src/ops/compile.rs b/zokrates_cli/src/ops/compile.rs index 5265aed72..449f7ac64 100644 --- a/zokrates_cli/src/ops/compile.rs +++ b/zokrates_cli/src/ops/compile.rs @@ -18,62 +18,71 @@ use zokrates_fs_resolver::FileSystemResolver; pub fn subcommand() -> App<'static, 'static> { SubCommand::with_name("compile") .about("Compiles into a runnable constraint system") - .arg(Arg::with_name("input") - .short("i") - .long("input") - .help("Path of the source code") - .value_name("FILE") - .takes_value(true) - .required(true) - ).arg(Arg::with_name("stdlib-path") - .long("stdlib-path") - .help("Path to the standard library") - .value_name("PATH") - .takes_value(true) - .required(false) - .env("ZOKRATES_STDLIB") - .default_value(cli_constants::DEFAULT_STDLIB_PATH.as_str()) - ).arg(Arg::with_name("abi-spec") - .short("s") - .long("abi-spec") - .help("Path of the ABI specification") - .value_name("FILE") - .takes_value(true) - .required(false) - .default_value(cli_constants::ABI_SPEC_DEFAULT_PATH) - ).arg(Arg::with_name("output") - .short("o") - .long("output") - .help("Path of the output binary") - .value_name("FILE") - .takes_value(true) - .required(false) - .default_value(cli_constants::FLATTENED_CODE_DEFAULT_PATH) - ).arg(Arg::with_name("r1cs") - .short("r1cs") - .long("r1cs") - .help("Path of the output r1cs file") - .value_name("FILE") - .takes_value(true) - .required(false) - .default_value(cli_constants::CIRCOM_R1CS_DEFAULT_PATH) -).arg(Arg::with_name("curve") - .short("c") - .long("curve") - .help("Curve to be used in the compilation") - .takes_value(true) - .required(false) - .possible_values(cli_constants::CURVES) - .default_value(BN128) - ).arg(Arg::with_name("isolate-branches") - .long("isolate-branches") - .help("Isolate the execution of branches: a panic in a branch only makes the program panic if this branch is being logically executed") - .required(false) - ).arg(Arg::with_name("debug") - .long("debug") - .help("Include logs") - .required(false) -) + .arg( + Arg::with_name("input") + .short("i") + .long("input") + .help("Path of the source code") + .value_name("FILE") + .takes_value(true) + .required(true), + ) + .arg( + Arg::with_name("stdlib-path") + .long("stdlib-path") + .help("Path to the standard library") + .value_name("PATH") + .takes_value(true) + .required(false) + .env("ZOKRATES_STDLIB") + .default_value(cli_constants::DEFAULT_STDLIB_PATH.as_str()), + ) + .arg( + Arg::with_name("abi-spec") + .short("s") + .long("abi-spec") + .help("Path of the ABI specification") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(cli_constants::ABI_SPEC_DEFAULT_PATH), + ) + .arg( + Arg::with_name("output") + .short("o") + .long("output") + .help("Path of the output binary") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(cli_constants::FLATTENED_CODE_DEFAULT_PATH), + ) + .arg( + Arg::with_name("r1cs") + .short("r1cs") + .long("r1cs") + .help("Path of the output r1cs file") + .value_name("FILE") + .takes_value(true) + .required(false) + .default_value(cli_constants::CIRCOM_R1CS_DEFAULT_PATH), + ) + .arg( + Arg::with_name("curve") + .short("c") + .long("curve") + .help("Curve to be used in the compilation") + .takes_value(true) + .required(false) + .possible_values(cli_constants::CURVES) + .default_value(BN128), + ) + .arg( + Arg::with_name("debug") + .long("debug") + .help("Include logs") + .required(false), + ) } pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { @@ -124,10 +133,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { )), }?; - let config = CompileConfig::default() - .isolate_branches(sub_matches.is_present("isolate-branches")) - .debug(sub_matches.is_present("debug")); - + let config = CompileConfig::default().debug(sub_matches.is_present("debug")); let resolver = FileSystemResolver::with_stdlib_root(stdlib_path); log::debug!("Compile"); @@ -138,10 +144,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { .map_err(|e| { format!( "Compilation failed:\n\n{}", - e.0.iter() - .map(|e| fmt_error(e)) - .collect::>() - .join("\n\n") + e.0.iter().map(fmt_error).collect::>().join("\n\n") ) })?; diff --git a/zokrates_codegen/src/lib.rs b/zokrates_codegen/src/lib.rs index 685c78d31..fa4a20c73 100644 --- a/zokrates_codegen/src/lib.rs +++ b/zokrates_codegen/src/lib.rs @@ -33,7 +33,6 @@ use zokrates_ast::zir::{ BooleanExpression, Conditional, FieldElementExpression, Identifier, Parameter as ZirParameter, UExpression, UExpressionInner, Variable as ZirVariable, ZirExpression, ZirStatement, }; -use zokrates_common::CompileConfig; use zokrates_field::Field; /// A container for statements produced during code generation @@ -80,13 +79,10 @@ impl<'ast, T> IntoIterator for FlatStatements<'ast, T> { /// /// # Arguments /// * `funct` - `ZirFunction` that will be flattened -pub fn from_program_and_config( - prog: ZirProgram, - config: CompileConfig, -) -> FlattenerIterator { +pub fn from_program_and_config(prog: ZirProgram) -> FlattenerIterator { let funct = prog.main; - let mut flattener = Flattener::new(config); + let mut flattener = Flattener::default(); let mut statements_flattened = FlatStatements::default(); // push parameters let arguments_flattened = funct @@ -135,9 +131,8 @@ impl<'ast, T: Field> Iterator for FlattenerIteratorInner<'ast, T> { } /// Flattener, computes flattened program. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Flattener<'ast, T> { - config: CompileConfig, /// Index of the next introduced variable while processing the program. next_var_idx: usize, /// `Variable`s corresponding to each `Identifier` @@ -274,16 +269,6 @@ impl FlatUExpression { } impl<'ast, T: Field> Flattener<'ast, T> { - /// Returns a `Flattener` with fresh `layout`. - fn new(config: CompileConfig) -> Flattener<'ast, T> { - Flattener { - config, - next_var_idx: 0, - layout: HashMap::new(), - bits_cache: HashMap::new(), - } - } - /// Flattens a definition, trying to avoid creating redundant variables fn define( &mut self, @@ -571,68 +556,6 @@ impl<'ast, T: Field> Flattener<'ast, T> { } } - fn make_conditional( - &mut self, - statements: FlatStatements<'ast, T>, - condition: FlatExpression, - ) -> FlatStatements<'ast, T> { - statements - .into_iter() - .flat_map(|s| match s { - FlatStatement::Condition(s) => { - let span = s.get_span(); - - let mut output = FlatStatements::default(); - - output.set_span(span); - - // we transform (a == b) into (c => (a == b)) which is (!c || (a == b)) - - // let's introduce new variables to make sure everything is linear - let name_lin = self.define(s.lin, &mut output); - let name_quad = self.define(s.quad, &mut output); - - // let's introduce an expression which is 1 iff `a == b` - let y = FlatExpression::add( - FlatExpression::sub(name_lin.into(), name_quad.into()), - T::one().into(), - ); // let's introduce !c - let x = FlatExpression::sub(T::one().into(), condition.clone()); - assert!(x.is_linear() && y.is_linear()); - let name_x_or_y = self.use_sym(); - output.push_back(FlatStatement::directive( - vec![name_x_or_y], - Solver::Or, - vec![x.clone(), y.clone()], - )); - output.push_back(FlatStatement::condition( - FlatExpression::add( - x.clone(), - FlatExpression::sub(y.clone(), name_x_or_y.into()), - ), - FlatExpression::mul(x, y), - RuntimeError::BranchIsolation, - )); - output.push_back(FlatStatement::condition( - name_x_or_y.into(), - T::one().into(), - s.error, - )); - - output - } - s => { - let mut v = FlatStatements::default(); - v.push_back(s); - v - } - }) - .fold(FlatStatements::default(), |mut acc, s| { - acc.push_back(s); - acc - }) - } - /// Flatten an if/else expression /// /// # Arguments @@ -658,35 +581,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { let condition_id = self.use_sym(); statements_flattened.push_back(FlatStatement::definition(condition_id, condition_flat)); - let (consequence, alternative) = if self.config.isolate_branches { - let mut consequence_statements = FlatStatements::default(); - - let consequence = consequence.flatten(self, &mut consequence_statements); - - let mut alternative_statements = FlatStatements::default(); - - let alternative = alternative.flatten(self, &mut alternative_statements); - - let consequence_statements = - self.make_conditional(consequence_statements, condition_id.into()); - let alternative_statements = self.make_conditional( - alternative_statements, - FlatExpression::sub(FlatExpression::value(T::one()), condition_id.into()), - ); - - statements_flattened.extend(consequence_statements); - statements_flattened.extend(alternative_statements); - - (consequence, alternative) - } else { - ( - consequence.flatten(self, statements_flattened), - alternative.flatten(self, statements_flattened), - ) - }; - - let consequence = consequence.flat(); - let alternative = alternative.flat(); + let consequence = consequence.flatten(self, statements_flattened).flat(); + let alternative = alternative.flatten(self, statements_flattened).flat(); let consequence_id = self.use_sym(); statements_flattened.push_back(FlatStatement::definition(consequence_id, consequence)); @@ -2448,34 +2344,12 @@ impl<'ast, T: Field> Flattener<'ast, T> { statements_flattened .push_back(FlatStatement::definition(condition_id, condition_flat)); - if self.config.isolate_branches { - let mut consequence_statements = FlatStatements::default(); - let mut alternative_statements = FlatStatements::default(); - - s.consequence - .into_iter() - .for_each(|s| self.flatten_statement(&mut consequence_statements, s)); - s.alternative - .into_iter() - .for_each(|s| self.flatten_statement(&mut alternative_statements, s)); - - let consequence_statements = - self.make_conditional(consequence_statements, condition_id.into()); - let alternative_statements = self.make_conditional( - alternative_statements, - FlatExpression::sub(FlatExpression::value(T::one()), condition_id.into()), - ); - - statements_flattened.extend(consequence_statements); - statements_flattened.extend(alternative_statements); - } else { - s.consequence - .into_iter() - .for_each(|s| self.flatten_statement(statements_flattened, s)); - s.alternative - .into_iter() - .for_each(|s| self.flatten_statement(statements_flattened, s)); - } + s.consequence + .into_iter() + .for_each(|s| self.flatten_statement(statements_flattened, s)); + s.alternative + .into_iter() + .for_each(|s| self.flatten_statement(statements_flattened, s)); } ZirStatement::Definition(s) => { // define n variables with n the number of primitive types for v_type @@ -2999,13 +2873,10 @@ mod tests { use zokrates_field::Bn128Field; fn flatten_function(f: ZirFunction) -> FlatProg { - from_program_and_config( - ZirProgram { - main: f, - module_map: Default::default(), - }, - CompileConfig::default(), - ) + from_program_and_config(ZirProgram { + main: f, + module_map: Default::default(), + }) .collect() } @@ -3801,7 +3672,6 @@ mod tests { #[test] fn if_else() { - let config = CompileConfig::default(); let expression = FieldElementExpression::conditional( BooleanExpression::field_eq( FieldElementExpression::value(Bn128Field::from(32)), @@ -3811,15 +3681,14 @@ mod tests { FieldElementExpression::value(Bn128Field::from(51)), ); - let mut flattener = Flattener::new(config); + let mut flattener = Flattener::default(); flattener.flatten_field_expression(&mut FlatStatements::default(), expression); } #[test] fn geq_leq() { - let config = CompileConfig::default(); - let mut flattener = Flattener::new(config); + let mut flattener = Flattener::default(); let expression_le = BooleanExpression::field_le( FieldElementExpression::value(Bn128Field::from(32)), FieldElementExpression::value(Bn128Field::from(4)), @@ -3829,8 +3698,7 @@ mod tests { #[test] fn bool_and() { - let config = CompileConfig::default(); - let mut flattener = Flattener::new(config); + let mut flattener = Flattener::default(); let expression = FieldElementExpression::conditional( BooleanExpression::bitand( @@ -3853,8 +3721,7 @@ mod tests { #[test] fn div() { // a = 5 / b / b - let config = CompileConfig::default(); - let mut flattener = Flattener::new(config); + let mut flattener = Flattener::default(); let mut statements_flattened = FlatStatements::default(); let definition = ZirStatement::definition( diff --git a/zokrates_common/src/lib.rs b/zokrates_common/src/lib.rs index a37d9112c..d1c6418ee 100644 --- a/zokrates_common/src/lib.rs +++ b/zokrates_common/src/lib.rs @@ -14,18 +14,11 @@ pub trait Resolver { #[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)] pub struct CompileConfig { - #[serde(default)] - pub isolate_branches: bool, #[serde(default)] pub debug: bool, } impl CompileConfig { - pub fn isolate_branches(mut self, flag: bool) -> Self { - self.isolate_branches = flag; - self - } - pub fn debug(mut self, debug: bool) -> Self { self.debug = debug; self diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 468c1b68b..3f9e32735 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -183,7 +183,7 @@ pub fn compile<'ast, T: Field, E: Into>( // flatten input program log::debug!("Flatten"); - let program_flattened = from_program_and_config(typed_ast, config); + let program_flattened = from_program_and_config(typed_ast); // convert to ir log::debug!("Convert to IR"); diff --git a/zokrates_core_test/tests/tests/panics/conditional_bound_throw_no_isolation.json b/zokrates_core_test/tests/tests/panics/conditional_bound_throw.json similarity index 100% rename from zokrates_core_test/tests/tests/panics/conditional_bound_throw_no_isolation.json rename to zokrates_core_test/tests/tests/panics/conditional_bound_throw.json diff --git a/zokrates_core_test/tests/tests/panics/conditional_bound_throw.zok b/zokrates_core_test/tests/tests/panics/conditional_bound_throw.zok index 0d4fad916..829c7324e 100644 --- a/zokrates_core_test/tests/tests/panics/conditional_bound_throw.zok +++ b/zokrates_core_test/tests/tests/panics/conditional_bound_throw.zok @@ -4,7 +4,7 @@ def throwing_bound(u32 x) -> u32 { } // this compiles: the conditional, even though it can throw, has a constant compile-time value of `1` -// However, the assertions are still checked at runtime, which leads to panics without branch isolation. +// However, the assertions are still checked at runtime, which leads to panics def main(u32 x) { for u32 i in 0..x == 0 ? throwing_bound::<0>(x) : throwing_bound::<1>(x) {} return; diff --git a/zokrates_core_test/tests/tests/panics/conditional_panic.json b/zokrates_core_test/tests/tests/panics/conditional_panic.json new file mode 100644 index 000000000..20494a894 --- /dev/null +++ b/zokrates_core_test/tests/tests/panics/conditional_panic.json @@ -0,0 +1,50 @@ +{ + "entry_point": "./tests/tests/panics/conditional_panic.zok", + "curves": ["Bn128"], + "tests": [ + { + "input": { + "values": [true] + }, + "output": { + "Err": { + "UnsatisfiedConstraint": { + "left": "1", + "right": "0", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/conditional_panic.zok", + "position": { + "line": 7, + "col": 5 + } + } + } + } + } + } + }, + { + "input": { + "values": [false] + }, + "output": { + "Err": { + "UnsatisfiedConstraint": { + "left": "1", + "right": "0", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/conditional_panic.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } + } + } + } + ] +} diff --git a/zokrates_core_test/tests/tests/panics/conditional_panic.zok b/zokrates_core_test/tests/tests/panics/conditional_panic.zok new file mode 100644 index 000000000..982043f55 --- /dev/null +++ b/zokrates_core_test/tests/tests/panics/conditional_panic.zok @@ -0,0 +1,14 @@ +def yes(bool x) -> bool { + assert(x); + return x; +} + +def no(bool x) -> bool { + assert(!x); + return x; +} + +def main(bool condition) -> bool { + // this will always panic + return condition ? yes(condition) : no(condition); +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/panics/deep_branch.json b/zokrates_core_test/tests/tests/panics/deep_branch.json index a9287c128..570291ec2 100644 --- a/zokrates_core_test/tests/tests/panics/deep_branch.json +++ b/zokrates_core_test/tests/tests/panics/deep_branch.json @@ -1,17 +1,48 @@ { "entry_point": "./tests/tests/panics/deep_branch.zok", "curves": ["Bn128"], - "config": { - "isolate_branches": true - }, "tests": [ + { + "input": { + "values": [[false, false, false]] + }, + "output": { + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/deep_branch.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } + } + } + }, { "input": { "values": [[true, true, true]] }, "output": { - "Ok": { - "value": [true, true, true] + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/deep_branch.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } } } }, @@ -20,8 +51,20 @@ "values": [[false, false, false]] }, "output": { - "Ok": { - "value": [false, false, false] + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/deep_branch.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } } } }, @@ -30,8 +73,20 @@ "values": [[false, true, false]] }, "output": { - "Ok": { - "value": [false, true, false] + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/deep_branch.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } } } }, @@ -40,8 +95,20 @@ "values": [[true, false, true]] }, "output": { - "Ok": { - "value": [true, false, true] + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": { + "SourceAssertion": { + "file": "./tests/tests/panics/deep_branch.zok", + "position": { + "line": 2, + "col": 5 + } + } + } + } } } } diff --git a/zokrates_core_test/tests/tests/panics/deep_branch_no_isolation.json b/zokrates_core_test/tests/tests/panics/deep_branch_no_isolation.json deleted file mode 100644 index 430a2c180..000000000 --- a/zokrates_core_test/tests/tests/panics/deep_branch_no_isolation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "entry_point": "./tests/tests/panics/deep_branch.zok", - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [[false, false, false]] - }, - "output": { - "Err": { - "UnsatisfiedConstraint": { - "left": "0", - "right": "1", - "error": { - "SourceAssertion": { - "file": "./tests/tests/panics/deep_branch.zok", - "position": { - "line": 2, - "col": 5 - } - } - } - } - } - } - } - ] -} diff --git a/zokrates_core_test/tests/tests/panics/internal_panic.json b/zokrates_core_test/tests/tests/panics/internal_panic.json index 6b5191253..c98e1cec2 100644 --- a/zokrates_core_test/tests/tests/panics/internal_panic.json +++ b/zokrates_core_test/tests/tests/panics/internal_panic.json @@ -1,9 +1,6 @@ { "entry_point": "./tests/tests/panics/internal_panic.zok", "curves": ["Bn128"], - "config": { - "isolate_branches": true - }, "tests": [ { "input": { @@ -20,8 +17,12 @@ "values": ["0"] }, "output": { - "Ok": { - "value": "0" + "Err": { + "UnsatisfiedConstraint": { + "left": "0", + "right": "1", + "error": "Inverse" + } } } } diff --git a/zokrates_core_test/tests/tests/panics/internal_panic_no_isolation.json b/zokrates_core_test/tests/tests/panics/internal_panic_no_isolation.json deleted file mode 100644 index c98e1cec2..000000000 --- a/zokrates_core_test/tests/tests/panics/internal_panic_no_isolation.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "entry_point": "./tests/tests/panics/internal_panic.zok", - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": ["1"] - }, - "output": { - "Ok": { - "value": "1" - } - } - }, - { - "input": { - "values": ["0"] - }, - "output": { - "Err": { - "UnsatisfiedConstraint": { - "left": "0", - "right": "1", - "error": "Inverse" - } - } - } - } - ] -} diff --git a/zokrates_core_test/tests/tests/panics/panic_isolation.json b/zokrates_core_test/tests/tests/panics/panic_isolation.json deleted file mode 100644 index b928bcd17..000000000 --- a/zokrates_core_test/tests/tests/panics/panic_isolation.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "entry_point": "./tests/tests/panics/panic_isolation.zok", - "config": { - "isolate_branches": true - }, - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [true, ["42", "42"], "0"] - }, - "output": { - "Err": { - "UnsatisfiedConstraint": { - "left": "1", - "right": "21888242871839275222246405745257275088548364400416034343698204186575808495577", - "error": { - "SourceAssertion": { - "file": "./tests/tests/panics/panic_isolation.zok", - "position": { - "line": 22, - "col": 5 - } - } - } - } - } - } - }, - { - "input": { - "values": [true, ["1", "1"], "1"] - }, - "output": { - "Ok": { - "value": [true, ["1", "1"], "1"] - } - } - }, - { - "input": { - "values": [false, ["2", "2"], "0"] - }, - "output": { - "Ok": { - "value": [false, ["2", "2"], "0"] - } - } - } - ] -} diff --git a/zokrates_core_test/tests/tests/panics/panic_isolation.zok b/zokrates_core_test/tests/tests/panics/panic_isolation.zok deleted file mode 100644 index 276bcc58b..000000000 --- a/zokrates_core_test/tests/tests/panics/panic_isolation.zok +++ /dev/null @@ -1,38 +0,0 @@ -def zero(field x) -> field { - assert(x == 0); - return 0; -} - -def inverse(field x) -> field { - assert(x != 0); - return 1/x; -} - -def yes(bool x) -> bool { - assert(x); - return x; -} - -def no(bool x) -> bool { - assert(!x); - return x; -} - -def ones(field[2] a) -> field[2] { - assert(a == [1, 1]); - return a; -} - -def twos(field[2] a) -> field[2] { - assert(a == [2, 2]); - return a; -} - -def main(bool condition, field[2] a, field x) -> (bool, field[2], field) { - // first branch asserts that `condition` is true, second branch asserts that `condition` is false. This should never throw. - // first branch asserts that all elements in `a` are 1, 2 in the second branch. This should throw only if `a` is neither ones or zeroes - // first branch asserts that `x` is zero and returns it, second branch asserts that `x` isn't 0 and returns its inverse (which internally generates a failing assert if x is 0). This should never throw - return (condition ? yes(condition) : no(condition), \ - condition ? ones(a) : twos(a), \ - x == 0 ? zero(x) : inverse(x)); -} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/panics/panic_no_isolation.json b/zokrates_core_test/tests/tests/panics/panic_no_isolation.json deleted file mode 100644 index 107f79cd4..000000000 --- a/zokrates_core_test/tests/tests/panics/panic_no_isolation.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "entry_point": "./tests/tests/panics/panic_isolation.zok", - "config": { - "isolate_branches": false - }, - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [true, ["1", "1"], "1"] - }, - "output": { - "Err": { - "UnsatisfiedConstraint": { - "left": "1", - "right": "0", - "error": { - "SourceAssertion": { - "file": "./tests/tests/panics/panic_isolation.zok", - "position": { - "line": 17, - "col": 5 - } - } - } - } - } - } - } - ] -} diff --git a/zokrates_interpreter/src/lib.rs b/zokrates_interpreter/src/lib.rs index 9e9bff770..46d1b8526 100644 --- a/zokrates_interpreter/src/lib.rs +++ b/zokrates_interpreter/src/lib.rs @@ -318,8 +318,8 @@ impl Interpreter { let s = x.to_dec_string(); ::Fr::from_str(&s).unwrap() }; - let i: Vec<_> = i.iter().map(|x| to_fr(x)).collect(); - let h: Vec<_> = h.iter().map(|x| to_fr(x)).collect(); + let i: Vec<_> = i.iter().map(to_fr).collect(); + let h: Vec<_> = h.iter().map(to_fr).collect(); assert_eq!(h.len(), 256); generate_sha256_round_witness::(&i, &h) .into_iter() diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index 425a3955a..8ec0b2ddb 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -12,7 +12,6 @@ declare module "zokrates-js" { ) => ResolverResult; export interface CompileConfig { - isolate_branches?: boolean; debug?: boolean; } diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs index b39d0169c..d70e145bb 100644 --- a/zokrates_js/src/lib.rs +++ b/zokrates_js/src/lib.rs @@ -276,13 +276,7 @@ mod internal { &arena, ) .map_err(|ce| { - JsValue::from_str( - &ce.0 - .iter() - .map(|e| fmt_error(e)) - .collect::>() - .join("\n"), - ) + JsValue::from_str(&ce.0.iter().map(fmt_error).collect::>().join("\n")) })?; let abi = artifacts.abi().clone();