From 08051b4b20694afaf3c3f411a88d39e319a99183 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 20 May 2021 15:58:04 +0100 Subject: [PATCH 01/86] Add bubblesort example --- zokrates_cli/examples/book/bubblesort.zok | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 zokrates_cli/examples/book/bubblesort.zok diff --git a/zokrates_cli/examples/book/bubblesort.zok b/zokrates_cli/examples/book/bubblesort.zok new file mode 100644 index 000000000..978ecff07 --- /dev/null +++ b/zokrates_cli/examples/book/bubblesort.zok @@ -0,0 +1,13 @@ +def bubblesort(u32[N] a) -> u32[N]: + for u32 i in 0..(N-1) do + for u32 j in 0..(N-1-i) do + bool swap = a[j + 1] < a[j] + u32 tmp = a[j] + a[j] = if swap then a[j + 1] else a[j] fi + a[j + 1] = if swap then tmp else a[j + 1] fi + endfor + endfor + return a + +def main(u32[10] a) -> u32[10]: + return bubblesort(a) From ea43c6f161c63442afefd8adb0d29629376a89f6 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 20 May 2021 17:36:02 +0100 Subject: [PATCH 02/86] Bubblesort using a helper function --- zokrates_cli/examples/book/bubblesort.zok | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zokrates_cli/examples/book/bubblesort.zok b/zokrates_cli/examples/book/bubblesort.zok index 978ecff07..342982e3d 100644 --- a/zokrates_cli/examples/book/bubblesort.zok +++ b/zokrates_cli/examples/book/bubblesort.zok @@ -1,10 +1,13 @@ +def swap(u32[10] a, u32 i, u32 j) -> u32[10]: + u32 tmp = a[i] + a[i] = a[j] + a[j] = tmp + return a + def bubblesort(u32[N] a) -> u32[N]: for u32 i in 0..(N-1) do for u32 j in 0..(N-1-i) do - bool swap = a[j + 1] < a[j] - u32 tmp = a[j] - a[j] = if swap then a[j + 1] else a[j] fi - a[j + 1] = if swap then tmp else a[j + 1] fi + a = if a[j + 1] < a[j] then swap(a, j, j + 1) else a fi endfor endfor return a From 9d47e000f5a83ea1ea40bda60fb6067578ac3f48 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 20 May 2021 17:38:28 +0100 Subject: [PATCH 03/86] Use tuple-swap function --- zokrates_cli/examples/book/bubblesort.zok | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zokrates_cli/examples/book/bubblesort.zok b/zokrates_cli/examples/book/bubblesort.zok index 342982e3d..29c037caf 100644 --- a/zokrates_cli/examples/book/bubblesort.zok +++ b/zokrates_cli/examples/book/bubblesort.zok @@ -1,13 +1,13 @@ -def swap(u32[10] a, u32 i, u32 j) -> u32[10]: - u32 tmp = a[i] - a[i] = a[j] - a[j] = tmp - return a +def swap(u32 a, u32 b, bool c) -> (u32, u32): + u32 a_prime = if c then b else a fi + b = if c then a else b fi + return a_prime, b def bubblesort(u32[N] a) -> u32[N]: for u32 i in 0..(N-1) do for u32 j in 0..(N-1-i) do - a = if a[j + 1] < a[j] then swap(a, j, j + 1) else a fi + bool need_swap = a[j + 1] < a[j] + a[j], a[j + 1] = swap(a[j], a[j + 1], need_swap) endfor endfor return a From e5fd35ac261d70c29211cbd365184059da8e2a9c Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 7 Jul 2021 17:11:09 +0200 Subject: [PATCH 04/86] wip --- zokrates_core/src/absy/from_ast.rs | 49 ++++++- zokrates_core/src/absy/mod.rs | 14 +- zokrates_core/src/absy/types.rs | 27 +++- zokrates_core/src/semantics.rs | 192 +++++++++++++++++++++++--- zokrates_core/src/typed_absy/types.rs | 57 +++++++- zokrates_parser/src/zokrates.pest | 8 +- zokrates_pest_ast/src/lib.rs | 2 + 7 files changed, 306 insertions(+), 43 deletions(-) diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 49e954a47..673f627c1 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -79,6 +79,11 @@ impl<'ast> From> for absy::SymbolDeclarationNode<'a let id = definition.id.span.as_str(); let ty = absy::StructDefinition { + generics: definition + .generics + .into_iter() + .map(absy::ConstantGenericNode::from) + .collect(), fields: definition .fields .into_iter() @@ -767,9 +772,25 @@ impl<'ast> From> for absy::UnresolvedTypeNode<'ast> { pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), }, - pest::BasicOrStructType::Struct(t) => { - UnresolvedType::User(t.span.as_str().to_string()).span(t.span) - } + pest::BasicOrStructType::Struct(t) => UnresolvedType::User( + t.span.as_str().to_string(), + t.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(absy::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => Some( + absy::Expression::Identifier(i.span.as_str()).span(i.span), + ), + }) + .collect() + }), + ) + .span(t.span), }; let span = t.span; @@ -785,9 +806,25 @@ impl<'ast> From> for absy::UnresolvedTypeNode<'ast> { .unwrap() .span(span.clone()) } - pest::Type::Struct(s) => { - UnresolvedType::User(s.id.span.as_str().to_string()).span(s.span) - } + pest::Type::Struct(s) => UnresolvedType::User( + s.id.span.as_str().to_string(), + s.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(absy::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => { + Some(absy::Expression::Identifier(i.span.as_str()).span(i.span)) + } + }) + .collect() + }), + ) + .span(s.span), } } } diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index e00a271de..d685151e1 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -153,7 +153,7 @@ impl<'ast> fmt::Display for SymbolDeclaration<'ast> { i.value.source.display(), i.value.id ), - SymbolDefinition::Struct(ref t) => write!(f, "struct {} {}", self.id, t), + SymbolDefinition::Struct(ref t) => write!(f, "struct {}{}", self.id, t), SymbolDefinition::Constant(ref c) => write!( f, "const {} {} = {}", @@ -199,6 +199,7 @@ pub type UnresolvedTypeNode<'ast> = Node>; /// A struct type definition #[derive(Debug, Clone, PartialEq)] pub struct StructDefinition<'ast> { + pub generics: Vec>, pub fields: Vec>, } @@ -206,12 +207,17 @@ impl<'ast> fmt::Display for StructDefinition<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "{}", + "<{}> {{\n {}\n}}", + self.generics + .iter() + .map(|g| g.to_string()) + .collect::>() + .join(", "), self.fields .iter() .map(|fi| fi.to_string()) .collect::>() - .join("\n") + .join("\n ") ) } } @@ -227,7 +233,7 @@ pub struct StructDefinitionField<'ast> { impl<'ast> fmt::Display for StructDefinitionField<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {},", self.id, self.ty) + write!(f, "{} {}", self.ty, self.id) } } diff --git a/zokrates_core/src/absy/types.rs b/zokrates_core/src/absy/types.rs index 439f9ca78..14f7274ea 100644 --- a/zokrates_core/src/absy/types.rs +++ b/zokrates_core/src/absy/types.rs @@ -3,9 +3,7 @@ use crate::absy::UnresolvedTypeNode; use std::fmt; pub type Identifier<'ast> = &'ast str; - pub type MemberId = String; - pub type UserTypeId = String; #[derive(Clone, PartialEq, Debug)] @@ -14,7 +12,7 @@ pub enum UnresolvedType<'ast> { Boolean, Uint(usize), Array(Box>, ExpressionNode<'ast>), - User(UserTypeId), + User(UserTypeId, Option>>>), } impl<'ast> fmt::Display for UnresolvedType<'ast> { @@ -24,7 +22,28 @@ impl<'ast> fmt::Display for UnresolvedType<'ast> { UnresolvedType::Boolean => write!(f, "bool"), UnresolvedType::Uint(bitwidth) => write!(f, "u{}", bitwidth), UnresolvedType::Array(ref ty, ref size) => write!(f, "{}[{}]", ty, size), - UnresolvedType::User(i) => write!(f, "{}", i), + UnresolvedType::User(ref id, ref generics) => { + write!( + f, + "{}{}", + id, + generics + .as_ref() + .map(|generics| { + format!( + "<{}>", + generics + .iter() + .map(|e| { + e.as_ref().map(|e| e.to_string()).unwrap_or("_".to_string()) + }) + .collect::>() + .join(", ") + ) + }) + .unwrap_or_default() + ) + } } } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 2753af169..ab990c258 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -407,10 +407,45 @@ impl<'ast, T: Field> Checker<'ast, T> { let mut fields: Vec<(_, _)> = vec![]; let mut fields_set = HashSet::new(); + let mut generics = vec![]; + let mut generics_map = HashMap::new(); + + for (index, g) in s.generics.iter().enumerate() { + if state + .constants + .get(module_id) + .and_then(|m| m.get(g.value)) + .is_some() + { + errors.push(ErrorInner { + pos: Some(g.pos()), + message: format!( + "Generic parameter {p} conflicts with constant symbol {p}", + p = g.value + ), + }); + } else { + match generics_map.insert(g.value, index).is_none() { + true => { + generics.push(Some(DeclarationConstant::Generic(GenericIdentifier { + name: g.value, + index, + }))); + } + false => { + errors.push(ErrorInner { + pos: Some(g.pos()), + message: format!("Generic parameter {} is already declared", g.value), + }); + } + } + } + } + for field in s.fields { let member_id = field.value.id.to_string(); match self - .check_declaration_type(field.value.ty, module_id, state, &HashMap::new()) + .check_declaration_type(field.value.ty, module_id, state, &generics_map) .map(|t| (member_id, t)) { Ok(f) => match fields_set.insert(f.0.clone()) { @@ -433,6 +468,7 @@ impl<'ast, T: Field> Checker<'ast, T> { Ok(DeclarationType::Struct(DeclarationStructType::new( module_id.to_path_buf(), id, + generics, fields .iter() .map(|f| DeclarationStructMember::new(f.0.clone(), f.1.clone())) @@ -1107,16 +1143,75 @@ impl<'ast, T: Field> Checker<'ast, T> { size, ))) } - UnresolvedType::User(id) => types - .get(module_id) - .unwrap() - .get(&id) - .cloned() - .ok_or_else(|| ErrorInner { - pos: Some(pos), - message: format!("Undefined type {}", id), - }) - .map(|t| t.into()), + UnresolvedType::User(id, generics) => { + let declaration_type = + types + .get(module_id) + .unwrap() + .get(&id) + .cloned() + .ok_or_else(|| ErrorInner { + pos: Some(pos), + message: format!("Undefined type {}", id), + })?; + + // check explicit generics if provided + if let Some(generics) = generics { + match declaration_type { + DeclarationType::Struct(struct_type) => { + match struct_type.generics.len() == generics.len() { + true => { + let checked_generics = generics + .into_iter() + .map(|e| match e { + Some(e) => self + .check_expression(e, module_id, types) + .and_then(|e| { + UExpression::try_from_typed(e, UBitwidth::B32) + .map(Some) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), + }) + }), + None => Ok(None), + }) + .collect::>()?; + + Ok(Type::Struct(StructType { + canonical_location: struct_type.canonical_location, + location: struct_type.location, + generics: checked_generics, + members: struct_type + .members + .into_iter() + .map(|m| m.into()) + .collect(), + })) + } + false => Err(ErrorInner { + pos: Some(pos), + message: format!( + "Expected {} generic argument{} on type {}, but got {}", + struct_type.generics.len(), + if struct_type.generics.len() == 1 { + "" + } else { + "s" + }, + id, + generics.len() + ), + }), + } + } + _ => Ok(declaration_type.into()), + } + } else { + // explicit generics were not provided, so we will infer later on + Ok(declaration_type.into()) + } + } } } fn check_generic_expression( @@ -1162,7 +1257,7 @@ impl<'ast, T: Field> Checker<'ast, T> { (None, Some(index)) => Ok(DeclarationConstant::Generic(GenericIdentifier { name, index: *index })), _ => Err(ErrorInner { pos: Some(pos), - message: format!("Undeclared symbol `{}` in function definition", name) + message: format!("Undeclared symbol `{}`", name) }) } } @@ -1203,16 +1298,67 @@ impl<'ast, T: Field> Checker<'ast, T> { checked_size, ))) } - UnresolvedType::User(id) => state - .types - .get(module_id) - .unwrap() - .get(&id) - .cloned() - .ok_or_else(|| ErrorInner { - pos: Some(pos), - message: format!("Undefined type {}", id), - }), + UnresolvedType::User(id, generics) => { + let ty = state + .types + .get(module_id) + .unwrap() + .get(&id) + .cloned() + .ok_or_else(|| ErrorInner { + pos: Some(pos), + message: format!("Undefined type {}", id), + })?; + + match ty { + DeclarationType::Struct(struct_type) => { + let generics = generics.unwrap_or_default(); + match struct_type.generics.len() == generics.len() { + true => { + let checked_generics = generics + .into_iter() + .map(|e| match e { + Some(e) => self + .check_generic_expression( + e, + module_id, + state + .constants + .get(module_id) + .unwrap_or(&HashMap::new()), + generics_map, + ) + .map(Some), + None => Ok(None), + }) + .collect::>()?; + + Ok(DeclarationType::Struct(DeclarationStructType { + canonical_location: struct_type.canonical_location, + location: struct_type.location, + generics: checked_generics, + members: struct_type.members, + })) + } + false => Err(ErrorInner { + pos: Some(pos), + message: format!( + "Expected {} generic argument{} on type {}, but got {}", + struct_type.generics.len(), + if struct_type.generics.len() == 1 { + "" + } else { + "s" + }, + id, + generics.len() + ), + }), + } + } + _ => Ok(ty), + } + } } } @@ -2675,7 +2821,7 @@ impl<'ast, T: Field> Checker<'ast, T> { } Expression::InlineStruct(id, inline_members) => { let ty = self.check_type( - UnresolvedType::User(id.clone()).at(42, 42, 42), + UnresolvedType::User(id.clone(), None).at(42, 42, 42), module_id, types, )?; diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 94794fcb5..f97376300 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -362,6 +362,7 @@ pub struct GStructType { pub canonical_location: StructLocation, #[serde(skip)] pub location: Option, + pub generics: Vec>, pub members: Vec>, } @@ -389,6 +390,14 @@ fn try_from_g_struct_type, U>( Ok(GStructType { location: t.location, canonical_location: t.canonical_location, + generics: t + .generics + .into_iter() + .map(|g| match g { + Some(g) => g.try_into().map(Some).map_err(|_| SpecializationError), + None => Ok(None), + }) + .collect::>()?, members: t .members .into_iter() @@ -424,10 +433,16 @@ impl<'ast, T> From> for StructType<'ast, T> { } impl GStructType { - pub fn new(module: PathBuf, name: String, members: Vec>) -> Self { + pub fn new( + module: PathBuf, + name: String, + generics: Vec>, + members: Vec>, + ) -> Self { GStructType { canonical_location: StructLocation { module, name }, location: None, + generics, members, } } @@ -694,7 +709,27 @@ impl fmt::Display for GType { GType::Uint(ref bitwidth) => write!(f, "u{}", bitwidth), GType::Int => write!(f, "{{integer}}"), GType::Array(ref array_type) => write!(f, "{}", array_type), - GType::Struct(ref struct_type) => write!(f, "{}", struct_type.name(),), + GType::Struct(ref struct_type) => write!( + f, + "{}{}", + struct_type.name(), + if !struct_type.generics.is_empty() { + format!( + "<{}>", + struct_type + .generics + .iter() + .map(|g| g + .as_ref() + .map(|g| g.to_string()) + .unwrap_or_else(|| '_'.to_string())) + .collect::>() + .join(", ") + ) + } else { + "".to_string() + } + ), } } } @@ -1039,6 +1074,24 @@ pub mod signature { specialize_type(*m.ty, constants).map(|ty| GStructMember { ty: box ty, id }) }) .collect::>()?, + generics: s0 + .generics + .into_iter() + .map(|g| match g { + Some(constant) => match constant { + DeclarationConstant::Generic(s) => { + constants.0.get(&s).cloned().ok_or(s).map(|v| Some(v)) + } + DeclarationConstant::Concrete(s) => Ok(Some(s.into())), + DeclarationConstant::Constant(..) => { + unreachable!( + "identifiers should have been removed in constant inlining" + ) + } + }, + _ => Ok(None), + }) + .collect::>()?, canonical_location: s0.canonical_location, location: s0.location, }), diff --git a/zokrates_parser/src/zokrates.pest b/zokrates_parser/src/zokrates.pest index e9b11411c..ce7499e70 100644 --- a/zokrates_parser/src/zokrates.pest +++ b/zokrates_parser/src/zokrates.pest @@ -34,9 +34,9 @@ ty_array = { ty_basic_or_struct ~ ("[" ~ expression ~ "]")+ } ty = { ty_array | ty_basic | ty_struct } type_list = _{(ty ~ ("," ~ ty)*)?} // structs -ty_struct = { identifier } +ty_struct = { identifier ~ explicit_generics? } // type definitions -ty_struct_definition = { "struct" ~ identifier ~ "{" ~ NEWLINE* ~ struct_field_list ~ NEWLINE* ~ "}" ~ NEWLINE* } +ty_struct_definition = { "struct" ~ identifier ~ constant_generics_declaration? ~ "{" ~ NEWLINE* ~ struct_field_list ~ NEWLINE* ~ "}" ~ NEWLINE* } struct_field_list = _{(struct_field ~ (NEWLINE+ ~ struct_field)*)? } struct_field = { ty ~ identifier } @@ -77,9 +77,9 @@ conditional_expression = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ ex postfix_expression = { identifier ~ access+ } // we force there to be at least one access, otherwise this matches single identifiers access = { array_access | call_access | member_access } array_access = { "[" ~ range_or_expression ~ "]" } -call_access = { explicit_generics? ~ "(" ~ arguments ~ ")" } +call_access = { ("::" ~ explicit_generics)? ~ "(" ~ arguments ~ ")" } arguments = { expression_list } -explicit_generics = { "::<" ~ constant_generics_values ~ ">" } +explicit_generics = { "<" ~ constant_generics_values ~ ">" } constant_generics_values = _{ constant_generics_value ~ ("," ~ constant_generics_value)* } constant_generics_value = { literal | identifier | underscore } underscore = { "_" } diff --git a/zokrates_pest_ast/src/lib.rs b/zokrates_pest_ast/src/lib.rs index 53a2a2a23..22b4d0d78 100644 --- a/zokrates_pest_ast/src/lib.rs +++ b/zokrates_pest_ast/src/lib.rs @@ -147,6 +147,7 @@ mod ast { #[pest_ast(rule(Rule::ty_struct_definition))] pub struct StructDefinition<'ast> { pub id: IdentifierExpression<'ast>, + pub generics: Vec>, pub fields: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, @@ -307,6 +308,7 @@ mod ast { #[pest_ast(rule(Rule::ty_struct))] pub struct StructType<'ast> { pub id: IdentifierExpression<'ast>, + pub explicit_generics: Option>, #[pest_ast(outer())] pub span: Span<'ast>, } From 3072f34938a1864f4e333800b4c45da2f7e8389e Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 9 Jul 2021 22:49:59 +0200 Subject: [PATCH 05/86] implement missing features, wip --- zokrates_core/src/semantics.rs | 321 +++++++++++------- zokrates_core/src/static_analysis/mod.rs | 5 + .../src/static_analysis/propagation.rs | 8 + zokrates_core/src/typed_absy/mod.rs | 2 + zokrates_core/src/typed_absy/types.rs | 240 ++++++------- 5 files changed, 345 insertions(+), 231 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index ab990c258..7487668e0 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -6,6 +6,7 @@ use crate::absy::Identifier; use crate::absy::*; +use crate::typed_absy::types::GGenericsAssignment; use crate::typed_absy::*; use crate::typed_absy::{DeclarationParameter, DeclarationVariable, Variable}; use num_bigint::BigUint; @@ -19,9 +20,9 @@ use crate::parser::Position; use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; use crate::typed_absy::types::{ - ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationFunctionKey, - DeclarationSignature, DeclarationStructMember, DeclarationStructType, DeclarationType, - GenericIdentifier, StructLocation, + check_type, specialize_type, ArrayType, DeclarationArrayType, DeclarationConstant, + DeclarationFunctionKey, DeclarationSignature, DeclarationStructMember, DeclarationStructType, + DeclarationType, GenericIdentifier, StructLocation, StructMember, }; use std::hash::{Hash, Hasher}; @@ -442,10 +443,18 @@ impl<'ast, T: Field> Checker<'ast, T> { } } + let mut used_generics = HashSet::new(); + for field in s.fields { let member_id = field.value.id.to_string(); match self - .check_declaration_type(field.value.ty, module_id, state, &generics_map) + .check_declaration_type( + field.value.ty, + module_id, + state, + &generics_map, + &mut used_generics, + ) .map(|t| (member_id, t)) { Ok(f) => match fields_set.insert(f.0.clone()) { @@ -461,6 +470,16 @@ impl<'ast, T: Field> Checker<'ast, T> { } } + // check that all declared generics were used + for declared_generic in generics_map.keys() { + if !used_generics.contains(declared_generic) { + errors.push(ErrorInner { + pos: Some(pos), + message: format!("Generic parameter {} must be used", declared_generic), + }); + } + } + if !errors.is_empty() { return Err(errors); } @@ -1058,7 +1077,13 @@ impl<'ast, T: Field> Checker<'ast, T> { } for t in signature.inputs { - match self.check_declaration_type(t, module_id, state, &generics_map) { + match self.check_declaration_type( + t, + module_id, + state, + &generics_map, + &mut HashSet::default(), + ) { Ok(t) => { inputs.push(t); } @@ -1069,7 +1094,13 @@ impl<'ast, T: Field> Checker<'ast, T> { } for t in signature.outputs { - match self.check_declaration_type(t, module_id, state, &generics_map) { + match self.check_declaration_type( + t, + module_id, + state, + &generics_map, + &mut HashSet::default(), + ) { Ok(t) => { outputs.push(t); } @@ -1155,61 +1186,59 @@ impl<'ast, T: Field> Checker<'ast, T> { message: format!("Undefined type {}", id), })?; - // check explicit generics if provided - if let Some(generics) = generics { - match declaration_type { - DeclarationType::Struct(struct_type) => { - match struct_type.generics.len() == generics.len() { - true => { - let checked_generics = generics + // absence of generics is treated as 0 generics, as we do not provide inference for now + let generics = generics.unwrap_or_default(); + + // check generics + match declaration_type { + DeclarationType::Struct(struct_type) => { + match struct_type.generics.len() == generics.len() { + true => { + let checked_generics = generics + .into_iter() + .map(|e| match e { + Some(e) => self + .check_expression(e, module_id, types) + .and_then(|e| { + UExpression::try_from_typed(e, UBitwidth::B32) + .map(Some) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), + }) + }), + None => Ok(None), + }) + .collect::>()?; + + Ok(Type::Struct(StructType { + canonical_location: struct_type.canonical_location, + location: struct_type.location, + generics: checked_generics, + members: struct_type + .members .into_iter() - .map(|e| match e { - Some(e) => self - .check_expression(e, module_id, types) - .and_then(|e| { - UExpression::try_from_typed(e, UBitwidth::B32) - .map(Some) - .map_err(|e| ErrorInner { - pos: Some(pos), - message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), - }) - }), - None => Ok(None), - }) - .collect::>()?; - - Ok(Type::Struct(StructType { - canonical_location: struct_type.canonical_location, - location: struct_type.location, - generics: checked_generics, - members: struct_type - .members - .into_iter() - .map(|m| m.into()) - .collect(), - })) - } - false => Err(ErrorInner { - pos: Some(pos), - message: format!( - "Expected {} generic argument{} on type {}, but got {}", - struct_type.generics.len(), - if struct_type.generics.len() == 1 { - "" - } else { - "s" - }, - id, - generics.len() - ), - }), + .map(|m| m.into()) + .collect(), + })) } + false => Err(ErrorInner { + pos: Some(pos), + message: format!( + "Expected {} generic argument{} on type {}, but got {}", + struct_type.generics.len(), + if struct_type.generics.len() == 1 { + "" + } else { + "s" + }, + id, + generics.len() + ), + }), } - _ => Ok(declaration_type.into()), } - } else { - // explicit generics were not provided, so we will infer later on - Ok(declaration_type.into()) + _ => unreachable!("user defined types should always be structs"), } } } @@ -1220,6 +1249,7 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id: &ModuleId, constants_map: &HashMap, Type<'ast, T>>, generics_map: &HashMap, usize>, + used_generics: &mut HashSet>, ) -> Result, ErrorInner> { let pos = expr.pos(); @@ -1241,6 +1271,8 @@ impl<'ast, T: Field> Checker<'ast, T> { } } Expression::Identifier(name) => { + used_generics.insert(name.clone()); + match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { match ty { @@ -1277,6 +1309,7 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id: &ModuleId, state: &State<'ast, T>, generics_map: &HashMap, usize>, + used_generics: &mut HashSet>, ) -> Result, ErrorInner> { let pos = ty.pos(); let ty = ty.value; @@ -1291,15 +1324,16 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id, state.constants.get(module_id).unwrap_or(&HashMap::new()), generics_map, + used_generics, )?; Ok(DeclarationType::Array(DeclarationArrayType::new( - self.check_declaration_type(*t, module_id, state, generics_map)?, + self.check_declaration_type(*t, module_id, state, generics_map, used_generics)?, checked_size, ))) } UnresolvedType::User(id, generics) => { - let ty = state + let declared_ty = state .types .get(module_id) .unwrap() @@ -1310,12 +1344,12 @@ impl<'ast, T: Field> Checker<'ast, T> { message: format!("Undefined type {}", id), })?; - match ty { - DeclarationType::Struct(struct_type) => { + match declared_ty { + DeclarationType::Struct(declared_struct_ty) => { let generics = generics.unwrap_or_default(); - match struct_type.generics.len() == generics.len() { + match declared_struct_ty.generics.len() == generics.len() { true => { - let checked_generics = generics + let checked_generics: Vec<_> = generics .into_iter() .map(|e| match e { Some(e) => self @@ -1327,25 +1361,49 @@ impl<'ast, T: Field> Checker<'ast, T> { .get(module_id) .unwrap_or(&HashMap::new()), generics_map, + used_generics, ) .map(Some), - None => Ok(None), + None => Err(ErrorInner { + pos: Some(pos), + message: format!("Expected u32 constant or identifier, but found `_`"), + }), }) .collect::>()?; + let mut assignment = GGenericsAssignment::default(); + + assignment.0.extend(declared_struct_ty.generics.iter().zip(checked_generics.iter()).map(|(decl_g, g_val)| match decl_g.clone().unwrap() { + DeclarationConstant::Generic(g) => (g, g_val.clone().unwrap()), + _ => unreachable!("generic on declaration struct types must be generic identifiers") + })); + + // generate actual type based on generic type and concrete generics + let members = declared_struct_ty + .members + .into_iter() + .map(|m| { + Ok(DeclarationStructMember { + ty: box specialize_type(*m.ty, &assignment) + .map_err(|_| unimplemented!())?, + ..m + }) + }) + .collect::, _>>()?; + Ok(DeclarationType::Struct(DeclarationStructType { - canonical_location: struct_type.canonical_location, - location: struct_type.location, + canonical_location: declared_struct_ty.canonical_location, + location: declared_struct_ty.location, generics: checked_generics, - members: struct_type.members, + members, })) } false => Err(ErrorInner { pos: Some(pos), message: format!( "Expected {} generic argument{} on type {}, but got {}", - struct_type.generics.len(), - if struct_type.generics.len() == 1 { + declared_struct_ty.generics.len(), + if declared_struct_ty.generics.len() == 1 { "" } else { "s" @@ -1356,7 +1414,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }), } } - _ => Ok(ty), + _ => Ok(declared_ty), } } } @@ -2820,26 +2878,28 @@ impl<'ast, T: Field> Checker<'ast, T> { .into()) } Expression::InlineStruct(id, inline_members) => { - let ty = self.check_type( - UnresolvedType::User(id.clone(), None).at(42, 42, 42), - module_id, - types, - )?; - let struct_type = match ty { - Type::Struct(struct_type) => struct_type, + let ty = match types.get(module_id).unwrap().get(&id).cloned() { + None => Err(ErrorInner { + pos: Some(pos), + message: format!("Undeclared type of name `{}`", id), + }), + Some(ty) => Ok(ty), + }?; + + let declared_struct_type = match ty { + DeclarationType::Struct(struct_type) => struct_type, _ => unreachable!(), }; // check that we provided the required number of values - - if struct_type.members_count() != inline_members.len() { + if declared_struct_type.members_count() != inline_members.len() { return Err(ErrorInner { pos: Some(pos), message: format!( "Inline struct {} does not match {} {{{}}}", Expression::InlineStruct(id, inline_members), - Type::Struct(struct_type.clone()), - struct_type + declared_struct_type, + declared_struct_type .members .iter() .map(|m| format!("{}: {}", m.id, m.ty)) @@ -2857,54 +2917,87 @@ impl<'ast, T: Field> Checker<'ast, T> { .into_iter() .map(|(id, v)| (id.to_string(), v)) .collect::>(); - let mut result: Vec> = vec![]; - - for member in struct_type.iter() { - match inline_members_map.remove(member.id.as_str()) { - Some(value) => { - let expression_checked = - self.check_expression(value, module_id, types)?; - let expression_checked = TypedExpression::align_to_type( - expression_checked, - *member.ty.clone(), - ) - .map_err(|e| ErrorInner { - pos: Some(pos), - message: format!( - "Member {} of struct {} has type {}, found {} of type {}", - member.id, - id.clone(), - e.1, - e.0, - e.0.get_type(), - ), - })?; + let inferred_values = declared_struct_type + .iter() + .map( + |member| match inline_members_map.remove(member.id.as_str()) { + Some(value) => { + let expression_checked = + self.check_expression(value, module_id, types)?; + + let expression_checked = TypedExpression::align_to_type( + expression_checked, + Type::from(*member.ty.clone()), + ) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!( + "Member {} of struct {} has type {}, found {} of type {}", + member.id, + id.clone(), + e.1, + e.0, + e.0.get_type(), + ), + })?; - result.push(expression_checked); - } - None => { - return Err(ErrorInner { + Ok(expression_checked) + } + None => Err(ErrorInner { pos: Some(pos), message: format!( "Member {} of struct {} {{{}}} not found in value {}", member.id, - Type::Struct(struct_type.clone()), - struct_type + declared_struct_type, + declared_struct_type .members .iter() .map(|m| format!("{}: {}", m.id, m.ty)) .collect::>() .join(", "), - Expression::InlineStruct(id, inline_members), + Expression::InlineStruct(id.clone(), inline_members.clone()), + ), + }), + }, + ) + .collect::, _>>()?; + + let mut generics_map = GGenericsAssignment::default(); + + let members = declared_struct_type + .iter() + .zip(inferred_values.iter()) + .map(|(m, v)| { + if !check_type(&m.ty, &v.get_type(), &mut generics_map) { + Err(ErrorInner { + pos: Some(pos), + message: format!( + "Value `{}` doesn't match the expected type `{}` because of conflict in generic values", + Expression::InlineStruct(id.clone(), inline_members.clone()), + declared_struct_type ), }) + } else { + Ok(StructMember { + id: m.id.clone(), + ty: box v.get_type().clone(), + }) } - } - } + }) + .collect::, _>>()?; + + let generics = generics_map.0.values().cloned().map(Some).collect(); + + let inferred_struct_type = StructType { + canonical_location: declared_struct_type.canonical_location.clone(), + location: declared_struct_type.location, + generics, + members, + }; - Ok(StructExpressionInner::Value(result) - .annotate(struct_type) + Ok(StructExpressionInner::Value(inferred_values) + .annotate(inferred_struct_type) .into()) } Expression::And(box e1, box e2) => { diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 80670eca2..bb3e2f829 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -76,6 +76,8 @@ impl fmt::Display for Error { impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { + println!("{}", self); + // inline user-defined constants let r = ConstantInliner::inline(self); // isolate branches @@ -87,6 +89,9 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { // reduce the program to a single function let r = reduce_program(r).map_err(Error::from)?; + + println!("{}", r); + // generate abi let abi = r.abi(); diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 2438971c0..5578cf704 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -329,10 +329,18 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { let expr = self.fold_expression(expr)?; let assignee = self.fold_assignee(assignee)?; + println!( + "{:#?} vs {:#?}", + assignee.get_type().clone(), + expr.get_type().clone() + ); + if let (Ok(a), Ok(e)) = ( ConcreteType::try_from(assignee.get_type()), ConcreteType::try_from(expr.get_type()), ) { + println!("{} vs {}", a, e); + if a != e { return Err(Error::Type(format!( "Cannot assign {} of type {} to {} of type {}", diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index eb4f272e0..dff34cf72 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -107,6 +107,8 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .arguments .iter() .map(|p| { + println!("{:#?}", p); + types::ConcreteType::try_from(types::Type::::from(p.id._type.clone())) .map(|ty| AbiInput { public: !p.private, diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index f97376300..e811acf2d 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -372,13 +372,14 @@ pub type StructType<'ast, T> = GStructType>; impl PartialEq for GStructType { fn eq(&self, other: &Self) -> bool { - self.canonical_location.eq(&other.canonical_location) + self.canonical_location.eq(&other.canonical_location) && self.generics.eq(&other.generics) } } impl Hash for GStructType { fn hash(&self, state: &mut H) { self.canonical_location.hash(state); + self.generics.hash(state); } } @@ -709,31 +710,36 @@ impl fmt::Display for GType { GType::Uint(ref bitwidth) => write!(f, "u{}", bitwidth), GType::Int => write!(f, "{{integer}}"), GType::Array(ref array_type) => write!(f, "{}", array_type), - GType::Struct(ref struct_type) => write!( - f, - "{}{}", - struct_type.name(), - if !struct_type.generics.is_empty() { - format!( - "<{}>", - struct_type - .generics - .iter() - .map(|g| g - .as_ref() - .map(|g| g.to_string()) - .unwrap_or_else(|| '_'.to_string())) - .collect::>() - .join(", ") - ) - } else { - "".to_string() - } - ), + GType::Struct(ref struct_type) => write!(f, "{}", struct_type), } } } +impl fmt::Display for GStructType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}{}", + self.name(), + if !self.generics.is_empty() { + format!( + "<{}>", + self.generics + .iter() + .map(|g| g + .as_ref() + .map(|g| g.to_string()) + .unwrap_or_else(|| '_'.to_string())) + .collect::>() + .join(", ") + ) + } else { + "".to_string() + } + ) + } +} + impl GType { pub fn array>>(array_ty: U) -> Self { GType::Array(array_ty.into()) @@ -948,6 +954,101 @@ impl<'ast> ConcreteFunctionKey<'ast> { } } +use std::collections::btree_map::Entry; + +pub fn check_type<'ast, S: Clone + PartialEq + PartialEq>( + decl_ty: &DeclarationType<'ast>, + ty: >ype, + constants: &mut GGenericsAssignment<'ast, S>, +) -> bool { + match (decl_ty, ty) { + (DeclarationType::Array(t0), GType::Array(t1)) => { + let s1 = t1.size.clone(); + + // both the inner type and the size must match + check_type(&t0.ty, &t1.ty, constants) + && match &t0.size { + // if the declared size is an identifier, we insert into the map, or check if the concrete size + // matches if this identifier is already in the map + DeclarationConstant::Generic(id) => match constants.0.entry(id.clone()) { + Entry::Occupied(e) => *e.get() == s1, + Entry::Vacant(e) => { + e.insert(s1); + true + } + }, + DeclarationConstant::Concrete(s0) => s1 == *s0 as usize, + // in the case of a constant, we do not know the value yet, so we optimistically assume it's correct + // if it does not match, it will be caught during inlining + DeclarationConstant::Constant(..) => true, + } + } + (DeclarationType::FieldElement, GType::FieldElement) + | (DeclarationType::Boolean, GType::Boolean) => true, + (DeclarationType::Uint(b0), GType::Uint(b1)) => b0 == b1, + (DeclarationType::Struct(s0), GType::Struct(s1)) => { + s0.canonical_location == s1.canonical_location + } + _ => false, + } +} + +pub fn specialize_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( + decl_ty: DeclarationType<'ast>, + constants: &GGenericsAssignment<'ast, S>, +) -> Result, GenericIdentifier<'ast>> { + Ok(match decl_ty { + DeclarationType::Int => unreachable!(), + DeclarationType::Array(t0) => { + // let s1 = t1.size.clone(); + + let ty = box specialize_type(*t0.ty, &constants)?; + let size = match t0.size { + DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), + DeclarationConstant::Concrete(s) => Ok(s.into()), + DeclarationConstant::Constant(..) => { + unreachable!("identifiers should have been removed in constant inlining") + } + }?; + + GType::Array(GArrayType { size, ty }) + } + DeclarationType::FieldElement => GType::FieldElement, + DeclarationType::Boolean => GType::Boolean, + DeclarationType::Uint(b0) => GType::Uint(b0), + DeclarationType::Struct(s0) => GType::Struct(GStructType { + members: s0 + .members + .into_iter() + .map(|m| { + let id = m.id; + specialize_type(*m.ty, constants).map(|ty| GStructMember { ty: box ty, id }) + }) + .collect::>()?, + generics: s0 + .generics + .into_iter() + .map(|g| match g { + Some(constant) => match constant { + DeclarationConstant::Generic(s) => { + constants.0.get(&s).cloned().ok_or(s).map(|v| Some(v)) + } + DeclarationConstant::Concrete(s) => Ok(Some(s.into())), + DeclarationConstant::Constant(..) => { + unreachable!( + "identifiers should have been removed in constant inlining" + ) + } + }, + _ => Ok(None), + }) + .collect::>()?, + canonical_location: s0.canonical_location, + location: s0.location, + }), + }) +} + pub use self::signature::{ConcreteSignature, DeclarationSignature, GSignature, Signature}; pub mod signature { @@ -1003,101 +1104,6 @@ pub mod signature { pub type ConcreteSignature = GSignature; pub type Signature<'ast, T> = GSignature>; - use std::collections::btree_map::Entry; - - fn check_type<'ast, S: Clone + PartialEq + PartialEq>( - decl_ty: &DeclarationType<'ast>, - ty: >ype, - constants: &mut GGenericsAssignment<'ast, S>, - ) -> bool { - match (decl_ty, ty) { - (DeclarationType::Array(t0), GType::Array(t1)) => { - let s1 = t1.size.clone(); - - // both the inner type and the size must match - check_type(&t0.ty, &t1.ty, constants) - && match &t0.size { - // if the declared size is an identifier, we insert into the map, or check if the concrete size - // matches if this identifier is already in the map - DeclarationConstant::Generic(id) => match constants.0.entry(id.clone()) { - Entry::Occupied(e) => *e.get() == s1, - Entry::Vacant(e) => { - e.insert(s1); - true - } - }, - DeclarationConstant::Concrete(s0) => s1 == *s0 as usize, - // in the case of a constant, we do not know the value yet, so we optimistically assume it's correct - // if it does not match, it will be caught during inlining - DeclarationConstant::Constant(..) => true, - } - } - (DeclarationType::FieldElement, GType::FieldElement) - | (DeclarationType::Boolean, GType::Boolean) => true, - (DeclarationType::Uint(b0), GType::Uint(b1)) => b0 == b1, - (DeclarationType::Struct(s0), GType::Struct(s1)) => { - s0.canonical_location == s1.canonical_location - } - _ => false, - } - } - - fn specialize_type<'ast, S: Clone + PartialEq + PartialEq + From + fmt::Debug>( - decl_ty: DeclarationType<'ast>, - constants: &GGenericsAssignment<'ast, S>, - ) -> Result, GenericIdentifier<'ast>> { - Ok(match decl_ty { - DeclarationType::Int => unreachable!(), - DeclarationType::Array(t0) => { - // let s1 = t1.size.clone(); - - let ty = box specialize_type(*t0.ty, &constants)?; - let size = match t0.size { - DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), - DeclarationConstant::Concrete(s) => Ok(s.into()), - DeclarationConstant::Constant(..) => { - unreachable!("identifiers should have been removed in constant inlining") - } - }?; - - GType::Array(GArrayType { size, ty }) - } - DeclarationType::FieldElement => GType::FieldElement, - DeclarationType::Boolean => GType::Boolean, - DeclarationType::Uint(b0) => GType::Uint(b0), - DeclarationType::Struct(s0) => GType::Struct(GStructType { - members: s0 - .members - .into_iter() - .map(|m| { - let id = m.id; - specialize_type(*m.ty, constants).map(|ty| GStructMember { ty: box ty, id }) - }) - .collect::>()?, - generics: s0 - .generics - .into_iter() - .map(|g| match g { - Some(constant) => match constant { - DeclarationConstant::Generic(s) => { - constants.0.get(&s).cloned().ok_or(s).map(|v| Some(v)) - } - DeclarationConstant::Concrete(s) => Ok(Some(s.into())), - DeclarationConstant::Constant(..) => { - unreachable!( - "identifiers should have been removed in constant inlining" - ) - } - }, - _ => Ok(None), - }) - .collect::>()?, - canonical_location: s0.canonical_location, - location: s0.location, - }), - }) - } - impl<'ast> PartialEq> for ConcreteSignature { fn eq(&self, other: &DeclarationSignature<'ast>) -> bool { // we keep track of the value of constants in a map, as a given constant can only have one value From c8b2d25e25af6e1c9b6cc34efb4a22dda315686e Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 14 Jul 2021 13:11:53 +0200 Subject: [PATCH 06/86] use constants in stdlib where applicable --- .../merkleTree/pedersenPathProof3.zok | 4 - .../stdlib/ecc/babyjubjubParams.zok | 50 ++- zokrates_stdlib/stdlib/ecc/edwardsAdd.zok | 5 +- zokrates_stdlib/stdlib/ecc/edwardsNegate.zok | 2 +- zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok | 4 +- .../stdlib/ecc/edwardsOrderCheck.zok | 2 +- .../stdlib/hashes/blake2/blake2s_p.zok | 68 ++-- .../stdlib/hashes/keccak/keccak.zok | 55 ++- .../stdlib/hashes/mimc7/constants.zok | 94 ----- zokrates_stdlib/stdlib/hashes/mimc7/mimc7.zok | 121 +++++- .../stdlib/hashes/mimcSponge/IVconstants.zok | 223 ----------- .../stdlib/hashes/mimcSponge/mimcFeistel.zok | 259 ++++++++++++- .../stdlib/hashes/mimcSponge/mimcSponge.zok | 31 +- .../stdlib/hashes/pedersen/512bitBool.zok | 348 +++++++++--------- .../stdlib/hashes/poseidon/constants.zok | 6 +- .../stdlib/hashes/poseidon/poseidon.zok | 7 +- .../stdlib/hashes/sha256/512bit.zok | 3 +- .../stdlib/hashes/sha256/512bitPacked.zok | 1 + .../stdlib/hashes/sha256/IVconstants.zok | 4 - .../hashes/sha256/embed/1024bitPadded.zok | 42 ++- .../hashes/sha256/embed/256bitPadded.zok | 36 +- .../stdlib/hashes/sha256/embed/512bit.zok | 7 +- .../hashes/sha256/embed/512bitPadded.zok | 41 ++- .../stdlib/hashes/sha256/sha256.zok | 17 +- .../stdlib/hashes/sha256/shaRound.zok | 23 +- .../tests/tests/ecc/edwardsAdd.zok | 17 +- .../tests/tests/ecc/edwardsCompress.zok | 9 +- .../tests/tests/ecc/edwardsOnCurve.zok | 7 +- .../tests/tests/ecc/edwardsOrderCheck.zok | 11 +- .../tests/tests/ecc/edwardsScalarMult.zok | 47 ++- .../tests/tests/ecc/proofOfOwnership.zok | 12 +- .../tests/hashes/mimcSponge/mimcFeistel.zok | 2 +- .../tests/hashes/mimcSponge/mimcSponge.zok | 14 +- .../tests/tests/signatures/verifyEddsa.zok | 8 +- 34 files changed, 797 insertions(+), 783 deletions(-) delete mode 100644 zokrates_stdlib/stdlib/hashes/mimc7/constants.zok delete mode 100644 zokrates_stdlib/stdlib/hashes/mimcSponge/IVconstants.zok delete mode 100644 zokrates_stdlib/stdlib/hashes/sha256/IVconstants.zok diff --git a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok index 9a7114be3..ad7b7af96 100644 --- a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok +++ b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok @@ -1,15 +1,11 @@ import "hashes/pedersen/512bit" as hash import "ecc/edwardsCompress" as edwardsCompress -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams import "hashes/utils/256bitsDirectionHelper" as multiplex // Merke-Tree inclusion proof for tree depth 3 using SNARK efficient pedersen hashes // directionSelector=> true if current digest is on the rhs of the hash def main(u32[8] rootDigest, private u32[8] leafDigest, private bool[3] directionSelector, u32[8] PathDigest0, private u32[8] PathDigest1, private u32[8] PathDigest2): - BabyJubJubParams context = context() - //Setup u32[8] currentDigest = leafDigest diff --git a/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok b/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok index 11fd783a8..766e09364 100644 --- a/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok +++ b/zokrates_stdlib/stdlib/ecc/babyjubjubParams.zok @@ -4,41 +4,33 @@ // Note: parameters will be updated soon to be more compatible with zCash's implementation struct BabyJubJubParams { - field JUBJUBC - field JUBJUBA - field JUBJUBD - field MONTA - field MONTB + field JUBJUB_C + field JUBJUB_A + field JUBJUB_D + field MONT_A + field MONT_B field[2] INFINITY field Gu field Gv } -def main() -> BabyJubJubParams: - - // Order of the curve for reference: 21888242871839275222246405745257275088614511777268538073601725287587578984328 - field JUBJUBC = 8 // Cofactor - field JUBJUBA = 168700 // Coefficient A - field JUBJUBD = 168696 // Coefficient D - field MONTA = 168698 // int(2*(JUBJUB_A+JUBJUB_D)/(JUBJUB_A-JUBJUB_D)) - field MONTB = 1 // int(4/(JUBJUB_A-JUBJUB_D)) +const BabyJubJubParams BABYJUBJUB_PARAMS = BabyJubJubParams { + // Order of the curve for reference: 21888242871839275222246405745257275088614511777268538073601725287587578984328 + JUBJUB_C: 8, // Cofactor + JUBJUB_A: 168700, // Coefficient A + JUBJUB_D: 168696, // Coefficient D -// Point at infinity - field[2] INFINITY = [0, 1] + // Montgomery parameters + MONT_A: 168698, + MONT_B: 1, -// Generator - field Gu = 16540640123574156134436876038791482806971768689494387082833631921987005038935 - field Gv = 20819045374670962167435360035096875258406992893633759881276124905556507972311 + // Point at infinity + INFINITY: [0, 1], -// Index -// 0 1 2 3 4 5 6 7 8 10 -return BabyJubJubParams { - JUBJUBA: JUBJUBA, - JUBJUBD: JUBJUBD, - INFINITY: INFINITY, - Gu: Gu, - Gv: Gv, - JUBJUBC: JUBJUBC, - MONTA: MONTA, - MONTB: MONTB + // Generator + Gu: 16540640123574156134436876038791482806971768689494387082833631921987005038935, + Gv: 20819045374670962167435360035096875258406992893633759881276124905556507972311 } + +def main() -> BabyJubJubParams: + return BABYJUBJUB_PARAMS \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok b/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok index 8202c639f..a66a61187 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsAdd.zok @@ -1,4 +1,3 @@ -from "ecc/babyjubjubParams" import main as context from "ecc/babyjubjubParams" import BabyJubJubParams // Add two points on a twisted Edwards curve @@ -6,8 +5,8 @@ from "ecc/babyjubjubParams" import BabyJubJubParams // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Addition_on_twisted_Edwards_curves def main(field[2] pt1, field[2] pt2, BabyJubJubParams context) -> field[2]: - field a = context.JUBJUBA - field d = context.JUBJUBD + field a = context.JUBJUB_A + field d = context.JUBJUB_D field u1 = pt1[0] field v1 = pt1[1] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok b/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok index f8d78178b..a86103060 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsNegate.zok @@ -6,4 +6,4 @@ def main(field[2] pt) -> field[2]: field u = pt[0] field v = pt[1] - return [0-u, v] + return [-u, v] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok b/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok index a76dcc4c4..31f98a18c 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsOnCurve.zok @@ -6,8 +6,8 @@ from "ecc/babyjubjubParams" import BabyJubJubParams // https://github.com/zcash/zips/blob/master/protocol/protocol.pdf def main(field[2] pt, BabyJubJubParams context) -> bool: - field a = context.JUBJUBA - field d = context.JUBJUBD + field a = context.JUBJUB_A + field d = context.JUBJUB_D field uu = pt[0] * pt[0] field vv = pt[1] * pt[1] diff --git a/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok b/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok index 85f5ded51..846abca31 100644 --- a/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok +++ b/zokrates_stdlib/stdlib/ecc/edwardsOrderCheck.zok @@ -11,7 +11,7 @@ from "ecc/babyjubjubParams" import BabyJubJubParams // https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/edwards.rs#L166 def main(field[2] pt, BabyJubJubParams context) -> bool: - field cofactor = context.JUBJUBC + field cofactor = context.JUBJUB_C assert(cofactor == 8) diff --git a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok index e1bfdf685..50e5a6225 100644 --- a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok +++ b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok @@ -3,6 +3,26 @@ import "utils/casts/u32_to_bits" import "utils/casts/u32_from_bits" +// Initialization Vector, section 2.6. +const u32[8] IV = [ + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +] + +// Message Schedule SIGMA, section 2.7. +const u32[10][16] SIGMA = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0] +] + // right rotation def rotr32(u32 x) -> u32: return (x >> N) | (x << (32 - N)) @@ -14,25 +34,6 @@ def swap_u32(u32 val) -> u32: ((val >> 8) & 0x0000ff00) | \ ((val >> 24) & 0x000000ff) -def blake2s_iv() -> (u32[8]): - return [ - 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 - ] - -def blake2s_sigma() -> (u32[10][16]): - return [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0] - ] def mixing_g(u32[16] v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> (u32[16]): v[a] = (v[a] + v[b] + x) @@ -46,16 +47,14 @@ def mixing_g(u32[16] v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> (u32[16]): return v def blake2s_compression(u32[8] h, u32[16] m, u32[2] t, bool last) -> (u32[8]): - u32[16] v = [...h, ...blake2s_iv()] + u32[16] v = [...h, ...IV] v[12] = v[12] ^ t[0] v[13] = v[13] ^ t[1] v[14] = if last then v[14] ^ 0xFFFFFFFF else v[14] fi - u32[10][16] sigma = blake2s_sigma() - for u32 i in 0..10 do - u32[16] s = sigma[i] + u32[16] s = SIGMA[i] v = mixing_g(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) v = mixing_g(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) v = mixing_g(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) @@ -72,22 +71,17 @@ def blake2s_compression(u32[8] h, u32[16] m, u32[2] t, bool last) -> (u32[8]): return h -def blake2s_init(u32[2] p) -> (u32[8]): - u32[8] iv = blake2s_iv() +def main(u32[K][16] input, u32[2] p) -> (u32[8]): u32[8] h = [ - iv[0] ^ 0x01010000 ^ 0x00000020, - iv[1], - iv[2], - iv[3], - iv[4], - iv[5], - iv[6] ^ swap_u32(p[0]), - iv[7] ^ swap_u32(p[1]) + IV[0] ^ 0x01010000 ^ 0x00000020, + IV[1], + IV[2], + IV[3], + IV[4], + IV[5], + IV[6] ^ swap_u32(p[0]), + IV[7] ^ swap_u32(p[1]) ] - return h - -def main(u32[K][16] input, u32[2] p) -> (u32[8]): - u32[8] h = blake2s_init(p) u32 t0 = 0 u32 t1 = 0 diff --git a/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok b/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok index 4eb63f64a..29ca37bbc 100644 --- a/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok +++ b/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok @@ -1,28 +1,26 @@ +// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf // based on keccak-f[1600] permutation -def rho() -> u32[24]: - return [ - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 - ] - -def pi() -> u32[24]: - return [ - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 - ] - -def rc() -> u64[24]: - return [ - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, - 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, - 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, - 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, - 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, - 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 - ] +const u32[24] RHO = [ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +] + +const u32[24] PI = [ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +] + +const u64[24] RC = [ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 +] // left rotation def rotl64(u64 x, u32 n) -> u64: @@ -36,10 +34,6 @@ def swap_u64(u64 val) -> u64: // compression function def keccakf(u64[25] st) -> u64[25]: - u32[24] rotc = rho() - u32[24] piln = pi() - u64[24] rndc = rc() - u64[5] bc = [0; 5] u64 t = 0 @@ -60,8 +54,9 @@ def keccakf(u64[25] st) -> u64[25]: // rho pi for u32 i in 0..24 do - bc[0] = st[piln[i]] - st[piln[i]] = rotl64(t, rotc[i]) + u32 j = PI[i] + bc[0] = st[j] + st[j] = rotl64(t, RHO[i]) t = bc[0] endfor @@ -77,7 +72,7 @@ def keccakf(u64[25] st) -> u64[25]: endfor // iota - st[0] = st[0] ^ rndc[r] + st[0] = st[0] ^ RC[r] endfor return st diff --git a/zokrates_stdlib/stdlib/hashes/mimc7/constants.zok b/zokrates_stdlib/stdlib/hashes/mimc7/constants.zok deleted file mode 100644 index b4780cbb9..000000000 --- a/zokrates_stdlib/stdlib/hashes/mimc7/constants.zok +++ /dev/null @@ -1,94 +0,0 @@ -def main() -> field[91]: - return [ - 0, - 20888961410941983456478427210666206549300505294776164667214940546594746570981, - 15265126113435022738560151911929040668591755459209400716467504685752745317193, - 8334177627492981984476504167502758309043212251641796197711684499645635709656, - 1374324219480165500871639364801692115397519265181803854177629327624133579404, - 11442588683664344394633565859260176446561886575962616332903193988751292992472, - 2558901189096558760448896669327086721003508630712968559048179091037845349145, - 11189978595292752354820141775598510151189959177917284797737745690127318076389, - 3262966573163560839685415914157855077211340576201936620532175028036746741754, - 17029914891543225301403832095880481731551830725367286980611178737703889171730, - 4614037031668406927330683909387957156531244689520944789503628527855167665518, - 19647356996769918391113967168615123299113119185942498194367262335168397100658, - 5040699236106090655289931820723926657076483236860546282406111821875672148900, - 2632385916954580941368956176626336146806721642583847728103570779270161510514, - 17691411851977575435597871505860208507285462834710151833948561098560743654671, - 11482807709115676646560379017491661435505951727793345550942389701970904563183, - 8360838254132998143349158726141014535383109403565779450210746881879715734773, - 12663821244032248511491386323242575231591777785787269938928497649288048289525, - 3067001377342968891237590775929219083706800062321980129409398033259904188058, - 8536471869378957766675292398190944925664113548202769136103887479787957959589, - 19825444354178182240559170937204690272111734703605805530888940813160705385792, - 16703465144013840124940690347975638755097486902749048533167980887413919317592, - 13061236261277650370863439564453267964462486225679643020432589226741411380501, - 10864774797625152707517901967943775867717907803542223029967000416969007792571, - 10035653564014594269791753415727486340557376923045841607746250017541686319774, - 3446968588058668564420958894889124905706353937375068998436129414772610003289, - 4653317306466493184743870159523234588955994456998076243468148492375236846006, - 8486711143589723036499933521576871883500223198263343024003617825616410932026, - 250710584458582618659378487568129931785810765264752039738223488321597070280, - 2104159799604932521291371026105311735948154964200596636974609406977292675173, - 16313562605837709339799839901240652934758303521543693857533755376563489378839, - 6032365105133504724925793806318578936233045029919447519826248813478479197288, - 14025118133847866722315446277964222215118620050302054655768867040006542798474, - 7400123822125662712777833064081316757896757785777291653271747396958201309118, - 1744432620323851751204287974553233986555641872755053103823939564833813704825, - 8316378125659383262515151597439205374263247719876250938893842106722210729522, - 6739722627047123650704294650168547689199576889424317598327664349670094847386, - 21211457866117465531949733809706514799713333930924902519246949506964470524162, - 13718112532745211817410303291774369209520657938741992779396229864894885156527, - 5264534817993325015357427094323255342713527811596856940387954546330728068658, - 18884137497114307927425084003812022333609937761793387700010402412840002189451, - 5148596049900083984813839872929010525572543381981952060869301611018636120248, - 19799686398774806587970184652860783461860993790013219899147141137827718662674, - 19240878651604412704364448729659032944342952609050243268894572835672205984837, - 10546185249390392695582524554167530669949955276893453512788278945742408153192, - 5507959600969845538113649209272736011390582494851145043668969080335346810411, - 18177751737739153338153217698774510185696788019377850245260475034576050820091, - 19603444733183990109492724100282114612026332366576932662794133334264283907557, - 10548274686824425401349248282213580046351514091431715597441736281987273193140, - 1823201861560942974198127384034483127920205835821334101215923769688644479957, - 11867589662193422187545516240823411225342068709600734253659804646934346124945, - 18718569356736340558616379408444812528964066420519677106145092918482774343613, - 10530777752259630125564678480897857853807637120039176813174150229243735996839, - 20486583726592018813337145844457018474256372770211860618687961310422228379031, - 12690713110714036569415168795200156516217175005650145422920562694422306200486, - 17386427286863519095301372413760745749282643730629659997153085139065756667205, - 2216432659854733047132347621569505613620980842043977268828076165669557467682, - 6309765381643925252238633914530877025934201680691496500372265330505506717193, - 20806323192073945401862788605803131761175139076694468214027227878952047793390, - 4037040458505567977365391535756875199663510397600316887746139396052445718861, - 19948974083684238245321361840704327952464170097132407924861169241740046562673, - 845322671528508199439318170916419179535949348988022948153107378280175750024, - 16222384601744433420585982239113457177459602187868460608565289920306145389382, - 10232118865851112229330353999139005145127746617219324244541194256766741433339, - 6699067738555349409504843460654299019000594109597429103342076743347235369120, - 6220784880752427143725783746407285094967584864656399181815603544365010379208, - 6129250029437675212264306655559561251995722990149771051304736001195288083309, - 10773245783118750721454994239248013870822765715268323522295722350908043393604, - 4490242021765793917495398271905043433053432245571325177153467194570741607167, - 19596995117319480189066041930051006586888908165330319666010398892494684778526, - 837850695495734270707668553360118467905109360511302468085569220634750561083, - 11803922811376367215191737026157445294481406304781326649717082177394185903907, - 10201298324909697255105265958780781450978049256931478989759448189112393506592, - 13564695482314888817576351063608519127702411536552857463682060761575100923924, - 9262808208636973454201420823766139682381973240743541030659775288508921362724, - 173271062536305557219323722062711383294158572562695717740068656098441040230, - 18120430890549410286417591505529104700901943324772175772035648111937818237369, - 20484495168135072493552514219686101965206843697794133766912991150184337935627, - 19155651295705203459475805213866664350848604323501251939850063308319753686505, - 11971299749478202793661982361798418342615500543489781306376058267926437157297, - 18285310723116790056148596536349375622245669010373674803854111592441823052978, - 7069216248902547653615508023941692395371990416048967468982099270925308100727, - 6465151453746412132599596984628739550147379072443683076388208843341824127379, - 16143532858389170960690347742477978826830511669766530042104134302796355145785, - 19362583304414853660976404410208489566967618125972377176980367224623492419647, - 1702213613534733786921602839210290505213503664731919006932367875629005980493, - 10781825404476535814285389902565833897646945212027592373510689209734812292327, - 4212716923652881254737947578600828255798948993302968210248673545442808456151, - 7594017890037021425366623750593200398174488805473151513558919864633711506220, - 18979889247746272055963929241596362599320706910852082477600815822482192194401, - 1360213922981323134938688511315690179366171918090039581890971975815045550053 - ] diff --git a/zokrates_stdlib/stdlib/hashes/mimc7/mimc7.zok b/zokrates_stdlib/stdlib/hashes/mimc7/mimc7.zok index 525d3147c..84869ff65 100644 --- a/zokrates_stdlib/stdlib/hashes/mimc7/mimc7.zok +++ b/zokrates_stdlib/stdlib/hashes/mimc7/mimc7.zok @@ -1,18 +1,111 @@ -import "./constants" as constants +const field[91] C = [ + 0, + 20888961410941983456478427210666206549300505294776164667214940546594746570981, + 15265126113435022738560151911929040668591755459209400716467504685752745317193, + 8334177627492981984476504167502758309043212251641796197711684499645635709656, + 1374324219480165500871639364801692115397519265181803854177629327624133579404, + 11442588683664344394633565859260176446561886575962616332903193988751292992472, + 2558901189096558760448896669327086721003508630712968559048179091037845349145, + 11189978595292752354820141775598510151189959177917284797737745690127318076389, + 3262966573163560839685415914157855077211340576201936620532175028036746741754, + 17029914891543225301403832095880481731551830725367286980611178737703889171730, + 4614037031668406927330683909387957156531244689520944789503628527855167665518, + 19647356996769918391113967168615123299113119185942498194367262335168397100658, + 5040699236106090655289931820723926657076483236860546282406111821875672148900, + 2632385916954580941368956176626336146806721642583847728103570779270161510514, + 17691411851977575435597871505860208507285462834710151833948561098560743654671, + 11482807709115676646560379017491661435505951727793345550942389701970904563183, + 8360838254132998143349158726141014535383109403565779450210746881879715734773, + 12663821244032248511491386323242575231591777785787269938928497649288048289525, + 3067001377342968891237590775929219083706800062321980129409398033259904188058, + 8536471869378957766675292398190944925664113548202769136103887479787957959589, + 19825444354178182240559170937204690272111734703605805530888940813160705385792, + 16703465144013840124940690347975638755097486902749048533167980887413919317592, + 13061236261277650370863439564453267964462486225679643020432589226741411380501, + 10864774797625152707517901967943775867717907803542223029967000416969007792571, + 10035653564014594269791753415727486340557376923045841607746250017541686319774, + 3446968588058668564420958894889124905706353937375068998436129414772610003289, + 4653317306466493184743870159523234588955994456998076243468148492375236846006, + 8486711143589723036499933521576871883500223198263343024003617825616410932026, + 250710584458582618659378487568129931785810765264752039738223488321597070280, + 2104159799604932521291371026105311735948154964200596636974609406977292675173, + 16313562605837709339799839901240652934758303521543693857533755376563489378839, + 6032365105133504724925793806318578936233045029919447519826248813478479197288, + 14025118133847866722315446277964222215118620050302054655768867040006542798474, + 7400123822125662712777833064081316757896757785777291653271747396958201309118, + 1744432620323851751204287974553233986555641872755053103823939564833813704825, + 8316378125659383262515151597439205374263247719876250938893842106722210729522, + 6739722627047123650704294650168547689199576889424317598327664349670094847386, + 21211457866117465531949733809706514799713333930924902519246949506964470524162, + 13718112532745211817410303291774369209520657938741992779396229864894885156527, + 5264534817993325015357427094323255342713527811596856940387954546330728068658, + 18884137497114307927425084003812022333609937761793387700010402412840002189451, + 5148596049900083984813839872929010525572543381981952060869301611018636120248, + 19799686398774806587970184652860783461860993790013219899147141137827718662674, + 19240878651604412704364448729659032944342952609050243268894572835672205984837, + 10546185249390392695582524554167530669949955276893453512788278945742408153192, + 5507959600969845538113649209272736011390582494851145043668969080335346810411, + 18177751737739153338153217698774510185696788019377850245260475034576050820091, + 19603444733183990109492724100282114612026332366576932662794133334264283907557, + 10548274686824425401349248282213580046351514091431715597441736281987273193140, + 1823201861560942974198127384034483127920205835821334101215923769688644479957, + 11867589662193422187545516240823411225342068709600734253659804646934346124945, + 18718569356736340558616379408444812528964066420519677106145092918482774343613, + 10530777752259630125564678480897857853807637120039176813174150229243735996839, + 20486583726592018813337145844457018474256372770211860618687961310422228379031, + 12690713110714036569415168795200156516217175005650145422920562694422306200486, + 17386427286863519095301372413760745749282643730629659997153085139065756667205, + 2216432659854733047132347621569505613620980842043977268828076165669557467682, + 6309765381643925252238633914530877025934201680691496500372265330505506717193, + 20806323192073945401862788605803131761175139076694468214027227878952047793390, + 4037040458505567977365391535756875199663510397600316887746139396052445718861, + 19948974083684238245321361840704327952464170097132407924861169241740046562673, + 845322671528508199439318170916419179535949348988022948153107378280175750024, + 16222384601744433420585982239113457177459602187868460608565289920306145389382, + 10232118865851112229330353999139005145127746617219324244541194256766741433339, + 6699067738555349409504843460654299019000594109597429103342076743347235369120, + 6220784880752427143725783746407285094967584864656399181815603544365010379208, + 6129250029437675212264306655559561251995722990149771051304736001195288083309, + 10773245783118750721454994239248013870822765715268323522295722350908043393604, + 4490242021765793917495398271905043433053432245571325177153467194570741607167, + 19596995117319480189066041930051006586888908165330319666010398892494684778526, + 837850695495734270707668553360118467905109360511302468085569220634750561083, + 11803922811376367215191737026157445294481406304781326649717082177394185903907, + 10201298324909697255105265958780781450978049256931478989759448189112393506592, + 13564695482314888817576351063608519127702411536552857463682060761575100923924, + 9262808208636973454201420823766139682381973240743541030659775288508921362724, + 173271062536305557219323722062711383294158572562695717740068656098441040230, + 18120430890549410286417591505529104700901943324772175772035648111937818237369, + 20484495168135072493552514219686101965206843697794133766912991150184337935627, + 19155651295705203459475805213866664350848604323501251939850063308319753686505, + 11971299749478202793661982361798418342615500543489781306376058267926437157297, + 18285310723116790056148596536349375622245669010373674803854111592441823052978, + 7069216248902547653615508023941692395371990416048967468982099270925308100727, + 6465151453746412132599596984628739550147379072443683076388208843341824127379, + 16143532858389170960690347742477978826830511669766530042104134302796355145785, + 19362583304414853660976404410208489566967618125972377176980367224623492419647, + 1702213613534733786921602839210290505213503664731919006932367875629005980493, + 10781825404476535814285389902565833897646945212027592373510689209734812292327, + 4212716923652881254737947578600828255798948993302968210248673545442808456151, + 7594017890037021425366623750593200398174488805473151513558919864633711506220, + 18979889247746272055963929241596362599320706910852082477600815822482192194401, + 1360213922981323134938688511315690179366171918090039581890971975815045550053 +] -def main(field x_in, field k) -> field: - field[91] c = constants() +def main(field x_in, field k) -> field: field t = 0 - field[ROUNDS] t2 = [0; ROUNDS] - field[ROUNDS] t4 = [0; ROUNDS] - field[ROUNDS] t6 = [0; ROUNDS] - field[ROUNDS] t7 = [0; ROUNDS] // we define t7 length +1 to reference implementation as ZoKrates wont allow conditional branching. -> out of bounds array error - for u32 i in 0..ROUNDS do + field[R] t2 = [0; R] + field[R] t4 = [0; R] + field[R] t6 = [0; R] + field[R] t7 = [0; R] // we define t7 length +1 to avoid conditional branching + + for u32 i in 0..R do u32 i2 = if i == 0 then 0 else i - 1 fi - t = if i == 0 then k+x_in else k + t7[i2] + c[i] fi - t2[i] = t*t - t4[i] = t2[i]*t2[i] - t6[i] = t4[i]*t2[i] - t7[i] = t6[i]*t + t = if i == 0 then k + x_in else k + t7[i2] + C[i] fi + t2[i] = t * t + t4[i] = t2[i] * t2[i] + t6[i] = t4[i] * t2[i] + t7[i] = t6[i] * t endfor - return t6[ROUNDS - 1]*t + k \ No newline at end of file + + return t6[R - 1] * t + k \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/mimcSponge/IVconstants.zok b/zokrates_stdlib/stdlib/hashes/mimcSponge/IVconstants.zok deleted file mode 100644 index bc2caf7a6..000000000 --- a/zokrates_stdlib/stdlib/hashes/mimcSponge/IVconstants.zok +++ /dev/null @@ -1,223 +0,0 @@ -def main() -> field[220]: - return [ - 0, - 7120861356467848435263064379192047478074060781135320967663101236819528304084, - 5024705281721889198577876690145313457398658950011302225525409148828000436681, - 17980351014018068290387269214713820287804403312720763401943303895585469787384, - 19886576439381707240399940949310933992335779767309383709787331470398675714258, - 1213715278223786725806155661738676903520350859678319590331207960381534602599, - 18162138253399958831050545255414688239130588254891200470934232514682584734511, - 7667462281466170157858259197976388676420847047604921256361474169980037581876, - 7207551498477838452286210989212982851118089401128156132319807392460388436957, - 9864183311657946807255900203841777810810224615118629957816193727554621093838, - 4798196928559910300796064665904583125427459076060519468052008159779219347957, - 17387238494588145257484818061490088963673275521250153686214197573695921400950, - 10005334761930299057035055370088813230849810566234116771751925093634136574742, - 11897542014760736209670863723231849628230383119798486487899539017466261308762, - 16771780563523793011283273687253985566177232886900511371656074413362142152543, - 749264854018824809464168489785113337925400687349357088413132714480582918506, - 3683645737503705042628598550438395339383572464204988015434959428676652575331, - 7556750851783822914673316211129907782679509728346361368978891584375551186255, - 20391289379084797414557439284689954098721219201171527383291525676334308303023, - 18146517657445423462330854383025300323335289319277199154920964274562014376193, - 8080173465267536232534446836148661251987053305394647905212781979099916615292, - 10796443006899450245502071131975731672911747129805343722228413358507805531141, - 5404287610364961067658660283245291234008692303120470305032076412056764726509, - 4623894483395123520243967718315330178025957095502546813929290333264120223168, - 16845753148201777192406958674202574751725237939980634861948953189320362207797, - 4622170486584704769521001011395820886029808520586507873417553166762370293671, - 16688277490485052681847773549197928630624828392248424077804829676011512392564, - 11878652861183667748838188993669912629573713271883125458838494308957689090959, - 2436445725746972287496138382764643208791713986676129260589667864467010129482, - 1888098689545151571063267806606510032698677328923740058080630641742325067877, - 148924106504065664829055598316821983869409581623245780505601526786791681102, - 18875020877782404439294079398043479420415331640996249745272087358069018086569, - 15189693413320228845990326214136820307649565437237093707846682797649429515840, - 19669450123472657781282985229369348220906547335081730205028099210442632534079, - 5521922218264623411380547905210139511350706092570900075727555783240701821773, - 4144769320246558352780591737261172907511489963810975650573703217887429086546, - 10097732913112662248360143041019433907849917041759137293018029019134392559350, - 1720059427972723034107765345743336447947522473310069975142483982753181038321, - 6302388219880227251325608388535181451187131054211388356563634768253301290116, - 6745410632962119604799318394592010194450845483518862700079921360015766217097, - 10858157235265583624235850660462324469799552996870780238992046963007491306222, - 20241898894740093733047052816576694435372877719072347814065227797906130857593, - 10165780782761211520836029617746977303303335603838343292431760011576528327409, - 2832093654883670345969792724123161241696170611611744759675180839473215203706, - 153011722355526826233082383360057587249818749719433916258246100068258954737, - 20196970640587451358539129330170636295243141659030208529338914906436009086943, - 3180973917010545328313139835982464870638521890385603025657430208141494469656, - 17198004293191777441573635123110935015228014028618868252989374962722329283022, - 7642160509228669138628515458941659189680509753651629476399516332224325757132, - 19346204940546791021518535594447257347218878114049998691060016493806845179755, - 11501810868606870391127866188394535330696206817602260610801897042898616817272, - 3113973447392053821824427670386252797811804954746053461397972968381571297505, - 6545064306297957002139416752334741502722251869537551068239642131448768236585, - 5203908808704813498389265425172875593837960384349653691918590736979872578408, - 2246692432011290582160062129070762007374502637007107318105405626910313810224, - 11760570435432189127645691249600821064883781677693087773459065574359292849137, - 5543749482491340532547407723464609328207990784853381797689466144924198391839, - 8837549193990558762776520822018694066937602576881497343584903902880277769302, - 12855514863299373699594410385788943772765811961581749194183533625311486462501, - 5363660674689121676875069134269386492382220935599781121306637800261912519729, - 13162342403579303950549728848130828093497701266240457479693991108217307949435, - 916941639326869583414469202910306428966657806899788970948781207501251816730, - 15618589556584434434009868216186115416835494805174158488636000580759692174228, - 8959562060028569701043973060670353733575345393653685776974948916988033453971, - 16390754464333401712265575949874369157699293840516802426621216808905079127650, - 168282396747788514908709091757591226095443902501365500003618183905496160435, - 8327443473179334761744301768309008451162322941906921742120510244986704677004, - 17213012626801210615058753489149961717422101711567228037597150941152495100640, - 10394369641533736715250242399198097296122982486516256408681925424076248952280, - 17784386835392322654196171115293700800825771210400152504776806618892170162248, - 16533189939837087893364000390641148516479148564190420358849587959161226782982, - 18725396114211370207078434315900726338547621160475533496863298091023511945076, - 7132325028834551397904855671244375895110341505383911719294705267624034122405, - 148317947440800089795933930720822493695520852448386394775371401743494965187, - 19001050671757720352890779127693793630251266879994702723636759889378387053056, - 18824274411769830274877839365728651108434404855803844568234862945613766611460, - 12771414330193951156383998390424063470766226667986423961689712557338777174205, - 11332046574800279729678603488745295198038913503395629790213378101166488244657, - 9607550223176946388146938069307456967842408600269548190739947540821716354749, - 8756385288462344550200229174435953103162307705310807828651304665320046782583, - 176061952957067086877570020242717222844908281373122372938833890096257042779, - 12200212977482648306758992405065921724409841940671166017620928947866825250857, - 10868453624107875516866146499877130701929063632959660262366632833504750028858, - 2016095394399807253596787752134573207202567875457560571095586743878953450738, - 21815578223768330433802113452339488275704145896544481092014911825656390567514, - 4923772847693564777744725640710197015181591950368494148029046443433103381621, - 1813584943682214789802230765734821149202472893379265320098816901270224589984, - 10810123816265612772922113403831964815724109728287572256602010709288980656498, - 1153669123397255702524721206511185557982017410156956216465120456256288427021, - 5007518659266430200134478928344522649876467369278722765097865662497773767152, - 2511432546938591792036639990606464315121646668029252285288323664350666551637, - 32883284540320451295484135704808083452381176816565850047310272290579727564, - 10484856914279112612610993418405543310546746652738541161791501150994088679557, - 2026733759645519472558796412979210009170379159866522399881566309631434814953, - 14731806221235869882801331463708736361296174006732553130708107037190460654379, - 14740327483193277147065845135561988641238516852487657117813536909482068950652, - 18787428285295558781869865751953016580493190547148386433580291216673009884554, - 3804047064713122820157099453648459188816376755739202017447862327783289895072, - 16709604795697901641948603019242067672006293290826991671766611326262532802914, - 11061717085931490100602849654034280576915102867237101935487893025907907250695, - 2821730726367472966906149684046356272806484545281639696873240305052362149654, - 17467794879902895769410571945152708684493991588672014763135370927880883292655, - 1571520786233540988201616650622796363168031165456869481368085474420849243232, - 10041051776251223165849354194892664881051125330236567356945669006147134614302, - 3981753758468103976812813304477670033098707002886030847251581853700311567551, - 4365864398105436789177703571412645548020537580493599380018290523813331678900, - 2391801327305361293476178683853802679507598622000359948432171562543560193350, - 214219368547551689972421167733597094823289857206402800635962137077096090722, - 18192064100315141084242006659317257023098826945893371479835220462302399655674, - 15487549757142039139328911515400805508248576685795694919457041092150651939253, - 10142447197759703415402259672441315777933858467700579946665223821199077641122, - 11246573086260753259993971254725613211193686683988426513880826148090811891866, - 6574066859860991369704567902211886840188702386542112593710271426704432301235, - 11311085442652291634822798307831431035776248927202286895207125867542470350078, - 20977948360215259915441258687649465618185769343138135384346964466965010873779, - 792781492853909872425531014397300057232399608769451037135936617996830018501, - 5027602491523497423798779154966735896562099398367163998686335127580757861872, - 14595204575654316237672764823862241845410365278802914304953002937313300553572, - 13973538843621261113924259058427434053808430378163734641175100160836376897004, - 16395063164993626722686882727042150241125309409717445381854913964674649318585, - 8465768840047024550750516678171433288207841931251654898809033371655109266663, - 21345603324471810861925019445720576814602636473739003852898308205213912255830, - 21171984405852590343970239018692870799717057961108910523876770029017785940991, - 10761027113757988230637066281488532903174559953630210849190212601991063767647, - 6678298831065390834922566306988418588227382406175769592902974103663687992230, - 4993662582188632374202316265508850988596880036291765531885657575099537176757, - 18364168158495573675698600238443218434246806358811328083953887470513967121206, - 3506345610354615013737144848471391553141006285964325596214723571988011984829, - 248732676202643792226973868626360612151424823368345645514532870586234380100, - 10090204501612803176317709245679152331057882187411777688746797044706063410969, - 21297149835078365363970699581821844234354988617890041296044775371855432973500, - 16729368143229828574342820060716366330476985824952922184463387490091156065099, - 4467191506765339364971058668792642195242197133011672559453028147641428433293, - 8677548159358013363291014307402600830078662555833653517843708051504582990832, - 1022951765127126818581466247360193856197472064872288389992480993218645055345, - 1888195070251580606973417065636430294417895423429240431595054184472931224452, - 4221265384902749246920810956363310125115516771964522748896154428740238579824, - 2825393571154632139467378429077438870179957021959813965940638905853993971879, - 19171031072692942278056619599721228021635671304612437350119663236604712493093, - 10780807212297131186617505517708903709488273075252405602261683478333331220733, - 18230936781133176044598070768084230333433368654744509969087239465125979720995, - 16901065971871379877929280081392692752968612240624985552337779093292740763381, - 146494141603558321291767829522948454429758543710648402457451799015963102253, - 2492729278659146790410698334997955258248120870028541691998279257260289595548, - 2204224910006646535594933495262085193210692406133533679934843341237521233504, - 16062117410185840274616925297332331018523844434907012275592638570193234893570, - 5894928453677122829055071981254202951712129328678534592916926069506935491729, - 4947482739415078212217504789923078546034438919537985740403824517728200332286, - 16143265650645676880461646123844627780378251900510645261875867423498913438066, - 397690828254561723549349897112473766901585444153303054845160673059519614409, - 11272653598912269895509621181205395118899451234151664604248382803490621227687, - 15566927854306879444693061574322104423426072650522411176731130806720753591030, - 14222898219492484180162096141564251903058269177856173968147960855133048449557, - 16690275395485630428127725067513114066329712673106153451801968992299636791385, - 3667030990325966886479548860429670833692690972701471494757671819017808678584, - 21280039024501430842616328642522421302481259067470872421086939673482530783142, - 15895485136902450169492923978042129726601461603404514670348703312850236146328, - 7733050956302327984762132317027414325566202380840692458138724610131603812560, - 438123800976401478772659663183448617575635636575786782566035096946820525816, - 814913922521637742587885320797606426167962526342166512693085292151314976633, - 12368712287081330853637674140264759478736012797026621876924395982504369598764, - 2494806857395134874309386694756263421445039103814920780777601708371037591569, - 16101132301514338989512946061786320637179843435886825102406248183507106312877, - 6252650284989960032925831409804233477770646333900692286731621844532438095656, - 9277135875276787021836189566799935097400042171346561246305113339462708861695, - 10493603554686607050979497281838644324893776154179810893893660722522945589063, - 8673089750662709235894359384294076697329948991010184356091130382437645649279, - 9558393272910366944245875920138649617479779893610128634419086981339060613250, - 19012287860122586147374214541764572282814469237161122489573881644994964647218, - 9783723818270121678386992630754842961728702994964214799008457449989291229500, - 15550788416669474113213749561488122552422887538676036667630838378023479382689, - 15016165746156232864069722572047169071786333815661109750860165034341572904221, - 6506225705710197163670556961299945987488979904603689017479840649664564978574, - 10796631184889302076168355684722130903785890709107732067446714470783437829037, - 19871836214837460419845806980869387567383718044439891735114283113359312279540, - 20871081766843466343749609089986071784031203517506781251203251608363835140622, - 5100105771517691442278432864090229416166996183792075307747582375962855820797, - 8777887112076272395250620301071581171386440850451972412060638225741125310886, - 5300440870136391278944213332144327695659161151625757537632832724102670898756, - 1205448543652932944633962232545707633928124666868453915721030884663332604536, - 5542499997310181530432302492142574333860449305424174466698068685590909336771, - 11028094245762332275225364962905938096659249161369092798505554939952525894293, - 19187314764836593118404597958543112407224947638377479622725713735224279297009, - 17047263688548829001253658727764731047114098556534482052135734487985276987385, - 19914849528178967155534624144358541535306360577227460456855821557421213606310, - 2929658084700714257515872921366736697080475676508114973627124569375444665664, - 15092262360719700162343163278648422751610766427236295023221516498310468956361, - 21578580340755653236050830649990190843552802306886938815497471545814130084980, - 1258781501221760320019859066036073675029057285507345332959539295621677296991, - 3819598418157732134449049289585680301176983019643974929528867686268702720163, - 8653175945487997845203439345797943132543211416447757110963967501177317426221, - 6614652990340435611114076169697104582524566019034036680161902142028967568142, - 19212515502973904821995111796203064175854996071497099383090983975618035391558, - 18664315914479294273286016871365663486061896605232511201418576829062292269769, - 11498264615058604317482574216318586415670903094838791165247179252175768794889, - 10814026414212439999107945133852431304483604215416531759535467355316227331774, - 17566185590731088197064706533119299946752127014428399631467913813769853431107, - 14016139747289624978792446847000951708158212463304817001882956166752906714332, - 8242601581342441750402731523736202888792436665415852106196418942315563860366, - 9244680976345080074252591214216060854998619670381671198295645618515047080988, - 12216779172735125538689875667307129262237123728082657485828359100719208190116, - 10702811721859145441471328511968332847175733707711670171718794132331147396634, - 6479667912792222539919362076122453947926362746906450079329453150607427372979, - 15117544653571553820496948522381772148324367479772362833334593000535648316185, - 6842203153996907264167856337497139692895299874139131328642472698663046726780, - 12732823292801537626009139514048596316076834307941224506504666470961250728055, - 6936272626871035740815028148058841877090860312517423346335878088297448888663, - 17297554111853491139852678417579991271009602631577069694853813331124433680030, - 16641596134749940573104316021365063031319260205559553673368334842484345864859, - 7400481189785154329569470986896455371037813715804007747228648863919991399081, - 2273205422216987330510475127669563545720586464429614439716564154166712854048, - 15162538063742142685306302282127534305212832649282186184583465569986719234456, - 5628039096440332922248578319648483863204530861778160259559031331287721255522, - 16085392195894691829567913404182676871326863890140775376809129785155092531260, - 14227467863135365427954093998621993651369686288941275436795622973781503444257, - 18224457394066545825553407391290108485121649197258948320896164404518684305122, - 274945154732293792784580363548970818611304339008964723447672490026510689427, - 11050822248291117548220126630860474473945266276626263036056336623671308219529, - 2119542016932434047340813757208803962484943912710204325088879681995922344971, - 0 - ] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcFeistel.zok b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcFeistel.zok index 6e23e44f8..ae01d45db 100644 --- a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcFeistel.zok +++ b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcFeistel.zok @@ -1,28 +1,249 @@ // MiMCFeistel configured with 220 rounds -import "./IVconstants" as IVconstants +const u32 R = 220 +const field[R] IV = [ + 0, + 7120861356467848435263064379192047478074060781135320967663101236819528304084, + 5024705281721889198577876690145313457398658950011302225525409148828000436681, + 17980351014018068290387269214713820287804403312720763401943303895585469787384, + 19886576439381707240399940949310933992335779767309383709787331470398675714258, + 1213715278223786725806155661738676903520350859678319590331207960381534602599, + 18162138253399958831050545255414688239130588254891200470934232514682584734511, + 7667462281466170157858259197976388676420847047604921256361474169980037581876, + 7207551498477838452286210989212982851118089401128156132319807392460388436957, + 9864183311657946807255900203841777810810224615118629957816193727554621093838, + 4798196928559910300796064665904583125427459076060519468052008159779219347957, + 17387238494588145257484818061490088963673275521250153686214197573695921400950, + 10005334761930299057035055370088813230849810566234116771751925093634136574742, + 11897542014760736209670863723231849628230383119798486487899539017466261308762, + 16771780563523793011283273687253985566177232886900511371656074413362142152543, + 749264854018824809464168489785113337925400687349357088413132714480582918506, + 3683645737503705042628598550438395339383572464204988015434959428676652575331, + 7556750851783822914673316211129907782679509728346361368978891584375551186255, + 20391289379084797414557439284689954098721219201171527383291525676334308303023, + 18146517657445423462330854383025300323335289319277199154920964274562014376193, + 8080173465267536232534446836148661251987053305394647905212781979099916615292, + 10796443006899450245502071131975731672911747129805343722228413358507805531141, + 5404287610364961067658660283245291234008692303120470305032076412056764726509, + 4623894483395123520243967718315330178025957095502546813929290333264120223168, + 16845753148201777192406958674202574751725237939980634861948953189320362207797, + 4622170486584704769521001011395820886029808520586507873417553166762370293671, + 16688277490485052681847773549197928630624828392248424077804829676011512392564, + 11878652861183667748838188993669912629573713271883125458838494308957689090959, + 2436445725746972287496138382764643208791713986676129260589667864467010129482, + 1888098689545151571063267806606510032698677328923740058080630641742325067877, + 148924106504065664829055598316821983869409581623245780505601526786791681102, + 18875020877782404439294079398043479420415331640996249745272087358069018086569, + 15189693413320228845990326214136820307649565437237093707846682797649429515840, + 19669450123472657781282985229369348220906547335081730205028099210442632534079, + 5521922218264623411380547905210139511350706092570900075727555783240701821773, + 4144769320246558352780591737261172907511489963810975650573703217887429086546, + 10097732913112662248360143041019433907849917041759137293018029019134392559350, + 1720059427972723034107765345743336447947522473310069975142483982753181038321, + 6302388219880227251325608388535181451187131054211388356563634768253301290116, + 6745410632962119604799318394592010194450845483518862700079921360015766217097, + 10858157235265583624235850660462324469799552996870780238992046963007491306222, + 20241898894740093733047052816576694435372877719072347814065227797906130857593, + 10165780782761211520836029617746977303303335603838343292431760011576528327409, + 2832093654883670345969792724123161241696170611611744759675180839473215203706, + 153011722355526826233082383360057587249818749719433916258246100068258954737, + 20196970640587451358539129330170636295243141659030208529338914906436009086943, + 3180973917010545328313139835982464870638521890385603025657430208141494469656, + 17198004293191777441573635123110935015228014028618868252989374962722329283022, + 7642160509228669138628515458941659189680509753651629476399516332224325757132, + 19346204940546791021518535594447257347218878114049998691060016493806845179755, + 11501810868606870391127866188394535330696206817602260610801897042898616817272, + 3113973447392053821824427670386252797811804954746053461397972968381571297505, + 6545064306297957002139416752334741502722251869537551068239642131448768236585, + 5203908808704813498389265425172875593837960384349653691918590736979872578408, + 2246692432011290582160062129070762007374502637007107318105405626910313810224, + 11760570435432189127645691249600821064883781677693087773459065574359292849137, + 5543749482491340532547407723464609328207990784853381797689466144924198391839, + 8837549193990558762776520822018694066937602576881497343584903902880277769302, + 12855514863299373699594410385788943772765811961581749194183533625311486462501, + 5363660674689121676875069134269386492382220935599781121306637800261912519729, + 13162342403579303950549728848130828093497701266240457479693991108217307949435, + 916941639326869583414469202910306428966657806899788970948781207501251816730, + 15618589556584434434009868216186115416835494805174158488636000580759692174228, + 8959562060028569701043973060670353733575345393653685776974948916988033453971, + 16390754464333401712265575949874369157699293840516802426621216808905079127650, + 168282396747788514908709091757591226095443902501365500003618183905496160435, + 8327443473179334761744301768309008451162322941906921742120510244986704677004, + 17213012626801210615058753489149961717422101711567228037597150941152495100640, + 10394369641533736715250242399198097296122982486516256408681925424076248952280, + 17784386835392322654196171115293700800825771210400152504776806618892170162248, + 16533189939837087893364000390641148516479148564190420358849587959161226782982, + 18725396114211370207078434315900726338547621160475533496863298091023511945076, + 7132325028834551397904855671244375895110341505383911719294705267624034122405, + 148317947440800089795933930720822493695520852448386394775371401743494965187, + 19001050671757720352890779127693793630251266879994702723636759889378387053056, + 18824274411769830274877839365728651108434404855803844568234862945613766611460, + 12771414330193951156383998390424063470766226667986423961689712557338777174205, + 11332046574800279729678603488745295198038913503395629790213378101166488244657, + 9607550223176946388146938069307456967842408600269548190739947540821716354749, + 8756385288462344550200229174435953103162307705310807828651304665320046782583, + 176061952957067086877570020242717222844908281373122372938833890096257042779, + 12200212977482648306758992405065921724409841940671166017620928947866825250857, + 10868453624107875516866146499877130701929063632959660262366632833504750028858, + 2016095394399807253596787752134573207202567875457560571095586743878953450738, + 21815578223768330433802113452339488275704145896544481092014911825656390567514, + 4923772847693564777744725640710197015181591950368494148029046443433103381621, + 1813584943682214789802230765734821149202472893379265320098816901270224589984, + 10810123816265612772922113403831964815724109728287572256602010709288980656498, + 1153669123397255702524721206511185557982017410156956216465120456256288427021, + 5007518659266430200134478928344522649876467369278722765097865662497773767152, + 2511432546938591792036639990606464315121646668029252285288323664350666551637, + 32883284540320451295484135704808083452381176816565850047310272290579727564, + 10484856914279112612610993418405543310546746652738541161791501150994088679557, + 2026733759645519472558796412979210009170379159866522399881566309631434814953, + 14731806221235869882801331463708736361296174006732553130708107037190460654379, + 14740327483193277147065845135561988641238516852487657117813536909482068950652, + 18787428285295558781869865751953016580493190547148386433580291216673009884554, + 3804047064713122820157099453648459188816376755739202017447862327783289895072, + 16709604795697901641948603019242067672006293290826991671766611326262532802914, + 11061717085931490100602849654034280576915102867237101935487893025907907250695, + 2821730726367472966906149684046356272806484545281639696873240305052362149654, + 17467794879902895769410571945152708684493991588672014763135370927880883292655, + 1571520786233540988201616650622796363168031165456869481368085474420849243232, + 10041051776251223165849354194892664881051125330236567356945669006147134614302, + 3981753758468103976812813304477670033098707002886030847251581853700311567551, + 4365864398105436789177703571412645548020537580493599380018290523813331678900, + 2391801327305361293476178683853802679507598622000359948432171562543560193350, + 214219368547551689972421167733597094823289857206402800635962137077096090722, + 18192064100315141084242006659317257023098826945893371479835220462302399655674, + 15487549757142039139328911515400805508248576685795694919457041092150651939253, + 10142447197759703415402259672441315777933858467700579946665223821199077641122, + 11246573086260753259993971254725613211193686683988426513880826148090811891866, + 6574066859860991369704567902211886840188702386542112593710271426704432301235, + 11311085442652291634822798307831431035776248927202286895207125867542470350078, + 20977948360215259915441258687649465618185769343138135384346964466965010873779, + 792781492853909872425531014397300057232399608769451037135936617996830018501, + 5027602491523497423798779154966735896562099398367163998686335127580757861872, + 14595204575654316237672764823862241845410365278802914304953002937313300553572, + 13973538843621261113924259058427434053808430378163734641175100160836376897004, + 16395063164993626722686882727042150241125309409717445381854913964674649318585, + 8465768840047024550750516678171433288207841931251654898809033371655109266663, + 21345603324471810861925019445720576814602636473739003852898308205213912255830, + 21171984405852590343970239018692870799717057961108910523876770029017785940991, + 10761027113757988230637066281488532903174559953630210849190212601991063767647, + 6678298831065390834922566306988418588227382406175769592902974103663687992230, + 4993662582188632374202316265508850988596880036291765531885657575099537176757, + 18364168158495573675698600238443218434246806358811328083953887470513967121206, + 3506345610354615013737144848471391553141006285964325596214723571988011984829, + 248732676202643792226973868626360612151424823368345645514532870586234380100, + 10090204501612803176317709245679152331057882187411777688746797044706063410969, + 21297149835078365363970699581821844234354988617890041296044775371855432973500, + 16729368143229828574342820060716366330476985824952922184463387490091156065099, + 4467191506765339364971058668792642195242197133011672559453028147641428433293, + 8677548159358013363291014307402600830078662555833653517843708051504582990832, + 1022951765127126818581466247360193856197472064872288389992480993218645055345, + 1888195070251580606973417065636430294417895423429240431595054184472931224452, + 4221265384902749246920810956363310125115516771964522748896154428740238579824, + 2825393571154632139467378429077438870179957021959813965940638905853993971879, + 19171031072692942278056619599721228021635671304612437350119663236604712493093, + 10780807212297131186617505517708903709488273075252405602261683478333331220733, + 18230936781133176044598070768084230333433368654744509969087239465125979720995, + 16901065971871379877929280081392692752968612240624985552337779093292740763381, + 146494141603558321291767829522948454429758543710648402457451799015963102253, + 2492729278659146790410698334997955258248120870028541691998279257260289595548, + 2204224910006646535594933495262085193210692406133533679934843341237521233504, + 16062117410185840274616925297332331018523844434907012275592638570193234893570, + 5894928453677122829055071981254202951712129328678534592916926069506935491729, + 4947482739415078212217504789923078546034438919537985740403824517728200332286, + 16143265650645676880461646123844627780378251900510645261875867423498913438066, + 397690828254561723549349897112473766901585444153303054845160673059519614409, + 11272653598912269895509621181205395118899451234151664604248382803490621227687, + 15566927854306879444693061574322104423426072650522411176731130806720753591030, + 14222898219492484180162096141564251903058269177856173968147960855133048449557, + 16690275395485630428127725067513114066329712673106153451801968992299636791385, + 3667030990325966886479548860429670833692690972701471494757671819017808678584, + 21280039024501430842616328642522421302481259067470872421086939673482530783142, + 15895485136902450169492923978042129726601461603404514670348703312850236146328, + 7733050956302327984762132317027414325566202380840692458138724610131603812560, + 438123800976401478772659663183448617575635636575786782566035096946820525816, + 814913922521637742587885320797606426167962526342166512693085292151314976633, + 12368712287081330853637674140264759478736012797026621876924395982504369598764, + 2494806857395134874309386694756263421445039103814920780777601708371037591569, + 16101132301514338989512946061786320637179843435886825102406248183507106312877, + 6252650284989960032925831409804233477770646333900692286731621844532438095656, + 9277135875276787021836189566799935097400042171346561246305113339462708861695, + 10493603554686607050979497281838644324893776154179810893893660722522945589063, + 8673089750662709235894359384294076697329948991010184356091130382437645649279, + 9558393272910366944245875920138649617479779893610128634419086981339060613250, + 19012287860122586147374214541764572282814469237161122489573881644994964647218, + 9783723818270121678386992630754842961728702994964214799008457449989291229500, + 15550788416669474113213749561488122552422887538676036667630838378023479382689, + 15016165746156232864069722572047169071786333815661109750860165034341572904221, + 6506225705710197163670556961299945987488979904603689017479840649664564978574, + 10796631184889302076168355684722130903785890709107732067446714470783437829037, + 19871836214837460419845806980869387567383718044439891735114283113359312279540, + 20871081766843466343749609089986071784031203517506781251203251608363835140622, + 5100105771517691442278432864090229416166996183792075307747582375962855820797, + 8777887112076272395250620301071581171386440850451972412060638225741125310886, + 5300440870136391278944213332144327695659161151625757537632832724102670898756, + 1205448543652932944633962232545707633928124666868453915721030884663332604536, + 5542499997310181530432302492142574333860449305424174466698068685590909336771, + 11028094245762332275225364962905938096659249161369092798505554939952525894293, + 19187314764836593118404597958543112407224947638377479622725713735224279297009, + 17047263688548829001253658727764731047114098556534482052135734487985276987385, + 19914849528178967155534624144358541535306360577227460456855821557421213606310, + 2929658084700714257515872921366736697080475676508114973627124569375444665664, + 15092262360719700162343163278648422751610766427236295023221516498310468956361, + 21578580340755653236050830649990190843552802306886938815497471545814130084980, + 1258781501221760320019859066036073675029057285507345332959539295621677296991, + 3819598418157732134449049289585680301176983019643974929528867686268702720163, + 8653175945487997845203439345797943132543211416447757110963967501177317426221, + 6614652990340435611114076169697104582524566019034036680161902142028967568142, + 19212515502973904821995111796203064175854996071497099383090983975618035391558, + 18664315914479294273286016871365663486061896605232511201418576829062292269769, + 11498264615058604317482574216318586415670903094838791165247179252175768794889, + 10814026414212439999107945133852431304483604215416531759535467355316227331774, + 17566185590731088197064706533119299946752127014428399631467913813769853431107, + 14016139747289624978792446847000951708158212463304817001882956166752906714332, + 8242601581342441750402731523736202888792436665415852106196418942315563860366, + 9244680976345080074252591214216060854998619670381671198295645618515047080988, + 12216779172735125538689875667307129262237123728082657485828359100719208190116, + 10702811721859145441471328511968332847175733707711670171718794132331147396634, + 6479667912792222539919362076122453947926362746906450079329453150607427372979, + 15117544653571553820496948522381772148324367479772362833334593000535648316185, + 6842203153996907264167856337497139692895299874139131328642472698663046726780, + 12732823292801537626009139514048596316076834307941224506504666470961250728055, + 6936272626871035740815028148058841877090860312517423346335878088297448888663, + 17297554111853491139852678417579991271009602631577069694853813331124433680030, + 16641596134749940573104316021365063031319260205559553673368334842484345864859, + 7400481189785154329569470986896455371037813715804007747228648863919991399081, + 2273205422216987330510475127669563545720586464429614439716564154166712854048, + 15162538063742142685306302282127534305212832649282186184583465569986719234456, + 5628039096440332922248578319648483863204530861778160259559031331287721255522, + 16085392195894691829567913404182676871326863890140775376809129785155092531260, + 14227467863135365427954093998621993651369686288941275436795622973781503444257, + 18224457394066545825553407391290108485121649197258948320896164404518684305122, + 274945154732293792784580363548970818611304339008964723447672490026510689427, + 11050822248291117548220126630860474473945266276626263036056336623671308219529, + 2119542016932434047340813757208803962484943912710204325088879681995922344971, + 0 + ] + def main(field xL_in, field xR_in, field k) -> field[2]: - field[220] IV = IVconstants() + field[R] t2 = [0; R] + field[R] t4 = [0; R] + field[R] xL = [0; R] + field[R] xR = [0; R] - field t = 0 - u32 nRounds = 220 - field[220] t2 = [0; 220] //length: nRounds - field[220] t4 = [0; 220] //... - field[220] xL = [0; 220] //... - field[220] xR = [0; 220] //... - field c = 0 + field t = 0 + field c = 0 - for u32 i in 0..nRounds do - u32 idx = if i == 0 then 0 else i - 1 fi + for u32 i in 0..R do + u32 j = if i == 0 then 0 else i - 1 fi - c = IV[i] - t = if i == 0 then k + xL_in else k + xL[idx] + c fi + c = IV[i] + t = if i == 0 then k + xL_in else k + xL[j] + c fi - t2[i] = t * t - t4[i] = t2[i] * t2[i] + t2[i] = t * t + t4[i] = t2[i] * t2[i] - xL[i] = if i < nRounds - 1 then (if i == 0 then xR_in + t4[i] * t else xR[idx] + t4[i] * t fi) else xL[idx] fi - xR[i] = if i < nRounds - 1 then (if i == 0 then xL_in else xL[idx] fi) else xR[idx] + t4[i]*t fi - endfor + xL[i] = if i < R - 1 then (if i == 0 then xR_in + t4[i] * t else xR[j] + t4[i] * t fi) else xL[j] fi + xR[i] = if i < R - 1 then (if i == 0 then xL_in else xL[j] fi) else xR[j] + t4[i] * t fi + endfor - return [xL[nRounds - 1], xR[nRounds - 1]] \ No newline at end of file + return [xL[R - 1], xR[R - 1]] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok index e58c1e37c..e30b74e55 100644 --- a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok +++ b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok @@ -1,22 +1,19 @@ import "./mimcFeistel" as MiMCFeistel -def main(field[2] ins, field k) -> field[3]: - //nInputs = 2, nOutputs = 3, - u32 nInputs = 2 - u32 nOutputs = 3 - field[4][2] S = [[0; 2]; 4] // Dim: (nInputs + nOutputs - 1, 2) - field[3] outs = [0; 3] +def main(field[N] ins, field k) -> field[P]: + field[N + P - 1][2] S = [[0; 2]; N + P - 1] + field[P] outs = [0; P] - for u32 i in 0..nInputs do - u32 idx = if i == 0 then 0 else i - 1 fi - S[i] = if i == 0 then MiMCFeistel(ins[0], 0, k) else MiMCFeistel(S[idx][0] + ins[i], S[idx][1], k) fi - endfor - outs[0] = S[nInputs - 1][0] + for u32 i in 0..N do + u32 j = if i == 0 then 0 else i - 1 fi + S[i] = if i == 0 then MiMCFeistel(ins[0], 0, k) else MiMCFeistel(S[j][0] + ins[i], S[j][1], k) fi + endfor - for u32 i in 0..(nOutputs - 1) do - field[2] feistelRes = MiMCFeistel(S[nInputs + i - 1][0], S[nInputs + i - 1][1], k) - S[nInputs + i] = feistelRes - outs[i + 1] = S[nInputs + i][0] - endfor + outs[0] = S[N - 1][0] - return outs + for u32 i in 0..(P - 1) do + S[N + i] = MiMCFeistel(S[N + i - 1][0], S[N + i - 1][1], k) + outs[i + 1] = S[N + i][0] + endfor + + return outs diff --git a/zokrates_stdlib/stdlib/hashes/pedersen/512bitBool.zok b/zokrates_stdlib/stdlib/hashes/pedersen/512bitBool.zok index 929d72d0c..6624eabc7 100644 --- a/zokrates_stdlib/stdlib/hashes/pedersen/512bitBool.zok +++ b/zokrates_stdlib/stdlib/hashes/pedersen/512bitBool.zok @@ -1,10 +1,9 @@ import "utils/multiplexer/lookup3bitSigned" as sel3s import "utils/multiplexer/lookup2bit" as sel2 -import "ecc/babyjubjubParams" as context import "ecc/edwardsAdd" as add import "ecc/edwardsCompress" as edwardsCompress -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS // Code to export generators used in this example: // import bitstring @@ -23,695 +22,694 @@ def main(bool[512] inputs) -> bool[256]: false ] - BabyJubJubParams context = context() - field[2] a = context.INFINITY //Infinity + field[2] a = BABYJUBJUB_PARAMS.INFINITY //Infinity field cx = 0 field cy = 0 //Round 0 cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 1 cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728 , 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]) cy = sel2([e[3], e[4]], [16704592219657141368520262522286248296157931669321735564513068002743507745908 , 11518684165372839249156788740134693928233608013641661856685773776747280808438, 21502372109496595498116676984635248026663470429940273577484250291841812814697, 17522620677401472201433112250371604936150385414760411280739362011041111141253]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 2 cx = sel3s([e[6], e[7], e[8]], [13312232735691933658355691628172862856002099081831058080743469900077389848112 , 19327977014594608605244544461851908604127577374373936700152837514516831827340, 5965720943494263185596399776343244990255258211404706922145440547143467603204, 11103963817151340664968920805661885925719434417460707046799768750046118166436]) cy = sel2([e[6], e[7]], [13997829888819279202328839701908695991998552542771378089573544166678617234314 , 13691878221338656794058835175667599549759724338245021721239544263931121101102, 706995887987748628352958611569702130644716818339521451078302067359882016752, 15519367213943391783104357888987456282196269996908068205680088855765566529720]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 3 cx = sel3s([e[9], e[10], e[11]], [3514614172108804338031132171140068954832144631243755202685348634084887116595 , 21412073555057635706619028382831866089835908408883521913045888015461883281372, 471607086653490738521346129178778785664646799897580486044670851346383461743, 10847495464297569158944970563387929708762967645792327184202073895773051681481]) cy = sel2([e[9], e[10]], [15464894923367337880246198022819299804461472054752016232660084768002214822896 , 12567819427817222147810760128898363854788230435988968217407844445582977743495, 12262870457786134457367539925912446664295463121045105711733382320777142547504, 18045012503832343228779780686530560760323693867512598336456499973983304678718]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 4 cx = sel3s([e[12], e[13], e[14]], [15118628380960917951049569119912548662747322287644759811263888312919249703276 , 16598886614963769408191675395388471256601718506085533073063821434952573740600, 18985834203956331009360396769407075613873303527461874103999130837255502328872, 4433382535573345454766736182894234755024333432764634149565968221321851794725]) cy = sel2([e[12], e[13]], [20910093482714196883913434341954530700836700132902516503233669201436063149009 , 1519565901492557479831267649363202289903292383838537677400586534724780525304, 10041416515147137792479948105907931790389702515927709045015890740481960188846, 14765380703378616132649352585549040264662795611639979047816682374423451525367]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 5 cx = sel3s([e[15], e[16], e[17]], [12047448614322625640496087488290723061283996543855169192549742347740217312911 , 4511402808301687111378591744698422835937202088514472343139677982999770140261, 12163443309105839408816984443621255269615222157093914420088948521258519452383, 3481629181674207202258216324378273648482838926623855453371874690866818821960]) cy = sel2([e[15], e[16]], [16179347143471683729835238045770641754106645772730542840306059882771262928390 , 1330606780692172668576026668607748751348574609524694619904517828208139587545, 21047796364446011793075955655871569603152857270194799075248022968227548164989, 19676582441619193608410544431560207171545714550092005317667230665261246116642]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 6 cx = sel3s([e[18], e[19], e[20]], [12701245173613054114260668542643518710151543759808175831262148773821226772548 , 18376560769194320940844431278184909327980744436343482850507604422674089850707, 2108750731998522594975480214785919514173920126687735114472940765769183959289, 8345688345972355310911106597696772464487464098975129504776508629148304380440]) cy = sel2([e[18], e[19]], [6893882093554801220855651573375911275440312424798351852776449414399981870319 , 10206179889544308860397247082680802082921236707029342452958684549094240474070, 20690576727949006946449925807058663187909753260538825130322359335830578756980, 934097825986417774187883244964416516816295235495828890679674782707274540176]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 7 cx = sel3s([e[21], e[22], e[23]], [2944698428855471170284815781705687753367479016293091716206788980482046638948 , 13677149007138113141214051970478824544363893133343069459792025336510743485579, 8778584537362078914166751980528033062427878768812683022653464796527206882567, 14187573305341020255138644844606451353103636392771375201751096173736574567883]) cy = sel2([e[21], e[22]], [17360101552805013843890050881314712134389035043192466182420273655548320239406 , 15585069751456986750767880753875189652981026069625633386060310449606941883984, 14103016602951516262329001181468262879087099584460171406752641724802127444882, 20246884593862204796710227582734862797721958090111806492549002716706329529389]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 8 cx = sel3s([e[24], e[25], e[26]], [14561966822440683665541629338358038450751192033904756806839710397580365916408 , 9033289676904424897161301113716021195450524279682799709206671901182123388512, 3130553029765252517071677341132737863162584406047933071036994763690628383497, 478748220028687672909774713203680223481010996519205842697362525656305870550]) cy = sel2([e[24], e[25]], [2103279357051120614300268561700949519576521616178686690761693996681299230890 , 20408096719725376095564479959189425244640061563902110565713028117867143533071, 10602190247054189080928144476332888853804880952034975460420247853133904008108, 8904086690633759655814572723164827369823592560037992353159979088242240507753]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 9 cx = sel3s([e[27], e[28], e[29]], [6226499033652114521979121779728984801913588832404495199289210905837818402723 , 8038917508002636084872059181598756897599119789741848736002584943229165162988, 2277325821476302201179031013369476744187798789480148846137091219460796268467, 967514222774662330369300003456258491278184516505205753272628639669418183698]) cy = sel2([e[27], e[28]], [7443974969385276473096219793909172323973358085935860096061435962537700448286 , 16080381380787087259419052592465179031841607813350912826860291224363330298665, 7197183980134554514649915487783920553359271769991651108349414168397349372685, 15259375744392791676426881929656094304768076565231411137199656518314416373020]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 10 cx = sel3s([e[30], e[31], e[32]], [7079401365241105225661961622760419818013463250349580158302569256283647306129 , 14357098412862251375028337875874646262567035230486208703024315026944432279497, 12132744267560027693690759266151433597852816079588628241106105645480008053825, 16149669420758195925157542983134397690644755714433681232247094526660232442631]) cy = sel2([e[30], e[31]], [11050535702333135359874644130653446287886435768224627066379760227644857448025 , 2102777351898195104147031754958199443749204333224032175429214522075012926330, 4445288497276728579279429434033072747592184765171167503126978668105350002482, 2895400734738526057690008272958539309751728639263619269043890651038357187575]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 11 cx = sel3s([e[33], e[34], e[35]], [20192636532359225751119979205906307972955330178954709766736232115035084682472 , 804195338747219623697418198937917828717652612397835452095971237574002648345, 6394431494852440399081028203192653448308162012036135765292083934292810191518, 11939476767684237945975176292664687849983867031644620074465117021204214089848]) cy = sel2([e[33], e[34]], [17748517956264309916268005941322895780280007418421226047127160997826331847601 , 19497513174101598882802026674952900838989414265369078336475842766531805130216, 5620469644231252504463650386222007834239202862082473485080174711171599148975, 5516661986429427386078472422851029350005420782971768428739820651749444868271]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 12 cx = sel3s([e[36], e[37], e[38]], [1324920405111324350836746707883938204858273081019435873511569172015916187999 , 15384225309297147198449617653578330654472159141743407174794062987091000857662, 9920404264935487368096005007182799973436766546149561065368669780566156587060, 15254057056535397961799214335179813200885132815863068943475012547021698517077]) cy = sel2([e[36], e[37]], [16984705452766649815073644511059333480190120433850502120324063182300137456908 , 18046160220855048074367913256918233739227589113215101142291000275961918974523, 13094718066881673586455686749880972268909309391825129019088029831712146780775, 17556146601257932451584708078305104848786797650062537873707738860847250565143]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 13 cx = sel3s([e[39], e[40], e[41]], [10184781845128697471817965179509651550812478664395958690225791623061609959495 , 5456125639262884825452992858423500073570690895733609235845616173174729575569, 2442835875584110487966438996784695688123609547017380844898154175948468234967, 1507509649954376860384651590722437356078107662975164713418836301939281575419]) cy = sel2([e[39], e[40]], [12481681651435870984379558646813686612408709833154117210578901875084149402369 , 11152008367598826226940260746556525580820232821082556208512958435351250898503, 7567915483885326926315083960846242855523572023844618551872662303018722806760, 20394803059296859730298132333424950360853695629226621934657959417500478188961]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 14 cx = sel3s([e[42], e[43], e[44]], [10680962982327504072121608021689834159178144997131600234373184928312768469752 , 2399077467035346531560164705357209055497431901223015425246039711757880798964, 3423125451159866822107483111524543716819043967842944968651561023348340629866, 9942880027482137313328709914157120920632734642771778240985776643385937071731]) cy = sel2([e[42], e[43]], [4698845013673361363032641974440465619959991809676353365742268606915462346702 , 16130578759626193985851427947711894136403468334125608062505774040115700327331, 15972516792261738383725187984065495328469263202118598475958253769706945995080, 7601042727654430423755752301100987459144576573414967660631298823059519301944]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 15 cx = sel3s([e[45], e[46], e[47]], [559099661340368706731458173062937049444139592208939239637572972395409815235 , 1445905511768661496314996877214005625534188630127375321650145036638654136508, 12558069540132067621925302006222579198925455408763618011362743955646129467625, 19809789628385980249290251944250230372682953514057413790020001670501854917090]) cy = sel2([e[45], e[46]], [10744092763718531253355077100374662669098109929848484460119044326894952631009 , 3973362040829593578154878010051739631231888449967620092704468180671355813892, 1362015208311760378785201188340495520529554642363760051915563618841646945115, 11588368620504227678083366267185871581602064602621931713732756924598104334083]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 16 cx = sel3s([e[48], e[49], e[50]], [1678013963086824122518234712588270403106471527976328603364788331772512526348 , 19217446816753374280163957047166499363370322773252755452762764797217084855190, 18251775792701212313037978569776264038974809413837373677702565241405411946778, 7791054681559787609111187809686247485256130898718509173169053332755413410611]) cy = sel2([e[48], e[49]], [2187428842929094383038114367392650175780437811274194322303902357941058607339 , 8626132368431980635626323475901790012728207722636477570331410763937692048466, 113795593186630447648084123083495614901087109757474270136294009546464903517, 3911253907085777766524239918145094862050185692851156691146764655435644911738]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 17 cx = sel3s([e[51], e[52], e[53]], [12873968423948310899392467568104977730716801401622261861937368089215309803500 , 12347009456329688755313379291270351313162786795095345538842244121034639964166, 1453033777281838070082852447488517173632198407446735454517038916605079634444, 11282290315868048695472900994602235661536258445850718305682561140328404797725]) cy = sel2([e[51], e[52]], [8139007031385157566567411468459940290231498857090568363629902873306461631248 , 9142412231629797319569179103935970351107774720462787670615972830568683805984, 12672100925996181868477785977558380430714799944709260345359951721012123501095, 16494953398584179618210238266126209360371451946684386111530845235540890038134]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 18 cx = sel3s([e[54], e[55], e[56]], [7778254495039611795685039895928787457435875136389165268120013630439201169232 , 18978376692784498976711790251498129273567483356717340918869164950830208175147, 6786343960634025784864145941287160961224170404722122001422161703472545445301, 963142484718869013546386102939529863406065949253846087785240390647819147126]) cy = sel2([e[54], e[55]], [7284679595773642123118330714484999203099307921555787993734753019057231440983 , 11863181578147413903879545253723831525079414688349285572164796614141056912840, 14506820856835670503131551890617399661938603609062325089041733284980790009293, 4347670008275218338032617206784753933320201662996772040726919225863771514568]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 19 cx = sel3s([e[57], e[58], e[59]], [3630756302007400417952089805331380555952289748859891438940570770932527475452 , 4733072488758626584177720052077496914661792393101658203493985364120366268281, 4526910185101338883574479225992287789853409001566403159278561225375682298543, 4955992755917650287600423903671744997417781344631255784951922382765227784141]) cy = sel2([e[57], e[58]], [16596280733402230599955345374089507399680037832193751466748596443674569931646 , 6390381659733151443695336725554471564240651107616043093647301732553182081233, 17125093365984505488419430885232358010204128822674623886572872558984812477756, 7907776458440631594337279500574606181494889317898652109149850067084027888619]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 20 cx = sel3s([e[60], e[61], e[62]], [13428507160783248146944378848829437095621758280249270905793449036777555016842 , 10292076501843933688687976934900220205880058108224904881677407523508189156342, 766857404192368568735095124452313950539381046754211726072981073742394879383, 19929977262929097751573344897093024390473135465066154321364399543253519251540]) cy = sel2([e[60], e[61]], [16698341695430068847582701171147088836738454320587148532489385958997389524692 , 15892936434362954902510964691481568586089663041057258511149661842770672240332, 7940515703899915602011570921990242082041971424425808524102519499134803569591, 6891504197906111172381550323513759741804319972496414093225387272302697012664]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 21 cx = sel3s([e[63], e[64], e[65]], [9001788585918405588944162583417858847457169702891113291878897002187678929577 , 6471893763677472946002018028525448192731896031469219164732421705849786414080, 6872696243264239672878286181725922526028148800020555100207514569826971690256, 6457059076269833003010871598305386357557482703463879737255688784535353986402]) cy = sel2([e[63], e[64]], [2208441895306047741608356002988212098270630744976300198681224594148576837458 , 18524825154497781981405149991295652940946623352876024366965123296382603920630, 4474085805150211658090190066955902897001661633303260299025041221776891523378, 7848328793479881488968680696062292137496770320699466501151951135248413225123]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 22 cx = sel3s([e[66], e[67], e[68]], [9370960127159127445266474449258070389736162441470427007490084241211557822341 , 14965609177224099035387154934147530900281499783229343066828915253839198476726, 10228455969106022490302521106014422994204231909208186519000062372321621002715, 329501376630941941063220737355314017862421104304435198239389326959464907258]) cy = sel2([e[66], e[67]], [10405035931558887078762806053185283924863039263200495982754625705264574757491 , 15502133231749593338314160389347860966662224717441686478526316588882854824409, 16159781620881884595657183508560936205420303661972673108699575582908291222745, 11627201183429653135859532750162240837549070563304757137644487859075461689878]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 23 cx = sel3s([e[69], e[70], e[71]], [9435538689621391149659891449161022313817917158768482063316123517911261629051 , 20034929826130067090642639519998781717754864739607562909796887703087596572733, 2387945787036487514595261230908460627602020385539203589000341684029816345462, 14287010417915184144199881651073103018750205011354171060170509879133644433324]) cy = sel2([e[69], e[70]], [3766822724536031967241092846229703633913210151222385593884505545907921188272 , 15647190524611689022349999926088308537492889236313676989549224633916679679521, 12082040904926878889054967598271733538467180307938292871588544645957948546982, 18694076414086475523793644660947803814318698157437774233969783951279622080580]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 24 cx = sel3s([e[72], e[73], e[74]], [5859172856191457066677368896012140820864205253768332100482413148381377691822 , 4109040705512320821322629424016219907769924434419769556997996401827477205364, 20898133598840700569835017147086534068242670333567622549169818027799138688520, 2562111968303466794360830608662119102867266861457203102917042145665851057610]) cy = sel2([e[72], e[73]], [4836009713585714465496581912154882382453931120914721557804515434755336832208 , 15143499611233432306382398214139440479742818510304232326049564749513747791130, 19356118393311375462052662305789820240618686111711161337705029468367145040988, 5688481852857742015073912476996667522213010914545901826896160233670889226775]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 25 cx = sel3s([e[75], e[76], e[77]], [4623242138639627730014370601705308411725596532862597538813607327046410321312 , 20015154717710755506154819006635497782515667453025611627915382742560093423171, 3514612823502534944140986983282927838609295377065173960376131742886885892219, 20191997625806343264590099369325683216271615998169853765554784065039674586670]) cy = sel2([e[75], e[76]], [6538526769564699401600543915225940144078494544354769810309083421131300518775 , 9118555176257537603156148628736012723504563452923782011591078402032233615522, 12815558970989336318868652718709831589595442899079588636818966291960853991023, 7703616604462929360855592091876031952747180200478430464323567906544600168109]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 26 cx = sel3s([e[78], e[79], e[80]], [7426207409769264985012540642921370782277366662985635838803842004294008785185 , 5999778250617485918891782298009709493035045140093544961901833503446031905913, 14130927440165985043471103750344848991689715792245153118451423398655300689873, 3796482870456559450471870663226834834712024906775762338643689176551263991246]) cy = sel2([e[78], e[79]], [16458635168452867431186476181702908205218256620571557119181621733008943007186 , 2408736441388526903801723805189252326923776373802231905332653169285504488507, 4539189593448662319023898529532785456602052593687554864880479361284144700884, 6490484418842862735983085938727562049587933870197049726191839108647357897041]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 27 cx = sel3s([e[81], e[82], e[83]], [9274793422641213328277630692090429447322754602554792362167389139799628719939 , 18213562677024477140777501284013103092531757860081519011108723177266099803615, 5928914343334640962747136863911294731157726634392529232872962806197144988571, 17364692793332784962323580622297080260599290963212510860189969183095513710617]) cy = sel2([e[81], e[82]], [2125001664000799929029867649528637137680130729147235858348667725168119291610 , 15787194912569598784093233335743719308944830093009287397433562464152875584662, 17778173794489364127449950674919162836220066518510591114146982109869842663244, 18328553264273479562530008673792097214292102347103296244385349755449098608225]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 28 cx = sel3s([e[84], e[85], e[86]], [13710259114758767844337497139752382122951774216678047790125818858626546865590 , 3343610505090632166881693615831990684789904804852523835888323130512752436557, 11550335352408668215051239093872906070657140182660747433535878335227749182418, 21793892863650948729507322696305982607072336532791041097212359516991274087980]) cy = sel2([e[84], e[85]], [11846136982947366289908137269088548542970460276305965388699657623060915691485 , 14439612735106182034303100596819001121085745615069593580210956482903072588413, 11243378354558219750264654469308879862376787156599458648274627817471028307109, 1416613801077957126034351583571856403044235139983509507026555602579721659100]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 29 cx = sel3s([e[87], e[88], e[89]], [16898533007964698268976570330413504736326631860509774315700399063143612293661 , 19762411747110048388233897239023416141949331694011759548598869652948167421240, 11749964437081939283728905999710450041654325285452589389081577137553602604162, 16314155164640857713960417655857498051596153632474886680423284957133775223285]) cy = sel2([e[87], e[88]], [19301014021919583977567348438857464752913991729661145830439339193394619822674 , 4081042960569737826610743202667127127506276066439423960421657857551695871422, 14520831020919654323745478654766278220911435521609622705053803095115677276928, 10347543397607839527923790122253286529883327940351684415635401368115385858121]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 30 cx = sel3s([e[90], e[91], e[92]], [184222443282411811008485293978090987184574946550463281113036487016967683795 , 4323925196392247451702039714921386345420807454721539995370304513020371659426, 2346825777983317939724845287942565740027799801885272779028341294742495881964, 3497425097320782814346947506403058330145264032565372769682636446824270312453]) cy = sel2([e[90], e[91]], [13850322095814274715426304026104710047724256505475254494587134658322670671529 , 11511819464672461161880080290029237185728360968222698390620899743097045452336, 8068296678016129536739401811575622149523917897086227154769231758295218255268, 10263809994502353117991909442849926729413925087877766198113026233378613424956]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 31 cx = sel3s([e[93], e[94], e[95]], [8995760760295995916308082490351740974639094331313720900267671545759667549796 , 11019493928623991376174717464416885911906134873939034428175124701672655752839, 14017581177532816290320938368540191606560126820406006677979240977503063555845, 5992767544073504039822155308781253229334004182511050716159238341577147193720]) cy = sel2([e[93], e[94]], [19514976680591593876219573359164805119998241765130948583982557052811782267484 , 16839145730766072636625126513480100227916490562760284965681235183731245254947, 1021292692554672699619028273609664837317397089685876358558294458673381089032, 19705834660126914988160966717581159186486910721909298688364547098333399879621]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 32 cx = sel3s([e[96], e[97], e[98]], [2527638437523893015660301196665088766965588386392795314680197258969354623363 , 1138471124880305373267488994599338604626881130398552196301155187554578496993, 18796280357765998280755689911684961342287093510307513491082157499389652187596, 17845424627755166990290252831103404879406229534320972756944316138691932923261]) cy = sel2([e[96], e[97]], [19210721144465266426749734142673856566947869352583355496554030705736452071361 , 14313930380744847001650971451811594041740544882894516063775993860263195402168, 21025107892840987725102949502655791789935181032924916608477285415225533245973, 3555509537083802658278452964512402851284368794121767087246797342866139363946]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 33 cx = sel3s([e[99], e[100], e[101]], [15846792621646742652974245065938230651829248095884295067743275618391603947137 , 252268672903219503110064676037004166486655891926695090023400798499584132445, 19530459807361347014390846162868811023755147873522489974990781147946076957319, 6779173153401014221878658847395058091689669042378445736327791547741105926579]) cy = sel2([e[99], e[100]], [13124560942345768357314581178595700674622208923899518932907915338485045148127 , 19427900801187548763760894641856199686412861734645157290016060446141874396762, 10578265528433465376709803300626505953445780532420709942597293441366167803051, 2814357683688249343045032287308948679662030207205739212100871663137250686972]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 34 cx = sel3s([e[102], e[103], e[104]], [9161164860624082016500689976633279187120278305601384250238486553068325633742 , 3594465641083658357640727503005755820863340547313408576898849399984296404007, 19745546026637204577602881915206827000693868119693662890799396502208696901732, 18116250696909523241042661347132525872828324429923244627289119813508105665938]) cy = sel2([e[102], e[103]], [13685063021736046635507535227140671955502404587270095297507854657927533098685 , 21481850865118949667886934355577641333398731968912180643307092533138863580900, 4539145198976864585367021826448478029652078179409326031693175016758410731544, 17461973876416788164599136875394849349337761082750935487057356278682772411162]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 35 cx = sel3s([e[105], e[106], e[107]], [13763732875937305178862849318112327966371606623409616602363024527079535241003 , 7146728911382113235576196126361394323865045988036623175328726379662117800087, 13957018179677684863250069220406779871369347949049594304698838627334319400324, 2983130106134530061974606593769911479536904265326576922594002168086009867582]) cy = sel2([e[105], e[106]], [15902927258231569893737955890837667742457214947649307818302524420399149241212 , 5394027336566373776896911094388660738090625577337970061356832815458464701108, 5175259754491075858870829756483758144360263281431531384832593797283930411109, 14151565798137996208654994826049340981954317623288904943712618832232605861595]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 36 cx = sel3s([e[108], e[109], e[110]], [3511208839914156996602850728297722115315702089624058744395068873552707949103 , 17785314838779826411805999953134869098297432649970533754606824062794244465005, 19568380235187862245567915799143793188430865272594403468605211965296271194922, 8968217637384711708369798047935037549991275897411766158377778716106218907618]) cy = sel2([e[108], e[109]], [9113093883676083424918242033136578270322417571556449454840754893578163802387 , 15195400406105586498427391734410887774383134313041084245786188708846588107061, 10391623490262978616498794103188417653962360594423044385370483010810406454393, 262198447430650388196958319338915798147458757989176286529479967365139093614]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 37 cx = sel3s([e[111], e[112], e[113]], [11522295231047132260758343744179190547608150890072723735296048871441325064339 , 6417300850099046536319790332124930285535196168151466782463281196540309297983, 19137291956859275825926699344301804549568562573423342909926469403211747707345, 2774443339156228722046927543564067034026765236710736809480294993459012359549]) cy = sel2([e[111], e[112]], [10997633658189180813501132314065688584832302881630691645920837501861598079973 , 11230602434226993956802641296087754248529927465162671110571036062223097035285, 62131588140380451567557177282839666875193860544849125919004473298285110712, 10450442472445392653150568721579575112681026302736591474982185692600259786523]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 38 cx = sel3s([e[114], e[115], e[116]], [13408931465122001423751414891302829165042502658140645208130973182525808774770 , 12919550455861565687920656314018840423444710872112059576718885637461594199393, 8902156077182438987081535936092318477847851529427670854791439040325983142815, 10551142139308027026174282362670932774470751296642556552082094389923387853839]) cy = sel2([e[114], e[115]], [9267742985382681478817853200119409918969418222977519894367804134923874406267 , 19027179442258820884726400809066833518658247567670360715860243154343698445860, 18038603127894002689531978859178109088479567097675385814346786297731217235404, 14150146649091182389991766732798336665028567292472735778013325601175132243538]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 39 cx = sel3s([e[117], e[118], e[119]], [6540890698262697218677202035403667770177820101154223149908034301445959517274 , 435497241504544923461214042595209510655313029058197261483355541334388444061, 12972419969438465538309509757262343703702203355603454637962110103300326018994, 6669959829681253734882192282716498450739929798663147573799606668374867628160]) cy = sel2([e[117], e[118]], [2642034845320222085946302229307945658183260378358994660373441270519802248925 , 14736341083198246245608013213787697485596965707560872888430876049025049794937, 4329454540840640926293454385395213780440355759242417354895666807552226740059, 13390807756542084619965526671660454489274096296730210772303889980314835989796]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 40 cx = sel3s([e[120], e[121], e[122]], [3375661072576892623715175468380800047905893262660913295358697027074087217513 , 5069202507845220698620539676049456933089654255996130713693017872693588276345, 307360032529211257870367390878851528397463530836715039216723323169226021440, 98081915276387897864111573201930613825497393423677224354881280134376446888]) cy = sel2([e[120], e[121]], [8987539541637688797931012030256009083390767313291834963652110291129797020941 , 17901947618091300697708370389296420066544823878914604900411880276648078042269, 10639219577401234864823685175468874052621402569992677814844863434253512890795, 13240331547980137691596357784155019878384406802888737259354896076218619627328]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 41 cx = sel3s([e[123], e[124], e[125]], [9662184175454991631880218147488300829920024817382740712599708905755708816803 , 17771020629416708231961523003444615645037663660747267683766850455503462282265, 14494133870721701214401742677540032810309496543890589653927595534007509078658, 16561168866198605810694591274909829276030780262733890202994760647724957996711]) cy = sel2([e[123], e[124]], [16632142917625566129622048663670437511136716491293457317746859226945397089536 , 18400270017828347077622860778898029123047396355399577145984944065126581795849, 8353334605287102455944569500604056116678191817084945684486328539838325378046, 12147075225903504606648888869906750158496142784038841529413244301117587609138]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 42 cx = sel3s([e[126], e[127], e[128]], [20252038718269174556829574777069549258100538764143309785207012647062643184902 , 19438750079062162172414919070069193686275943617816957878302458952613247286975, 2739523700389893370248547110285910821118647890992955640060929464309561828074, 18986163209792052202203221314221453057559857704913672555327882100075093616752]) cy = sel2([e[126], e[127]], [1949203652074521007058676904301415827566224382778317340432698169556879788463 , 4017921177690528677848183821427142247358574441895228503258380087834359360501, 10532220115833479369586881444322308530349489476356817032718755221032796227335, 20767633640647488765234831415684490207979213320475813611233243261000228414020]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 43 cx = sel3s([e[129], e[130], e[131]], [13929197264592281054662634434397205757522163835293158725199610804948038924930 , 18983630674546465400919161958500748450652609469567091049588112148279229509416, 21298720061922244441608259922072286340766498728629540286898859613690667559954, 1255771444824172694387038994365972934222854858110644765629654650968093841237]) cy = sel2([e[129], e[130]], [20928589942441069163400310179733448745002695258624629275677130484867901611592 , 20945151313192869288039616217247173168964585800167278953053768079971885757820, 13394130995265898710013904122336137332320804034657805114241934415456940879520, 8345380486550648681305351465341710151021284756322349929795845243989999089313]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 44 cx = sel3s([e[132], e[133], e[134]], [20820962511183569148336349677594457306122370638840390080208640481304634109972 , 21271204223521868772910817161761075423625575552213963956907846089587689594662, 10733658208915381791180435538254458430504966830986768682084274021501716755708, 3213872100717631866873070659546947812880485326599459130685149408092349854866]) cy = sel2([e[132], e[133]], [18802948623154501291575097526503171935564067914914679326677986205652424463305 , 18671196065143385675890877955428696189287618414074487330442057564568301653630, 17500512499632911097527623128158674292347613137609268450560746154383855656852, 10140717739675826292242942694935483711727546989965783109636404988746901047250]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 45 cx = sel3s([e[135], e[136], e[137]], [14908874845345243542374913242177817956756346686642792660468745914078612972964 , 6494892024924675012540500602558430897039227451488331729419886431227425262471, 19660118982815103063271284609401904064050204952733042875484811495633642263876, 10404140614423982473417062438060653585074743419249328530274575800693260655367]) cy = sel2([e[135], e[136]], [5109688569541183345813508363367270401129385455666732942384933494548859595681 , 6488452587861781859966899732568514074249818909310744177483425914897141192195, 19759144330570995637436877834773866770106917696169828968224667729682932948543, 19372158643071160860924236286390794017939077735118276297478085704446653404487]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 46 cx = sel3s([e[138], e[139], e[140]], [1154476465911192808082307928347900064111325728833428891094393674593800812900 , 6647319020085089760145868568636007917712315513936955502164154733998378717177, 12584569464684026880899751873241162942166450853083376779447501714905643756083, 14243280142991602029691394563175478833697759877979687578140951697024930901167]) cy = sel2([e[138], e[139]], [6461899930945412323497751736369894620103555271239754245787726192367462376648 , 11218209351589240489615573530963044202098579836550413344228327749253510456169, 20533060824796367399322624999408451192171574545415433951669661225068106752784, 11799997625790604641690313275280372066913716290701708574743226300595877165728]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 47 cx = sel3s([e[141], e[142], e[143]], [3106120971963814637086817095821216892657807437909030172048489357608690908664 , 19983788499223635315597700897580134177379185544458724791602486120287361195709, 20011311503290782295958825256275853340402122848359336349363185226433870439371, 17061518479999755720537296647402074631690029621158571296727706119729187756044]) cy = sel2([e[141], e[142]], [11655780578227604806047758025034240629153798954712964172707380870816316797993 , 622054523287271568164593718522127794491026889292924398674394690726823527200, 16135285950085594062254918487673085571627312978983012587993350339361155816604, 16823182833153464340537049615227906529068252572342151311965980898836651237386]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 48 cx = sel3s([e[144], e[145], e[146]], [20374356410965803131887119977813187747682102078262988894186807366145009893312 , 16140790886679277390055909624981354111468382311692868339667095804914180995816, 5269708933005858910719244518715051229221686961187992215177561544872857207052, 17003669964193566226265890987693478032205879390270724431641892912757008513023]) cy = sel2([e[144], e[145]], [15298182760377768633156209223343487909782393543670382286190369588693664098885 , 15694313374278606393252570906724471325000910752891934797182427274800382725179, 20211423855194801900153066955584657931131527051780164510917465106404910099513, 15455288363376670716062020330944532534047008363514636685826622499678373390425]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 49 cx = sel3s([e[147], e[148], e[149]], [14165004713755765453589527153323887724160944086658242248604905215519807263185 , 301131970962481505862420187551701457358785403147894839379498410579773149817, 20703780629190814394908582715811669803434202446164042946560257906844612159868, 12367443634404793487462362639029662097550355799821945744713867599113535990920]) cy = sel2([e[147], e[148]], [20401715072789557220769413113920881979690352159560582443280493351937640089943 , 9512744351810164617160144481900582699060463555523641782334998030336637339295, 19997026788203221539856525472799656962300551306251956395441891331721763269878, 4420107516401930587358239495168429945976230331917756712920657983670672632753]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 50 cx = sel3s([e[150], e[151], e[152]], [8103748105126096403620617531109165346111017883414253359146860083465308290054 , 14803748343013980101691104453457628404765420707022107332787520877316491921572, 6553189032217952509828188229822974795796651131494012230703062173727191718256, 14488140647832162063035434131927730449663617866962750748399561354722976225897]) cy = sel2([e[150], e[151]], [6900602880532330473224374524196761198151861405485326291615150754345009304151 , 1513115647408875522957756488493462370777248725072062752756727843920832160085, 14896301840535712091808125164986771300932651268478608922083726618785610993431, 18048817115801653510192862998462822947761670069362294686696577131702147477504]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 51 cx = sel3s([e[153], e[154], e[155]], [382543238316875203894587902417533689378617036331411163099475938996384971274 , 9619454944964330535387495829359535093743583319913348616872361595592109685167, 6081261874729821958303230238004699407225832699063899155741932401034312247576, 3156137884201329913786702605630625537320273632812696416791152392474314037759]) cy = sel2([e[153], e[154]], [4793004393185972052681267640894832507973895495734257655931836941627180322533 , 12524126851245821931846984936446041288760976334671736634358685272033969216980, 6277340058786227516467028124755004985063566609742747175031180490042372405740, 6981569030046806591634476164525159834865090256544287529201527685109358245562]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 52 cx = sel3s([e[156], e[157], e[158]], [7242980429824960501440666232145028986161691674990466362832703971174936796830 , 8045674190780012690331364750465564303458553754280502177743436741257674712579, 11260599103741407968666669605286104777635431193927929500939820855376897097946, 18466264932289657017935069178634633780361979903681010210726608765753592098197]) cy = sel2([e[156], e[157]], [2313823382391584526084833833122921512331314230217820828722208559851046887792 , 10089801374498501989652677350203014944991951797848003015280234323125565001040, 17328843896403558624774477961071623822106890748911687259696765820336743222251, 9096128104648798569037169791537313868030583174665566146242611146033775655076]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 53 cx = sel3s([e[159], e[160], e[161]], [14129501557712467097681133312480956681237794589418881140932742431414452181802 , 14215253979300894109266393937905007744674886266134853669970409340633353105422, 5101954416353969027375336730301151965881345391948426977373049227857281866232, 14576353231486654843487902119173617652532372118230138091256904812874365465828]) cy = sel2([e[159], e[160]], [8967890713970048745032869372462848543847652746940083058618452105243173038725 , 6265601060440963621915827684472693851147234848878380918293598569151688236174, 640827344679117882936589383352750227742240703205324868948399729377934123492, 9724475542168570127797711494687143027178927970205326782155651202256929792882]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 54 cx = sel3s([e[162], e[163], e[164]], [5456157947126010471455582105823966618048439614862840203794276433144936442303 , 21043218890179638595653930578748044093798652379401035786184926212259053133276, 1927155268257451951778867733460386031395807546286255979317875653435797662494, 2742904689169248143495331827109449907113748836918731412006506067439664106654]) cy = sel2([e[162], e[163]], [9440520397717291873292501513394144011971438675685104804031688857727475979708 , 4417998885632129975756353073742958617120204855631898102096412742879398656621, 21718244289007192530526626848367390261419399428442075984244560471039861817138, 8877177915758141474927139565405950662745390581859900899551672907102924557478]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 55 cx = sel3s([e[165], e[166], e[167]], [14850732473677774396477975866215714018387310838284937771253941847508860390570 , 15346251439912975799100173523179670100616030950715800206631108275859894555954, 9806744113621004413976521475016417033548532640900224199389230684453784278689, 21096603979133316753091339975348990230540836494614368335651248862844085270520]) cy = sel2([e[165], e[166]], [11812452402407343928752680921354215607515699690942611270817873638995622443255 , 6279013985783386608484242724725362666241553499782119548714289191679033556648, 19001277736410456807324578202368992701796359861619482537978016830870842626762, 14081519926521914451511625869848591232696520686473918498999632052868953710854]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 56 cx = sel3s([e[168], e[169], e[170]], [13157890071808158704354468737847471048810392369152727364639634059504126884874 , 8008722424616547903294828680672771630855086822683412918399539174241338981774, 18594694810411494426945160098830123105355833500416479749049639533195702072502, 3003039638546974941710738006242011804553647552380262745534233703293489168909]) cy = sel2([e[168], e[169]], [893279927671356626449601197530638356692800493991878277093322197544680454846 , 13710236865890222581902901564951693313216932700203676104342205227571583021557, 11991140728188265308988894689292592177761583244141205754043533415013439187396, 7408159576060936012801497750876509797959683640624248586584358220473720101773]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 57 cx = sel3s([e[171], e[172], e[173]], [20379496501734200220097501155104742700678033944324898621914782326376426827694 , 5628902661740155176800052287728775683561775403751721906542502141173662773805, 6649334930850298644282280075473454376493217119135753313843458230202317946465, 13953386616146853105384995231337773651826685901371822028427880819484312577968]) cy = sel2([e[171], e[172]], [6312536910770269621417292581781438152243262819530627194840110225345012746549 , 6128625960467547051042766267966540761259574034224991328868848127157477007514, 2178504154437332931470309748598630309367590073987406533802402874933913898875, 10049120191768569519993419401578117655266529530568527176008678950298967775522]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 58 cx = sel3s([e[174], e[175], e[176]], [14193197030749382932133736734505537242924559995077781886176225169837220402133 , 2565010016572214675455233006763278152319972391059007175692722972374012019501, 20022269140157840221511080273245661956116845958170472382643581298431129105222, 15951592620529204477279907750991493798200861674998832536410750610279414881478]) cy = sel2([e[174], e[175]], [10015961841973388881391587018151977950817576225746650865142918877894543270446 , 10962609190943341745700082387389939598903593214578149618076217369020441344245, 10875728650787073188338824979727792178460025858689164586811311106195554874546, 8704250736813220528338393230481759654328677814076110220308209376595986509914]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 59 cx = sel3s([e[177], e[178], e[179]], [21185904177969045625821216347084191287459806531017721293624058180265336503811 , 1250611256248923800378335492392268625608584743125298517147184362502718557754, 4732901842829850758626640836087921620095030893254064254821493648172485065995, 4686012912505407137434711885457531064310116778761775095814150050521297721079]) cy = sel2([e[177], e[178]], [21681922300753515822840018285496181872470481450737464910861242457369823926925 , 8250546098596619229605270054781796306579374634169772718113961166155976799791, 19064654253935902908485961089200674782438523882800790190859631804189001729500, 7893084863238812828005589178028293328994403260619345443806395973318698162130]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 60 cx = sel3s([e[180], e[181], e[182]], [14071560871369419892033259843192185467358801846474749773427241883409830032328 , 9559459046618636497241065316366978002044190960713451216793292122894012900863, 13031319565545666906249801044337083380860313201803429372439840529717343742035, 20069400641162643493898109922008601219601618686364720341639616051841829074334]) cy = sel2([e[180], e[181]], [8710777380190521326883551341251426052007249230093350101154473409247609882825 , 10439377650670164179707163339178975058403688089785136107598148495986084488509, 20130072726000251358667317961033491205160472226244307309389477611437739154303, 17216059825244204015919013637129845877195519789582013765405196142334767977705]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 61 cx = sel3s([e[183], e[184], e[185]], [20777314589605673759170070653370407645867665889025835324139659856710113131826 , 17380793433135473426803899659206730936771330488910864786997506181753180852018, 9135535394443552083655851762956576299400389583070951313661035134759057889658, 19259342468126216922767538099314197508403261200862162612026099962268769453780]) cy = sel2([e[183], e[184]], [2644721599238941245572401477946144870669550581359063534170381908963477379532 , 12369176861935895868206428376006904712013007036288222495431735574326142454609, 17367574625533031619575225680253098966157776114681359698904430545328078639283, 21794479452176520273231597892096817659539111123775968164861961429589103329517]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 62 cx = sel3s([e[186], e[187], e[188]], [11749872627669176692285695179399857264465143297451429569602068921530882657945 , 31939593233430950996158270398727464286178387866161404769182205304632811436, 6016890150518491477122345305716423891405612103278736006824977752295838970965, 10857254852618093631105790010825256882158099527623146563961929227148379359444]) cy = sel2([e[186], e[187]], [2495745987765795949478491016197984302943511277003077751830848242972604164102 , 6997914616631605853238336322733192620418492595988404136191499921296408710465, 6173428954671571373132804754825927617043378457799815000168451967196664752847, 9007836187082518685036356739793187792845982511088020304887245789556567564055]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 63 cx = sel3s([e[189], e[190], e[191]], [5139361255050232661773452561726452928115803730344567411456642256556217045338 , 18849283619433745348738480276785423370734769795033289874458118507070173353564, 8448578350964247311518616492977206693278225803594287158372550008714482924618, 9689086950770336907190180706142608582993499523814136266854852845122214734392]) cy = sel2([e[189], e[190]], [14036051510959474100046039284978060652197630794277473374328558492372137493500 , 16611708132761924749528167866816090876717761056993928787802780141779996313373, 830643686092782069152588625317289527987176650776268015346372712951408738404, 7124577892782407025863252010240336830171667706358033009166413008136074540762]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 64 cx = sel3s([e[192], e[193], e[194]], [7037199118537155369331275916815326054696699996573020862644806346516390510132 , 15801832773874273151484928140234822912161499004629735400320792200594998558674, 20529919447890597649764739102616587236240564012012882223198985848792346137419, 15587579342628673804059001440002406839596944474602936992474297171186661645909]) cy = sel2([e[192], e[193]], [13107688056462500445700480209995877016295689081542565992250464593152667593220 , 2950999836230463387014662253708191376901146777669866592618407913815214817829, 4910645882425237270468350930391794068554002250789220952036477599584216368730, 3842197005807929553563656299566067039385580918555124491435963737335985608367]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 65 cx = sel3s([e[195], e[196], e[197]], [5946112335249256697077095359378565725733629742750694340878812663903909175901 , 19030634249222736450152769682445487635301904450722490014396919999971262563725, 20272077332559936653726679368964023857291782018546895109417787179027229259529, 4325773325239231432990045180370600024086140077952119719002873860984820794777]) cy = sel2([e[195], e[196]], [7559787099338642680034184654424868894988928943730034769673486129058256478240 , 14955054800505659097184643689663447282484820948805633199847088945313706647256, 20527315092050743721874398127103128550881291654522271023332206474058940158292, 9254615232744118309709861811378827051213745889996697483998530345751148041402]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 66 cx = sel3s([e[198], e[199], e[200]], [41373522534463253583709483090344938032869463670116114182911184041610044395 , 123058269904779894306385100149700584700988943576532400555257363214064615908, 2188259327903131136942811179577591848088244960706164332041753317001971084806, 5677272600001855408525885379297081872841669910685379249005421935936405438326]) cy = sel2([e[198], e[199]], [1812970364913777725848745565574644898635129603904027984751613694625700239455 , 6325479481133126048154398075474627535983053143312386360869927669212098083218, 13018920334214076613442336156617958094802950850259563883918734414290288034687, 11007863126994999194753256186448493793850907406765917922947224071691321773988]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 67 cx = sel3s([e[201], e[202], e[203]], [19366353265983664793480214800587120487923062015491759603977854723148315579274 , 13009712389497066149642205706505053720391552889715847781477674095579012684216, 7540090586243428109828867879678893096981460680323209865296583411528024312326, 16312880719251887899651071843693753472207446322138586240016038563189666076704]) cy = sel2([e[201], e[202]], [10425762558101863677692090103799691698591185440858290129753641015260969124568 , 19889759528114345474077603906066211135049113446169104039752988610769598108616, 10189577411425365730046714422122931951193107064366232919940491025624263274830, 19402847860324611226251435664012558569374211845205502575728141649693622181131]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 68 cx = sel3s([e[204], e[205], e[206]], [15647575844595805283124278572298605369081553302159286302039104118434564547757 , 11119588224460846619648329471078205852940427394545403397495758589586019867123, 11531502595396972280500527673404404955773795456604503116176223280757803701142, 8880302652736630728773712083983401143315564427649676162399333300472018402820]) cy = sel2([e[204], e[205]], [18121989769429113110431033241130632527148185431169035091659247063715924437727 , 20873727571773157361636727287434618496229040659202161464546752313173048350714, 20691117161323169072636575178583071560333787206766658873639451682743014282486, 8341316767034979343476640425183870254531797329971610276320314018660072501097]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 69 cx = sel3s([e[207], e[208], e[209]], [15099126396506559307312697471585164108461593918632286769972271267945539855806 , 19719992822745709208744805037389314455441129806628318848823336999297717461102, 2498623947360180463813005839687911187525292314091943320262937967401409761873, 6773513521666107580427042608663114222160509705880285715315137855519926605076]) cy = sel2([e[207], e[208]], [11185464183896587792324099270269738719144599552792757002841466742562118002961 , 17962378754832909648632213279341274522205662106198070463591287770511029247082, 9572883626752796327156744085207279145562604122052196885537416403686418306743, 849739335033117039567862203783008236118271414428303942526044722712316390134]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 70 cx = sel3s([e[210], e[211], e[212]], [5586425841805464495367763159434170408121119147683098906675715851224959199555 , 2275887592294698256371035540589451793263643729528648494997423042939590025265, 21623018362589173579186020601617142922337607155324626054728009524185014872882, 6470935377837087985284657580709150204914393986124872780110914178120147824883]) cy = sel2([e[210], e[211]], [18977748529759410811480134751116373952642146764796083016667926272252310801539 , 15415054474257926323577643558627142211566179025425425674112343915385225979379, 10178696720359974033063364767044087765079200964723755314869211737985682962880, 2751262919149939488788372835165540688204591943865442185170575019042791606144]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 71 cx = sel3s([e[213], e[214], e[215]], [8067396068830332270789178613335432253659758303711969642714931687060160381303 , 8639011650360344590794984878540401640139910601923862912593792315052343319076, 11233915498048422123675368878285943174009257862418242010192825609765986035356, 14474288438243449444797392475230229280689019808482654245523987676777400402951]) cy = sel2([e[213], e[214]], [1109389204114118726338211511183391561882818362713716952828416479757048480713 , 20658495580821728113676289889282525822016081521980495256710356417074439523320, 5734616557338566574377893898300784804059511397655030429323489999855673254133, 7694030151585859685333610687574701561418848021817379115721565206849330185976]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 72 cx = sel3s([e[216], e[217], e[218]], [14694205333290671963708923368506587408024223912051732033761240288927263651380 , 16846840700984603406007084554481852964137248522784508429412010549513323188912, 13176399412773372610094105377631574988462669519590170596472033646615482615262, 2687848140625094867763341291336975245615611233615607599401834736964978577349]) cy = sel2([e[216], e[217]], [9656049051507081163863869851380474393220762381365090138663873299937439711626 , 16257833452680722743254377629669121273261457821544261762335781528496650481193, 6465537052899418297534883094198381748729828452125250541158965933076691478294, 709697610986733714785106299677092114124154955937070541190663241187641683175]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 73 cx = sel3s([e[219], e[220], e[221]], [12368397247649882906953915991250714931614715588424094368585746160811998953306 , 18782888042679815293214947449937714827609414183597755427793821090364126288476, 14980906670860851104998617553690749074165805207013703141953243482569349981523, 6579728809126224271038924161669519472291072114357057900231021883849035745958]) cy = sel2([e[219], e[220]], [813793955589589118694666569995091571992486583635127942664119751723536369919 , 7944299604444967298799338830762202580774561040186193713045849824532426689590, 10002642178009570948907228870686621440930898426698423035982221525801621370935, 8479337223317874954343670583381865510386888037444628897905418707487375421325]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 74 cx = sel3s([e[222], e[223], e[224]], [7187732531650016705045248947412886871494880941757180032721434029527647591174 , 21429737681997573327768382790700665701419541321736653106996131182050077581533, 11836369351087123833634897021408898134248512107687639835461193259880629295891, 19132784475506243814038464623366364810380933540097619300595341694560215897043]) cy = sel2([e[222], e[223]], [7505964932526905326140236282846132917485872002527800757209057356562826370965 , 7446191000078603169082551991705097881255381261806164450828019975914186121730, 20501368217451607884813098738754813918145802982055856468691458112065708320700, 12111360534733555932929570216465933882611889545473508372687771008732927246750]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 75 cx = sel3s([e[225], e[226], e[227]], [11880592453253678945312808709337779570677968939895786745513483795196121148239 , 15885465855717299709344092447684246292163545547216436459368792952573638150871, 15785265541005027154032372858808930773051366971093462129449868653918773012805, 18569197812514885943202170611076608358219751234067371040250790526837986392838]) cy = sel2([e[225], e[226]], [19319714983097503154896952315362236888483358620825042533226116711980128027594 , 16203396727641772481371087324762669694595077074099718953937599120235089562441, 8069072007055358551280258194912706575285364270109077890462380604843344248137, 14879918508369225877688675007526587407926006842700210091106836056129459129297]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 76 cx = sel3s([e[228], e[229], e[230]], [4665897628623235203637312232323957679483103295583092141578808282040205079719 , 13624944208440724520944284383225072602905876122550187793344788447894380752405, 13240065107073736104958720757918020581159288509346627802839384665867212601652, 5404872141819776433203748684385984691445987755176034496638153799038857512389]) cy = sel2([e[228], e[229]], [20713846021060085908071105513304556412817630308151607438714049866357354550752 , 12308156363070414998141304956459569678321247441462175945058420898750569812289, 7869135919638822130359819523186642202243136255410646018113662355856102696554, 18106721900555088660857020092432838491684499647468676099930405315728768226404]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 77 cx = sel3s([e[231], e[232], e[233]], [18212889377782903846034117170355855193339291343619773736161614903123505780500 , 5724371935927035469891307360583032289870105083635885948626519084327837492412, 15018564556029978781532805643572668082137657619876811702006326742091833640503, 1980690392504623526106436839420486135508948878537486163191798777558809427629]) cy = sel2([e[231], e[232]], [14150007145691261709583376556777715716099818143565185837820917588114159379297 , 20022624235079706615759218203483775626475427851084411515081825296526003331089, 3653600812499303949236693031235500821149221426419723829534939359247593779698, 17687818220966506140783793822520601258809092691114698078370817997514472088683]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 78 cx = sel3s([e[234], e[235], e[236]], [20014362392122060372382978901186124374461219393111624832280409989286374019151 , 7678149165067745993890478281145655203076154350573466295728882151032664933813, 3225698435546178867794794576435022149554488042976954865856749306115721077662, 11309031064526492555710928277445241789558140050876975815061803061421298770441]) cy = sel2([e[234], e[235]], [3781524301363795687584984812832316590367643113392401377547409393858835211208 , 14954378542264966404669454369751236758988379152056658083888298000396867621936, 1762346050163239223923110798598502612894079706374187891044283390513959164382, 4511820337785812086858556857918524260240820667203320876468844848816354037596]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 79 cx = sel3s([e[237], e[238], e[239]], [9734499467834650890192498500298459962067559704398257089549121433441674087115 , 5215135617552133686060655322881340267001697536486897440412599806944209294580, 4188240743485809003397687109987123955188618656835900004447532212211334022150, 10646753846009034357734238656245532993332944314059322522045789305478499710981]) cy = sel2([e[237], e[238]], [4354361275489184569727883669567924050940590772506719250562939951242102459556 , 11812679101253609883065116716426172392592451529279171373836703114919477018303, 15938685241828674681356945591247179905945286496762161102822537588243702016335, 2396399767043799129388585002615296373717040489521252489057941017313192676808]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 80 cx = sel3s([e[240], e[241], e[242]], [9547054830379311239093093214427099367592481292385809745992166194109928893132 , 15809211758984123203744250589992081971737344928666499432318524828207451637502, 2317605133926452505125489082200124096354438531853199813212363802981648616781, 11720218057191867199121604823871387192503455956722025424220873115151171617846]) cy = sel2([e[240], e[241]], [13627319622459471863286677434492810110443625239619395014230589374758547978269 , 1429116229161069264517866355097922507661063351137334983223517731193665190730, 8760550298269703331457356635709373772631633074463698514870757469189354319951, 1695059580774200437965405056230849147697820569205516838038543601601027611172]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 81 cx = sel3s([e[243], e[244], e[245]], [5462734684060346793723051717116621327144354637585189012464556861789633254735 , 1574368603481037100592052661337337694471748163849816976465511323905498090898, 21017620690824743015216528248522045704369427405753453300912995325024062710748, 335774257251677761852834523904277348100779994383726453798657085528043830396]) cy = sel2([e[243], e[244]], [19956048369873968081515874523485925798105246605761695905870795560621002747577 , 9838187823381646970305000918713399614038197140004128824046441620722100628627, 9761598443789947780667845618272433395258577614354457312915153694570906468084, 5678382193061301565104967410106463714669588791192144419019555111526838349597]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 82 cx = sel3s([e[246], e[247], e[248]], [14120934246971429747829618071104732571014495017644755746350410437296386191831 , 6321525285327330824512104449106606616844709114576208465479970358050873874349, 9828948304711234867338016094087396323909457869737239406325931677882463208355, 18078003119304519959309175940845224181126936983821549690560235900824217790962]) cy = sel2([e[246], e[247]], [20946993100078048703890437478651577253995893117657499778417778292965813281806 , 14356404021232332461217625395600664517715960389258731685389867303545696108853, 2810577432005044954032138045179699447584646279814848461184496089430514835598, 8767040452903340993130881597424027588451974218686780194782289690479045090015]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 83 cx = sel3s([e[249], e[250], e[251]], [10074124480658003038181060843544012751655263682971006047574974839001332519369 , 12077899488247602319223956898393373607365192976733626340271805296106145121355, 16135938726601100366620437452815649119119591825429317780601932003124015669028, 8179818941824323394614877573129531443686047058703515433852568295536575458823]) cy = sel2([e[249], e[250]], [6742523042997173838799423244280133352249230789995302906545025471831316165384 , 20571270140927253125417728386763981919687051926731085366043566448009069227191, 923263495309221023264076470401516657594260797987069910555955234338720881738, 10846387476002903807347429282866412191160400241233297902208546470305682775632]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 84 cx = sel3s([e[252], e[253], e[254]], [9734317150772506967195863825775613184177780587009303743393397724706924797808 , 11208201130011695436334652728584169313726840614571295516236997046457697153324, 1222680486642983364052833343811429934453835860106899436901212790725638894713, 12019238493894483056724448289009076436822742112482573063847552596048227585627]) cy = sel2([e[252], e[253]], [21086552119896541186107689532205383551960199801453516689016972250104900583432 , 3056767815025727154134820681013380076250249612276183869180162238277626532027, 8232281317297626211055636489579107493658454229617058760791605403582002142140, 14549672514437654184453326941604694948116368249587796119338038904533837120165]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 85 cx = sel3s([e[255], e[256], e[257]], [19897146034704593618377175099239959996606643851373776355482440566659528393713 , 13567220274372260527197800746127305934893509881083589343644604005840555405371, 19175080795372179131749429828665039169211560827471558543841205575231867635965, 6917449549804522032498038894724900459329834531091410689621076525743611296938]) cy = sel2([e[255], e[256]], [12223657826278264815494051932052421695129917274617530304443478482578919678308 , 8295548603728936503708692859047908287111164162226375098145740427985958712611, 6607229719664137890140258196376647042900642854569636028419328459816951119658, 14110421155257010376968111292134385106023449978845823063864491477811661996253]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 86 cx = sel3s([e[258], e[259], e[260]], [8185677100333640041421355126903921619342273914070568426300075868606141405021 , 1670466886055998857358105826250955310011203741639197041742892893805477021056, 671638389102335040808130453738616724135371178235871000115155863725237535561, 15155007602444057841308084879571465766457754342497255444459746080732112337898]) cy = sel2([e[258], e[259]], [5730721122742653576294802609542803235749403433458024692842251665338778112357 , 14898703166129675283863893661050084311561656604196737234704191900969087474133, 2459074141813559460216507737311533957327810551114696579502401763839835381335, 15516107503085209346875467061340145906150528515154791297494671889511125291207]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 87 cx = sel3s([e[261], e[262], e[263]], [13654034957145907815962106285631017905892861670471883127206658577251723739165 , 8633158844589460452837721754446206625865140330878411953122575379370751622485, 10232722293127899126024059808155635562748968165573438955077544464410325913567, 15328263964181874734867171882863588382257876665732200627067485961683406281267]) cy = sel2([e[261], e[262]], [14648234277430895067547661111448501238234630914838612427562971477472564218927 , 12394752068682518494797840832073763890437175762631359486643184011399642941695, 19427382571659868487644833684469199967640111942906298364811415181281091481616, 182598521940883711045871251162735110551301299145061787687905605212153955957]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 88 cx = sel3s([e[264], e[265], e[266]], [10625366736090949097208784405733508126867531010210504034282606844498242195460 , 5745457912443473561064508106222759378152708028067817946740487826967842596074, 19720099885004155494384241598041924024056522066497340576395346816817691557959, 4411557748754390593675263772383003703921572549170163035845149756207936580167]) cy = sel2([e[264], e[265]], [14732913015624058203205922728424826465278063568996784510238321594483738024116 , 8539999814473505400128567752428776172019356440581684960088711125461388816752, 8671134805346361443739204337860301475415660510460401138135319415884938499794, 12889649495366374604591900250806268552879620119403975808021738180701264567775]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 89 cx = sel3s([e[267], e[268], e[269]], [8424620995080153959855099087384460880708718787657472234234125992142104413784 , 1213413054380708818479960383614577938132447492306231448400493113424770669073, 17993616645286674150803280096391639271887381916203322164869533675674274690369, 153030618728554031479557843767027262505356544554897273649773418701874030937]) cy = sel2([e[267], e[268]], [8774350273413061850499929377371854983526435316805379820854063460345613579740 , 160874859222003480689240665151063301233791348742268400199413950144629148606, 3864981636983763871420661536128329698816776138190284810024785475130342429509, 8927799801878514388025533121285392339945739901708290822291826043102309328947]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 90 cx = sel3s([e[270], e[271], e[272]], [8559837035180670877234803295116293964077309001575836599087921933374799946149 , 18335809791652365585369283816437201104065890639760635850904865621132150615442, 20223042693949477624057496950714682763488956308852238106089638364544757819336, 956531986282862630457073126978994765430652506058410664783115436243377137130]) cy = sel2([e[270], e[271]], [839500690449928047855071514156387100713350925422279056462945330783580827563 , 16644736196961833445797352798716804869773621626799896168771841453493474463773, 604545836161644183235683876796430911898168138926947606928620724963455977159, 13372011982201734306725124438714782615028067496534473713140957917136368058903]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 91 cx = sel3s([e[273], e[274], e[275]], [2094128027031828157560092686172909842260483168819281235210539106189673022187 , 14831470033363035728579660771199958641838096197597230010879786959469055433282, 14580113677826055589909107333827815551732916495147612562237413782243389891044, 21457439024195964947733246659608329461028391228550531897929776149059108022400]) cy = sel2([e[273], e[274]], [11349460624897126395359735030876451695289908168621129531254166231469594999395 , 19428708736392770387243553726555356520800900418277262898221664159221843559913, 4432119977004888069457445133143529511285856348699582219607694824086497898807, 9160542608356323143471297830883618199584611885676024272763585312451903134897]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 92 cx = sel3s([e[276], e[277], e[278]], [4354759259287077683606602421630609654573093874872166313972356669642414450557 , 13648951383939395268518611670175324834705441295145081802011558222046663990635, 14109063296906889436525684297777423342039664400074253643711178181120772454442, 7920829805332901764517739207944367186855755092397343817260945923718690867274]) cy = sel2([e[276], e[277]], [215179997319049227050677351252505122489806707992988193421803248841509506088 , 15514289571504865101354424086151224801481680739860239328031576438563705370521, 5904618612526890474103927634405504783798865056645457180704237978103781216311, 5748211772814574948909294216861178264766343013494657271260147929020820008781]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 93 cx = sel3s([e[279], e[280], e[281]], [8507753630181199902479216321724505843375506218865451254864654248120523505482 , 9450124212352501425016224885075456626937137054710829941179274211424392402188, 14617760695968479875555170000896560124384001439628509056518085157675385430999, 11259792651191057957240332532512267993084988584437199185342993378682410436972]) cy = sel2([e[279], e[280]], [10815868200773974736475276546832667321164179489094422703987813447328543028788 , 270750089909256057588643640569447562301277634245971255743235422454022028456, 12525264811662854133497240150104162834870195408235601736200987821770575683753, 21492322023082787855062324449039977497952909569982074113097211015628539637105]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 94 cx = sel3s([e[282], e[283], e[284]], [13109291774440010508838814834344208104350382843329321595606001193219335478061 , 18178081082215000330236621415683992037792438414607902561151998975591610672159, 1825689425393769600328701494994687539687903068590739461592021486333291661266, 7793684058500310840246186772109776829776364159558184911962167538064855177290]) cy = sel2([e[282], e[283]], [12538966751785809241486764416198217361134417700423840996157483469862141526006 , 18918692038570377322252840249784989027502652471358614978414943590808682898821, 10739840318098234656669579810873413661071494114926975536918927404574756289141, 19177195314890990393062332918745346394029203576215723513167013054282705104509]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 95 cx = sel3s([e[285], e[286], e[287]], [10225920463059329189289679689043403756461771898061631555012236633674500607894 , 19821058226025589223575559712382894896410588163797548720897159700660021786692, 4342530929634070742874132949165242936564090903607131574088848141363806195244, 5402483411262228419126012059406829285695506472234034454332016959299908934815]) cy = sel2([e[285], e[286]], [14845268720181506270843668435047795143673881800644972711347963164805203292028 , 13672974733920510644893233723674603797496603310630434825704649796138313401676, 6411707949262855152252009198588056473458716851460397006471717726058983234993, 18779680229580121519443328584313676056219616039194596697158403462222387132381]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 96 cx = sel3s([e[288], e[289], e[290]], [4836760236524137019788853323648085337078365119204570171912328851849081302469 , 17868028324749251162769441309905628927317218753130618155651317995445082462075, 1772933343466453031175704703581215603932939906355841484695391914536709138761, 3546600638749568273439745161679319484611182076185127936908592367054940973889]) cy = sel2([e[288], e[289]], [15727462261854339392836033936665994570356817309630572739663218192786419709049 , 1337461376408438722980356088847283448049292537148264126525086899131501823829, 12238707625348281750296588592788256417660177170554983893114345282873428793086, 15525437884516977515442248737754366741726151193578138245479811700230576818338]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 97 cx = sel3s([e[291], e[292], e[293]], [20126221763126240993614454578144859888701958472483256034667342833856637405284 , 19699064573618103786080175406330154847584332570598813466503995653274429215656, 5989506922601319310850294681562133253116809072854033597983216925515271522735, 1000911579713616921402553874631906432389325985380989857769833587362794312630]) cy = sel2([e[291], e[292]], [20063374408209966489810045113711694748195105838875731221209079272072900704065 , 9194215440981146522641296536570335847038564333573070389731736048602585014353, 9856108459841119062384164372572927792749846793172495377480072007040372623532, 16456996545907573633695460898581306270452076960241899452978065386508672788709]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 98 cx = sel3s([e[294], e[295], e[296]], [335301756618437339439144029360964383534478515390448989496515998200065120560 , 8900295787747118853873347685755889791679080209434225159052383890249026687118, 7128354610803275364524320321498051406687079176221803083268519268078181474486, 10587524605383993790235166395264599817111999691721750015186077104713345396025]) cy = sel2([e[294], e[295]], [5048381480643837407413881593434054866090196361251156389103862466064034755870 , 5633507321470690754598569732643608340435754341640194463936636395149026354734, 14155759183302230320588700447409830028824433982845500795956824041195173925296, 8029144329154622500871732803176023714578210937344495829905950083327660868243]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 99 cx = sel3s([e[297], e[298], e[299]], [4778598962832696072676642978625204359871247189399816084941520023705687820799 , 1041656446764385248839445285580789894072064765593570151992974139621577464190, 16604772736533716135897718386428759521995904068172209060160905451073360508438, 5434449975739162120230503825057718004673241312353068784008427484008820677975]) cy = sel2([e[297], e[298]], [6056883361340614567315212379835078890341975776819628834401238537031161511515 , 12948572080347797369632667255105735306309789288527345335385584655912071062991, 2047203431451992701474247296709372094572802843600017662927813418631212656090, 4132565694324682855622172238297326586214736771195057409015171400249163749388]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 100 cx = sel3s([e[300], e[301], e[302]], [6916961985409927380628327393774423923434707859806165446564471158322143896430 , 5992074540412063352415311056228455935293166060283849428112990098777744329018, 15928943908823412922424046027263578805013830577468518797177611363337136608209, 9165805262654590321870254579036281540959358923531526687992873621654142568029]) cy = sel2([e[300], e[301]], [19113997592137471372275504986229466743101683336744251847362311356790431849943 , 14004712182695079610522706143578502649621084194457654873685315715331271860709, 19337382334092833222650792928980596008310896977712987991984497026496963328127, 19598147310295874176650103171586127283815601834965516057565002042355878900904]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 101 cx = sel3s([e[303], e[304], e[305]], [10948634109523663410073892096301229908363974454242026292710198013874268733721 , 15429431087099938206375989354827088309373134102432374989679474148007045226404, 15424933350139202912640857850279200342934439164947473620816895024212952340734, 7249326591094430300092421476233168005480477057146500206388167575638063334006]) cy = sel2([e[303], e[304]], [13978844239437491612582517692269818179489578402023377256168376965218369369939 , 2030861900932117628118671150363276958527364035939087076359289004302891739342, 15817916211331592751911789779171300716227893840209480318007078572691072662437, 11627409307299027242340485688430280907603952564355973323102745520536413654480]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 102 cx = sel3s([e[306], e[307], e[308]], [18995578047969205917336954191535061050094635635378379108624715348396977983189 , 4225372875497776800681698864198574622710499387413704002947025943614195612470, 17351437921298308953512714184518159189123423974926314714485788395814969849744, 8648037604000808882689040136601171409077000943524268908332163815927078223586]) cy = sel2([e[306], e[307]], [13847262887662907650775044616657488013627923118617883909535158774246706595453 , 16327475809001511779800793713087994795688106377254965385366798254360171531485, 9662682437808722890180813130657795806130406684446667889065062080930078837985, 2502962306844881519115529360019706751646009100590601561262014681428188719652]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 103 cx = sel3s([e[309], e[310], e[311]], [15920090333582846150341817050024564335649064112537068561935372152494077145209 , 5605643430930274732542971456995927736808851585930096579266761796229766916419, 16417626123069839752924241752177228747744623168825833393208640134299321885615, 10047503027147056454952493773282171263110464519924564641292405110762258997532]) cy = sel2([e[309], e[310]], [17200096279975283058225939790642290750952306062383335630123644381672038262866 , 9789126042032908977600199303915152601153926597218655498907321898754260478045, 8000890408406693601499028261723138327296400099255905955307073434675924377491, 4588804177243916206243160261751431868697632792491002746485364561078105548339]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 104 cx = sel3s([e[312], e[313], e[314]], [17405833224461846119127359023602459766899246377474167154738658246656617261320 , 17497966949182265924717994126031328897613192226672854325764486326873236644838, 18112601253331073769860162727184645241197911130662557597456857637926799952771, 18917984642138666446882277898695258545411024830699319452174655151221791211048]) cy = sel2([e[312], e[313]], [2379006936139604897517171125029127132096844925377650383092744055973319489305 , 12749848257678287712950295235536433677019860991481258729313170570275169590140, 19636804280533422414605179875456610832289030857729756765481423873607782896032, 1918232436869295272222782754406246415048195875894409329377075908962690232744]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 105 cx = sel3s([e[315], e[316], e[317]], [12917351824629483440622737030529674983967542988637720886395195031194160632079 , 8841322465723154205678020011172362816775587975165151786897606627457187155545, 14002729598867581256643018976730132585331390790166577050573493502425421127182, 15268061642248917754819598857052007481406516866069427006418085798086854466171]) cy = sel2([e[315], e[316]], [16674117998706559220643814233136742237729068875288271911312504301619597199572 , 15156988565931490695937923747057400310765196912391035444903438612244254494193, 10444568487973458741284119360757120950097746658650645740311119491238200646302, 385547467860345680569692008987772843718726855128251196487129380665836896693]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 106 cx = sel3s([e[318], e[319], e[320]], [11485514708661668839797104792911993330100465395538998907154500209956717209980 , 2378564891356297882391172511058064121371341057541144541265151112602629407486, 15431113736930357829525054375951018432490410667610553241393471463868088483568, 15128200972190674116782495538728842150282218770763850888538540847691112710086]) cy = sel2([e[318], e[319]], [9353349283824572334689034791316525426505799181965760097150790472211583538470 , 2565250682258865603262212838934596650511603775929760392607203509225620090349, 19046693709474252308020355261538860605259941620276924614654553264840108783324, 15978910116968143273641610096037639009526883121076925418594134134597880991636]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 107 cx = sel3s([e[321], e[322], e[323]], [12732753810746517185428320079630798046136898905138090354428070504022561261129 , 14570979590504848605419638850092710612576634760731998010991154705829891960303, 7081876654999237785822068068775175823259789900038464857602167050792131983158, 11911397750859796885754857056361505572472692036239385315518934824432070976827]) cy = sel2([e[321], e[322]], [18703753174721947326863540292822225800192529767109903887849391280378615950879 , 19613778040124100165889220227898498533129133505873538625549588791740345005884, 15039820717144729975607443780109118368904218216499993640810787891283371396202, 7893305471806697580362861198809218871446498187812275173987543199956558198521]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 108 cx = sel3s([e[324], e[325], e[326]], [4396441250850868966014141809834014631796411613521413364533261157108807304791 , 16836648497150572549121598580118959226192434996387135129991940567405870268725, 19465159793724690099931261171165210166819967882352842855510624454147581274670, 18758053793437253746142721581116755417112792746753684636213054094477781477382]) cy = sel2([e[324], e[325]], [2981405188098805378415778407831807030725264692497108694734382487084076855210 , 20469108288868835484927940943356623938045830438424196869633899618683134613519, 933161936100801959708943470285929527457537321589386575156679532348625637985, 269411351035529607018992916380602655161076148137839318392666564540836404599]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 109 cx = sel3s([e[327], e[328], e[329]], [18448980711993048271679830178954781281796619509660919482566515137849326949705 , 19744948717433186245821639271216553763028577858032707139265783707853921912155, 19819689638742986969009459074952228930363474994050981268236002838584672060867, 16852310388498099768769862489306840010510354704163417110628769300551675410617]) cy = sel2([e[327], e[328]], [13538295481673593444396948705042001770075594914797407330259513771278632533788 , 14779507856773747214980057665178562325159137267699293184545672938786460137545, 18422483889209125213732972603904783756680200857795267276573963126785961918198, 4225410028652447730956912638069668360808266049871102249949930413024208501463]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 110 cx = sel3s([e[330], e[331], e[332]], [8789386218557174287787274081526754120821582438440596481230009033085305168336 , 19604730670978725971286378588091820043225493993475360080974783305559899794334, 5754400819903612415922678283536801620301085919072204701407326554289862247, 8133367062275595631112870441047385208403330263311352404563334748971640119238]) cy = sel2([e[330], e[331]], [14711352054903619189890311113670897561016852508413508359380114647296690234759 , 15505081148609421707654891794900819606599284654426944331953154100271365747946, 10498745521808868190882616751430118808278388180031887838543438537592782154020, 14283723444930116423678497723705206282538086486601870839003576853131844860728]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 111 cx = sel3s([e[333], e[334], e[335]], [16410879947793378178852309134034691965068173351773904636443113803287073468165 , 2459742793248426443467557681746013841012911230130900204552944771295773437965, 14148653292536659971692314351826075143664660164844520450779907656237062521024, 3823568337665129538914482600317854425115614575078537531810182911935066246893]) cy = sel2([e[333], e[334]], [13525280335627612179489028500357999227382280656020782481971742893960563718069 , 13906986326008385599879221793305773429690045797230325194617940541283670975066, 17928827609489859058711914379940226888033289004797111427100202351646756410052, 7751873896780721346657011057490735623065509677587909473561532470621436328656]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 112 cx = sel3s([e[336], e[337], e[338]], [6360670162449266467030644276184864100593477111108480032796373772347480922189 , 6238026479435781753480651584008291445457129357178771800497280501659229824509, 14372912505742790548866622516086728314858808340582492719789600777407852624706, 2504355035079143757819920622529907675398702401030398889002491033376003993290]) cy = sel2([e[336], e[337]], [14257529111287275777165336596087530152135443364949890695933859730727871380736 , 362630247512640601958597579829458123399369864147591061426591055098065517091, 17799973102921706872164223253101644481160962872432375782799635148100439645882, 16292554915278539427322523921562887226516459098783274424269678044297404132797]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 113 cx = sel3s([e[339], e[340], e[341]], [10885915218940734071225780147170174316285574070557833147925199753671864395970 , 16952199638513201931184233985077369412021694081253114169931799009969944845190, 6579022618957621849920927439620464464347948481098737101648586523931683396941, 8954730328909621308689740172956171586217761959578457105814991014419829084276]) cy = sel2([e[339], e[340]], [11029057981581926429073650712620964484769971154264787930046960173769123662678 , 14057756519867963926667557918235357382317971790756175535573262066939972782226, 14508105580605381633693926053140229084417508695027158358695356916669309852365, 8985315555716651207654399675191261186115135312348808559060054412234307291987]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 114 cx = sel3s([e[342], e[343], e[344]], [9591625063099557813317657356201310094684652614430671855551305338577894715651 , 21710627476302748728292369634413673464477226906421695181551559967392730749884, 10189696652015358480306279349674126142601586910844054141319090928400967920492, 14575448555178809619615329760249104735737622500547600222673171666044253032327]) cy = sel2([e[342], e[343]], [13661097518448111362501604180288489621905168345464166181035334250815558586292 , 6541927678640542532346030316589325212935454830056081625698359290342280209696, 19655534040611331062875671654696954076416928174908705322979343601347718766841, 18893407984789248251370377180059349323487262100431967496838185583910928677618]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 115 cx = sel3s([e[345], e[346], e[347]], [18886312892727437565309004732784060353326028914324367568840970250261109059822 , 4969806713830542782459289156960092729650598975239889678453184524343618399703, 16622981471374298426508813360547940582831388597832992696194782397307736766285, 17207217606628134149600916884515052475396230199786007830822049511835023327746]) cy = sel2([e[345], e[346]], [20097067895510901824034782908594630518461908899922907976633298936904395310483 , 7549705567086856493177008201999701185795474113091244286639270279144087122600, 6359914741562734059777896085058461481450840152242223222499923214787802554266, 4523686415566243191697029234004097207393002925819292838991423859908963592134]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 116 cx = sel3s([e[348], e[349], e[350]], [9611980085915454916721710377398516249069657290776790665729578385653465657608 , 2808629496317279665377941162907583528406102092075003683612652910715356989065, 5146801454146059628396374424703327885864890381251241815068083494646287896482, 9712822633793199870569132733680515369277288793857035023884821044404624931246]) cy = sel2([e[348], e[349]], [12531050708955702438977554896456788618229483698488185884652134859969233228127 , 7759740123661798513430229604959580258805004199555419745903987161601748379417, 12676630374277918228347114736241248443643025357735194824989982902529942631987, 7957263793605029493947914798589160413665834659013858298537818906355583201202]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 117 cx = sel3s([e[351], e[352], e[353]], [1741783015222897367309800534949631760951606605798891132137371646304340462458 , 15753951377666759323512681415584732767525844411650049393938120048851867306800, 11318371057965241278094291737048639440256637452901941620275041654781038395027, 9043834682180335510097190442699980857932890158044577184782692529141130240824]) cy = sel2([e[351], e[352]], [163811524362553669200342941603136686901966525127089114473510248213711571683 , 20253563341205755839890642239029020576032044419644567576263861445077574198624, 1129293390247992239629138633531986375671761935795719290973869330578475352706, 12864200497534810115296604114235985076138506691530959360993894765742849428715]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 118 cx = sel3s([e[354], e[355], e[356]], [19845239752872171546325855177077796460784181475810291663797620022786920823647 , 13524819092286579506826904337550390593582530067994137276480823345309729489925, 6812066149319989921217367650719188106577252681936159930531352608504453614106, 7222950523682776178187164591717978364824407709855563372464941677077475909161]) cy = sel2([e[354], e[355]], [10413380090476979012716640518612591288231919255093118763710930970879877622297 , 13124406349881024599134718908760433545313158896610258373843772982921905937617, 10544285464977662192736078007137407440374594005235468167522962555324745898878, 4262511480267656654185538760448950673777806215660569720854482040852407424457]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 119 cx = sel3s([e[357], e[358], e[359]], [21840644145325684882015312401601386817913954005861480185552664536266852358123 , 17245795366378478445622830709744244736981686761608208515847580487483274745119, 13807005991933596253278252430914713127227144098393113439031517565273756047729, 7508257045596568083350722191515656587852775770850324460219207057837744147846]) cy = sel2([e[357], e[358]], [8473655227220833354585864220301666825011510607427101884196854510787991763100 , 12360766780968617496459580910362246207458173665456601955392871687431450155437, 16167977026195109940196928407142099851728373085986722415539043108707307260209, 198020065443013508235269047245522994471757343128188653900779810305583184096]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 120 cx = sel3s([e[360], e[361], e[362]], [408538855946993109150255210001390137328762855947155164309686603040268044308 , 9956106896094805762100856187967638241058986877712947272175178827260922476691, 10413057148806203104120616811444687722773209463542545789320471445420824622479, 11902530720628689665925185225980720963660904880464037650526790156354563593259]) cy = sel2([e[360], e[361]], [1479997830732538227417547327573357263920837878818360220214252494202287418999 , 14987839414386761194654231515173353164503075512219993482548242568337943854755, 21713504951370328462347781999791817908891510961297311340202728964936620298516, 20863127910126532592439656993995677084099363872120709138917554483343369113988]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 121 cx = sel3s([e[363], e[364], e[365]], [16909060815089078676939420644976457427406147473547024017569298235433420995548 , 13780618743481311116310648367060473410410597997822855004264478650194424563904, 2732495529118703111995546569867225395498452112166729675036576016860030980932, 13122008905793271330592610678764878579485569855365858119720314545298458579129]) cy = sel2([e[363], e[364]], [9691045028169014905240668289132134803037917344396639164551352440947925851528 , 3058069811496358922966440231506430818794592620746845318344939704361344313857, 5622098116652966523875299529800829301718212684029447361840034988407307855810, 7183269074283900923163991117263230892311528827769843151316519486217947924186]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 122 cx = sel3s([e[366], e[367], e[368]], [20571623498624005071141088211057092924213194074152586837454876463843418144025 , 14097761035973961045955839030064191145683851652701331413184120292691554339371, 4700343263415821617058086844751479864993855871131720446111591033305616384725, 15018715227933376511503870740434993985805930984246159457731592079602230709953]) cy = sel2([e[366], e[367]], [16001479421972757821409642160488722706981473283972847385882762682377724905156 , 16084059586346766494553050527349239192146155351545756557596881128274718933483, 15099192410657454417038148697642033151361229914558920712490911402249873000238, 6321931552493003117300598295325862984882362303961074819842172524617810976022]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 123 cx = sel3s([e[369], e[370], e[371]], [9888014007610840933022906589732806947017424423907994528302713554488676542739 , 8913934326838155827928873892003131738033383847534784434581587200177151201442, 11175569252941365912268295578620074710236065357166442341964835896122343271089, 14897216243038767404517178131890350534529367853478353360851740975433826101343]) cy = sel2([e[369], e[370]], [15251452715683470293001422999667336542311051361914428663773647008481320118023 , 13776813195393840721224885537714951191622587841642219673672717728440679190719, 109393055477786022036855578884727112792551641118563108378161158873180208830, 4672879465153093973501790898266208077997221906104002063988725461236876037213]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 124 cx = sel3s([e[372], e[373], e[374]], [11201877561392804928547433284377926158320532448010089457664943460838007583898 , 14898313039936563609742185951856291683792301837166735453885728355621976660447, 271087861779394868518887048853047396941902217944929345703753181641065491942, 4441061173173027475223782298768839441149677456214218957851727123779445089634]) cy = sel2([e[372], e[373]], [17554707027223374526818340909253875671094356182527312776837442099008513816809 , 20394478950504145529480516245504739970884923781915405632423034600555134724554, 16722605284146576015540826794584204150250626411625717127438407440061496436970, 18186321490023557384895834600063402151493085858585827781091438725428737294598]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 125 cx = sel3s([e[375], e[376], e[377]], [8041169655049264647027531522783115313651111026520000925526843693578880103225 , 14515227610041424277087375692958559713914998916629738058046674629183188354305, 19607007966889476958718540412171510858381328905787578252786377727252482454742, 2784733087979918000560628875496578392394872735862389774966301201852627273440]) cy = sel2([e[375], e[376]], [16996116430274827689271070440218340032465717731948638724397047789367189212654 , 1334527779675942376452476259926180292226498546209192760351592699867703388666, 2040984273885096997446285553479523685705477968103260410171803510149440153201, 1362381113387759937979242007199225976741286448134891397298462226220340605980]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 126 cx = sel3s([e[378], e[379], e[380]], [19334565048001467439446889504730002771044189757270166846813098304840682799995 , 12950908278008251424596267965839781465537497199604011584300739900170800951940, 21595247577936157693500985718654956851081515776736906827009279412148715287229, 15215490137474227465600889880755209339274086672218612829479984354294020155457]) cy = sel2([e[378], e[379]], [11177666514768283886285136134046021748603781779508224469021361511080086667157 , 19019917071840025176852012694579443932947880720292648245869222295962307004975, 4637723565271538497699679545822400204099231070875646671160251633445655525972, 17666228617432733285346663026898759021573050617000716798909504211448351974426]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 127 cx = sel3s([e[381], e[382], e[383]], [10764100134342681938975151936530775454161936697333679961141539476099641645903 , 16887585392329741143712714812495679688982136908448490321095843300899468374984, 17732836192725467148065242235309558107289861496038148884513643994394428900356, 1445275363508375975763521380916891145219085429516411016928665376398954093593]) cy = sel2([e[381], e[382]], [19850691100864531393976360616243718992492409320965998539447518686463634627384 , 11041690436464044133197365654525664032353519287590211059695239069687237542566, 12282683178748394297470306056106686277334235538468988533692942720363799093795, 21342615132598490749588725326967212830166119543678585183102318245731915882892]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 128 cx = sel3s([e[384], e[385], e[386]], [7984775939876417845202037337929702281039643807160799398396389954446436630245 , 11385355274910748832054888360458973063107383418973550712148639893241354902280, 1459026779105998101465829026524789739182470402517704469029876736898952870477, 13412666792048974377925483462948441322790663427949756029941851541794367956141]) cy = sel2([e[384], e[385]], [11644088529951120466123058306783377782553679447618569394424538939634266570688 , 3423766185322892807020818425845766412060736093511436910964946420904954554780, 4248997486365074893462023447486954255437098681775520477410894095041115503490, 13508520946233121439054409300327739993661203591041357972218149016790406863855]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 129 cx = sel3s([e[387], e[388], e[389]], [5565157198993964726485879908963280627890845525340341493437203971709365228330 , 7321058630137598328136197614874359518495943608220094707772133348409941566403, 7424926497991627209495812948930411917848701932818206777924739403931504666904, 2952280234707044917845773867363672510563637804197143708410321227590096039398]) cy = sel2([e[387], e[388]], [16047978233091600592523116252839158499254716982332498268149527514947495047441 , 3013461674923738179146278200182113922630443185951298626004001204030842783133, 21733406038088991240575501132398939052212396619770619197864537159847335678397, 9758173327391957613571828756022551933369392423107899686458119829785341358149]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 130 cx = sel3s([e[390], e[391], e[392]], [724617195994552100441707186007100945318061137735042194166321801565168264994 , 21457482305994995060621698878673403410439584990848189791210666985898821778689, 12733018351677357535096192491479720026355634001914123270202692797811692793469, 17876157828650849091584102879830086520321631185862731111337702980715729860154]) cy = sel2([e[390], e[391]], [1941243639179655563586549731833523575056282199989602716546318426577162114198 , 7186671745389328078718719957510862463188189283547797342924706384031236512232, 181655793349501388675021326982297619804658251127556562657041847324134931318, 17955220324559325573119985254939537965603633897040077737890918084344489169000]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 131 cx = sel3s([e[393], e[394], e[395]], [20917363825188238552045899784153496987535745925685770873105753565860443082365 , 4540090524117153259059229343653410962125958868702729157110889632173091362337, 19931748170703315405614719529478161068009956569206884593254142678501117968416, 2400060542928241404744010463507020801241694851019173560965950546401444426082]) cy = sel2([e[393], e[394]], [1745736425002501661522536470728945366618822522645696668197436988525466413140 , 3366347972505547411030140128225789817592493957844838153202867496815084725868, 13538672659394937012305631615026094764214309199641714104321427476435723762022, 5730310969197975636538358956003546448924042719236605822193245706535947879790]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 132 cx = sel3s([e[396], e[397], e[398]], [12673489410414637838905637938820402546181123854591818062100393889121109718668 , 2399760455052989852989301770450241617652861646522026007293921167342274767344, 20212599267512455026947565441242728025855774594658042161574807775907652589242, 8096283485634551421043683037450718803162713602325821677928898619562706870069]) cy = sel2([e[396], e[397]], [2273218791680662828916671149332560291571458847138066661294611637128783792792 , 8189321225342615133315741008578315746871762722980986965249683543300354337817, 15342161105292713352374449802912175534449400959133109035836260415735518836755, 18075013689729624974967362235212984989450911765049481574404064991547015443791]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 133 cx = sel3s([e[399], e[400], e[401]], [1596291013949010721288060595532569432608538778619836480784785471074053165112 , 6808491683819461025655595089437806112418825101974851283793281398274802390485, 364241503925827187366795904611796342209607893955620582589568264631586955422, 16490550871285168246186419126591524969189857825357227166657318003550977024941]) cy = sel2([e[399], e[400]], [7862378404177401992071889396713852447802454946236648304807328682371781930090 , 507291250759269099980701396020232970806066743976022636589996988193601483784, 10744127551738752560827414410584235701822856001225517338822143012287884858602, 18241779151498711099077315181629505156252250432591841498036131464452558240559]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 134 cx = sel3s([e[402], e[403], e[404]], [13383782376835328120051264492485947246229335501182593669024066132006083860995 , 6829659109797487915393241205795046921708391483622784165963215585089039907693, 9316519590383340417002353253254231934003449806173856616162378794199227402893, 13002922510988749141229072125743986091046064285797312111247897533544865920246]) cy = sel2([e[402], e[403]], [1452388014885069534714863742557414467294079407912495717272255602231974271039 , 5900502409092025397559171952410984687860230521181044855453255892660864354438, 10043095963739821148582141213281494171132379314509020019652213752752234376602, 9999295030621233000765070897582529515356078631699063530749343953422947829219]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 135 cx = sel3s([e[405], e[406], e[407]], [13165533527694513928104129943149460933916076941607396715443729707678633985673 , 20294369464168299590806576821399517301857816000499415634107985306452722815938, 6067645363539607688922626118164207320418666861212948609146588413602170467017, 119932367132867885429975847232185792475931817114142487620518936723703313296]) cy = sel2([e[405], e[406]], [17238425515895072477563840544058923640858290538130746390995636765338905591675 , 20628042696308823655110673878535950075986980894297665479048269813590306242580, 11749486899455580256560135562925052584441889327031335669536847121302580177052, 16957619631025354458723169845456497220362554006891490260455748609237426050971]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 136 cx = sel3s([e[408], e[409], e[410]], [7326992374695153334569399469397596928696501586886381702972942656080738560504 , 4198555626333615585226486302590784054103224208504401294485393840072962221472, 18288510281806332963207620050180295922486954421289661405933207406160563376204, 19378648346334975363564386629109544268031565617795572270340255835354171953065]) cy = sel2([e[408], e[409]], [3441991977044037545935620478935168226411039028254665140927991316702138513190 , 7980022316348851053079344973315144435710609854183180078433220232446348072790, 10703403289781310156812833248447222548151317595810496437901793212311982317063, 16301246072292511450557090225826608132244132307038997545230147196603338285964]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 137 cx = sel3s([e[411], e[412], e[413]], [4380971751033847027929691061398944531722909263311553031455521197665070771642 , 1958998764514462202561805635784673640011091472752464180193064104296547581169, 16607632498550062722823535936950763735998138401664871177932105851574722673362, 18107842395238833528194122400147411460295339366691168281515267029707554163796]) cy = sel2([e[411], e[412]], [16794605741797752486161164743285493892529567663448780177764044251817860406839 , 627364605348057780240790756195705309805910423716172983190978634837740895756, 15938340690702031578469687601244712133164105954943969813204470601233395408177, 1337728022058609756453976167140964506743665540101352471912041874198880786028]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 138 cx = sel3s([e[414], e[415], e[416]], [4325450975911066881724043517797022496124195434220888316197251865366294339361 , 16239262892194658073042878979066943080253388067983326658313518038231343725333, 3224923392579231188607529005374853676842589239602348970956358059045513499844, 18711810040957806004127569353264972856236116117792057333129328498567653245337]) cy = sel2([e[414], e[415]], [18556589125306655880844231674670238467511897504977535323905816448582480367724 , 14450907030938846250134541582271892920169763336845349109491176054829079021938, 5489164165718004081061600001298776199757130654902992957321875892970948684039, 3404126456231281994449938636645452663538090331489692208486381139765931389947]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 139 cx = sel3s([e[417], e[418], e[419]], [3049906494165633773067493912990013841965806179225048735919293547905816967010 , 2425405604681482172566807394598240014734338608183001729881716084701331638207, 21560391195338031738549905898033672840916947395960523186297949490337780382461, 10640880946275949996544592530048605056441276931537882586193904453232482475238]) cy = sel2([e[417], e[418]], [1139270967545262231620743596254789040950691396231510347534297369410226811042 , 20852287956575668107697863776884710196273757688539515338600627283890571581133, 17188605966302742252765339963794720668370341043552053263753117294010969693650, 19246586050423626713095252320183688353765457408019346352862271422811659317777]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 140 cx = sel3s([e[420], e[421], e[422]], [19942746034266536069392101170115851306620344112551007974939114086497358930858 , 15726708481134151732276229872451366695420040201434018827381159241014716358033, 3452250047812572894016965388138239348795538732265416477858038566576272340399, 732825901760241932909222883465959257672029209130800755766287912812473135470]) cy = sel2([e[420], e[421]], [5234335526367392822375043936890479400588416815383747301372644960641216357795 , 16682782393317738699538698600037172468451638588454521003611347304172554322239, 4800939729460682232720559307513657730880675292200605768084865538547688695396, 13002618796997179002671199181852958465089986403190513123030050511152310206971]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 141 cx = sel3s([e[423], e[424], e[425]], [4345203866646269633300579468877411954334981515932585752657225898484243906660 , 18369957391582635573293322493321958485207102003892958136897534329158731684885, 20673831086732472000273127370905823039882723856850376643114084876980363716192, 2498213507326390169362081908041456736901489034606083564552630396661416090091]) cy = sel2([e[423], e[424]], [19711785928362785984568609948298550809737208754846854010480265206080190724688 , 11436630733281926268922633177556600595162960771369546050376297927685306050908, 7773194831659524501769470153758921383337560398544153003929463015874290745463, 8133306555008250199402612262687855812899186562206213570420163947809045175265]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 142 cx = sel3s([e[426], e[427], e[428]], [13604959715661441436052939762464429298226713418171390314110026091418525209941 , 771054573202666486644315008474869467749501529120937703475279735897998473318, 10650739155896636131407567213077995361727149157766675911133814003745320974607, 21082274336612203666519840927907859383019309974047946161440422017817660726149]) cy = sel2([e[426], e[427]], [9106634253925907822997376723908848470389744101982447244238790923479221740587 , 7324910184007890101804849358851153077116609835592182327277588695666568522132, 9210749700131521931808418873690269098719063379384664590576822932928021903283, 12373345790154524492998539937744274645461345882077071841080883186883404184026]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 143 cx = sel3s([e[429], e[430], e[431]], [12272981972646946567553896730199881959247853499104488943992635249117595393209 , 17484113948306348142106921779441669789323552473173221235726133380929727014173, 15117556748390824311921483809280404911428464810641842112990732230853500342878, 18738665459003240153367275566837691463796036422817751002779294781153509048410]) cy = sel2([e[429], e[430]], [12840198036955871442566173317906222816787870441489199428401326600711994709214 , 13447048657087191261352674553209997835888060694120420289379298057286058954919, 11085124394828809185369563175800089294678889500629428639251047427113804175136, 20040932616180013985013159566209210337758333701488325181237556234029685365086]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 144 cx = sel3s([e[432], e[433], e[434]], [3005593847772820450050205074163314509976806377772621088836578637506564062913 , 2910567614812792758847544159495544141576095133298651646543717734234356651464, 8630893570634023334653627900758492588201195084156991103796478188432785900122, 20068438612873289533893462991408376904784837411837844241529573433855826118434]) cy = sel2([e[432], e[433]], [17258587025904856892544250820556722922327972240440200527118380921147955645556 , 9839944666562674042904466515196204595921896101136113309540898758440523509232, 382264312380680546118029507176039576064064377468124376294215202312670233326, 16859633470889096937094854459393230196320754799783499045789361347337904723211]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 145 cx = sel3s([e[435], e[436], e[437]], [21553262056684585969628674122764109775958361035991194009613252605155913211334 , 15282636750399879299317591027894754559134990135454294656134105963760417995544, 4066930541781809252860144352581968840798983673586834922803928000950012716773, 17266825085778436273993504052249489036678132768169211810048007631121526004292]) cy = sel2([e[435], e[436]], [14469270633466381305852216281125837079646617198515099740000541993840798471084 , 16980111987593030332881454298183054033228595894840772569146266548134494583283, 15118688184376333116924615779850360769477969453186921964192734694461085893102, 4748807943449256265621737370336238625547081211863390407052811770007138872316]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 146 cx = sel3s([e[438], e[439], e[440]], [11763347508086007810977359866267798246514404258245360557926263268200652076963 , 8663905006927572311188991703236656874376542152827973004022578290253373528008, 2952845374549988741320721621283121797914244173004620545437372716814928986849, 17071883097921153691621062529879599274949735278299892231358334236565401545899]) cy = sel2([e[438], e[439]], [14706162498378202954074913829047629685039231677186626739445882650545999503202 , 1719746349330736449674857345290037499267579249273019799523377364214790913723, 21616731410397798448193163892890526448374926979106286339849727909287686706845, 11446919769449393256780992769707214683226878212422736672766658759052425409242]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 147 cx = sel3s([e[441], e[442], e[443]], [4356994949172878276640972387865792898708144237321291982532719592191935134502 , 9058912028451204788275313382642068418310841490274106696805181452416351257146, 15190160120915818686650557755704440198069036613617930484645880424887234233075, 9960154561010441532105561845082645172957096392270554555453954413006726871798]) cy = sel2([e[441], e[442]], [14574692378125259586817945291111936727424704391123959334117252195469092200764 , 9224728228539828897416026999778106548490158473228676095012930511474594231477, 1760463507739730034367125481096536174852992494939001755761219582349351757169, 17340078450196530212205314520279311841731993777309479440929707007860057490354]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 148 cx = sel3s([e[444], e[445], e[446]], [21880820504467716634106664909402072165472960350877194774465177915127008092893 , 11747606579643600398471099307152208653405848363842457205852065247815894902054, 19027263041564841350573847395951723454691080012198506245692747602145336686229, 5632682422077314837831565983660289273448221389165648008167925020530588300924]) cy = sel2([e[444], e[445]], [5182168744456816656485869911241149693404052223082761825064601932558781730740 , 2685937932147288674316610675212322222716444961674715249218650895750571659552, 1912852125196207140975649985472776011293820313776376659814516409955251806791, 18263958114524880676274451483937610105571465623681831140376587635788141241088]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 149 cx = sel3s([e[447], e[448], e[449]], [8936781701927368370215210870827508937678765478808217533286287559934624784681 , 5108431664028439851662340341125863641795570652264053957564019035084276122804, 12999653496005517730722186355139904948504508219343877303366358022761375044402, 19179622495081980573635923134343351242929014436693872859625873727501193848932]) cy = sel2([e[447], e[448]], [4623029543859886044767307470074323247069187031547412019261660683452990785239 , 9857015684855568488276378660083416741199186578332924215590492662945432272825, 5242391447932956625671668911434466570194372869876929059550830464880164528131, 14646928672286452058469223988095085156895208600523868135204725017248298504143]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 150 cx = sel3s([e[450], e[451], e[452]], [7946459614521142644206204774850419894186577869297360917934350740375926112382 , 11530085592691934773947896113217121596676226719554558175458752626759168307130, 12291215261278045612022495371137973264064622535432110273152233125306665396787, 4442266885858584741818610179233325487185053295954810407262511211378152048331]) cy = sel2([e[450], e[451]], [20393528966549387266343193152712146799161036298032725317477228673291507957942 , 1831259860608244620805838343666664146008857962101286629882205237950513972028, 2581270768505724914793947599867596421087089340177029937008824731251155270286, 1824038414762784797700995677077189626495506231241155951144255369814082278582]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 151 cx = sel3s([e[453], e[454], e[455]], [16996326686259093178712301719114535464147004200933701699216923172711169217776 , 10135668620867881915901635109225909232593721615476228193005378643989870282190, 12684696285143358527008494835928613367424428569071148860201922633463847362163, 19520340433574445384932755965450431313046400213079154403779893187900476007389]) cy = sel2([e[453], e[454]], [10879703765081907416589976314120373073533854885503210038919805342729980088501 , 3042952377945780941440480619239495862925076770257741464841490662991367990723, 20568201167449878452522309826171296534890589395210499691162182782776592901489, 2515435614825363087293388949409937340469196878839891206929432371588941120828]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 152 cx = sel3s([e[456], e[457], e[458]], [5948355082391370971277814822201259570199411254972015395356071689733858457870 , 14435295688288574008552320445654835668230448171821339773392204385711009673498, 4555707692840173328761632986080641237899354311390885658902712711385985152474, 21377793559898523325502642621273525075966615158530502938404139072744665720725]) cy = sel2([e[456], e[457]], [18781938632634665629392534748457372928296731257744451684662925940692495070899 , 20870582266287640319635222130472633641883455183531701982867810507045631654099, 6255001622610081365809867580322152519018111820804890853975941295493185079617, 11444903546950465193484459453464362458126976218066241321940461471249831055834]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 153 cx = sel3s([e[459], e[460], e[461]], [4801783634053958699406131208260321653724147389806778300442394152288266622390 , 13657947007455887667569605985083889328718870615545221619668723775205747840135, 177598511756923881728697053947837521554079408931967588956714727282062478754, 1374290142752108446259268973165307183295759382785138144661109763848127727476]) cy = sel2([e[459], e[460]], [10503832530625380631086165586158401732075983866290617431349835924922749109699 , 8383317413774803586670187834721088561764237477263859389570115631886656905028, 2834233504802602126712103599378293010472650755759227696185340490923006971103, 17330582798076118742935459828744886802843487551551606246519220146369990307779]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 154 cx = sel3s([e[462], e[463], e[464]], [5093610893249308867168031458336741939196884648123926997975341654608609426830 , 12248279767532955250746877738475030196514076889129781370472666862024900770669, 5043009492124624507652527263244758360087085758651362799261288863076362039187, 16591909200159417412409462652077399999824413751859530227695887196356321679228]) cy = sel2([e[462], e[463]], [10952612598118313917631759693602817846928839860096429550603703046117049639522 , 2884939241145303979172401496138136665819626424676215132904685536232137032921, 21092145374321584925227081195844245213760374840107123770724422721835988876958, 5499840197627421265036310285493143039360364243394878011782966367266344217732]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 155 cx = sel3s([e[465], e[466], e[467]], [3794104339739491010449122661216407115137782001618163380131794160705537757426 , 7514419529276933284458458535371966876401883528785013067210805765651582633130, 2534189532451386749189970776179117832798970009395742348348119108287813471216, 5610243014937776775874159841646817951854662385825951664842167532212856045068]) cy = sel2([e[465], e[466]], [12842968623255283384772731210441087433561383555541999360200972373794310794093 , 10823437952973686303915120116380996262045441725571077692704581218749963605907, 21253964658659775229061107104903539871763760188604842330476347939642955209002, 1745535366815989039402026181267179197840739481539734000808670009580269211142]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 156 cx = sel3s([e[468], e[469], e[470]], [3459245219635302288341483992140272707638915493010622274381776793623419230591 , 9849021255480129732487752167924340739614806540698786580158805033907788030853, 3255308487469886623287718398314898379309460957968181729113829918571419337145, 15359614079733122216507425018253600855203543497608695539122606260839625565617]) cy = sel2([e[468], e[469]], [17415928452277952995861857592997544802223350915817518744596816398543561612106 , 9999856236606156376100952785476675300524456948913069129769906530665355058037, 17734497746752242925262857913765409819203458581088950917188119245918082092030, 6881580842463060802624074515204787264906621652045323766233447264566499944530]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 157 cx = sel3s([e[471], e[472], e[473]], [634964597278986129282215293208138156361395902716873910540311662219517773576 , 310253852479958835592393232442887907344502522183801152945448588489452412569, 384881480274621505303330466062621612997526527075542749162723700081976881288, 11767445114097831765826464678890553621483551558949563523534328471079851963281]) cy = sel2([e[471], e[472]], [17203635141310737823252743409317633065422478971915442288649227045499339781109 , 2545094457118912372548408336893899649182443951551613850781196845141738637170, 8609139198776064973664903858401535131314034007074283879284230416121615542308, 20092107484372320312567981037155807130829118997137612522175958096520972507336]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 158 cx = sel3s([e[474], e[475], e[476]], [20098437969178934435495041700635313630962028038875583770224318127835756299529 , 311104306589906971684844795811359683864786473908061989245919427082915904714, 5007249687217418940511624233021226494914521342148545152148356064906320432035, 9785851145981523672688289938894315309424412779439726667571213830109657407900]) cy = sel2([e[474], e[475]], [877613904095171787446316454384924363436490179245069691113043218080238972652 , 15255392602742007855606168874483544819258797919038984937824266131810915403967, 3482868076428758563707184390706074120455579821747810434457575250407348632455, 5737555899585712614112644175034540180519345050397396205967955592318835422324]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 159 cx = sel3s([e[477], e[478], e[479]], [17889638686175315317941901427709143202478522471798280927986774735210637820526 , 4586587171981050785204495209615167868746399227792813638212786811256473778221, 1864752565757236746122736751796835904389046064841800598816325031089096557478, 13943403942544820674673437343502779310324858400636923221774342029216604251440]) cy = sel2([e[477], e[478]], [17728898667133884634264046347611298588924985692465583707491826367590591819161 , 18365428070394378833051912713200271982753415548931989923757430748929339745094, 13355801165885814561827651110098104649674895992244923613944279081535896494292, 12718254346735593182641856097514926990330253814732909832265502852628068735026]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 160 cx = sel3s([e[480], e[481], e[482]], [17159516188699622404527134263356371503443962451842558111890221401200764258125 , 19697000438877661546696672369476849653861527230741461549059757921200307256689, 8082602544025295110701438493605046299287009032703969632384937719700791606339, 5936552380580117855548116310401989958728171511356588061450350806482980900531]) cy = sel2([e[480], e[481]], [288697205606498046198642124865852628925547477970007319079115715396675917499 , 11438994931015502912944770174743669059446783563412696311667974558402876489825, 2713576975757110627428489368530113978475830565467996635364633792472336700891, 20023822454992925006561366839036620580908513505208980493011483098957399405656]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 161 cx = sel3s([e[483], e[484], e[485]], [11476903323853344813827041345787850966667514952865946400953029235796901464022 , 15662688482882450089332164944545567115920791913333567306810233998084574572841, 16165244090421658682362860955446523155721204004465368156540492359518946703685, 13233236504179066734589049314166320998745790229936719431495551951291164368688]) cy = sel2([e[483], e[484]], [21544495907681885621399294493301860022991247894450553860102494438499516461036 , 15070356063300726246376329439697612629246560015487953180041607494107482212328, 10932308314438454016363769449242767120417784090441698745502660483728820506459, 15142440904746497443767345573381088273730091577283493618193631903901402378371]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 162 cx = sel3s([e[486], e[487], e[488]], [6740469135284996394159167279126920754449900660887428959259136317440159292867 , 1951789672920637712186229138057234008172951294439716801691622239946406362446, 10614706090196653889949286489862565736131644495539213256761186995450585212820, 20219336380099606710973890974478494924791931389585459347005405927908068729651]) cy = sel2([e[486], e[487]], [12559437556228574824459283742977065667884462966124147526010574650373707978536 , 11353250997656326728675199688614508617263787972463605193791786351817731868528, 9955679877407075213882986027032271351625902587325271136145291798547578901197, 7587664180577472344145946155058239620135123893989614056504418351234639990359]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 163 cx = sel3s([e[489], e[490], e[491]], [11683193590608313373089435698057644614965227085254736967478627707109364481009 , 5373593679075319624506848608700634791297845735799356231319125589754901432010, 14330496678432059141319543266495924665988744049796260830269932610430618839231, 16147138941500612947680025577703299264094926996519490683694344514795650552030]) cy = sel2([e[489], e[490]], [14089407095672561058133609212857713657125336981293206062798215054918146117895 , 5921405729554308485753035966317904019193857886291312338471036342984958996974, 14219166018565381341875979253176613205499868708487414627746489465729919459602, 9173206043848059861761039827886516664018988512989876666692360758637877840001]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 164 cx = sel3s([e[492], e[493], e[494]], [12391241461796318677666973225906912103063953603374991439355987755433936571792 , 11342324255021537810533271600486943249554637261483201032733188357979300928906, 6762143596567875242093282841823575455167081327592834568853990326935018728741, 1729094316763263611553329689516612131095524285732807879509329720064037980971]) cy = sel2([e[492], e[493]], [6256323253756510425990684148198273229283967340029341825763386143854418092931 , 608479563301898577121898469798459144789668559311173727644698121661161535370, 16118965412641868779259712849902459712114606105053804845952965420804403776265, 5207196556914412218334602277590189653542873808697180315162104560234636073976]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 165 cx = sel3s([e[495], e[496], e[497]], [12090834415198821488072985841187199896460619427268475889346428879276625683876 , 20435352555053416469114817994605784220258558984767053371686545934216871498097, 7919766463107746640570694574991853522177141706128568812747727580994437010928, 18791819403195060520893758220974368558662433382958799315116210085990602330263]) cy = sel2([e[495], e[496]], [11186634643432676423242372187246648742599522445001126220151236883458565017089 , 730264789631663387855933585769199256797088038637783970560657523730947722943, 9789319816975923274967045544277604801648452652703289939384714401867885689451, 20390569650377326057430918388837541684089995685084097630788684319064176189296]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 166 cx = sel3s([e[498], e[499], e[500]], [9073477014345643942359994649331122800736234440180113066690071117218958686221 , 17848891043122277658033397684650904021333601784635518417727821688552518594475, 8394455238188958480130266174842497177830879983439478526032000789572056999540, 3969215253795918818810265899749520158876595254756141389552909935321879395990]) cy = sel2([e[498], e[499]], [15421230006761899572959376594938017439120427450367920423701622807634638005218 , 691759570775251457416249989322179808019152722619656278259527490301863241777, 19687896560656750069557210923004770524699515901561346847457425701096560281307, 13013403796046695153969709190889488389508063704805702465177729278466953096077]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 167 cx = sel3s([e[501], e[502], e[503]], [17605212659450062681090282709904508607567301109002577655966314961623397498778 , 20706453518066591671344075213608634140534260809172831962434708646209603184096, 20530641835252913976176823270868884490574732596806683216254892843407024651486, 19512520336574558609801187648395617364107060095538444150298099264798316486399]) cy = sel2([e[501], e[502]], [18088283300102077232647028354145534410326244238430555546504288886091850910025 , 19624767204537830958950503358240075916787006780432673880401115874844576604739, 13389739174441700308398229420122777340874705736681526274430502297758537243393, 2768660518118504029156154123602101814256009402463064802144883490594220059578]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 168 cx = sel3s([e[504], e[505], e[506]], [3898901470837850662399020072718316987511815396623761376502150466549773974269 , 20681259404330431411774484706350104535474957110888110413896201115382255532278, 12146860081497614316907871444885755439616687087776665508013517962132514932126, 10103366418676857183019670163194546750004223272088526675082633522057697832251]) cy = sel2([e[504], e[505]], [18552945270636575492780160887690665046683842994616480518496617903497833044944 , 16280318807141467057522946128901953503954886894473765482004622686048871784896, 16511259671446150110679883995503700110523460228865394020432354340848786592304, 11820015885519382016829607197866756084707670961286078960070207041832708513141]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 169 cx = sel3s([e[507], e[508], e[509]], [6124403322044682705571649214069113177521499060664580284884665715951975035077 , 3806547960677312456106393355578152447583324120952390972170284549005371006887, 12796416634735923176681417392847285391386920336707070519873332365264500996292, 18113312677912280033934533469627761267183403533244965210112870702471687667512]) cy = sel2([e[507], e[508]], [18191174947339798787646910619446409943766046946921136035021645191602921923040 , 16559060177998758852323304784771936179434931576336411584121379336820727372618, 13858115732979799183025726471151602712224733686530960054365665740611187232029, 9933192519609817862698304326029579651414877338671776883175639003837130283966]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) //Round 170 cx = sel3s([e[510], e[511], e[512]], [3342564788366736273905106071612128667477972061160313630133110787799686301495 , 13766193863701503939885263345152684798552605679140222504700163745347162493183, 18523279471468319520962369406962457727155204375043681943707151819380964978377, 8094164074569624021939357073285075790695279643883973800173037824312344195506]) cy = sel2([e[510], e[511]], [2329094643034533408459502544740928833981119919633412709248656884170940780093 , 3216329736050668550647765981020076413548845117352735257893224753954595290363, 18710403072495673647060422294369054840513840567808020912157404388689648711093, 9785201456176703812798077455183487364035650707229293534561747881523562553649]) - a = add(a, [cx, cy], context) + a = add(a, [cx, cy], BABYJUBJUB_PARAMS) return edwardsCompress(a) diff --git a/zokrates_stdlib/stdlib/hashes/poseidon/constants.zok b/zokrates_stdlib/stdlib/hashes/poseidon/constants.zok index 5c8040a02..c54a0685c 100644 --- a/zokrates_stdlib/stdlib/hashes/poseidon/constants.zok +++ b/zokrates_stdlib/stdlib/hashes/poseidon/constants.zok @@ -1,5 +1,4 @@ -def poseidon_c() -> field[6][497]: - return [ +const field[6][497] POSEIDON_C = [ [ 4417881134626180770308697923359573201005643519861877412381846989312604493735, 5433650512959517612316327474713065966758808864213826738576266661723522780033, @@ -1843,8 +1842,7 @@ def poseidon_c() -> field[6][497]: ] ] -def poseidon_m() -> field[6][7][7]: - return [ +const field[6][7][7] POSEIDON_M = [ [ [ 2910766817845651019878574839501801340070030115151021261302834310722729507541, diff --git a/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok b/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok index 351a4bb45..62c8903d0 100644 --- a/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok +++ b/zokrates_stdlib/stdlib/hashes/poseidon/poseidon.zok @@ -1,7 +1,6 @@ // https://eprint.iacr.org/2019/458.pdf -from "./constants.zok" import poseidon_c -from "./constants.zok" import poseidon_m +from "./constants.zok" import POSEIDON_C, POSEIDON_M def ark(field[N] state, field[497] c, u32 it) -> field[N]: for u32 i in 0..N do @@ -42,8 +41,8 @@ def main(field[N] inputs) -> field: // and we do not want callers passing down constants. // This should be revisited once compiler limitations are gone. - field[497] c = poseidon_c()[t - 2] - field[7][7] m = poseidon_m()[t - 2] + field[497] c = POSEIDON_C[t - 2] + field[7][7] m = POSEIDON_M[t - 2] field[t] state = [0; t] for u32 i in 1..t do diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok index 4d1c1b608..9cead0afd 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok @@ -5,5 +5,4 @@ import "./sha256" as sha256 // Note: no padding is applied def main(u32[8] a, u32[8] b) -> u32[8]: - - return sha256([[...a, ...b]]) + return sha256([[...a, ...b]]) \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok index 8e7fb6fad..55d5ae8f6 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok @@ -1,6 +1,7 @@ import "../../utils/pack/u32/pack128" as pack128 import "../../utils/pack/u32/unpack128" as unpack128 import "./512bitPadded" as sha256 + // A function that takes an array of 4 field elements as input, unpacks each of them to 128 // bits (big endian), concatenates them and applies sha256. // It then returns an array of two field elements, each representing 128 bits of the result. diff --git a/zokrates_stdlib/stdlib/hashes/sha256/IVconstants.zok b/zokrates_stdlib/stdlib/hashes/sha256/IVconstants.zok deleted file mode 100644 index 5d5f558af..000000000 --- a/zokrates_stdlib/stdlib/hashes/sha256/IVconstants.zok +++ /dev/null @@ -1,4 +0,0 @@ -// SHA-256 is specified in FIPS 180-3 and initial values are listed in section 5.3.3 -// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf -def main() -> u32[8]: - return [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19] diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok index 655925898..b7253006c 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -7,10 +7,44 @@ def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): // Hash is computed on the full 1024bit block size // padding does not fit in the first two blocks // add dummy block (single "1" followed by "0" + total length) - bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] - // total length of message is 1024 bits: 0b10000000000 - bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false] + bool[256] dummyblock1 = [ + true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false + ] - bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) + // Total length of message is 1024 bits: 0b10000000000 + bool[256] dummyblock2 = [ + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false + ] + bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok index 89620056f..52b666d8a 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -7,24 +7,24 @@ def main(bool[256] a) -> (bool[256]): // Hash is computed on 256 bits of input // padding fits in the remaining 256 bits of the first block // add dummy block (single "true" followed by "false" + total length) - bool[256] dummyblock1 = [ \ - true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, \ - false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false] + bool[256] dummyblock1 = [ + true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false + ] bool[256] digest = sha256(a, dummyblock1) - return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok index a05d4a709..75680ca8f 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok @@ -3,13 +3,8 @@ import "./shaRoundNoBoolCheck" as sha256 // A function that takes 2 bool[256] arrays as inputs // and returns their sha256 compression function as an array of 256 bool. -// In contrast to full_round.zok no padding is being applied +// No padding is being applied def main(bool[256] a, bool[256] b) -> (bool[256]): - - // a and b is NOT checked to be of type bool - bool[256] IV = IVconstants() bool[256] digest = sha256(a, b, IV) - //digest is constraint to be of type bool - return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok index 7c1959154..2aba8c2a3 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -7,11 +7,44 @@ def main(bool[256] a, bool[256] b) -> (bool[256]): // Hash is computed on the full 512bit block size // padding does not fit in the primary block // add dummy block (single "1" followed by "0" + total length) - bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] dummyblock1 = [ + true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false + ] - // total length of message is 512 bits: 0b1000000000 - bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false] + // Total length of message is 512 bits: 0b1000000000 + bool[256] dummyblock2 = [ + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false + ] bool[256] digest = sha256(a, b, dummyblock1, dummyblock2) - return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/sha256.zok b/zokrates_stdlib/stdlib/hashes/sha256/sha256.zok index cf067e486..e50afe5b9 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/sha256.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/sha256.zok @@ -1,14 +1,19 @@ -import "./IVconstants" as IVconstants import "./shaRound" as shaRound -// A function that takes K u32[8] arrays as inputs, concatenates them, +// Initial values, FIPS 180-3, section 5.3.3 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +const u32[8] IV = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +] + +// A function that takes N u32[8] arrays as inputs, concatenates them, // and returns their sha256 compression as a u32[8]. // Note: no padding is applied +def main(u32[N][16] a) -> u32[8]: + u32[8] current = IV -def main(u32[K][16] a) -> u32[8]: - u32[8] current = IVconstants() - - for u32 i in 0..K do + for u32 i in 0..N do current = shaRound(a[i], current) endfor diff --git a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok index c06080d4c..182f70cf4 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok @@ -1,4 +1,15 @@ -import "./IVconstants.zok" +// FIPS 180-3, section 4.2.2 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +const u32[64] K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +] def rotr32(u32 x) -> u32: return (x >> N) | (x << (32 - N)) @@ -31,7 +42,6 @@ def temp2(u32 a, u32 b, u32 c) -> u32: // A function that computes one round of the SHA256 compression function given an input and the current value of the hash // this is used by other components however many times needed def main(u32[16] input, u32[8] current) -> u32[8]: - u32 h0 = current[0] u32 h1 = current[1] u32 h2 = current[2] @@ -41,9 +51,7 @@ def main(u32[16] input, u32[8] current) -> u32[8]: u32 h6 = current[6] u32 h7 = current[7] - u32[64] k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2] - - u32[64] w = [...input, ...[0x00000000; 48]] + u32[64] w = [...input, ...[0u32; 48]] for u32 i in 16..64 do w[i] = extend(w, i) @@ -59,9 +67,7 @@ def main(u32[16] input, u32[8] current) -> u32[8]: u32 h = h7 for u32 i in 0..64 do - - u32 t1 = temp1(e, f, g, h, k[i], w[i]) - + u32 t1 = temp1(e, f, g, h, K[i], w[i]) u32 t2 = temp2(a, b, c) h = g @@ -72,7 +78,6 @@ def main(u32[16] input, u32[8] current) -> u32[8]: c = b b = a a = t1 + t2 - endfor h0 = h0 + a diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok index cfdd1ffcf..dca703cef 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.zok @@ -1,15 +1,13 @@ import "ecc/edwardsAdd" as add import "ecc/edwardsNegate" as neg -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS // Code to create test cases: // https://github.com/Zokrates/pycrypto def testDoubleViaAdd() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] - field[2] out = add(G, G, context) + field[2] out = add(G, G, BABYJUBJUB_PARAMS) assert(out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830) assert(out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831) @@ -17,14 +15,13 @@ def testDoubleViaAdd() -> bool: return true def testIdentities() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] - field[2] inf = context.INFINITY + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] + field[2] inf = BABYJUBJUB_PARAMS.INFINITY - assert(G == add(G, inf, context)) + assert(G == add(G, inf, BABYJUBJUB_PARAMS)) field[2] nG = neg(G) - field[2] nGaddG = add(G, nG, context) + field[2] nGaddG = add(G, nG, BABYJUBJUB_PARAMS) assert(inf == nGaddG) diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok index 06f5dfe3b..74282bd72 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.zok @@ -1,14 +1,11 @@ import "ecc/edwardsCompress" as edwardsCompress -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS // Code to create test cases: // https://github.com/Zokrates/pycrypto def testCompress() -> bool: - BabyJubJubParams context = context() - - field Gu = context.Gu - field Gv = context.Gv + field Gu = BABYJUBJUB_PARAMS.Gu + field Gv = BABYJUBJUB_PARAMS.Gv bool[256] Gcompressed = edwardsCompress([Gu, Gv]) diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok index 6738162a2..f5a50a504 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.zok @@ -1,16 +1,13 @@ -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS import "ecc/edwardsOnCurve" as onCurve // Code to create test cases: // https://github.com/Zokrates/pycrypto def testOnCurveTrue() -> bool: - BabyJubJubParams context = context() - field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830 field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831 - assert(onCurve([testU, testV], context)) + assert(onCurve([testU, testV], BABYJUBJUB_PARAMS)) return true diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok index 3a719fe01..9f310cc67 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.zok @@ -1,27 +1,22 @@ import "ecc/edwardsOrderCheck" as orderCheck -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS // Code to create test cases: // https://github.com/Zokrates/pycrypto def testOrderCheckTrue() -> bool: - BabyJubJubParams context = context() - field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830 field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831 - bool out = orderCheck([testU, testV], context) + bool out = orderCheck([testU, testV], BABYJUBJUB_PARAMS) assert(out) return true def testOrderCheckFalse() -> bool: - BabyJubJubParams context = context() - field testU = 4342719913949491028786768530115087822524712248835451589697801404893164183326 field testV = 4826523245007015323400664741523384119579596407052839571721035538011798951543 - bool out = orderCheck([testU, testV], context) + bool out = orderCheck([testU, testV], BABYJUBJUB_PARAMS) assert(!out) return true diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok index fd494c904..d246641ed 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok +++ b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.zok @@ -1,29 +1,26 @@ -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS import "ecc/edwardsScalarMult" as mul // Code to create test cases: // https://github.com/Zokrates/pycrypto def testCyclic() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] // exp = JUBJUB_E + 1 bool[256] exp = [false, false, true, true, false, false, false, false, false, true, true, false, false, true, false, false, false, true, false, false, true, true, true, false, false, true, true, true, false, false, true, false, true, true, true, false, false, false, false, true, false, false, true, true, false, false, false, true, true, false, true, false, false, false, false, false, false, false, true, false, true, false, false, true, true, false, true, true, true, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, true, true, false, true, true, false, true, true, false, true, false, false, false, false, false, false, true, true, false, false, false, false, false, false, true, false, true, false, true, true, false, false, false, false, true, false, true, true, true, false, true, false, true, false, true, true, false, false, true, true, true, true, true, false, true, true, true, false, true, true, false, true, true, false, true, true, true, false, false, false, false, false, true, true, true, false, false, true, false, false, true, false, false, false, false, false, true, true, true, false, true, true, true, false, false, false, false, false, true, false, true, false, false, true, true, false, false, true, true, true, false, true, true, true, false, false, true, false, true, false, false, true, false, true, true, true, true, true, false, true, true, true, false, false, false, false, true, true, true, false, false, true, false, false, true, false, false, false, false, true, false, false, true, false, false, true, true, false, true, true, true, true, false, false, false, true, false, false, true] - field[2] out = mul(exp, G, context) + field[2] out = mul(exp, G, BABYJUBJUB_PARAMS) assert(G == out) return true def testMul2() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] // exp == 2 bool[256] exp = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false] - field[2] out = mul(exp, G, context) + field[2] out = mul(exp, G, BABYJUBJUB_PARAMS) assert(out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830) assert(out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831) @@ -31,8 +28,7 @@ def testMul2() -> bool: return true def testAssociativity() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] // a = 1234 bool[256] a = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, true, false, true, false, false, true, false] @@ -43,17 +39,17 @@ def testAssociativity() -> bool: bool[256] c = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, true, false, true, false, false, true, false] - field[2] Ga = mul(a, G, context) - field[2] Gab = mul(b, Ga, context) - field[2] Gabc = mul(c, Gab, context) + field[2] Ga = mul(a, G, BABYJUBJUB_PARAMS) + field[2] Gab = mul(b, Ga, BABYJUBJUB_PARAMS) + field[2] Gabc = mul(c, Gab, BABYJUBJUB_PARAMS) - field[2] Gb = mul(b, G, context) - field[2] Gbc = mul(c, Gb, context) - field[2] Gbca = mul(a, Gbc, context) + field[2] Gb = mul(b, G, BABYJUBJUB_PARAMS) + field[2] Gbc = mul(c, Gb, BABYJUBJUB_PARAMS) + field[2] Gbca = mul(a, Gbc, BABYJUBJUB_PARAMS) - field[2] Gc = mul(c, G, context) - field[2] Gca = mul(a, Gc, context) - field[2] Gcab = mul(b, Gca, context) + field[2] Gc = mul(c, G, BABYJUBJUB_PARAMS) + field[2] Gca = mul(a, Gc, BABYJUBJUB_PARAMS) + field[2] Gcab = mul(b, Gca, BABYJUBJUB_PARAMS) assert(Gabc == Gbca) assert(Gbca == Gcab) @@ -62,8 +58,7 @@ def testAssociativity() -> bool: return true def testMultiplicative() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] // a = 1234 bool[256] a = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, true, false, true, false, false, true, false] @@ -73,13 +68,13 @@ def testMultiplicative() -> bool: // ab = a*b = 7006652 bool[256] ab = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, true, false, true, false, true, true, true, false, true, false, false, true, true, false, true, true, true, true, false, false] - field[2] Ga = mul(a, G, context) - field[2] Gb = mul(b, G, context) + field[2] Ga = mul(a, G, BABYJUBJUB_PARAMS) + field[2] Gb = mul(b, G, BABYJUBJUB_PARAMS) - field[2] Gab = mul(b, Ga, context) - field[2] Gba = mul(a, Gb, context) + field[2] Gab = mul(b, Ga, BABYJUBJUB_PARAMS) + field[2] Gba = mul(a, Gb, BABYJUBJUB_PARAMS) - field[2] Gmab = mul(ab, G, context) + field[2] Gmab = mul(ab, G, BABYJUBJUB_PARAMS) assert(Gab == Gba) assert(Gba == Gmab) diff --git a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok index 0facb911b..5d94dd0bc 100644 --- a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok +++ b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.zok @@ -1,28 +1,24 @@ -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS import "ecc/proofOfOwnership" as proofOfOwnership import "ecc/edwardsScalarMult" as multiply // Code to create test cases: // https://github.com/Zokrates/pycrypto def testOwnershipTrue() -> bool: - BabyJubJubParams context = context() - field[2] G = [context.Gu, context.Gv] + field[2] G = [BABYJUBJUB_PARAMS.Gu, BABYJUBJUB_PARAMS.Gv] field[2] Pk = [14897476871502190904409029696666322856887678969656209656241038339251270171395, 16668832459046858928951622951481252834155254151733002984053501254009901876174] field sk = 1997011358982923168928344992199991480689546837621580239342656433234255379025 - bool out = proofOfOwnership(Pk, sk, context) + bool out = proofOfOwnership(Pk, sk, BABYJUBJUB_PARAMS) assert(out) return true def testtOwnershipFalse() -> bool: - BabyJubJubParams context = context() - field[2] Pk = [16328093915569409528980874702678312730273137210288183490878184636452430630129, 9377227749598842756429258362864743065769435972445705966557343775367597326529] field sk = 1997011358982923168928344992199991480689546837621580239342656433234255379025 - bool out = proofOfOwnership(Pk, sk, context) + bool out = proofOfOwnership(Pk, sk, BABYJUBJUB_PARAMS) assert(!out) return true diff --git a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.zok b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.zok index e0316ea8d..e37415f9c 100644 --- a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.zok +++ b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.zok @@ -1,4 +1,4 @@ import "hashes/mimcSponge/mimcFeistel" as mimcFeistel def main(field a, field b, field c) -> field[2]: - return mimcFeistel(a, b, c) \ No newline at end of file + return mimcFeistel(a, b, c) \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.zok b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.zok index decdfeed9..4924b8dfa 100644 --- a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.zok +++ b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.zok @@ -1,6 +1,14 @@ import "hashes/mimcSponge/mimcSponge" as mimcSponge def main(): - assert(mimcSponge([1,2], 3) == [20225509322021146255705869525264566735642015554514977326536820959638320229084,13871743498877225461925335509899475799121918157213219438898506786048812913771,21633608428713573518356618235457250173701815120501233429160399974209848779097f]) - assert(mimcSponge([0,0], 0) == [20636625426020718969131298365984859231982649550971729229988535915544421356929,6046202021237334713296073963481784771443313518730771623154467767602059802325,16227963524034219233279650312501310147918176407385833422019760797222680144279f]) - return \ No newline at end of file + assert(mimcSponge::<2, 3>([1, 2], 3) == [ + 20225509322021146255705869525264566735642015554514977326536820959638320229084, + 13871743498877225461925335509899475799121918157213219438898506786048812913771, + 21633608428713573518356618235457250173701815120501233429160399974209848779097 + ]) + assert(mimcSponge::<2, 3>([0, 0], 0) == [ + 20636625426020718969131298365984859231982649550971729229988535915544421356929, + 6046202021237334713296073963481784771443313518730771623154467767602059802325, + 16227963524034219233279650312501310147918176407385833422019760797222680144279 + ]) + return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok index fe71adb7d..9229ef548 100644 --- a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok +++ b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.zok @@ -1,13 +1,9 @@ import "signatures/verifyEddsa" as verifyEddsa -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS // Code to create test case: // https://github.com/Zokrates/pycrypto def main(): - - BabyJubJubParams context = context() - field[2] R = [20197911405516193152560090893341588680064377398162745404177962124159545390767, 9171190326927340493105240100684097896571028312802691203521747450053192554927] field S = 6050429445242986634735172402304257690628456074852538287769363221635064371045 @@ -17,7 +13,7 @@ def main(): u32[8] M0 = [0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000] u32[8] M1 = [0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000005] - bool isVerified = verifyEddsa(R, S, A, M0, M1, context) + bool isVerified = verifyEddsa(R, S, A, M0, M1, BABYJUBJUB_PARAMS) assert(isVerified) return \ No newline at end of file From aba16cdc8bf1f92b239dd2c11ef79921673064a7 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 14 Jul 2021 14:10:16 +0200 Subject: [PATCH 07/86] use field constants to avoid curve dependant code --- .../runtime_errors/lt_overflow_max_plus_1.zok | 11 +++++------ .../runtime_errors/lt_overflow_p_minus_one.zok | 4 +++- zokrates_cli/examples/test_lt_max_value.zok | 7 +++---- zokrates_core_test/tests/tests/native_le.zok | 12 ++++-------- zokrates_core_test/tests/tests/split.zok | 6 ++++++ zokrates_core_test/tests/tests/split_bls.json | 2 +- zokrates_core_test/tests/tests/split_bls.zok | 7 ------- zokrates_core_test/tests/tests/split_bn.json | 2 +- zokrates_core_test/tests/tests/split_bn.zok | 7 ------- 9 files changed, 23 insertions(+), 35 deletions(-) create mode 100644 zokrates_core_test/tests/tests/split.zok delete mode 100644 zokrates_core_test/tests/tests/split_bls.zok delete mode 100644 zokrates_core_test/tests/tests/split_bn.zok diff --git a/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok b/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok index d4affb1c1..5011c2112 100644 --- a/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok +++ b/zokrates_cli/examples/runtime_errors/lt_overflow_max_plus_1.zok @@ -1,12 +1,11 @@ -#pragma curve bn128 +from "field" import FIELD_SIZE_IN_BITS // we can compare numbers up to 2^(pbits - 2) - 1, ie any number which fits in (pbits - 2) bits // It should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one // /!\ should be called with a = 0 def main(field a) -> bool: - field pbits = 254 - // maxvalue = 2**252 - 1 - field maxvalue = a + 7237005577332262213973186563042994240829374041602535252466099000494570602496 - 1 - // we added a = 0 to prevent the condition to be evaluated at compile time - return a < (maxvalue + 1) \ No newline at end of file + u32 pbits = FIELD_SIZE_IN_BITS + // we added a = 0 to prevent the condition to be evaluated at compile time + field maxvalue = a + (2**(pbits - 2) - 1) + return a < (maxvalue + 1) \ No newline at end of file diff --git a/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok b/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok index e0b5d7751..6703cecc4 100644 --- a/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok +++ b/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok @@ -1,7 +1,9 @@ +from "field" import FIELD_MAX + // as p - 1 is greater than p/2, comparing to it should fail // /!\ should be called with a = 0 def main(field a) -> bool: - field p = 21888242871839275222246405745257275088548364400416034343698204186575808495616 + a + field p = FIELD_MAX + a // we added a = 0 to prevent the condition to be evaluated at compile time return a < p \ No newline at end of file diff --git a/zokrates_cli/examples/test_lt_max_value.zok b/zokrates_cli/examples/test_lt_max_value.zok index c2b97966d..087cf9275 100644 --- a/zokrates_cli/examples/test_lt_max_value.zok +++ b/zokrates_cli/examples/test_lt_max_value.zok @@ -1,10 +1,9 @@ -#pragma curve bn128 +from "field" import FIELD_SIZE_IN_BITS // we can compare numbers up to 2^(pbits - 2) - 1, ie any number which fits in (pbits - 2) bits // lt should work for the maxvalue = 2^(pbits - 2) - 1 def main(field a) -> bool: - field pbits = 254 - // maxvalue = 2**252 - 1 - field maxvalue = 7237005577332262213973186563042994240829374041602535252466099000494570602496 - 1 + u32 pbits = FIELD_SIZE_IN_BITS + field maxvalue = 2**(pbits - 2) - 1 return 0 < maxvalue \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/native_le.zok b/zokrates_core_test/tests/tests/native_le.zok index d1f50437e..95ec21f4e 100644 --- a/zokrates_core_test/tests/tests/native_le.zok +++ b/zokrates_core_test/tests/tests/native_le.zok @@ -1,5 +1,6 @@ from "utils/pack/bool/unpack.zok" import main as unpack from "utils/casts/u32_to_bits" import main as u32_to_bits +from "field" import FIELD_MAX, FIELD_SIZE_IN_BITS // this comparison works for any N smaller than the field size, which is the case in practice def le(bool[N] a_bits, bool[N] c_bits) -> bool: @@ -17,11 +18,9 @@ def le(bool[N] a_bits, bool[N] c_bits) -> bool: return verified_conditions == N // this checks that all conditions were verified -// this instanciates comparison starting from field elements +// this instantiates comparison starting from field elements def le(field a, field c) -> bool: - - field MAX = 21888242871839275222246405745257275088548364400416034343698204186575808495616 - bool[N] MAX_BITS = unpack::(MAX) + bool[N] MAX_BITS = unpack::(FIELD_MAX) bool[N] a_bits = unpack(a) assert(le(a_bits, MAX_BITS)) @@ -38,10 +37,7 @@ def le(u32 a, u32 c) -> bool: return le(a_bits, c_bits) def main(field a, u32 b) -> (bool, bool): - - u32 N = 254 field c = 42 - u32 d = 42 - return le::(a, c), le(b, d) \ No newline at end of file + return le::(a, c), le(b, d) \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/split.zok b/zokrates_core_test/tests/tests/split.zok new file mode 100644 index 000000000..4bc9707b6 --- /dev/null +++ b/zokrates_core_test/tests/tests/split.zok @@ -0,0 +1,6 @@ +from "EMBED" import unpack +from "field" import FIELD_SIZE_IN_BITS + +def main(field a) -> bool[FIELD_SIZE_IN_BITS]: + bool[FIELD_SIZE_IN_BITS] b = unpack(a) + return b \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/split_bls.json b/zokrates_core_test/tests/tests/split_bls.json index ee9ce853d..5d4dd9811 100644 --- a/zokrates_core_test/tests/tests/split_bls.json +++ b/zokrates_core_test/tests/tests/split_bls.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/split_bls.zok", + "entry_point": "./tests/tests/split.zok", "curves": ["Bls12_381"], "tests": [ { diff --git a/zokrates_core_test/tests/tests/split_bls.zok b/zokrates_core_test/tests/tests/split_bls.zok deleted file mode 100644 index fbf59197f..000000000 --- a/zokrates_core_test/tests/tests/split_bls.zok +++ /dev/null @@ -1,7 +0,0 @@ -from "EMBED" import unpack - -def main(field a) -> (bool[255]): - - bool[255] b = unpack(a) - - return b diff --git a/zokrates_core_test/tests/tests/split_bn.json b/zokrates_core_test/tests/tests/split_bn.json index 0fd9a5bc1..989427a7a 100644 --- a/zokrates_core_test/tests/tests/split_bn.json +++ b/zokrates_core_test/tests/tests/split_bn.json @@ -1,5 +1,5 @@ { - "entry_point": "./tests/tests/split_bn.zok", + "entry_point": "./tests/tests/split.zok", "curves": ["Bn128"], "tests": [ { diff --git a/zokrates_core_test/tests/tests/split_bn.zok b/zokrates_core_test/tests/tests/split_bn.zok deleted file mode 100644 index a33762fad..000000000 --- a/zokrates_core_test/tests/tests/split_bn.zok +++ /dev/null @@ -1,7 +0,0 @@ -from "EMBED" import unpack - -def main(field a) -> (bool[254]): - - bool[254] b = unpack(a) - - return b From 18d57a00124490e674455d79788a21e5567e0952 Mon Sep 17 00:00:00 2001 From: dark64 Date: Wed, 14 Jul 2021 15:37:26 +0200 Subject: [PATCH 08/86] run rng tutorial as a test --- zokrates_book/src/examples/rng_tutorial.md | 87 +++++++++---------- .../examples/book/rng_tutorial/test.sh | 32 +++++++ zokrates_cli/tests/integration.rs | 22 +++++ 3 files changed, 94 insertions(+), 47 deletions(-) create mode 100755 zokrates_cli/examples/book/rng_tutorial/test.sh diff --git a/zokrates_book/src/examples/rng_tutorial.md b/zokrates_book/src/examples/rng_tutorial.md index 05a5e54f6..53bf6aa27 100644 --- a/zokrates_book/src/examples/rng_tutorial.md +++ b/zokrates_book/src/examples/rng_tutorial.md @@ -32,13 +32,13 @@ There are many ways to calculate a hash, but here we use Zokrates. 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. ``` -zokrates compile -i get_hash.zok -o get_hash --ztf +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:6}} ``` 3. The input to the Zokrates program is sixteen 32 bit values, each in decimal. specify those values to get a hash. For example, to calculate the hash of `0x00000000000000010000000200000003000000040000000500000006...` use this command: ``` -zokrates compute-witness --verbose -i get_hash -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:7}} ``` The result is: ``` @@ -56,8 +56,8 @@ This line imports a Zokrates function from the [standard library](https://github You can see the specific function we are importing [here](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok). It will be called `sha256`. -```javascript -import "hashes/sha256/512bit" as sha256 +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:1}} ```   @@ -68,8 +68,8 @@ line parameter. The total number of input bits is *32 × 16 = 512*. The output is `u32[8]`, a *32 × 8 = 256* bit value. -```javascript -def main(u32[16] hashMe) -> u32[8]: +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:3}} ```   @@ -80,16 +80,16 @@ This variable is initialized using `sha256`, the function we The `sha256` function expects to get two arrays of eight values each, so we use a [slice `..`](https://zokrates.github.io/language/types.html#slices) to divide `hashMe` into two arrays. -```javascript - u32[8] h = sha256(hashMe[0..8], hashMe[8..16]) +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:4}} ```   Finally, return `h` to the caller to display the hash. -```javascript - return h +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:5}} ``` @@ -103,9 +103,8 @@ The next step is to reveal a single bit. ``` 2. Compile and run as you did the previous program: -```bash -zokrates compile -i reveal_bit.zok -o reveal_bit -zokrates compute-witness --verbose -i reveal_bit -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 510 +``` +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23:24}} ``` 3. The output should be similar to: ``` @@ -121,8 +120,8 @@ This line imports a function that converts a `u32` value to an array of 32 boole There are cast functions to convert `u8`s, `u16`s, and `u32`s to boolean arrays and back again, [you can see them here](https://github.com/Zokrates/ZoKrates/blob/master/zokrates_stdlib/stdlib/utils/casts). -```javascript -import "utils/casts/u32_to_bits" as u32_to_bits +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:2}} ```   @@ -132,8 +131,8 @@ The preimage is declared `private` so it won't be revealed by the zero knowledge A Zokrates function can return multiple values. In this case, it returns the hash and a boolean which is the value of the bit being revealed. -```javascript -def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool): +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:10}} ```   @@ -144,9 +143,8 @@ an array of 512 `false` values. The syntax `[; ]` initializes the copies of ``. It is necessary to include it here because a Zokrates variable must be initialized when it is declared. -```javascript - // Convert the secret to bits - bool[512] preimageBits = [false; 512] +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:11:12}} ```   @@ -154,40 +152,37 @@ when it is declared. This is a [for loop](https://zokrates.github.io/language/control_flow.html#for-loops). For loops have to have an index of type `u32`, and their bounds need to be known at compile time. In this case, we go over each of the sixteen 32 bit words. -```javascript - for u32 i in 0..16 do +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:13}} ``` The function we imported, `u32_to_bits`, converts a `u32` value to an array of bits. -```javascript - bool[32] val = u32_to_bits(preimage[i]) +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:14}} ```   The inner loop copies the bits from `val` to `preimageBits`, the bit array for the preimage. -```javascript - for u32 bit in 0..32 do - preimageBits[i*32+bit] = val[bit] - endfor - endfor +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:15:18}} ```   To return multiple values, separate them by commas. -```javascript - return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum] +```zokrates +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:20}} ``` ## Actually using zero knowledge proofs -The `reveal_bit.zok`program reveals a bit from the preimage, but who runs it? +The `reveal_bit.zok` program reveals a bit from the preimage, but who runs it? 1. If Alice runs the program, she can feed it her secret preimage and receive the correct result. However, when she sends the output there is no reason for Bob to trust that she is providing the correct output. @@ -204,34 +199,32 @@ Proofs give us. ### Bob's setup stage 2. Compile `reveal_bit.zok` and create the proving and verification keys. - ``` - zokrates compile -i reveal_bit.zok -o reveal_bit - zokrates setup -i reveal_bit - ``` +``` +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:16:17}} +``` 3. Copy the file `proving.key` to Alice's directory. ### Alice reveals a bit 4. Alice should compile `reveal_bit.zok` independently to make sure it doesn't disclose information she wants to keep secret. - ``` - zokrates compile -i reveal_bit.zok -o reveal_bit - ``` +``` +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23}} +``` 5. Next, Alice creates the `witness` file with the values of all the parameters in the program. Using this `witness`, Bob's `proving.key`, and the compiled program she generates the actual proof. - ``` - zokrates compute-witness -i reveal_bit -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 510 - zokrates generate-proof -i reveal_bit - ``` +``` +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:24:25}} +``` 6. The proof is created in the file `proof.json`. Copy this file to Bob's directory. ### Bob accepts the proof 7. Finally, Bob verifies the proof: - ``` - zokrates verify - ``` +``` +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:31}} +``` 8. As a sanity check, modify any of the values in `proof.json` and see that the verification fails. @@ -242,7 +235,7 @@ So far, Alice and Bob calculated the random bit between themselves. However, it published on the blockchain. To do this, Bob creates a Solidity program: ``` -zokrates export-verifier +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:32}} ``` The Solidity program is called `verifier.sol`. diff --git a/zokrates_cli/examples/book/rng_tutorial/test.sh b/zokrates_cli/examples/book/rng_tutorial/test.sh new file mode 100755 index 000000000..a352fb938 --- /dev/null +++ b/zokrates_cli/examples/book/rng_tutorial/test.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e + +alias zokrates=$1 + +zokrates compile -i get_hash.zok -o get_hash --ztf +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 + +cp reveal_bit.zok bob/reveal_bit.zok +cp reveal_bit.zok alice/reveal_bit.zok + +cd bob + +zokrates compile -i reveal_bit.zok -o reveal_bit +zokrates setup -i reveal_bit + +cd .. +cp bob/proving.key alice/proving.key + +cd alice +zokrates compile -i reveal_bit.zok -o reveal_bit +zokrates compute-witness --verbose -i reveal_bit -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 510 +zokrates generate-proof -i reveal_bit + +cd .. +cp alice/proof.json bob/proof.json + +cd bob +zokrates verify +zokrates export-verifier \ No newline at end of file diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 23afd3122..d8d46832e 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -404,4 +404,26 @@ mod integration { } } } + + #[test] + fn test_rng_tutorial() { + let tmp_dir = TempDir::new(".tmp").unwrap(); + let tmp_base = tmp_dir.path(); + + let dir = Path::new("./examples/book/rng_tutorial"); + let entries = std::fs::read_dir(dir) + .unwrap() + .map(|res| res.map(|e| e.path())) + .collect::, std::io::Error>>() + .unwrap(); + + entries.iter().for_each(|p| { + std::fs::copy(p, tmp_base.join(p.file_name().unwrap())).unwrap(); + }); + + assert_cli::Assert::command(&["./test.sh", env!("CARGO_BIN_EXE_zokrates")]) + .current_dir(tmp_base) + .succeeds() + .unwrap(); + } } From e5bcbed81f549cf8793956c1d06eca1bd6c811f0 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 10:44:44 +0200 Subject: [PATCH 09/86] refactor types, implement struct generics --- zokrates_abi/src/lib.rs | 4 + zokrates_core/src/compile.rs | 2 + zokrates_core/src/semantics.rs | 253 ++++++++++------- .../src/static_analysis/constant_inliner.rs | 61 ++--- .../static_analysis/flatten_complex_types.rs | 6 +- zokrates_core/src/static_analysis/mod.rs | 5 +- .../src/static_analysis/propagation.rs | 9 +- zokrates_core/src/typed_absy/abi.rs | 10 + zokrates_core/src/typed_absy/folder.rs | 11 +- zokrates_core/src/typed_absy/integer.rs | 259 ++++++++++++------ zokrates_core/src/typed_absy/mod.rs | 63 ++--- zokrates_core/src/typed_absy/result_folder.rs | 11 +- zokrates_core/src/typed_absy/types.rs | 153 +++++------ zokrates_core/src/typed_absy/variable.rs | 2 +- 14 files changed, 489 insertions(+), 360 deletions(-) diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index f828825e5..81e3fdfea 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -432,6 +432,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -453,6 +454,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -470,6 +472,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -487,6 +490,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 093031ec5..9f9919a84 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -417,11 +417,13 @@ struct Bar { field a } ty: ConcreteType::Struct(ConcreteStructType::new( "foo".into(), "Foo".into(), + vec![], vec![ConcreteStructMember { id: "b".into(), ty: box ConcreteType::Struct(ConcreteStructType::new( "bar".into(), "Bar".into(), + vec![], vec![ConcreteStructMember { id: "a".into(), ty: box ConcreteType::FieldElement diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 7487668e0..2dd02f017 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -20,7 +20,7 @@ use crate::parser::Position; use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; use crate::typed_absy::types::{ - check_type, specialize_type, ArrayType, DeclarationArrayType, DeclarationConstant, + check_type, specialize_declaration_type, ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationFunctionKey, DeclarationSignature, DeclarationStructMember, DeclarationStructType, DeclarationType, GenericIdentifier, StructLocation, StructMember, }; @@ -357,29 +357,34 @@ impl<'ast, T: Field> Checker<'ast, T> { state: &State<'ast, T>, ) -> Result, ErrorInner> { let pos = c.pos(); - let ty = self.check_type(c.value.ty.clone(), module_id, &state.types)?; + let ty = self.check_declaration_type( + c.value.ty.clone(), + module_id, + &state, + &HashMap::default(), + &mut HashSet::default(), + )?; let checked_expr = self.check_expression(c.value.expression.clone(), module_id, &state.types)?; match ty { - Type::FieldElement => { + DeclarationType::FieldElement => { FieldElementExpression::try_from_typed(checked_expr).map(TypedExpression::from) } - Type::Boolean => { + DeclarationType::Boolean => { BooleanExpression::try_from_typed(checked_expr).map(TypedExpression::from) } - Type::Uint(bitwidth) => { - UExpression::try_from_typed(checked_expr, bitwidth).map(TypedExpression::from) + DeclarationType::Uint(bitwidth) => { + UExpression::try_from_typed(checked_expr, &bitwidth).map(TypedExpression::from) } - Type::Array(ref array_ty) => { - ArrayExpression::try_from_typed(checked_expr, *array_ty.ty.clone()) - .map(TypedExpression::from) + DeclarationType::Array(ref array_ty) => { + ArrayExpression::try_from_typed(checked_expr, &array_ty).map(TypedExpression::from) } - Type::Struct(ref struct_ty) => { - StructExpression::try_from_typed(checked_expr, struct_ty.clone()) + DeclarationType::Struct(ref struct_ty) => { + StructExpression::try_from_typed(checked_expr, &struct_ty) .map(TypedExpression::from) } - Type::Int => Err(checked_expr), // Integers cannot be assigned + DeclarationType::Int => Err(checked_expr), // Integers cannot be assigned } .map_err(|e| ErrorInner { pos: Some(pos), @@ -391,7 +396,7 @@ impl<'ast, T: Field> Checker<'ast, T> { ty ), }) - .map(|e| TypedConstant::new(ty, e)) + .map(|e| TypedConstant::new(e)) } fn check_struct_type_declaration( @@ -1152,14 +1157,17 @@ impl<'ast, T: Field> Checker<'ast, T> { ), }), }, - TypedExpression::Int(v) => UExpression::try_from_int(v.clone(), UBitwidth::B32) - .map_err(|_| ErrorInner { - pos: Some(pos), - message: format!( + TypedExpression::Int(v) => { + UExpression::try_from_int(v.clone(), &UBitwidth::B32).map_err(|_| { + ErrorInner { + pos: Some(pos), + message: format!( "Expected array dimension to be a u32 constant, found {} of type {}", v, ty ), - }), + } + }) + } _ => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1194,33 +1202,38 @@ impl<'ast, T: Field> Checker<'ast, T> { DeclarationType::Struct(struct_type) => { match struct_type.generics.len() == generics.len() { true => { - let checked_generics = generics + // downcast the generics to identifiers, as this is the only possibility here + let generic_identifiers = struct_type.generics.iter().map(|c| { + match c.as_ref().unwrap() { + DeclarationConstant::Generic(g) => g.clone(), + _ => unreachable!(), + } + }); + + // build the generic assignment for this type + let assignment = GGenericsAssignment(generics .into_iter() - .map(|e| match e { - Some(e) => self + .zip(generic_identifiers) + .filter_map(|(e, g)| e.map(|e| { + self .check_expression(e, module_id, types) .and_then(|e| { - UExpression::try_from_typed(e, UBitwidth::B32) - .map(Some) + UExpression::try_from_typed(e, &UBitwidth::B32) + .map(|e| (g, e)) .map_err(|e| ErrorInner { pos: Some(pos), message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), }) - }), - None => Ok(None), - }) - .collect::>()?; - - Ok(Type::Struct(StructType { - canonical_location: struct_type.canonical_location, - location: struct_type.location, - generics: checked_generics, - members: struct_type - .members - .into_iter() - .map(|m| m.into()) - .collect(), - })) + }) + })) + .collect::>()?); + + // specialize the declared type using the generic assignment + Ok(specialize_declaration_type( + DeclarationType::Struct(struct_type), + &assignment, + ) + .unwrap()) } false => Err(ErrorInner { pos: Some(pos), @@ -1384,7 +1397,7 @@ impl<'ast, T: Field> Checker<'ast, T> { .into_iter() .map(|m| { Ok(DeclarationStructMember { - ty: box specialize_type(*m.ty, &assignment) + ty: box specialize_declaration_type(*m.ty, &assignment) .map_err(|_| unimplemented!())?, ..m }) @@ -1465,7 +1478,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }), }, TypedExpression::Int(v) => { - UExpression::try_from_int(v, UBitwidth::B32).map_err(|_| ErrorInner { + UExpression::try_from_int(v, &UBitwidth::B32).map_err(|_| ErrorInner { pos: Some(pos), message: format!( "Expected lower loop bound to be of type u32, found {}", @@ -1495,7 +1508,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }), }, TypedExpression::Int(v) => { - UExpression::try_from_int(v, UBitwidth::B32).map_err(|_| ErrorInner { + UExpression::try_from_int(v, &UBitwidth::B32).map_err(|_| ErrorInner { pos: Some(pos), message: format!( "Expected upper loop bound to be of type u32, found {}", @@ -1550,9 +1563,10 @@ impl<'ast, T: Field> Checker<'ast, T> { let res = match expression_list_checked.len() == return_types.len() { true => match expression_list_checked - .iter() - .zip(return_types.clone()) - .map(|(e, t)| TypedExpression::align_to_type(e.clone(), t.into())) + .clone() + .into_iter() + .zip(return_types.iter()) + .map(|(e, t)| TypedExpression::align_to_type(e, t)) .collect::, _>>() .map_err(|e| { vec![ErrorInner { @@ -1641,19 +1655,19 @@ impl<'ast, T: Field> Checker<'ast, T> { let var_type = var.get_type(); // make sure the assignee has the same type as the rhs - match var_type.clone() { + match var_type { Type::FieldElement => FieldElementExpression::try_from_typed(checked_expr) .map(TypedExpression::from), Type::Boolean => { BooleanExpression::try_from_typed(checked_expr).map(TypedExpression::from) } - Type::Uint(bitwidth) => UExpression::try_from_typed(checked_expr, bitwidth) + Type::Uint(bitwidth) => UExpression::try_from_typed(checked_expr, &bitwidth) .map(TypedExpression::from), - Type::Array(array_ty) => { - ArrayExpression::try_from_typed(checked_expr, *array_ty.ty) + Type::Array(ref array_ty) => { + ArrayExpression::try_from_typed(checked_expr, array_ty) .map(TypedExpression::from) } - Type::Struct(struct_ty) => { + Type::Struct(ref struct_ty) => { StructExpression::try_from_typed(checked_expr, struct_ty) .map(TypedExpression::from) } @@ -1710,7 +1724,7 @@ impl<'ast, T: Field> Checker<'ast, T> { g.map(|g| { let pos = g.pos(); self.check_expression(g, module_id, types).and_then(|g| { - UExpression::try_from_typed(g, UBitwidth::B32).map_err( + UExpression::try_from_typed(g, &UBitwidth::B32).map_err( |e| ErrorInner { pos: Some(pos), message: format!( @@ -1759,7 +1773,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let mut functions = functions; let f = functions.pop().unwrap(); - let arguments_checked = arguments_checked.into_iter().zip(f.signature.inputs.clone()).map(|(a, t)| TypedExpression::align_to_type(a, t.into())).collect::, _>>().map_err(|e| vec![ErrorInner { + let arguments_checked = arguments_checked.into_iter().zip(f.signature.inputs.iter()).map(|(a, t)| TypedExpression::align_to_type(a, t)).collect::, _>>().map_err(|e| vec![ErrorInner { pos: Some(pos), message: format!("Expected function call argument to be of type {}, found {} of type {}", e.1, e.0, e.0.get_type()) }])?; @@ -1827,7 +1841,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }; let checked_typed_index = - UExpression::try_from_typed(checked_index, UBitwidth::B32).map_err( + UExpression::try_from_typed(checked_index, &UBitwidth::B32).map_err( |e| ErrorInner { pos: Some(pos), message: format!( @@ -2127,7 +2141,7 @@ impl<'ast, T: Field> Checker<'ast, T> { Ok(e) => e.into(), Err(e) => e, }; - let e2_checked = match UExpression::try_from_typed(e2_checked, UBitwidth::B32) { + let e2_checked = match UExpression::try_from_typed(e2_checked, &UBitwidth::B32) { Ok(e) => e.into(), Err(e) => e, }; @@ -2261,7 +2275,7 @@ impl<'ast, T: Field> Checker<'ast, T> { g.map(|g| { let pos = g.pos(); self.check_expression(g, module_id, types).and_then(|g| { - UExpression::try_from_typed(g, UBitwidth::B32).map_err( + UExpression::try_from_typed(g, &UBitwidth::B32).map_err( |e| ErrorInner { pos: Some(pos), message: format!( @@ -2307,7 +2321,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let signature = f.signature; - let arguments_checked = arguments_checked.into_iter().zip(signature.inputs.clone()).map(|(a, t)| TypedExpression::align_to_type(a, t.into())).collect::, _>>().map_err(|e| ErrorInner { + let arguments_checked = arguments_checked.into_iter().zip(signature.inputs.iter()).map(|(a, t)| TypedExpression::align_to_type(a, &t)).collect::, _>>().map_err(|e| ErrorInner { pos: Some(pos), message: format!("Expected function call argument to be of type {}, found {}", e.1, e.0) })?; @@ -2513,9 +2527,7 @@ impl<'ast, T: Field> Checker<'ast, T> { (TypedExpression::Array(e1), TypedExpression::Array(e2)) => { Ok(BooleanExpression::ArrayEq(box e1, box e2).into()) } - (TypedExpression::Struct(e1), TypedExpression::Struct(e2)) - if e1.get_type() == e2.get_type() => - { + (TypedExpression::Struct(e1), TypedExpression::Struct(e2)) => { Ok(BooleanExpression::StructEq(box e1, box e2).into()) } (TypedExpression::Uint(e1), TypedExpression::Uint(e2)) @@ -2659,7 +2671,7 @@ impl<'ast, T: Field> Checker<'ast, T> { .map(|e| self.check_expression(e, module_id, types)) .unwrap_or_else(|| Ok(array_size.clone().into()))?; - let from = UExpression::try_from_typed(from, UBitwidth::B32).map_err(|e| ErrorInner { + let from = UExpression::try_from_typed(from, &UBitwidth::B32).map_err(|e| ErrorInner { pos: Some(pos), message: format!( "Expected the lower bound of the range to be a u32, found {} of type {}", @@ -2668,7 +2680,7 @@ impl<'ast, T: Field> Checker<'ast, T> { ), })?; - let to = UExpression::try_from_typed(to, UBitwidth::B32).map_err(|e| ErrorInner { + let to = UExpression::try_from_typed(to, &UBitwidth::B32).map_err(|e| ErrorInner { pos: Some(pos), message: format!( "Expected the upper bound of the range to be a u32, found {} of type {}", @@ -2699,7 +2711,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let index = self.check_expression(index, module_id, types)?; let index = - UExpression::try_from_typed(index, UBitwidth::B32).map_err(|e| { + UExpression::try_from_typed(index, &UBitwidth::B32).map_err(|e| { ErrorInner { pos: Some(pos), message: format!( @@ -2813,19 +2825,24 @@ impl<'ast, T: Field> Checker<'ast, T> { .next() .unwrap_or(Type::Int); - let unwrapped_expressions_or_spreads = match &inferred_type { + let unwrapped_expressions_or_spreads = match inferred_type.clone() { Type::Int => expressions_or_spreads_checked, - t => expressions_or_spreads_checked - .into_iter() - .map(|e| { - TypedExpressionOrSpread::align_to_type(e, t.clone()).map_err( - |(e, ty)| ErrorInner { - pos: Some(pos), - message: format!("Expected {} to have type {}", e, ty,), - }, - ) - }) - .collect::, _>>()?, + t => { + let target_array_ty = + ArrayType::new(t, UExpressionInner::Value(0).annotate(UBitwidth::B32)); + + expressions_or_spreads_checked + .into_iter() + .map(|e| { + TypedExpressionOrSpread::align_to_type(e, &target_array_ty).map_err( + |(e, ty)| ErrorInner { + pos: Some(pos), + message: format!("Expected {} to have type {}", e, ty,), + }, + ) + }) + .collect::, _>>()? + } }; // the size of the inline array is the sum of the size of its elements. However expressed as a u32 expression, @@ -2863,15 +2880,16 @@ impl<'ast, T: Field> Checker<'ast, T> { let count = self.check_expression(count, module_id, types)?; - let count = - UExpression::try_from_typed(count, UBitwidth::B32).map_err(|e| ErrorInner { + let count = UExpression::try_from_typed(count, &UBitwidth::B32).map_err(|e| { + ErrorInner { pos: Some(pos), message: format!( "Expected array initializer count to be a u32, found {} of type {}", e, e.get_type(), ), - })?; + } + })?; Ok(ArrayExpressionInner::Repeat(box e, box count.clone()) .annotate(ty, count) @@ -2881,7 +2899,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let ty = match types.get(module_id).unwrap().get(&id).cloned() { None => Err(ErrorInner { pos: Some(pos), - message: format!("Undeclared type of name `{}`", id), + message: format!("Undefined type `{}`", id), }), Some(ty) => Ok(ty), }?; @@ -2926,13 +2944,11 @@ impl<'ast, T: Field> Checker<'ast, T> { let expression_checked = self.check_expression(value, module_id, types)?; - let expression_checked = TypedExpression::align_to_type( - expression_checked, - Type::from(*member.ty.clone()), - ) - .map_err(|e| ErrorInner { - pos: Some(pos), - message: format!( + let expression_checked = + TypedExpression::align_to_type(expression_checked, &*member.ty) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!( "Member {} of struct {} has type {}, found {} of type {}", member.id, id.clone(), @@ -2940,7 +2956,7 @@ impl<'ast, T: Field> Checker<'ast, T> { e.0, e.0.get_type(), ), - })?; + })?; Ok(expression_checked) } @@ -3056,7 +3072,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let e2 = self.check_expression(e2, module_id, types)?; let e2 = - UExpression::try_from_typed(e2, UBitwidth::B32).map_err(|e| ErrorInner { + UExpression::try_from_typed(e2, &UBitwidth::B32).map_err(|e| ErrorInner { pos: Some(pos), message: format!( "Expected the left shift right operand to have type `u32`, found {}", @@ -3083,7 +3099,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let e2 = self.check_expression(e2, module_id, types)?; let e2 = - UExpression::try_from_typed(e2, UBitwidth::B32).map_err(|e| ErrorInner { + UExpression::try_from_typed(e2, &UBitwidth::B32).map_err(|e| ErrorInner { pos: Some(pos), message: format!( "Expected the right shift right operand to be of type `u32`, found {}", @@ -3402,11 +3418,16 @@ mod tests { use super::*; fn struct0() -> StructDefinitionNode<'static> { - StructDefinition { fields: vec![] }.mock() + StructDefinition { + generics: vec![], + fields: vec![], + } + .mock() } fn struct1() -> StructDefinitionNode<'static> { StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -3730,7 +3751,7 @@ mod tests { checker.check_module(&*MODULE_ID, &mut state).unwrap_err()[0] .inner .message, - "Undeclared symbol `P` in function definition" + "Undeclared symbol `P`" ); } } @@ -3839,7 +3860,11 @@ mod tests { SymbolDeclaration { id: "foo", symbol: Symbol::Here(SymbolDefinition::Struct( - StructDefinition { fields: vec![] }.mock(), + StructDefinition { + generics: vec![], + fields: vec![], + } + .mock(), )), } .mock(), @@ -3990,7 +4015,7 @@ mod tests { Checker::::new().check_signature(signature, &*MODULE_ID, &state), Err(vec![ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Undeclared symbol `K` in function definition".to_string() + message: "Undeclared symbol `K`".to_string() }]) ); } @@ -5287,12 +5312,17 @@ mod tests { let modules = Modules::new(); let state = State::new(modules); - let declaration: StructDefinitionNode = StructDefinition { fields: vec![] }.mock(); + let declaration: StructDefinitionNode = StructDefinition { + generics: vec![], + fields: vec![], + } + .mock(); let expected_type = DeclarationType::Struct(DeclarationStructType::new( "".into(), "Foo".into(), vec![], + vec![], )); assert_eq!( @@ -5313,6 +5343,7 @@ mod tests { let state = State::new(modules); let declaration: StructDefinitionNode = StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", @@ -5331,6 +5362,7 @@ mod tests { let expected_type = DeclarationType::Struct(DeclarationStructType::new( "".into(), "Foo".into(), + vec![], vec![ DeclarationStructMember::new("foo".into(), DeclarationType::FieldElement), DeclarationStructMember::new("bar".into(), DeclarationType::Boolean), @@ -5355,6 +5387,7 @@ mod tests { let state = State::new(modules); let declaration: StructDefinitionNode = StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", @@ -5397,6 +5430,7 @@ mod tests { id: "Foo", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -5411,9 +5445,10 @@ mod tests { id: "Bar", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", - ty: UnresolvedType::User("Foo".into()).mock(), + ty: UnresolvedType::User("Foo".into(), None).mock(), } .mock()], } @@ -5439,11 +5474,13 @@ mod tests { &DeclarationType::Struct(DeclarationStructType::new( (*MODULE_ID).clone(), "Bar".into(), + vec![], vec![DeclarationStructMember::new( "foo".into(), DeclarationType::Struct(DeclarationStructType::new( (*MODULE_ID).clone(), "Foo".into(), + vec![], vec![DeclarationStructMember::new( "foo".into(), DeclarationType::FieldElement @@ -5465,9 +5502,10 @@ mod tests { id: "Bar", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", - ty: UnresolvedType::User("Foo".into()).mock(), + ty: UnresolvedType::User("Foo".into(), None).mock(), } .mock()], } @@ -5497,9 +5535,10 @@ mod tests { id: "Foo", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", - ty: UnresolvedType::User("Foo".into()).mock(), + ty: UnresolvedType::User("Foo".into(), None).mock(), } .mock()], } @@ -5531,9 +5570,10 @@ mod tests { id: "Foo", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "bar", - ty: UnresolvedType::User("Bar".into()).mock(), + ty: UnresolvedType::User("Bar".into(), None).mock(), } .mock()], } @@ -5545,9 +5585,10 @@ mod tests { id: "Bar", symbol: Symbol::Here(SymbolDefinition::Struct( StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", - ty: UnresolvedType::User("Foo".into()).mock(), + ty: UnresolvedType::User("Foo".into(), None).mock(), } .mock()], } @@ -5582,6 +5623,7 @@ mod tests { // Bar let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -5591,13 +5633,14 @@ mod tests { assert_eq!( checker.check_type( - UnresolvedType::User("Foo".into()).mock(), + UnresolvedType::User("Foo".into(), None).mock(), &*MODULE_ID, &state.types ), Ok(Type::Struct(StructType::new( "".into(), "Foo".into(), + vec![], vec![StructMember::new("foo".into(), Type::FieldElement)] ))) ); @@ -5605,7 +5648,7 @@ mod tests { assert_eq!( checker .check_type( - UnresolvedType::User("Bar".into()).mock(), + UnresolvedType::User("Bar".into(), None).mock(), &*MODULE_ID, &state.types ) @@ -5628,6 +5671,7 @@ mod tests { // Foo { foo: 42 }.foo let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -5657,6 +5701,7 @@ mod tests { .annotate(StructType::new( "".into(), "Foo".into(), + vec![], vec![StructMember::new("foo".into(), Type::FieldElement)] )), "foo".into() @@ -5673,6 +5718,7 @@ mod tests { // Foo { foo: 42 }.bar let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -5711,6 +5757,7 @@ mod tests { // a A value cannot be defined with B as id, even if A and B have the same members let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), @@ -5731,7 +5778,7 @@ mod tests { ) .unwrap_err() .message, - "Undefined type Bar" + "Undefined type `Bar`" ); } @@ -5743,6 +5790,7 @@ mod tests { // Foo foo = Foo { foo: 42, bar: true } let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", @@ -5777,6 +5825,7 @@ mod tests { .annotate(StructType::new( "".into(), "Foo".into(), + vec![], vec![ StructMember::new("foo".into(), Type::FieldElement), StructMember::new("bar".into(), Type::Boolean) @@ -5794,6 +5843,7 @@ mod tests { // Foo foo = Foo { bar: true, foo: 42 } let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", @@ -5828,6 +5878,7 @@ mod tests { .annotate(StructType::new( "".into(), "Foo".into(), + vec![], vec![ StructMember::new("foo".into(), Type::FieldElement), StructMember::new("bar".into(), Type::Boolean) @@ -5845,6 +5896,7 @@ mod tests { // Foo foo = Foo { foo: 42 } let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", @@ -5886,6 +5938,7 @@ mod tests { // Foo { foo: 42, baz: 42 } // error let (mut checker, state) = create_module_with_foo(StructDefinition { + generics: vec![], fields: vec![ StructDefinitionField { id: "foo", diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index ad00d292c..25b0242cd 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -112,7 +112,6 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { ( id, TypedConstantSymbol::Here(TypedConstant { - ty: constant.get_type().clone(), expression: constant, }), ) @@ -268,10 +267,9 @@ mod tests { let constants: TypedConstantSymbols<_> = vec![( CanonicalConstantIdentifier::new(const_id, "main".into()), - TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, - TypedExpression::FieldElement(FieldElementExpression::Number(Bn128Field::from(1))), - )), + TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( + FieldElementExpression::Number(Bn128Field::from(1)), + ))), )] .into_iter() .collect(); @@ -356,10 +354,9 @@ mod tests { let constants: TypedConstantSymbols<_> = vec![( CanonicalConstantIdentifier::new(const_id, "main".into()), - TypedConstantSymbol::Here(TypedConstant::new( - GType::Boolean, - TypedExpression::Boolean(BooleanExpression::Value(true)), - )), + TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::Boolean( + BooleanExpression::Value(true), + ))), )] .into_iter() .collect(); @@ -446,7 +443,6 @@ mod tests { let constants: TypedConstantSymbols<_> = vec![( CanonicalConstantIdentifier::new(const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( - GType::Uint(UBitwidth::B32), UExpressionInner::Value(1u128) .annotate(UBitwidth::B32) .into(), @@ -546,19 +542,16 @@ mod tests { let constants: TypedConstantSymbols<_> = vec![( CanonicalConstantIdentifier::new(const_id, "main".into()), - TypedConstantSymbol::Here(TypedConstant::new( - GType::array(GArrayType::new(GType::FieldElement, 2usize)), - TypedExpression::Array( - ArrayExpressionInner::Value( - vec![ - FieldElementExpression::Number(Bn128Field::from(2)).into(), - FieldElementExpression::Number(Bn128Field::from(2)).into(), - ] - .into(), - ) - .annotate(GType::FieldElement, 2usize), - ), - )), + TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::Array( + ArrayExpressionInner::Value( + vec![ + FieldElementExpression::Number(Bn128Field::from(2)).into(), + FieldElementExpression::Number(Bn128Field::from(2)).into(), + ] + .into(), + ) + .annotate(GType::FieldElement, 2usize), + ))), )] .into_iter() .collect(); @@ -686,7 +679,6 @@ mod tests { ( CanonicalConstantIdentifier::new(const_a_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(1), )), @@ -695,7 +687,6 @@ mod tests { ( CanonicalConstantIdentifier::new(const_b_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Add( box FieldElementExpression::Identifier(Identifier::from( const_a_id, @@ -744,7 +735,6 @@ mod tests { ( CanonicalConstantIdentifier::new(const_a_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(1), )), @@ -753,7 +743,6 @@ mod tests { ( CanonicalConstantIdentifier::new(const_b_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(2), )), @@ -804,12 +793,9 @@ mod tests { .collect(), constants: vec![( CanonicalConstantIdentifier::new(foo_const_id, "foo".into()), - TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, - TypedExpression::FieldElement(FieldElementExpression::Number( - Bn128Field::from(42), - )), - )), + TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( + FieldElementExpression::Number(Bn128Field::from(42)), + ))), )] .into_iter() .collect(), @@ -877,12 +863,9 @@ mod tests { .collect(), constants: vec![( CanonicalConstantIdentifier::new(foo_const_id, "main".into()), - TypedConstantSymbol::Here(TypedConstant::new( - GType::FieldElement, - TypedExpression::FieldElement(FieldElementExpression::Number( - Bn128Field::from(42), - )), - )), + TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( + FieldElementExpression::Number(Bn128Field::from(42)), + ))), )] .into_iter() .collect(), diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index 4e2294af1..af1825f59 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -1101,7 +1101,11 @@ fn fold_function<'ast, T: Field>( .collect(), statements: main_statements_buffer, signature: typed_absy::types::ConcreteSignature::try_from( - typed_absy::types::Signature::::try_from(fun.signature).unwrap(), + crate::typed_absy::types::try_from_g_signature::< + crate::typed_absy::types::DeclarationConstant<'ast>, + crate::typed_absy::UExpression<'ast, T>, + >(fun.signature) + .unwrap(), ) .unwrap() .into(), diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index a58faeddf..8740f1dc4 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -72,8 +72,6 @@ impl fmt::Display for Error { impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { - println!("{}", self); - // inline user-defined constants let r = ConstantInliner::inline(self); // isolate branches @@ -86,13 +84,12 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { // reduce the program to a single function let r = reduce_program(r).map_err(Error::from)?; - println!("{}", r); - // generate abi let abi = r.abi(); // propagate let r = Propagator::propagate(r).map_err(Error::from)?; + // remove assignment to variable index let r = VariableWriteRemover::apply(r); // detect non constant shifts diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index c03d6cb4d..5d51a05a1 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -327,20 +327,13 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { // propagation to the defined variable if rhs is a constant TypedStatement::Definition(assignee, expr) => { let expr = self.fold_expression(expr)?; - let assignee = self.fold_assignee(assignee)?; - println!( - "{:#?} vs {:#?}", - assignee.get_type().clone(), - expr.get_type().clone() - ); + let assignee = self.fold_assignee(assignee)?; if let (Ok(a), Ok(e)) = ( ConcreteType::try_from(assignee.get_type()), ConcreteType::try_from(expr.get_type()), ) { - println!("{} vs {}", a, e); - if a != e { return Err(Error::Type(format!( "Cannot assign {} of type {} to {} of type {}", diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index f3adbdea7..4aa831a8c 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -231,6 +231,7 @@ mod tests { ty: ConcreteType::Struct(ConcreteStructType::new( "".into(), "Foo".into(), + vec![], vec![ ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement), ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean), @@ -240,6 +241,7 @@ mod tests { outputs: vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "Foo".into(), + vec![], vec![ ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement), ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean), @@ -258,6 +260,7 @@ mod tests { "type": "struct", "components": { "name": "Foo", + "generics": [], "members": [ { "name": "a", @@ -276,6 +279,7 @@ mod tests { "type": "struct", "components": { "name": "Foo", + "generics": [], "members": [ { "name": "a", @@ -305,11 +309,13 @@ mod tests { ty: ConcreteType::Struct(ConcreteStructType::new( "".into(), "Foo".into(), + vec![], vec![ConcreteStructMember::new( String::from("bar"), ConcreteType::Struct(ConcreteStructType::new( "".into(), "Bar".into(), + vec![], vec![ ConcreteStructMember::new( String::from("a"), @@ -338,12 +344,14 @@ mod tests { "type": "struct", "components": { "name": "Foo", + "generics": [], "members": [ { "name": "bar", "type": "struct", "components": { "name": "Bar", + "generics": [], "members": [ { "name": "a", @@ -378,6 +386,7 @@ mod tests { ConcreteType::Struct(ConcreteStructType::new( "".into(), "Foo".into(), + vec![], vec![ ConcreteStructMember::new( String::from("b"), @@ -406,6 +415,7 @@ mod tests { "type": "struct", "components": { "name": "Foo", + "generics": [], "members": [ { "name": "b", diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 0dcab517c..794b4cc41 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -138,6 +138,11 @@ pub trait Folder<'ast, T: Field>: Sized { fn fold_struct_type(&mut self, t: StructType<'ast, T>) -> StructType<'ast, T> { StructType { + generics: t + .generics + .into_iter() + .map(|g| g.map(|g| self.fold_uint_expression(g))) + .collect(), members: t .members .into_iter() @@ -175,6 +180,11 @@ pub trait Folder<'ast, T: Field>: Sized { t: DeclarationStructType<'ast>, ) -> DeclarationStructType<'ast> { DeclarationStructType { + generics: t + .generics + .into_iter() + .map(|g| g.map(|g| self.fold_declaration_constant(g))) + .collect(), members: t .members .into_iter() @@ -1044,7 +1054,6 @@ pub fn fold_constant<'ast, T: Field, F: Folder<'ast, T>>( c: TypedConstant<'ast, T>, ) -> TypedConstant<'ast, T> { TypedConstant { - ty: f.fold_type(c.ty), expression: f.fold_expression(c.expression), } } diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index 851acf7a2..4fc6bb169 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -1,9 +1,12 @@ -use crate::typed_absy::types::{ArrayType, Type}; +use crate::typed_absy::types::{ + ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationType, GArrayType, GStructType, + GType, StructMember, StructType, Type, +}; use crate::typed_absy::UBitwidth; use crate::typed_absy::{ ArrayExpression, ArrayExpressionInner, BooleanExpression, FieldElementExpression, IfElse, - IfElseExpression, Select, SelectExpression, StructExpression, Typed, TypedExpression, - TypedExpressionOrSpread, TypedSpread, UExpression, UExpressionInner, + IfElseExpression, Select, SelectExpression, StructExpression, StructExpressionInner, Typed, + TypedExpression, TypedExpressionOrSpread, TypedSpread, UExpression, UExpressionInner, }; use num_bigint::BigUint; use std::convert::TryFrom; @@ -14,20 +17,46 @@ use zokrates_field::Field; type TypedExpressionPair<'ast, T> = (TypedExpression<'ast, T>, TypedExpression<'ast, T>); impl<'ast, T: Field> TypedExpressionOrSpread<'ast, T> { - pub fn align_to_type(e: Self, ty: Type<'ast, T>) -> Result)> { + pub fn align_to_type>>( + e: Self, + ty: &GArrayType, + ) -> Result)> { match e { - TypedExpressionOrSpread::Expression(e) => TypedExpression::align_to_type(e, ty) + TypedExpressionOrSpread::Expression(e) => TypedExpression::align_to_type(e, &ty.ty) .map(|e| e.into()) - .map_err(|(e, t)| (e.into(), t)), - TypedExpressionOrSpread::Spread(s) => { - ArrayExpression::try_from_int(s.array, ty.clone()) - .map(|e| TypedExpressionOrSpread::Spread(TypedSpread { array: e })) - .map_err(|e| (e.into(), ty)) - } + .map_err(|(e, _)| (e.into(), ty)), + TypedExpressionOrSpread::Spread(s) => ArrayExpression::try_from_int(s.array, ty) + .map(|e| TypedExpressionOrSpread::Spread(TypedSpread { array: e })) + .map_err(|e| (e.into(), ty)), } } } +fn get_common_type<'a, T: Field>(t: Type<'a, T>, u: Type<'a, T>) -> Result, ()> { + match (t, u) { + (Type::Int, Type::Int) => Err(()), + (Type::Int, u) => Ok(u), + (t, Type::Int) => Ok(t), + (Type::Array(t), Type::Array(u)) => Ok(Type::Array(ArrayType::new( + get_common_type(*t.ty, *u.ty)?, + t.size, + ))), + (Type::Struct(t), Type::Struct(u)) => Ok(Type::Struct(StructType { + members: t + .members + .into_iter() + .zip(u.members.into_iter()) + .map(|(m_t, m_u)| { + get_common_type(*m_t.ty.clone(), *m_u.ty) + .map(|ty| StructMember { ty: box ty, ..m_t }) + }) + .collect::, _>>()?, + ..t + })), + (t, _) => Ok(t), + } +} + impl<'ast, T: Field> TypedExpression<'ast, T> { // return two TypedExpression, replacing IntExpression by FieldElement or Uint to try to align the two types if possible. // Post condition is that (lhs, rhs) cannot be made equal by further removing IntExpressions @@ -51,7 +80,7 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { .into(), )), (Int(lhs), Uint(rhs)) => Ok(( - UExpression::try_from_int(lhs, rhs.bitwidth()) + UExpression::try_from_int(lhs, &rhs.bitwidth()) .map_err(|lhs| (lhs.into(), rhs.clone().into()))? .into(), Uint(rhs), @@ -60,47 +89,46 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { let bitwidth = lhs.bitwidth(); Ok(( Uint(lhs.clone()), - UExpression::try_from_int(rhs, bitwidth) + UExpression::try_from_int(rhs, &bitwidth) .map_err(|rhs| (lhs.into(), rhs.into()))? .into(), )) } (Array(lhs), Array(rhs)) => { - fn get_common_type<'a, T: Field>( - t: Type<'a, T>, - u: Type<'a, T>, - ) -> Result, ()> { - match (t, u) { - (Type::Int, Type::Int) => Err(()), - (Type::Int, u) => Ok(u), - (t, Type::Int) => Ok(t), - (Type::Array(t), Type::Array(u)) => Ok(Type::Array(ArrayType::new( - get_common_type(*t.ty, *u.ty)?, - t.size, - ))), - (t, _) => Ok(t), - } - } + let common_type = get_common_type(lhs.get_type().clone(), rhs.get_type().clone()) + .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; - let common_type = - get_common_type(lhs.inner_type().clone(), rhs.inner_type().clone()) - .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; + let common_type = match common_type { + Type::Array(ty) => ty, + _ => unreachable!(), + }; Ok(( - ArrayExpression::try_from_int(lhs.clone(), common_type.clone()) + ArrayExpression::try_from_int(lhs.clone(), &common_type) .map_err(|lhs| (lhs.clone(), rhs.clone().into()))? .into(), - ArrayExpression::try_from_int(rhs, common_type) + ArrayExpression::try_from_int(rhs, &common_type) .map_err(|rhs| (lhs.clone().into(), rhs.clone()))? .into(), )) } (Struct(lhs), Struct(rhs)) => { - if lhs.get_type() == rhs.get_type() { - Ok((Struct(lhs), Struct(rhs))) - } else { - Err((Struct(lhs), Struct(rhs))) - } + let common_type = get_common_type(lhs.get_type(), rhs.get_type()) + .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; + + let common_type = match common_type { + Type::Struct(ty) => ty, + _ => unreachable!(), + }; + + Ok(( + StructExpression::try_from_int(lhs.clone(), &common_type) + .map_err(|lhs| (lhs.clone(), rhs.clone().into()))? + .into(), + StructExpression::try_from_int(rhs, &common_type) + .map_err(|rhs| (lhs.clone().into(), rhs.clone()))? + .into(), + )) } (Uint(lhs), Uint(rhs)) => Ok((lhs.into(), rhs.into())), (Boolean(lhs), Boolean(rhs)) => Ok((lhs.into(), rhs.into())), @@ -110,22 +138,25 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { } } - pub fn align_to_type(e: Self, ty: Type<'ast, T>) -> Result)> { - match ty.clone() { - Type::FieldElement => { + pub fn align_to_type>>( + e: Self, + ty: >ype, + ) -> Result)> { + match ty { + GType::FieldElement => { FieldElementExpression::try_from_typed(e).map(TypedExpression::from) } - Type::Boolean => BooleanExpression::try_from_typed(e).map(TypedExpression::from), - Type::Uint(bitwidth) => { + GType::Boolean => BooleanExpression::try_from_typed(e).map(TypedExpression::from), + GType::Uint(bitwidth) => { UExpression::try_from_typed(e, bitwidth).map(TypedExpression::from) } - Type::Array(array_ty) => { - ArrayExpression::try_from_typed(e, *array_ty.ty).map(TypedExpression::from) + GType::Array(array_ty) => { + ArrayExpression::try_from_typed(e, array_ty).map(TypedExpression::from) } - Type::Struct(struct_ty) => { + GType::Struct(struct_ty) => { StructExpression::try_from_typed(e, struct_ty).map(TypedExpression::from) } - Type::Int => Err(e), + GType::Int => Err(e), } .map_err(|e| (e, ty)) } @@ -299,7 +330,7 @@ impl<'ast, T: Field> FieldElementExpression<'ast, T> { )), IntExpression::Pow(box e1, box e2) => Ok(Self::Pow( box Self::try_from_int(e1)?, - box UExpression::try_from_int(e2, UBitwidth::B32)?, + box UExpression::try_from_int(e2, &UBitwidth::B32)?, )), IntExpression::Div(box e1, box e2) => Ok(Self::Div( box Self::try_from_int(e1)?, @@ -323,15 +354,21 @@ impl<'ast, T: Field> FieldElementExpression<'ast, T> { let values = values .into_iter() .map(|v| { - TypedExpressionOrSpread::align_to_type(v, Type::FieldElement) - .map_err(|(e, _)| match e { - TypedExpressionOrSpread::Expression(e) => { - IntExpression::try_from(e).unwrap() - } - TypedExpressionOrSpread::Spread(a) => { - IntExpression::select(a.array, 0u32) - } - }) + TypedExpressionOrSpread::align_to_type( + v, + &DeclarationArrayType::new( + DeclarationType::FieldElement, + DeclarationConstant::Concrete(0), + ), + ) + .map_err(|(e, _)| match e { + TypedExpressionOrSpread::Expression(e) => { + IntExpression::try_from(e).unwrap() + } + TypedExpressionOrSpread::Spread(a) => { + IntExpression::select(a.array, 0u32) + } + }) }) .collect::, _>>()?; Ok(FieldElementExpression::select( @@ -351,10 +388,10 @@ impl<'ast, T: Field> FieldElementExpression<'ast, T> { impl<'ast, T: Field> UExpression<'ast, T> { pub fn try_from_typed( e: TypedExpression<'ast, T>, - bitwidth: UBitwidth, + bitwidth: &UBitwidth, ) -> Result> { match e { - TypedExpression::Uint(e) => match e.bitwidth == bitwidth { + TypedExpression::Uint(e) => match e.bitwidth == *bitwidth { true => Ok(e), _ => Err(TypedExpression::Uint(e)), }, @@ -367,7 +404,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { pub fn try_from_int( i: IntExpression<'ast, T>, - bitwidth: UBitwidth, + bitwidth: &UBitwidth, ) -> Result> { use self::IntExpression::*; @@ -377,7 +414,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { Ok(UExpressionInner::Value( u128::from_str_radix(&i.to_str_radix(16), 16).unwrap(), ) - .annotate(bitwidth)) + .annotate(*bitwidth)) } else { Err(Value(i)) } @@ -435,20 +472,26 @@ impl<'ast, T: Field> UExpression<'ast, T> { let values = values .into_iter() .map(|v| { - TypedExpressionOrSpread::align_to_type(v, Type::Uint(bitwidth)) - .map_err(|(e, _)| match e { - TypedExpressionOrSpread::Expression(e) => { - IntExpression::try_from(e).unwrap() - } - TypedExpressionOrSpread::Spread(a) => { - IntExpression::select(a.array, 0u32) - } - }) + TypedExpressionOrSpread::align_to_type( + v, + &DeclarationArrayType::new( + DeclarationType::Uint(*bitwidth), + DeclarationConstant::Concrete(0), + ), + ) + .map_err(|(e, _)| match e { + TypedExpressionOrSpread::Expression(e) => { + IntExpression::try_from(e).unwrap() + } + TypedExpressionOrSpread::Spread(a) => { + IntExpression::select(a.array, 0u32) + } + }) }) .collect::, _>>()?; Ok(UExpression::select( ArrayExpressionInner::Value(values.into()) - .annotate(Type::Uint(bitwidth), size), + .annotate(Type::Uint(*bitwidth), size), index, )) } @@ -461,35 +504,35 @@ impl<'ast, T: Field> UExpression<'ast, T> { } impl<'ast, T: Field> ArrayExpression<'ast, T> { - pub fn try_from_typed( + pub fn try_from_typed>>( e: TypedExpression<'ast, T>, - target_inner_ty: Type<'ast, T>, + target_array_ty: &GArrayType, ) -> Result> { match e { - TypedExpression::Array(e) => Self::try_from_int(e.clone(), target_inner_ty) + TypedExpression::Array(e) => Self::try_from_int(e.clone(), target_array_ty) .map_err(|_| TypedExpression::Array(e)), e => Err(e), } } // precondition: `array` is only made of inline arrays and repeat constructs unless it does not contain the Integer type - pub fn try_from_int( + pub fn try_from_int>>( array: Self, - target_inner_ty: Type<'ast, T>, + target_array_ty: &GArrayType, ) -> Result> { let array_ty = array.ty(); // elements must fit in the target type match array.into_inner() { ArrayExpressionInner::Value(inline_array) => { - let res = match target_inner_ty.clone() { - Type::Int => Ok(inline_array), - t => { + let res = match &*target_array_ty.ty { + GType::Int => Ok(inline_array), + _ => { // try to convert all elements to the target type inline_array .into_iter() .map(|v| { - TypedExpressionOrSpread::align_to_type(v, t.clone()).map_err( + TypedExpressionOrSpread::align_to_type(v, &target_array_ty).map_err( |(e, _)| match e { TypedExpressionOrSpread::Expression(e) => e, TypedExpressionOrSpread::Spread(a) => { @@ -508,11 +551,11 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, array_ty.size)) } ArrayExpressionInner::Repeat(box e, box count) => { - match target_inner_ty.clone() { - Type::Int => Ok(ArrayExpressionInner::Repeat(box e, box count) + match &*target_array_ty.ty { + GType::Int => Ok(ArrayExpressionInner::Repeat(box e, box count) .annotate(Type::Int, array_ty.size)), // try to align the repeated element to the target type - t => TypedExpression::align_to_type(e, t) + t => TypedExpression::align_to_type(e, &t) .map(|e| { let ty = e.get_type().clone(); @@ -523,7 +566,7 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { } } a => { - if array_ty.ty.weak_eq(&target_inner_ty) { + if *target_array_ty.ty == *array_ty.ty { Ok(a.annotate(*array_ty.ty, array_ty.size)) } else { Err(a.annotate(*array_ty.ty, array_ty.size).into()) @@ -533,6 +576,50 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { } } +impl<'ast, T: Field> StructExpression<'ast, T> { + pub fn try_from_int>>( + struc: Self, + target_struct_ty: &GStructType, + ) -> Result> { + let struct_ty = struc.ty().clone(); + + match struc.into_inner() { + StructExpressionInner::Value(inline_struct) => inline_struct + .into_iter() + .zip(target_struct_ty.members.iter()) + .map(|(value, target_member)| { + TypedExpression::align_to_type(value, &*target_member.ty) + }) + .collect::, _>>() + .map(|v| StructExpressionInner::Value(v).annotate(struct_ty.clone())) + .map_err(|_| unimplemented!()), + s => { + if struct_ty + .members + .iter() + .zip(target_struct_ty.members.iter()) + .all(|(m, target_m)| *target_m.ty == *m.ty) + { + Ok(s.annotate(struct_ty.clone())) + } else { + Err(s.annotate(struct_ty.clone()).into()) + } + } + } + } + + pub fn try_from_typed>>( + e: TypedExpression<'ast, T>, + target_struct_ty: &GStructType, + ) -> Result> { + match e { + TypedExpression::Struct(e) => Self::try_from_int(e.clone(), target_struct_ty) + .map_err(|_| TypedExpression::Struct(e)), + e => Err(e), + } + } +} + impl<'ast, T> From for IntExpression<'ast, T> { fn from(v: BigUint) -> Self { IntExpression::Value(v) @@ -652,7 +739,7 @@ mod tests { for (r, e) in expressions .into_iter() - .map(|e| UExpression::try_from_int(e, UBitwidth::B32).unwrap()) + .map(|e| UExpression::try_from_int(e, &UBitwidth::B32).unwrap()) .zip(expected) { assert_eq!(r, e); @@ -665,7 +752,7 @@ mod tests { for e in should_error .into_iter() - .map(|e| UExpression::try_from_int(e, UBitwidth::B32)) + .map(|e| UExpression::try_from_int(e, &UBitwidth::B32)) { assert!(e.is_err()); } diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index dff34cf72..30ca25c3c 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -107,15 +107,19 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .arguments .iter() .map(|p| { - println!("{:#?}", p); - - types::ConcreteType::try_from(types::Type::::from(p.id._type.clone())) - .map(|ty| AbiInput { - public: !p.private, - name: p.id.id.to_string(), - ty, - }) - .unwrap() + types::ConcreteType::try_from( + crate::typed_absy::types::try_from_g_type::< + crate::typed_absy::types::DeclarationConstant<'ast>, + UExpression<'ast, T>, + >(p.id._type.clone()) + .unwrap(), + ) + .map(|ty| AbiInput { + public: !p.private, + name: p.id.id.to_string(), + ty, + }) + .unwrap() }) .collect(), outputs: main @@ -123,7 +127,14 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .outputs .iter() .map(|ty| { - types::ConcreteType::try_from(types::Type::::from(ty.clone())).unwrap() + types::ConcreteType::try_from( + crate::typed_absy::types::try_from_g_type::< + crate::typed_absy::types::DeclarationConstant<'ast>, + UExpression<'ast, T>, + >(ty.clone()) + .unwrap(), + ) + .unwrap() }) .collect(), } @@ -194,7 +205,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedModule<'ast, T> { .iter() .map(|(id, symbol)| match symbol { TypedConstantSymbol::Here(ref tc) => { - format!("const {} {} = {}", tc.ty, id.id, tc.expression) + format!("const {} {} = {}", "todo", id.id, tc.expression) } TypedConstantSymbol::There(ref imported_id) => { format!( @@ -300,27 +311,25 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> { #[derive(Clone, PartialEq, Debug)] pub struct TypedConstant<'ast, T> { - // the type is already stored in the TypedExpression, but we want to avoid awkward trait bounds in `fmt::Display` - pub ty: Type<'ast, T>, pub expression: TypedExpression<'ast, T>, } impl<'ast, T> TypedConstant<'ast, T> { - pub fn new(ty: Type<'ast, T>, expression: TypedExpression<'ast, T>) -> Self { - TypedConstant { ty, expression } + pub fn new(expression: TypedExpression<'ast, T>) -> Self { + TypedConstant { expression } } } impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // using `self.expression.get_type()` would be better here but ends up requiring stronger trait bounds - write!(f, "const {}({})", self.ty, self.expression) + write!(f, "const {}({})", "todo", self.expression) } } -impl<'ast, T: Clone> Typed<'ast, T> for TypedConstant<'ast, T> { +impl<'ast, T: Field> Typed<'ast, T> for TypedConstant<'ast, T> { fn get_type(&self) -> Type<'ast, T> { - self.ty.clone() + self.expression.get_type() } } @@ -1168,24 +1177,6 @@ pub struct StructExpression<'ast, T> { inner: StructExpressionInner<'ast, T>, } -impl<'ast, T: Field> StructExpression<'ast, T> { - pub fn try_from_typed( - e: TypedExpression<'ast, T>, - target_struct_ty: StructType<'ast, T>, - ) -> Result> { - match e { - TypedExpression::Struct(e) => { - if e.ty() == &target_struct_ty { - Ok(e) - } else { - Err(TypedExpression::Struct(e)) - } - } - e => Err(e), - } - } -} - impl<'ast, T> StructExpression<'ast, T> { pub fn ty(&self) -> &StructType<'ast, T> { &self.ty diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_core/src/typed_absy/result_folder.rs index ebc708dd3..724682110 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_core/src/typed_absy/result_folder.rs @@ -225,6 +225,11 @@ pub trait ResultFolder<'ast, T: Field>: Sized { t: StructType<'ast, T>, ) -> Result, Self::Error> { Ok(StructType { + generics: t + .generics + .into_iter() + .map(|g| g.map(|g| self.fold_uint_expression(g)).transpose()) + .collect::, _>>()?, members: t .members .into_iter() @@ -260,6 +265,11 @@ pub trait ResultFolder<'ast, T: Field>: Sized { t: DeclarationStructType<'ast>, ) -> Result, Self::Error> { Ok(DeclarationStructType { + generics: t + .generics + .into_iter() + .map(|g| g.map(|g| self.fold_declaration_constant(g)).transpose()) + .collect::, _>>()?, members: t .members .into_iter() @@ -1092,7 +1102,6 @@ pub fn fold_constant<'ast, T: Field, F: ResultFolder<'ast, T>>( c: TypedConstant<'ast, T>, ) -> Result, F::Error> { Ok(TypedConstant { - ty: f.fold_type(c.ty)?, expression: f.fold_expression(c.expression)?, }) } diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index e811acf2d..65fec3c57 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -122,6 +122,21 @@ pub enum DeclarationConstant<'ast> { Constant(CanonicalConstantIdentifier<'ast>), } +impl<'ast, T> PartialEq> for DeclarationConstant<'ast> { + fn eq(&self, other: &UExpression<'ast, T>) -> bool { + match (self, other.as_inner()) { + (DeclarationConstant::Concrete(c), UExpressionInner::Value(v)) => *c == *v as u32, + _ => true, + } + } +} + +impl<'ast, T> PartialEq> for UExpression<'ast, T> { + fn eq(&self, other: &DeclarationConstant<'ast>) -> bool { + other.eq(self) + } +} + impl<'ast> From for DeclarationConstant<'ast> { fn from(e: u32) -> Self { DeclarationConstant::Concrete(e) @@ -198,7 +213,7 @@ impl<'ast> TryInto for DeclarationConstant<'ast> { pub type MemberId = String; -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] pub struct GStructMember { #[serde(rename = "name")] pub id: MemberId, @@ -210,8 +225,8 @@ pub type DeclarationStructMember<'ast> = GStructMember pub type ConcreteStructMember = GStructMember; pub type StructMember<'ast, T> = GStructMember>; -impl<'ast, T: PartialEq> PartialEq> for StructMember<'ast, T> { - fn eq(&self, other: &DeclarationStructMember<'ast>) -> bool { +impl<'ast, S, R: PartialEq> PartialEq> for GStructMember { + fn eq(&self, other: &GStructMember) -> bool { self.id == other.id && *self.ty == *other.ty } } @@ -239,19 +254,19 @@ impl<'ast, T> From for StructMember<'ast, T> { } } -impl<'ast> From for DeclarationStructMember<'ast> { - fn from(t: ConcreteStructMember) -> Self { - try_from_g_struct_member(t).unwrap() - } -} +// impl<'ast> From for DeclarationStructMember<'ast> { +// fn from(t: ConcreteStructMember) -> Self { +// try_from_g_struct_member(t).unwrap() +// } +// } -impl<'ast, T> From> for StructMember<'ast, T> { - fn from(t: DeclarationStructMember<'ast>) -> Self { - try_from_g_struct_member(t).unwrap() - } -} +// impl<'ast, T> From> for StructMember<'ast, T> { +// fn from(t: DeclarationStructMember<'ast>) -> Self { +// try_from_g_struct_member(t).unwrap() +// } +// } -#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)] +#[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)] pub struct GArrayType { pub size: S, #[serde(flatten)] @@ -262,13 +277,9 @@ pub type DeclarationArrayType<'ast> = GArrayType>; pub type ConcreteArrayType = GArrayType; pub type ArrayType<'ast, T> = GArrayType>; -impl<'ast, T: PartialEq> PartialEq> for ArrayType<'ast, T> { - fn eq(&self, other: &DeclarationArrayType<'ast>) -> bool { - *self.ty == *other.ty - && match (self.size.as_inner(), &other.size) { - (UExpressionInner::Value(l), DeclarationConstant::Concrete(r)) => *l as u32 == *r, - _ => true, - } +impl<'ast, S, R: PartialEq> PartialEq> for GArrayType { + fn eq(&self, other: &GArrayType) -> bool { + *self.ty == *other.ty && self.size == other.size } } @@ -298,22 +309,6 @@ impl fmt::Display for GArrayType { } } -impl<'ast, T: PartialEq + fmt::Display> Type<'ast, T> { - // array type equality with non-strict size checks - // sizes always match unless they are different constants - pub fn weak_eq(&self, other: &Self) -> bool { - match (self, other) { - (Type::Array(t), Type::Array(u)) => t.ty.weak_eq(&u.ty), - (Type::Struct(t), Type::Struct(u)) => t - .members - .iter() - .zip(u.members.iter()) - .all(|(m, n)| m.ty.weak_eq(&n.ty)), - (t, u) => t == u, - } - } -} - fn try_from_g_array_type, U>( t: GArrayType, ) -> Result, SpecializationError> { @@ -370,9 +365,18 @@ pub type DeclarationStructType<'ast> = GStructType>; pub type ConcreteStructType = GStructType; pub type StructType<'ast, T> = GStructType>; -impl PartialEq for GStructType { - fn eq(&self, other: &Self) -> bool { - self.canonical_location.eq(&other.canonical_location) && self.generics.eq(&other.generics) +impl<'ast, S, R: PartialEq> PartialEq> for GStructType { + fn eq(&self, other: &GStructType) -> bool { + self.canonical_location == other.canonical_location + && self + .generics + .iter() + .zip(other.generics.iter()) + .all(|(a, b)| match (a, b) { + (Some(a), Some(b)) => a == b, + (None, None) => true, + _ => false, + }) } } @@ -427,11 +431,11 @@ impl<'ast> From for DeclarationStructType<'ast> { } } -impl<'ast, T> From> for StructType<'ast, T> { - fn from(t: DeclarationStructType<'ast>) -> Self { - try_from_g_struct_type(t).unwrap() - } -} +// impl<'ast, T> From> for StructType<'ast, T> { +// fn from(t: DeclarationStructType<'ast>) -> Self { +// try_from_g_struct_type(t).unwrap() +// } +// } impl GStructType { pub fn new( @@ -514,7 +518,7 @@ impl fmt::Display for UBitwidth { } } -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[derive(Clone, Eq, Hash, PartialOrd, Ord, Debug)] pub enum GType { FieldElement, Boolean, @@ -624,13 +628,13 @@ pub type DeclarationType<'ast> = GType>; pub type ConcreteType = GType; pub type Type<'ast, T> = GType>; -impl<'ast, T: PartialEq> PartialEq> for Type<'ast, T> { - fn eq(&self, other: &DeclarationType<'ast>) -> bool { +impl<'ast, S, R: PartialEq> PartialEq> for GType { + fn eq(&self, other: >ype) -> bool { use self::GType::*; match (self, other) { (Array(l), Array(r)) => l == r, - (Struct(l), Struct(r)) => l.canonical_location == r.canonical_location, + (Struct(l), Struct(r)) => l == r, (FieldElement, FieldElement) | (Boolean, Boolean) => true, (Uint(l), Uint(r)) => l == r, _ => false, @@ -638,7 +642,7 @@ impl<'ast, T: PartialEq> PartialEq> for Type<'ast, T> { } } -fn try_from_g_type, U>(t: GType) -> Result, SpecializationError> { +pub fn try_from_g_type, U>(t: GType) -> Result, SpecializationError> { match t { GType::FieldElement => Ok(GType::FieldElement), GType::Boolean => Ok(GType::Boolean), @@ -669,12 +673,6 @@ impl<'ast> From for DeclarationType<'ast> { } } -impl<'ast, T> From> for Type<'ast, T> { - fn from(t: DeclarationType<'ast>) -> Self { - try_from_g_type(t).unwrap() - } -} - impl> From<(GType, U)> for GArrayType { fn from(tup: (GType, U)) -> Self { GArrayType { @@ -758,7 +756,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> { pub fn can_be_specialized_to(&self, other: &DeclarationType) -> bool { use self::GType::*; - if self == other { + if other == self { true } else { match (self, other) { @@ -776,7 +774,13 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> { } _ => false, }, - (Struct(_), Struct(_)) => false, + (Struct(l), Struct(r)) => { + l.canonical_location == r.canonical_location + && l.members + .iter() + .zip(r.members.iter()) + .all(|(m, d_m)| m.ty.can_be_specialized_to(&*d_m.ty)) + } _ => false, } } @@ -889,14 +893,6 @@ impl<'ast, T> TryFrom> for ConcreteFunctionKey<'ast> { } } -// impl<'ast> TryFrom> for ConcreteFunctionKey<'ast> { -// type Error = SpecializationError; - -// fn try_from(k: DeclarationFunctionKey<'ast>) -> Result { -// try_from_g_function_key(k) -// } -// } - impl<'ast, T> From> for FunctionKey<'ast, T> { fn from(k: ConcreteFunctionKey<'ast>) -> Self { try_from_g_function_key(k).unwrap() @@ -909,12 +905,6 @@ impl<'ast> From> for DeclarationFunctionKey<'ast> { } } -impl<'ast, T> From> for FunctionKey<'ast, T> { - fn from(k: DeclarationFunctionKey<'ast>) -> Self { - try_from_g_function_key(k).unwrap() - } -} - impl<'ast, S> GFunctionKey<'ast, S> { pub fn with_location, U: Into>>( module: T, @@ -993,7 +983,7 @@ pub fn check_type<'ast, S: Clone + PartialEq + PartialEq>( } } -pub fn specialize_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( +pub fn specialize_declaration_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( decl_ty: DeclarationType<'ast>, constants: &GGenericsAssignment<'ast, S>, ) -> Result, GenericIdentifier<'ast>> { @@ -1002,7 +992,7 @@ pub fn specialize_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( DeclarationType::Array(t0) => { // let s1 = t1.size.clone(); - let ty = box specialize_type(*t0.ty, &constants)?; + let ty = box specialize_declaration_type(*t0.ty, &constants)?; let size = match t0.size { DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), DeclarationConstant::Concrete(s) => Ok(s.into()), @@ -1022,7 +1012,8 @@ pub fn specialize_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( .into_iter() .map(|m| { let id = m.id; - specialize_type(*m.ty, constants).map(|ty| GStructMember { ty: box ty, id }) + specialize_declaration_type(*m.ty, constants) + .map(|ty| GStructMember { ty: box ty, id }) }) .collect::>()?, generics: s0 @@ -1049,7 +1040,9 @@ pub fn specialize_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( }) } -pub use self::signature::{ConcreteSignature, DeclarationSignature, GSignature, Signature}; +pub use self::signature::{ + try_from_g_signature, ConcreteSignature, DeclarationSignature, GSignature, Signature, +}; pub mod signature { use super::*; @@ -1194,7 +1187,7 @@ pub mod signature { self.outputs .clone() .into_iter() - .map(|t| specialize_type(t, &constants)) + .map(|t| specialize_declaration_type(t, &constants)) .collect::>() } } @@ -1244,12 +1237,6 @@ pub mod signature { } } - impl<'ast, T> From> for Signature<'ast, T> { - fn from(s: DeclarationSignature<'ast>) -> Self { - try_from_g_signature(s).unwrap() - } - } - impl fmt::Display for GSignature { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if !self.generics.is_empty() { diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index 27ced9176..f49a86b90 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -45,7 +45,7 @@ impl<'ast, T> From> for Variable<'ast, T> { impl<'ast, T> From> for Variable<'ast, T> { fn from(v: DeclarationVariable<'ast>) -> Self { - let _type = v._type.into(); + let _type = crate::typed_absy::types::try_from_g_type(v._type).unwrap(); Self { _type, id: v.id } } From 044da908ea5aea7c099e493085fe0384073103c2 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 12:05:25 +0200 Subject: [PATCH 10/86] implement display for const declaration, add breaking test for wrong const type --- .../compile_errors/constant_type_error.zok | 4 +++ zokrates_core/src/semantics.rs | 25 ++++++++++--------- zokrates_core/src/typed_absy/folder.rs | 1 + zokrates_core/src/typed_absy/mod.rs | 7 +++--- zokrates_core/src/typed_absy/result_folder.rs | 1 + zokrates_core/src/typed_absy/types.rs | 13 ++++++++-- 6 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 zokrates_cli/examples/compile_errors/constant_type_error.zok diff --git a/zokrates_cli/examples/compile_errors/constant_type_error.zok b/zokrates_cli/examples/compile_errors/constant_type_error.zok new file mode 100644 index 000000000..feebb7f56 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/constant_type_error.zok @@ -0,0 +1,4 @@ +const u32[2] A = [1] + +def main() -> u32[2]: + return A \ No newline at end of file diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 2dd02f017..93eede6dd 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -56,8 +56,8 @@ impl ErrorInner { } type TypeMap<'ast> = HashMap>>; -type ConstantMap<'ast, T> = - HashMap, Type<'ast, T>>>; +type ConstantMap<'ast> = + HashMap, DeclarationType<'ast>>>; /// The global state of the program during semantic checks #[derive(Debug)] @@ -69,7 +69,7 @@ struct State<'ast, T> { /// The user-defined types, which we keep track at this phase only. In later phases, we rely only on basic types and combinations thereof types: TypeMap<'ast>, // The user-defined constants - constants: ConstantMap<'ast, T>, + constants: ConstantMap<'ast>, } /// A symbol for a given name: either a type or a group of functions. Not both! @@ -355,7 +355,7 @@ impl<'ast, T: Field> Checker<'ast, T> { c: ConstantDefinitionNode<'ast>, module_id: &ModuleId, state: &State<'ast, T>, - ) -> Result, ErrorInner> { + ) -> Result<(DeclarationType<'ast>, TypedConstant<'ast, T>), ErrorInner> { let pos = c.pos(); let ty = self.check_declaration_type( c.value.ty.clone(), @@ -396,7 +396,7 @@ impl<'ast, T: Field> Checker<'ast, T> { ty ), }) - .map(|e| TypedConstant::new(e)) + .map(|e| (ty, TypedConstant::new(e))) } fn check_struct_type_declaration( @@ -553,7 +553,7 @@ impl<'ast, T: Field> Checker<'ast, T> { } Symbol::Here(SymbolDefinition::Constant(c)) => { match self.check_constant_definition(declaration.id, c, module_id, state) { - Ok(c) => { + Ok((d_t, c)) => { match symbol_unifier.insert_constant(declaration.id) { false => errors.push( ErrorInner { @@ -570,6 +570,7 @@ impl<'ast, T: Field> Checker<'ast, T> { CanonicalConstantIdentifier::new( declaration.id, module_id.into(), + d_t.clone(), ), TypedConstantSymbol::Here(c.clone()), )); @@ -581,7 +582,7 @@ impl<'ast, T: Field> Checker<'ast, T> { .constants .entry(module_id.to_path_buf()) .or_default() - .insert(declaration.id, c.get_type()) + .insert(declaration.id, d_t) .is_none()); } }; @@ -720,11 +721,11 @@ impl<'ast, T: Field> Checker<'ast, T> { }}); } true => { - let imported_id = CanonicalConstantIdentifier::new(import.symbol_id, import.module_id); - let id = CanonicalConstantIdentifier::new(declaration.id, module_id.into()); + let imported_id = CanonicalConstantIdentifier::new(import.symbol_id, import.module_id, ty.clone()); + let id = CanonicalConstantIdentifier::new(declaration.id, module_id.into(), ty.clone()); constants.push((id.clone(), TypedConstantSymbol::There(imported_id))); - self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone())); + self.insert_into_scope(Variable::with_id_and_type(declaration.id, crate::typed_absy::types::try_from_g_type(ty.clone()).unwrap())); state .constants @@ -1260,7 +1261,7 @@ impl<'ast, T: Field> Checker<'ast, T> { &mut self, expr: ExpressionNode<'ast>, module_id: &ModuleId, - constants_map: &HashMap, Type<'ast, T>>, + constants_map: &HashMap, DeclarationType<'ast>>, generics_map: &HashMap, usize>, used_generics: &mut HashSet>, ) -> Result, ErrorInner> { @@ -1289,7 +1290,7 @@ impl<'ast, T: Field> Checker<'ast, T> { match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { match ty { - Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(CanonicalConstantIdentifier::new(name, module_id.into()))), + DeclarationType::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(CanonicalConstantIdentifier::new(name, module_id.into(), DeclarationType::Uint(UBitwidth::B32)))), _ => Err(ErrorInner { pos: Some(pos), message: format!( diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 794b4cc41..6bb1cc197 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -232,6 +232,7 @@ pub trait Folder<'ast, T: Field>: Sized { CanonicalConstantIdentifier { module: self.fold_module_id(i.module), id: i.id, + ty: box self.fold_declaration_type(*i.ty), } } diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 30ca25c3c..39deba237 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -205,7 +205,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedModule<'ast, T> { .iter() .map(|(id, symbol)| match symbol { TypedConstantSymbol::Here(ref tc) => { - format!("const {} {} = {}", "todo", id.id, tc.expression) + format!("const {} {} = {}", id.ty, id.id, tc) } TypedConstantSymbol::There(ref imported_id) => { format!( @@ -322,14 +322,13 @@ impl<'ast, T> TypedConstant<'ast, T> { impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // using `self.expression.get_type()` would be better here but ends up requiring stronger trait bounds - write!(f, "const {}({})", "todo", self.expression) + write!(f, "{}", self.expression) } } impl<'ast, T: Field> Typed<'ast, T> for TypedConstant<'ast, T> { fn get_type(&self) -> Type<'ast, T> { - self.expression.get_type() + self.expression.get_type().clone() } } diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_core/src/typed_absy/result_folder.rs index 724682110..162554706 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_core/src/typed_absy/result_folder.rs @@ -121,6 +121,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized { Ok(CanonicalConstantIdentifier { module: self.fold_module_id(i.module)?, id: i.id, + ty: box self.fold_declaration_type(*i.ty)?, }) } diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 65fec3c57..f1d84e25b 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -107,11 +107,20 @@ pub type ConstantIdentifier<'ast> = &'ast str; pub struct CanonicalConstantIdentifier<'ast> { pub module: OwnedTypedModuleId, pub id: ConstantIdentifier<'ast>, + pub ty: Box>, } impl<'ast> CanonicalConstantIdentifier<'ast> { - pub fn new(id: ConstantIdentifier<'ast>, module: OwnedTypedModuleId) -> Self { - CanonicalConstantIdentifier { module, id } + pub fn new( + id: ConstantIdentifier<'ast>, + module: OwnedTypedModuleId, + ty: DeclarationType<'ast>, + ) -> Self { + CanonicalConstantIdentifier { + module, + id, + ty: box ty, + } } } From 02a04758421c3b3a96528f03f802ada6c2d82fc7 Mon Sep 17 00:00:00 2001 From: dark64 Date: Thu, 15 Jul 2021 12:10:26 +0200 Subject: [PATCH 11/86] fix tests --- zokrates_book/src/examples/rng_tutorial.md | 88 +++++++++---------- zokrates_book/src/examples/sha256example.md | 33 ++++--- .../examples/book/rng_tutorial/get_hash.zok | 2 +- .../examples/book/rng_tutorial/reveal_bit.zok | 2 +- .../{ => sha256_tutorial}/hashexample.zok | 0 .../hashexample_updated.zok | 0 .../examples/book/sha256_tutorial/test.sh | 17 ++++ zokrates_cli/src/bin.rs | 10 +-- zokrates_cli/tests/integration.rs | 27 ++++-- 9 files changed, 99 insertions(+), 80 deletions(-) rename zokrates_cli/examples/book/{ => sha256_tutorial}/hashexample.zok (100%) rename zokrates_cli/examples/book/{ => sha256_tutorial}/hashexample_updated.zok (100%) create mode 100755 zokrates_cli/examples/book/sha256_tutorial/test.sh diff --git a/zokrates_book/src/examples/rng_tutorial.md b/zokrates_book/src/examples/rng_tutorial.md index 53bf6aa27..9e99997c4 100644 --- a/zokrates_book/src/examples/rng_tutorial.md +++ b/zokrates_book/src/examples/rng_tutorial.md @@ -24,22 +24,25 @@ In this tutorial you learn how to use Zokrates and zero knowledge proofs to reve The first step is for Alice and Bob to each come up with a preimage value and calculate the hash to commit to it. There are many ways to calculate a hash, but here we use Zokrates. -1. Create this file under the name `get_hash.zok`: +Create this file under the name `get_hash.zok`: ```zokrates {{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok}} ``` -2. Compile the program to a form that is usable for zero knowledge proofs. This command writes + +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. ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:6}} ``` -3. The input to the Zokrates program is sixteen 32 bit values, each in decimal. specify those values + +The input to the Zokrates program is sixteen 32 bit values, each in decimal. specify those values to get a hash. For example, to calculate the hash of `0x00000000000000010000000200000003000000040000000500000006...` use this command: ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:7}} ``` + The result is: ``` Computing witness... @@ -60,10 +63,8 @@ called `sha256`. {{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:1}} ``` -  - This is the main function. The input (`u32[16]`) is an array of sixteen values, each an unsigned 32-bit integer (a number -between \\(0\\) and \\( 2^{32} - 1 \\)). As you have seen above, you specify these numbers using the `-a` command +between \(0\) and \(2^{32} - 1\)). As you have seen above, you specify these numbers using the `-a` command line parameter. The total number of input bits is *32 × 16 = 512*. The output is `u32[8]`, a *32 × 8 = 256* bit value. @@ -72,8 +73,6 @@ The output is `u32[8]`, a *32 × 8 = 256* bit value. {{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:3}} ``` -  - This line does several things. First, `u32[8] h` defines a variable called `h`, whose type is an array of eight 32-bit unsigned integers. This variable is initialized using `sha256`, the function we [imported from the standard library](https://github.com/Zokrates/ZoKrates/blob/latest/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok). @@ -84,8 +83,6 @@ to divide `hashMe` into two arrays. {{#include ../../../zokrates_cli/examples/book/rng_tutorial/get_hash.zok:4}} ``` -  - Finally, return `h` to the caller to display the hash. ```zokrates @@ -97,16 +94,17 @@ Finally, return `h` to the caller to display the hash. The next step is to reveal a single bit. -1. Use this program, `reveal_bit.zok`: +Use this program, `reveal_bit.zok`: ```zokrates {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok}} ``` -2. Compile and run as you did the previous program: +Compile and run as you did the previous program: ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23:24}} ``` -3. The output should be similar to: + +The output should be similar to: ``` Witness: @@ -124,8 +122,6 @@ There are cast functions to convert `u8`s, `u16`s, and `u32`s to boolean arrays {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:2}} ``` -  - The preimage is declared `private` so it won't be revealed by the zero knowledge proof. A Zokrates function can return multiple values. In this case, it returns the hash and a boolean which is the @@ -135,8 +131,6 @@ value of the bit being revealed. {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:10}} ``` -  - To find the value of the bit being revealed, we convert the entire preimage into bits and access it at the index `bitNum`. The first line defines an array of 512 boolean values (`bool[512]`) called `preimageBits`. It is initialized to an array of 512 `false` values. The syntax `[; ]` initializes the an array of `` @@ -147,8 +141,6 @@ when it is declared. {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:11:12}} ``` -  - This is a [for loop](https://zokrates.github.io/language/control_flow.html#for-loops). For loops have to have an index of type `u32`, and their bounds need to be known at compile time. In this case, we go over each of the sixteen 32 bit words. @@ -162,16 +154,12 @@ The function we imported, `u32_to_bits`, converts a `u32` value to an array of b {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:14}} ``` -  - The inner loop copies the bits from `val` to `preimageBits`, the bit array for the preimage. ```zokrates {{#include ../../../zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok:15:18}} ``` -  - To return multiple values, separate them by commas. ```zokrates @@ -193,40 +181,41 @@ Proofs give us. ### Set up the environment -1. Create two separate directories, `alice` and `bob`. You will perform the actions of Alice in the `alice` directory, - and the actions of Bob in the `bob` directory. +Create two separate directories, `alice` and `bob`. You will perform the actions of Alice in the `alice` directory, +and the actions of Bob in the `bob` directory. ### Bob's setup stage -2. Compile `reveal_bit.zok` and create the proving and verification keys. +Compile `reveal_bit.zok` and create the proving and verification keys. ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:16:17}} ``` -3. Copy the file `proving.key` to Alice's directory. + +Copy the file `proving.key` to Alice's directory. ### Alice reveals a bit -4. Alice should compile `reveal_bit.zok` independently to make sure it doesn't disclose information she wants to keep secret. +Alice should compile `reveal_bit.zok` independently to make sure it doesn't disclose information she wants to keep secret. ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23}} ``` -5. Next, Alice creates the `witness` file with the values of all the parameters in the program. Using this `witness`, - Bob's `proving.key`, and the compiled program she generates the actual proof. +Next, Alice creates the `witness` file with the values of all the parameters in the program. Using this `witness`, +Bob's `proving.key`, and the compiled program she generates the actual proof. ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:24:25}} ``` -6. The proof is created in the file `proof.json`. Copy this file to Bob's directory. +The proof is created in the file `proof.json`. Copy this file to Bob's directory. ### Bob accepts the proof -7. Finally, Bob verifies the proof: +Finally, Bob verifies the proof: ``` {{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:31}} ``` -8. As a sanity check, modify any of the values in `proof.json` and see that the verification fails. +As a sanity check, modify any of the values in `proof.json` and see that the verification fails. ## Connecting to Ethereum @@ -244,43 +233,52 @@ Here are the instructions to use this program when using [Truffle and Ganache](h We'll assume they are installed, and the Ganache blockchain is running. 1. Create a new project with `truffle init` and copy `verify.sol` to the subdirectory `contracts`. -1. Identify the version of Solidity used by `verifier.sol`: + +2. Identify the version of Solidity used by `verifier.sol`: ``` grep solidity contracts/verifier.sol ``` -1. Edit `truffle-config.js`: + +3. Edit `truffle-config.js`: * Change `module.exports.compilers.solc.version` to the version required by `verifier.sol`. * Uncomment `modules.exports.networks.development`. Make sure you delete the comma after the definition. -1. Compile the contract. + +4. Compile the contract. ``` truffle compile ``` -1. Start the Truffle console. The rest of this procedure is done in the JavaScript prompt inside that console. + +5. Start the Truffle console. The rest of this procedure is done in the JavaScript prompt inside that console. ``` truffle console ``` -1. Deploy the Verifier contract. + +6. Deploy the Verifier contract. ```javascript contract = await Verifier.new() ``` -1. Read the content of `proof.json`. + +7. Read the content of `proof.json`. ```javascript proof = JSON.parse(fs.readFileSync("path/to/your/proof.json")) ``` -1. Verify the proof. Check that you get the result `true`. + +8. Verify the proof. Check that you get the result `true`. ```javascript await contract.verifyTx(proof.proof.a, proof.proof.b, proof.proof.c, proof.inputs) ``` -1. Pretend to be Alice and try to cheat. Create `cheat` which flips the result + +9. Pretend to be Alice and try to cheat. Create `cheat` which flips the result bit. ```javascript cheat = [...proof.inputs] cheat[cheat.length-1] = cheat[cheat.length-1].replace(/[01]$/, cheat[cheat.length-1][65] == '1' ? '0': '1') ``` -1. As Bob, try to verify a cheating proof, and check that it fails. - ```javascript - await contract.verifyTx(proof.proof.a, proof.proof.b, proof.proof.c, cheat) - ``` + +10. As Bob, try to verify a cheating proof, and check that it fails. + ```javascript + await contract.verifyTx(proof.proof.a, proof.proof.b, proof.proof.c, cheat) + ``` ## Conclusion diff --git a/zokrates_book/src/examples/sha256example.md b/zokrates_book/src/examples/sha256example.md index 208b03144..eca02435d 100644 --- a/zokrates_book/src/examples/sha256example.md +++ b/zokrates_book/src/examples/sha256example.md @@ -16,7 +16,7 @@ We will start this tutorial by using ZoKrates to compute the hash for an arbitra First, we create a new file named `hashexample.zok` with the following content: ```zokrates -{{#include ../../../zokrates_cli/examples/book/hashexample.zok}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/hashexample.zok}} ``` The first line imports the `sha256packed` function from the ZoKrates standard library. @@ -31,22 +31,22 @@ Having our problem described in ZoKrates' DSL, we can now continue using ZoKrate First, we compile the program into an arithmetic circuit using the `compile` command. -```sh -./zokrates compile -i hashexample.zok +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:6}} ``` As a next step we can create a witness file using the following command: -```sh -./zokrates compute-witness -a 0 0 0 5 +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:7}} ``` Using the flag `-a` we pass arguments to the program. Recall that our goal is to compute the hash for the number `5`. Consequently we set `a`, `b` and `c` to `0` and `d` to `5`. Still here? Great! At this point, we can check the `witness` file for the return values: -```sh -grep '~out' witness +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:9}} ``` which should lead to the following output: @@ -70,22 +70,21 @@ To make it work, the two parties have to follow their roles in the protocol: First, Victor has to specify what hash he is interested in. Therefore, we have to adjust the zkSNARK circuit, compiled by ZoKrates, such that in addition to computing the digest, it also validates it against the digest of interest, provided by Victor. This leads to the following update for `hashexample.zok`: ```zokrates -{{#include ../../../zokrates_cli/examples/book/hashexample_updated.zok}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/hashexample_updated.zok}} ``` Note that we now compare the result of `sha256packed` with the hard-coded correct solution defined by Victor. The lines which we added are treated as assertions: the verifier will not accept a proof where these constraints were not satisfied. Clearly, this program only returns 1 if all of the computed bits are equal. So, having defined the program, Victor is now ready to compile the code: -```sh -./zokrates compile -i hashexample.zok +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:13}} ``` Based on that Victor can run the setup phase and export a verifier smart contract as a Solidity file: -```sh -./zokrates setup -./zokrates export-verifier +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:14:15}} ``` `setup` creates a `verifiation.key` file and a `proving.key` file. Victor gives the proving key to Peggy. @@ -94,14 +93,14 @@ Based on that Victor can run the setup phase and export a verifier smart contrac Peggy provides the correct pre-image as an argument to the program. -```sh -./zokrates compute-witness -a 0 0 0 5 +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:16}} ``` Finally, Peggy can run the command to construct the proof: -```sh -./zokrates generate-proof +``` +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:17}} ``` As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero-knowledge property of the protocol. diff --git a/zokrates_cli/examples/book/rng_tutorial/get_hash.zok b/zokrates_cli/examples/book/rng_tutorial/get_hash.zok index 5e672a89b..5bfd8e909 100644 --- a/zokrates_cli/examples/book/rng_tutorial/get_hash.zok +++ b/zokrates_cli/examples/book/rng_tutorial/get_hash.zok @@ -2,4 +2,4 @@ import "hashes/sha256/512bit" as sha256 def main(u32[16] hashMe) -> u32[8]: u32[8] h = sha256(hashMe[0..8], hashMe[8..16]) - return h + return h \ No newline at end of file diff --git a/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok b/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok index 51938c655..0b0f8c464 100644 --- a/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok +++ b/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok @@ -17,4 +17,4 @@ def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool): endfor endfor - return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum] + return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum] \ No newline at end of file diff --git a/zokrates_cli/examples/book/hashexample.zok b/zokrates_cli/examples/book/sha256_tutorial/hashexample.zok similarity index 100% rename from zokrates_cli/examples/book/hashexample.zok rename to zokrates_cli/examples/book/sha256_tutorial/hashexample.zok diff --git a/zokrates_cli/examples/book/hashexample_updated.zok b/zokrates_cli/examples/book/sha256_tutorial/hashexample_updated.zok similarity index 100% rename from zokrates_cli/examples/book/hashexample_updated.zok rename to zokrates_cli/examples/book/sha256_tutorial/hashexample_updated.zok diff --git a/zokrates_cli/examples/book/sha256_tutorial/test.sh b/zokrates_cli/examples/book/sha256_tutorial/test.sh new file mode 100755 index 000000000..ee4727892 --- /dev/null +++ b/zokrates_cli/examples/book/sha256_tutorial/test.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +alias zokrates=$1 + +zokrates compile -i hashexample.zok +zokrates compute-witness -a 0 0 0 5 + +grep '~out' witness + +cp -f hashexample_updated.zok hashexample.zok + +zokrates compile -i hashexample.zok +zokrates setup +zokrates export-verifier +zokrates compute-witness -a 0 0 0 5 +zokrates generate-proof \ No newline at end of file diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 907c65f40..ad957483f 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -124,20 +124,14 @@ mod tests { builder .spawn(|| { - for p in glob("./examples/**/*").expect("Failed to read glob pattern") { + for p in glob("./examples/**/*.zok").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), }; - if !path.is_file() { - continue; - } - println!("Testing {:?}", path); - assert!(path.extension().expect("extension expected") == "zok"); - let should_error = path.to_str().unwrap().contains("compile_errors"); let file = File::open(path.clone()).unwrap(); @@ -196,7 +190,7 @@ mod tests { #[test] fn execute_examples_err() { //these examples should compile but not run - for p in glob("./examples/runtime_errors/*").expect("Failed to read glob pattern") { + for p in glob("./examples/runtime_errors/*.zok").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index d8d46832e..ec2784bbb 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -4,6 +4,7 @@ extern crate serde_json; #[cfg(test)] mod integration { + use glob::glob; use serde_json::from_reader; use std::fs; use std::fs::File; @@ -410,16 +411,26 @@ mod integration { let tmp_dir = TempDir::new(".tmp").unwrap(); let tmp_base = tmp_dir.path(); - let dir = Path::new("./examples/book/rng_tutorial"); - let entries = std::fs::read_dir(dir) - .unwrap() - .map(|res| res.map(|e| e.path())) - .collect::, std::io::Error>>() + for p in glob("./examples/book/rng_tutorial/*").expect("Failed to read glob pattern") { + let path = p.unwrap(); + std::fs::copy(path.clone(), tmp_base.join(path.file_name().unwrap())).unwrap(); + } + + assert_cli::Assert::command(&["./test.sh", env!("CARGO_BIN_EXE_zokrates")]) + .current_dir(tmp_base) + .succeeds() .unwrap(); + } - entries.iter().for_each(|p| { - std::fs::copy(p, tmp_base.join(p.file_name().unwrap())).unwrap(); - }); + #[test] + fn test_sha256_tutorial() { + let tmp_dir = TempDir::new(".tmp").unwrap(); + let tmp_base = tmp_dir.path(); + + for p in glob("./examples/book/sha256_tutorial/*").expect("Failed to read glob pattern") { + let path = p.unwrap(); + std::fs::copy(path.clone(), tmp_base.join(path.file_name().unwrap())).unwrap(); + } assert_cli::Assert::command(&["./test.sh", env!("CARGO_BIN_EXE_zokrates")]) .current_dir(tmp_base) From f52250f6e8fde355bf83fad6180389c24d266f3b Mon Sep 17 00:00:00 2001 From: dark64 Date: Thu, 15 Jul 2021 12:46:56 +0200 Subject: [PATCH 12/86] remove alias --- zokrates_book/src/examples/rng_tutorial.md | 16 ++++++++-------- zokrates_book/src/examples/sha256example.md | 14 +++++++------- zokrates_cli/examples/book/rng_tutorial/test.sh | 6 +++++- .../examples/book/sha256_tutorial/test.sh | 6 +++++- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/zokrates_book/src/examples/rng_tutorial.md b/zokrates_book/src/examples/rng_tutorial.md index 9e99997c4..f4ce6adf1 100644 --- a/zokrates_book/src/examples/rng_tutorial.md +++ b/zokrates_book/src/examples/rng_tutorial.md @@ -33,14 +33,14 @@ Compile the program to a form that is usable for zero knowledge proofs. This com 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. ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:6}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:10}} ``` The input to the Zokrates program is sixteen 32 bit values, each in decimal. specify those values to get a hash. For example, to calculate the hash of `0x00000000000000010000000200000003000000040000000500000006...` use this command: ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:7}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:11}} ``` The result is: @@ -101,7 +101,7 @@ Use this program, `reveal_bit.zok`: Compile and run as you did the previous program: ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23:24}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:27:28}} ``` The output should be similar to: @@ -188,7 +188,7 @@ and the actions of Bob in the `bob` directory. Compile `reveal_bit.zok` and create the proving and verification keys. ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:16:17}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:20:21}} ``` Copy the file `proving.key` to Alice's directory. @@ -197,13 +197,13 @@ Copy the file `proving.key` to Alice's directory. Alice should compile `reveal_bit.zok` independently to make sure it doesn't disclose information she wants to keep secret. ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:23}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:27}} ``` Next, Alice creates the `witness` file with the values of all the parameters in the program. Using this `witness`, Bob's `proving.key`, and the compiled program she generates the actual proof. ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:24:25}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:28:29}} ``` The proof is created in the file `proof.json`. Copy this file to Bob's directory. @@ -212,7 +212,7 @@ The proof is created in the file `proof.json`. Copy this file to Bob's directory Finally, Bob verifies the proof: ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:31}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:35}} ``` As a sanity check, modify any of the values in `proof.json` and see that the verification fails. @@ -224,7 +224,7 @@ So far, Alice and Bob calculated the random bit between themselves. However, it published on the blockchain. To do this, Bob creates a Solidity program: ``` -{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:32}} +{{#include ../../../zokrates_cli/examples/book/rng_tutorial/test.sh:36}} ``` The Solidity program is called `verifier.sol`. diff --git a/zokrates_book/src/examples/sha256example.md b/zokrates_book/src/examples/sha256example.md index eca02435d..0fd050695 100644 --- a/zokrates_book/src/examples/sha256example.md +++ b/zokrates_book/src/examples/sha256example.md @@ -32,13 +32,13 @@ Having our problem described in ZoKrates' DSL, we can now continue using ZoKrate First, we compile the program into an arithmetic circuit using the `compile` command. ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:6}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:10}} ``` As a next step we can create a witness file using the following command: ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:7}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:11}} ``` Using the flag `-a` we pass arguments to the program. Recall that our goal is to compute the hash for the number `5`. Consequently we set `a`, `b` and `c` to `0` and `d` to `5`. @@ -46,7 +46,7 @@ Using the flag `-a` we pass arguments to the program. Recall that our goal is to Still here? Great! At this point, we can check the `witness` file for the return values: ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:9}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:13}} ``` which should lead to the following output: @@ -78,13 +78,13 @@ Note that we now compare the result of `sha256packed` with the hard-coded correc So, having defined the program, Victor is now ready to compile the code: ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:13}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:17}} ``` Based on that Victor can run the setup phase and export a verifier smart contract as a Solidity file: ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:14:15}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:18:19}} ``` `setup` creates a `verifiation.key` file and a `proving.key` file. Victor gives the proving key to Peggy. @@ -94,13 +94,13 @@ Based on that Victor can run the setup phase and export a verifier smart contrac Peggy provides the correct pre-image as an argument to the program. ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:16}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:20}} ``` Finally, Peggy can run the command to construct the proof: ``` -{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:17}} +{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:21}} ``` As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero-knowledge property of the protocol. diff --git a/zokrates_cli/examples/book/rng_tutorial/test.sh b/zokrates_cli/examples/book/rng_tutorial/test.sh index a352fb938..9b1a8bfd9 100755 --- a/zokrates_cli/examples/book/rng_tutorial/test.sh +++ b/zokrates_cli/examples/book/rng_tutorial/test.sh @@ -1,7 +1,11 @@ #!/bin/bash set -e -alias zokrates=$1 +bin=$1 + +function zokrates() { + $bin $* +} zokrates compile -i get_hash.zok -o get_hash --ztf zokrates compute-witness --verbose -i get_hash -a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 diff --git a/zokrates_cli/examples/book/sha256_tutorial/test.sh b/zokrates_cli/examples/book/sha256_tutorial/test.sh index ee4727892..40648a560 100755 --- a/zokrates_cli/examples/book/sha256_tutorial/test.sh +++ b/zokrates_cli/examples/book/sha256_tutorial/test.sh @@ -1,7 +1,11 @@ #!/bin/bash set -e -alias zokrates=$1 +bin=$1 + +function zokrates() { + $bin $* +} zokrates compile -i hashexample.zok zokrates compute-witness -a 0 0 0 5 From 0554f799c50c5e58842b7b978af525e4f6eb281a Mon Sep 17 00:00:00 2001 From: dark64 Date: Thu, 15 Jul 2021 13:43:44 +0200 Subject: [PATCH 13/86] use correct stdlib path in tutorial tests --- .../examples/book/rng_tutorial/test.sh | 4 +-- .../examples/book/sha256_tutorial/test.sh | 4 +-- zokrates_cli/tests/integration.rs | 28 +++++++++++++------ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/zokrates_cli/examples/book/rng_tutorial/test.sh b/zokrates_cli/examples/book/rng_tutorial/test.sh index 9b1a8bfd9..ba4cd113c 100755 --- a/zokrates_cli/examples/book/rng_tutorial/test.sh +++ b/zokrates_cli/examples/book/rng_tutorial/test.sh @@ -1,10 +1,10 @@ #!/bin/bash set -e -bin=$1 +bin=$1; stdlib=$2 function zokrates() { - $bin $* + ZOKRATES_STDLIB=$stdlib $bin $* } zokrates compile -i get_hash.zok -o get_hash --ztf diff --git a/zokrates_cli/examples/book/sha256_tutorial/test.sh b/zokrates_cli/examples/book/sha256_tutorial/test.sh index 40648a560..89fb75583 100755 --- a/zokrates_cli/examples/book/sha256_tutorial/test.sh +++ b/zokrates_cli/examples/book/sha256_tutorial/test.sh @@ -1,10 +1,10 @@ #!/bin/bash set -e -bin=$1 +bin=$1; stdlib=$2 function zokrates() { - $bin $* + ZOKRATES_STDLIB=$stdlib $bin $* } zokrates compile -i hashexample.zok diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index ec2784bbb..80b9ad692 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -416,10 +416,16 @@ mod integration { std::fs::copy(path.clone(), tmp_base.join(path.file_name().unwrap())).unwrap(); } - assert_cli::Assert::command(&["./test.sh", env!("CARGO_BIN_EXE_zokrates")]) - .current_dir(tmp_base) - .succeeds() - .unwrap(); + let stdlib = std::fs::canonicalize("../zokrates_stdlib/stdlib").unwrap(); + + assert_cli::Assert::command(&[ + "./test.sh", + env!("CARGO_BIN_EXE_zokrates"), + stdlib.to_str().unwrap(), + ]) + .current_dir(tmp_base) + .succeeds() + .unwrap(); } #[test] @@ -432,9 +438,15 @@ mod integration { std::fs::copy(path.clone(), tmp_base.join(path.file_name().unwrap())).unwrap(); } - assert_cli::Assert::command(&["./test.sh", env!("CARGO_BIN_EXE_zokrates")]) - .current_dir(tmp_base) - .succeeds() - .unwrap(); + let stdlib = std::fs::canonicalize("../zokrates_stdlib/stdlib").unwrap(); + + assert_cli::Assert::command(&[ + "./test.sh", + env!("CARGO_BIN_EXE_zokrates"), + stdlib.to_str().unwrap(), + ]) + .current_dir(tmp_base) + .succeeds() + .unwrap(); } } From f656616683b9f1e9e6ddb3f5d2f5ccca3ec2de69 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 15:01:06 +0200 Subject: [PATCH 14/86] fix tests, add changelog --- changelogs/unreleased/945-schaeff | 1 + .../compile_errors/constant_wrong_type.zok | 4 ++ zokrates_core/src/absy/types.rs | 4 +- zokrates_core/src/semantics.rs | 6 +- .../src/static_analysis/constant_inliner.rs | 71 +++++++++++++++---- zokrates_core/src/typed_absy/abi.rs | 6 +- zokrates_core/src/typed_absy/mod.rs | 8 +-- zokrates_core/src/typed_absy/types.rs | 12 ++-- 8 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 changelogs/unreleased/945-schaeff create mode 100644 zokrates_cli/examples/compile_errors/constant_wrong_type.zok diff --git a/changelogs/unreleased/945-schaeff b/changelogs/unreleased/945-schaeff new file mode 100644 index 000000000..6a5a97b40 --- /dev/null +++ b/changelogs/unreleased/945-schaeff @@ -0,0 +1 @@ +Enable constant generics on structs \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/constant_wrong_type.zok b/zokrates_cli/examples/compile_errors/constant_wrong_type.zok new file mode 100644 index 000000000..feebb7f56 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/constant_wrong_type.zok @@ -0,0 +1,4 @@ +const u32[2] A = [1] + +def main() -> u32[2]: + return A \ No newline at end of file diff --git a/zokrates_core/src/absy/types.rs b/zokrates_core/src/absy/types.rs index 14f7274ea..a35820764 100644 --- a/zokrates_core/src/absy/types.rs +++ b/zokrates_core/src/absy/types.rs @@ -35,7 +35,9 @@ impl<'ast> fmt::Display for UnresolvedType<'ast> { generics .iter() .map(|e| { - e.as_ref().map(|e| e.to_string()).unwrap_or("_".to_string()) + e.as_ref() + .map(|e| e.to_string()) + .unwrap_or_else(|| "_".to_string()) }) .collect::>() .join(", ") diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 93eede6dd..53f007013 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1285,7 +1285,7 @@ impl<'ast, T: Field> Checker<'ast, T> { } } Expression::Identifier(name) => { - used_generics.insert(name.clone()); + used_generics.insert(name); match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { @@ -1380,7 +1380,9 @@ impl<'ast, T: Field> Checker<'ast, T> { .map(Some), None => Err(ErrorInner { pos: Some(pos), - message: format!("Expected u32 constant or identifier, but found `_`"), + message: + "Expected u32 constant or identifier, but found `_`" + .into(), }), }) .collect::>()?; diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 25b0242cd..e0d6da987 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -242,8 +242,9 @@ mod tests { use super::*; use crate::typed_absy::types::DeclarationSignature; use crate::typed_absy::{ - DeclarationFunctionKey, DeclarationType, FieldElementExpression, GType, Identifier, - TypedConstant, TypedExpression, TypedFunction, TypedFunctionSymbol, TypedStatement, + DeclarationArrayType, DeclarationFunctionKey, DeclarationType, FieldElementExpression, + GType, Identifier, TypedConstant, TypedExpression, TypedFunction, TypedFunctionSymbol, + TypedStatement, }; use zokrates_field::Bn128Field; @@ -266,7 +267,11 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - CanonicalConstantIdentifier::new(const_id, "main".into()), + CanonicalConstantIdentifier::new( + const_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( FieldElementExpression::Number(Bn128Field::from(1)), ))), @@ -353,7 +358,7 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - CanonicalConstantIdentifier::new(const_id, "main".into()), + CanonicalConstantIdentifier::new(const_id, "main".into(), DeclarationType::Boolean), TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::Boolean( BooleanExpression::Value(true), ))), @@ -441,7 +446,11 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - CanonicalConstantIdentifier::new(const_id, "main".into()), + CanonicalConstantIdentifier::new( + const_id, + "main".into(), + DeclarationType::Uint(UBitwidth::B32), + ), TypedConstantSymbol::Here(TypedConstant::new( UExpressionInner::Value(1u128) .annotate(UBitwidth::B32) @@ -541,7 +550,14 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - CanonicalConstantIdentifier::new(const_id, "main".into()), + CanonicalConstantIdentifier::new( + const_id, + "main".into(), + DeclarationType::Array(DeclarationArrayType::new( + DeclarationType::FieldElement, + 2u32, + )), + ), TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::Array( ArrayExpressionInner::Value( vec![ @@ -677,7 +693,11 @@ mod tests { .collect(), constants: vec![ ( - CanonicalConstantIdentifier::new(const_a_id, "main".into()), + CanonicalConstantIdentifier::new( + const_a_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new( TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(1), @@ -685,7 +705,11 @@ mod tests { )), ), ( - CanonicalConstantIdentifier::new(const_b_id, "main".into()), + CanonicalConstantIdentifier::new( + const_b_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new( TypedExpression::FieldElement(FieldElementExpression::Add( box FieldElementExpression::Identifier(Identifier::from( @@ -733,7 +757,11 @@ mod tests { .collect(), constants: vec![ ( - CanonicalConstantIdentifier::new(const_a_id, "main".into()), + CanonicalConstantIdentifier::new( + const_a_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new( TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(1), @@ -741,7 +769,11 @@ mod tests { )), ), ( - CanonicalConstantIdentifier::new(const_b_id, "main".into()), + CanonicalConstantIdentifier::new( + const_b_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new( TypedExpression::FieldElement(FieldElementExpression::Number( Bn128Field::from(2), @@ -792,7 +824,11 @@ mod tests { .into_iter() .collect(), constants: vec![( - CanonicalConstantIdentifier::new(foo_const_id, "foo".into()), + CanonicalConstantIdentifier::new( + foo_const_id, + "foo".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( FieldElementExpression::Number(Bn128Field::from(42)), ))), @@ -821,10 +857,15 @@ mod tests { .into_iter() .collect(), constants: vec![( - CanonicalConstantIdentifier::new(foo_const_id, "main".into()), + CanonicalConstantIdentifier::new( + foo_const_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::There(CanonicalConstantIdentifier::new( foo_const_id, "foo".into(), + DeclarationType::FieldElement, )), )] .into_iter() @@ -862,7 +903,11 @@ mod tests { .into_iter() .collect(), constants: vec![( - CanonicalConstantIdentifier::new(foo_const_id, "main".into()), + CanonicalConstantIdentifier::new( + foo_const_id, + "main".into(), + DeclarationType::FieldElement, + ), TypedConstantSymbol::Here(TypedConstant::new(TypedExpression::FieldElement( FieldElementExpression::Number(Bn128Field::from(42)), ))), diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index 4aa831a8c..db30311a4 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -395,7 +395,7 @@ mod tests { ConcreteStructMember::new(String::from("c"), ConcreteType::Boolean), ], )), - 2, + 2usize, )), }], outputs: vec![ConcreteType::Boolean], @@ -449,8 +449,8 @@ mod tests { name: String::from("a"), public: false, ty: ConcreteType::Array(ConcreteArrayType::new( - ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2)), - 2, + ConcreteType::Array(ConcreteArrayType::new(ConcreteType::FieldElement, 2usize)), + 2usize, )), }], outputs: vec![ConcreteType::FieldElement], diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 39deba237..7b353f451 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -20,9 +20,9 @@ pub use self::identifier::CoreIdentifier; pub use self::parameter::{DeclarationParameter, GParameter}; pub use self::types::{ CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteType, - ConstantIdentifier, DeclarationFunctionKey, DeclarationSignature, DeclarationType, GArrayType, - GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, Type, Types, - UBitwidth, + ConstantIdentifier, DeclarationArrayType, DeclarationFunctionKey, DeclarationSignature, + DeclarationStructType, DeclarationType, GArrayType, GStructType, GType, GenericIdentifier, + IntoTypes, Signature, StructType, Type, Types, UBitwidth, }; use crate::typed_absy::types::ConcreteGenericsAssignment; @@ -328,7 +328,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> { impl<'ast, T: Field> Typed<'ast, T> for TypedConstant<'ast, T> { fn get_type(&self) -> Type<'ast, T> { - self.expression.get_type().clone() + self.expression.get_type() } } diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index f1d84e25b..888422ef7 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -692,10 +692,10 @@ impl> From<(GType, U)> for GArrayType { } impl GArrayType { - pub fn new(ty: GType, size: S) -> Self { + pub fn new>(ty: GType, size: U) -> Self { GArrayType { ty: Box::new(ty), - size, + size: size.into(), } } } @@ -1031,7 +1031,7 @@ pub fn specialize_declaration_type<'ast, S: Clone + PartialEq + From + fmt: .map(|g| match g { Some(constant) => match constant { DeclarationConstant::Generic(s) => { - constants.0.get(&s).cloned().ok_or(s).map(|v| Some(v)) + constants.0.get(&s).cloned().ok_or(s).map(Some) } DeclarationConstant::Concrete(s) => Ok(Some(s.into())), DeclarationConstant::Constant(..) => { @@ -1384,8 +1384,7 @@ pub mod signature { GenericIdentifier { name: "P", index: 0, - } - .into(), + }, ))]); let generic2 = DeclarationSignature::new() .generics(vec![Some( @@ -1400,8 +1399,7 @@ pub mod signature { GenericIdentifier { name: "Q", index: 0, - } - .into(), + }, ))]); assert_eq!(generic1, generic2); From 7f33ddf4f770ee3f5ad012cad5469c13aaf7cca7 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 15:01:42 +0200 Subject: [PATCH 15/86] remove duplicated example --- zokrates_cli/examples/compile_errors/constant_wrong_type.zok | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 zokrates_cli/examples/compile_errors/constant_wrong_type.zok diff --git a/zokrates_cli/examples/compile_errors/constant_wrong_type.zok b/zokrates_cli/examples/compile_errors/constant_wrong_type.zok deleted file mode 100644 index feebb7f56..000000000 --- a/zokrates_cli/examples/compile_errors/constant_wrong_type.zok +++ /dev/null @@ -1,4 +0,0 @@ -const u32[2] A = [1] - -def main() -> u32[2]: - return A \ No newline at end of file From db2e0f08491f8744d4a816bbc7d4917ee12ffc53 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Mon, 3 May 2021 23:14:36 +0200 Subject: [PATCH 16/86] Bump Solidity version --- zokrates_core/src/proof_system/solidity.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zokrates_core/src/proof_system/solidity.rs b/zokrates_core/src/proof_system/solidity.rs index 1eee2b002..16e54c50e 100644 --- a/zokrates_core/src/proof_system/solidity.rs +++ b/zokrates_core/src/proof_system/solidity.rs @@ -25,7 +25,7 @@ impl SolidityAbi { pub const SOLIDITY_G2_ADDITION_LIB: &str = r#"// SPDX-License-Identifier: LGPL-3.0-only // This file is LGPL3 Licensed -pragma solidity ^0.6.1; +pragma solidity ^0.8.0; /** * @title Elliptic curve operations on twist points for alt_bn128 @@ -427,8 +427,8 @@ pub const SOLIDITY_PAIRING_LIB_V2: &str = r#"// This file is MIT Licensed. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pragma solidity ^0.6.1; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; + library Pairing { struct G1Point { uint X; @@ -576,7 +576,7 @@ pub const SOLIDITY_PAIRING_LIB: &str = r#"// This file is MIT Licensed. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pragma solidity ^0.6.1; +pragma solidity ^0.8.0; library Pairing { struct G1Point { uint X; From de93e500981cfea30fb7368af57dc1d3d4ab6eeb Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 16:46:08 +0200 Subject: [PATCH 17/86] fix early specialization panic --- zokrates_core/src/semantics.rs | 5 +++++ zokrates_core/src/typed_absy/types.rs | 31 +++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 53f007013..29bb9e935 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -357,6 +357,9 @@ impl<'ast, T: Field> Checker<'ast, T> { state: &State<'ast, T>, ) -> Result<(DeclarationType<'ast>, TypedConstant<'ast, T>), ErrorInner> { let pos = c.pos(); + + println!("check def {} {}", id, c); + let ty = self.check_declaration_type( c.value.ty.clone(), module_id, @@ -1325,6 +1328,8 @@ impl<'ast, T: Field> Checker<'ast, T> { generics_map: &HashMap, usize>, used_generics: &mut HashSet>, ) -> Result, ErrorInner> { + println!("check {}", ty); + let pos = ty.pos(); let ty = ty.value; diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 888422ef7..dde96217f 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -992,22 +992,35 @@ pub fn check_type<'ast, S: Clone + PartialEq + PartialEq>( } } -pub fn specialize_declaration_type<'ast, S: Clone + PartialEq + From + fmt::Debug>( +impl<'ast, T> From> for UExpression<'ast, T> { + fn from(_: CanonicalConstantIdentifier<'ast>) -> Self { + unreachable!("constants should have been removed in constant inlining") + } +} + +impl<'ast> From> for DeclarationConstant<'ast> { + fn from(c: CanonicalConstantIdentifier<'ast>) -> Self { + DeclarationConstant::Constant(c) + } +} + +pub fn specialize_declaration_type< + 'ast, + S: Clone + PartialEq + From + fmt::Debug + From>, +>( decl_ty: DeclarationType<'ast>, - constants: &GGenericsAssignment<'ast, S>, + generics: &GGenericsAssignment<'ast, S>, ) -> Result, GenericIdentifier<'ast>> { Ok(match decl_ty { DeclarationType::Int => unreachable!(), DeclarationType::Array(t0) => { // let s1 = t1.size.clone(); - let ty = box specialize_declaration_type(*t0.ty, &constants)?; + let ty = box specialize_declaration_type(*t0.ty, &generics)?; let size = match t0.size { - DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), + DeclarationConstant::Generic(s) => generics.0.get(&s).cloned().ok_or(s), DeclarationConstant::Concrete(s) => Ok(s.into()), - DeclarationConstant::Constant(..) => { - unreachable!("identifiers should have been removed in constant inlining") - } + DeclarationConstant::Constant(c) => Ok(c.into()), }?; GType::Array(GArrayType { size, ty }) @@ -1021,7 +1034,7 @@ pub fn specialize_declaration_type<'ast, S: Clone + PartialEq + From + fmt: .into_iter() .map(|m| { let id = m.id; - specialize_declaration_type(*m.ty, constants) + specialize_declaration_type(*m.ty, generics) .map(|ty| GStructMember { ty: box ty, id }) }) .collect::>()?, @@ -1031,7 +1044,7 @@ pub fn specialize_declaration_type<'ast, S: Clone + PartialEq + From + fmt: .map(|g| match g { Some(constant) => match constant { DeclarationConstant::Generic(s) => { - constants.0.get(&s).cloned().ok_or(s).map(Some) + generics.0.get(&s).cloned().ok_or(s).map(Some) } DeclarationConstant::Concrete(s) => Ok(Some(s.into())), DeclarationConstant::Constant(..) => { From ec3fca73122b63ab5fe10fbfc0799fbf992f0fea Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 15 Jul 2021 16:48:58 +0200 Subject: [PATCH 18/86] remove print --- zokrates_core/src/semantics.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 29bb9e935..2a89dc17b 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -358,8 +358,6 @@ impl<'ast, T: Field> Checker<'ast, T> { ) -> Result<(DeclarationType<'ast>, TypedConstant<'ast, T>), ErrorInner> { let pos = c.pos(); - println!("check def {} {}", id, c); - let ty = self.check_declaration_type( c.value.ty.clone(), module_id, @@ -1328,8 +1326,6 @@ impl<'ast, T: Field> Checker<'ast, T> { generics_map: &HashMap, usize>, used_generics: &mut HashSet>, ) -> Result, ErrorInner> { - println!("check {}", ty); - let pos = ty.pos(); let ty = ty.value; From 82828560282a63364da9e00c244a8ce98e125afe Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 16 Jul 2021 12:20:34 +0200 Subject: [PATCH 19/86] use repeat on sha dummy blocks --- .../hashes/sha256/embed/1024bitPadded.zok | 38 +------------------ .../hashes/sha256/embed/256bitPadded.zok | 19 +--------- .../hashes/sha256/embed/512bitPadded.zok | 38 +------------------ 3 files changed, 5 insertions(+), 90 deletions(-) diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok index b7253006c..5d764ca7e 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -7,44 +7,10 @@ def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): // Hash is computed on the full 1024bit block size // padding does not fit in the first two blocks // add dummy block (single "1" followed by "0" + total length) - bool[256] dummyblock1 = [ - true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false - ] + bool[256] dummyblock1 = [true, ...[false; 255]] // Total length of message is 1024 bits: 0b10000000000 - bool[256] dummyblock2 = [ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false - ] + bool[256] dummyblock2 = [...[false; 245], ...[true, ...[false; 10]]] bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok index 52b666d8a..d23827601 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -7,24 +7,7 @@ def main(bool[256] a) -> (bool[256]): // Hash is computed on 256 bits of input // padding fits in the remaining 256 bits of the first block // add dummy block (single "true" followed by "false" + total length) - bool[256] dummyblock1 = [ - true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false - ] + bool[256] dummyblock1 = [...[true, ...[false; 246]], ...[true, ...[false; 8]]] bool[256] digest = sha256(a, dummyblock1) return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok index 2aba8c2a3..63ecf72e7 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -7,44 +7,10 @@ def main(bool[256] a, bool[256] b) -> (bool[256]): // Hash is computed on the full 512bit block size // padding does not fit in the primary block // add dummy block (single "1" followed by "0" + total length) - bool[256] dummyblock1 = [ - true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false - ] + bool[256] dummyblock1 = [true, ...[false; 255]] // Total length of message is 512 bits: 0b1000000000 - bool[256] dummyblock2 = [ - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false - ] + bool[256] dummyblock2 = [...[false; 246], ...[true, ...[false; 9]]] bool[256] digest = sha256(a, b, dummyblock1, dummyblock2) return digest \ No newline at end of file From 5e2d0d5b5c23ac94d9c4668da421a5457ec870d8 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Mon, 3 May 2021 23:26:25 +0200 Subject: [PATCH 20/86] Changelog --- changelogs/unreleased/844-leonardoalt | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/844-leonardoalt diff --git a/changelogs/unreleased/844-leonardoalt b/changelogs/unreleased/844-leonardoalt new file mode 100644 index 000000000..f4cd44d5d --- /dev/null +++ b/changelogs/unreleased/844-leonardoalt @@ -0,0 +1 @@ +Bump Solidity version to latest breaking release and use Solidity's ABI v2. This means that the `export-verifier` CLI flag to choose the ABI coder was removed. From 2857ceb9727218689c4c9dda986721f01f7d0334 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 4 May 2021 16:05:49 +0200 Subject: [PATCH 21/86] bump solidity in integration tests --- zokrates_cli/tests/contract/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_cli/tests/contract/package.json b/zokrates_cli/tests/contract/package.json index f7b050754..a229b88a5 100644 --- a/zokrates_cli/tests/contract/package.json +++ b/zokrates_cli/tests/contract/package.json @@ -9,7 +9,7 @@ "author": "Paul Etscheit", "license": "LGPL-3.0-only", "dependencies": { - "solc": "^0.6.1", + "solc": "0.8.0", "web3": "^1.0.0" } } From 939f1eb58cda6130798a3616352e0d2a5eda2db0 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 16 Jul 2021 12:12:06 +0200 Subject: [PATCH 22/86] Remove Sol abi differences --- zokrates_cli/src/ops/export_verifier.rs | 14 +- zokrates_cli/tests/contract/test.js | 23 +-- zokrates_cli/tests/integration.rs | 55 +++--- zokrates_core/src/proof_system/scheme/gm17.rs | 93 +--------- .../src/proof_system/scheme/groth16.rs | 86 +-------- .../src/proof_system/scheme/pghr13.rs | 114 +----------- zokrates_core/src/proof_system/solidity.rs | 166 +----------------- zokrates_js/src/lib.rs | 8 +- zokrates_js/tests/tests.js | 2 +- 9 files changed, 54 insertions(+), 507 deletions(-) diff --git a/zokrates_cli/src/ops/export_verifier.rs b/zokrates_cli/src/ops/export_verifier.rs index d19afdec6..225c8dc60 100644 --- a/zokrates_cli/src/ops/export_verifier.rs +++ b/zokrates_cli/src/ops/export_verifier.rs @@ -52,16 +52,6 @@ pub fn subcommand() -> App<'static, 'static> { .possible_values(constants::SCHEMES) .default_value(constants::G16), ) - .arg( - Arg::with_name("solidity-abi") - .short("a") - .long("solidity-abi") - .help("Flag for setting the version of the ABI Encoder used in the contract") - .takes_value(true) - .possible_values(&["v1", "v2"]) - .default_value("v1") - .required(false), - ) } pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> { @@ -99,9 +89,7 @@ fn cli_export_verifier 0 ? [args, proof[1]] : [args]; @@ -104,18 +99,6 @@ console.log(jsonInterface); }); } - function verifyTx_ABIV1(proof, account, correct) { - var args = proof[0]; - args = proof[1].length > 0 ? [...args, proof[1]] : args; - - return contract.methods.verifyTx( - ...args - ).send({ - from: account, - gas: 5000000 - }); - } - function getProof(correct) { let json = JSON.parse(fs.readFileSync(proofPath)); let inputs = json["inputs"]; diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 23afd3122..ec7485ac3 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -295,36 +295,31 @@ mod integration { .unwrap(); if scheme != &"marlin" { - for abi_version in &["v1", "v2"] { - // EXPORT-VERIFIER - assert_cli::Assert::command(&[ - "../target/release/zokrates", - "export-verifier", - "-i", - verification_key_path.to_str().unwrap(), - "-o", - verification_contract_path.to_str().unwrap(), - "--proving-scheme", - scheme, - "-a", - abi_version, - ]) - .succeeds() - .unwrap(); - - // TEST VERIFIER - assert_cli::Assert::command(&[ - "node", - "test.js", - verification_contract_path.to_str().unwrap(), - proof_path.to_str().unwrap(), - scheme, - abi_version, - ]) - .current_dir(concat!(env!("OUT_DIR"), "/contract")) - .succeeds() - .unwrap(); - } + // EXPORT-VERIFIER + assert_cli::Assert::command(&[ + "../target/release/zokrates", + "export-verifier", + "-i", + verification_key_path.to_str().unwrap(), + "-o", + verification_contract_path.to_str().unwrap(), + "--proving-scheme", + scheme, + ]) + .succeeds() + .unwrap(); + + // TEST VERIFIER + assert_cli::Assert::command(&[ + "node", + "test.js", + verification_contract_path.to_str().unwrap(), + proof_path.to_str().unwrap(), + scheme, + ]) + .current_dir(concat!(env!("OUT_DIR"), "/contract")) + .succeeds() + .unwrap(); } } } diff --git a/zokrates_core/src/proof_system/scheme/gm17.rs b/zokrates_core/src/proof_system/scheme/gm17.rs index 1541533e8..a50cd8833 100644 --- a/zokrates_core/src/proof_system/scheme/gm17.rs +++ b/zokrates_core/src/proof_system/scheme/gm17.rs @@ -1,7 +1,5 @@ use crate::proof_system::scheme::{NonUniversalScheme, Scheme}; -use crate::proof_system::solidity::{ - SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, -}; +use crate::proof_system::solidity::{SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB}; use crate::proof_system::{ G1Affine, G2Affine, G2AffineFq, SolidityCompatibleField, SolidityCompatibleScheme, }; @@ -49,20 +47,11 @@ impl Scheme for GM17 { } impl SolidityCompatibleScheme for GM17 { - fn export_solidity_verifier( - vk: >::VerificationKey, - abi: SolidityAbi, - ) -> String { - let (mut template_text, solidity_pairing_lib) = match abi { - SolidityAbi::V1 => ( - String::from(CONTRACT_TEMPLATE), - String::from(SOLIDITY_PAIRING_LIB), - ), - SolidityAbi::V2 => ( - String::from(CONTRACT_TEMPLATE_V2), - String::from(SOLIDITY_PAIRING_LIB_V2), - ), - }; + fn export_solidity_verifier(vk: >::VerificationKey) -> String { + let (mut template_text, solidity_pairing_lib) = ( + String::from(CONTRACT_TEMPLATE), + String::from(SOLIDITY_PAIRING_LIB), + ); // replace things in template let vk_regex = Regex::new(r#"(<%vk_[^i%]*%>)"#).unwrap(); @@ -158,7 +147,7 @@ impl SolidityCompatibleScheme f } } -const CONTRACT_TEMPLATE_V2: &str = r#" +const CONTRACT_TEMPLATE: &str = r#" contract Verifier { using Pairing for *; struct VerifyingKey { @@ -219,71 +208,3 @@ contract Verifier { } } "#; - -const CONTRACT_TEMPLATE: &str = r#" -contract Verifier { - using Pairing for *; - struct VerifyingKey { - Pairing.G2Point h; - Pairing.G1Point g_alpha; - Pairing.G2Point h_beta; - Pairing.G1Point g_gamma; - Pairing.G2Point h_gamma; - Pairing.G1Point[] query; - } - struct Proof { - Pairing.G1Point a; - Pairing.G2Point b; - Pairing.G1Point c; - } - function verifyingKey() pure internal returns (VerifyingKey memory vk) { - vk.h = Pairing.G2Point(<%vk_h%>); - vk.g_alpha = Pairing.G1Point(<%vk_g_alpha%>); - vk.h_beta = Pairing.G2Point(<%vk_h_beta%>); - vk.g_gamma = Pairing.G1Point(<%vk_g_gamma%>); - vk.h_gamma = Pairing.G2Point(<%vk_h_gamma%>); - vk.query = new Pairing.G1Point[](<%vk_query_length%>); - <%vk_query_pts%> - } - function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { - uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - VerifyingKey memory vk = verifyingKey(); - require(input.length + 1 == vk.query.length); - // Compute the linear combination vk_x - Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); - for (uint i = 0; i < input.length; i++) { - require(input[i] < snark_scalar_field); - vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.query[i + 1], input[i])); - } - vk_x = Pairing.addition(vk_x, vk.query[0]); - /** - * e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) - * * e(C, H) - * where psi = \sum_{i=0}^l input_i pvk.query[i] - */ - if (!Pairing.pairingProd4(vk.g_alpha, vk.h_beta, vk_x, vk.h_gamma, proof.c, vk.h, Pairing.negate(Pairing.addition(proof.a, vk.g_alpha)), Pairing.addition(proof.b, vk.h_beta))) return 1; - /** - * e(A, H^{gamma}) = e(G^{gamma}, b) - */ - if (!Pairing.pairingProd2(proof.a, vk.h_gamma, Pairing.negate(vk.g_gamma), proof.b)) return 2; - return 0; - } - function verifyTx( - uint[2] memory a, - uint[2][2] memory b, - uint[2] memory c<%input_argument%> - ) public view returns (bool r) { - Proof memory proof; - proof.a = Pairing.G1Point(a[0], a[1]); - proof.b = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); - proof.c = Pairing.G1Point(c[0], c[1]); - uint[] memory inputValues = new uint[](<%vk_input_length%>); - <%input_loop%> - if (verify(inputValues, proof) == 0) { - return true; - } else { - return false; - } - } -} -"#; diff --git a/zokrates_core/src/proof_system/scheme/groth16.rs b/zokrates_core/src/proof_system/scheme/groth16.rs index 908edb866..b84b762bb 100644 --- a/zokrates_core/src/proof_system/scheme/groth16.rs +++ b/zokrates_core/src/proof_system/scheme/groth16.rs @@ -1,7 +1,5 @@ use crate::proof_system::scheme::{NonUniversalScheme, Scheme}; -use crate::proof_system::solidity::{ - SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, -}; +use crate::proof_system::solidity::{SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB}; use crate::proof_system::{G1Affine, G2Affine, SolidityCompatibleField, SolidityCompatibleScheme}; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -33,20 +31,11 @@ impl Scheme for G16 { impl NonUniversalScheme for G16 {} impl SolidityCompatibleScheme for G16 { - fn export_solidity_verifier( - vk: >::VerificationKey, - abi: SolidityAbi, - ) -> String { - let (mut template_text, solidity_pairing_lib) = match abi { - SolidityAbi::V1 => ( - String::from(CONTRACT_TEMPLATE), - String::from(SOLIDITY_PAIRING_LIB), - ), - SolidityAbi::V2 => ( - String::from(CONTRACT_TEMPLATE_V2), - String::from(SOLIDITY_PAIRING_LIB_V2), - ), - }; + fn export_solidity_verifier(vk: >::VerificationKey) -> String { + let (mut template_text, solidity_pairing_lib) = ( + String::from(CONTRACT_TEMPLATE), + String::from(SOLIDITY_PAIRING_LIB), + ); let vk_regex = Regex::new(r#"(<%vk_[^i%]*%>)"#).unwrap(); let vk_gamma_abc_len_regex = Regex::new(r#"(<%vk_gamma_abc_length%>)"#).unwrap(); @@ -140,61 +129,6 @@ impl SolidityCompatibleScheme for G16 { } } -const CONTRACT_TEMPLATE_V2: &str = r#" -contract Verifier { - using Pairing for *; - struct VerifyingKey { - Pairing.G1Point alpha; - Pairing.G2Point beta; - Pairing.G2Point gamma; - Pairing.G2Point delta; - Pairing.G1Point[] gamma_abc; - } - struct Proof { - Pairing.G1Point a; - Pairing.G2Point b; - Pairing.G1Point c; - } - function verifyingKey() pure internal returns (VerifyingKey memory vk) { - vk.alpha = Pairing.G1Point(<%vk_alpha%>); - vk.beta = Pairing.G2Point(<%vk_beta%>); - vk.gamma = Pairing.G2Point(<%vk_gamma%>); - vk.delta = Pairing.G2Point(<%vk_delta%>); - vk.gamma_abc = new Pairing.G1Point[](<%vk_gamma_abc_length%>); - <%vk_gamma_abc_pts%> - } - function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { - uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - VerifyingKey memory vk = verifyingKey(); - require(input.length + 1 == vk.gamma_abc.length); - // Compute the linear combination vk_x - Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); - for (uint i = 0; i < input.length; i++) { - require(input[i] < snark_scalar_field); - vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.gamma_abc[i + 1], input[i])); - } - vk_x = Pairing.addition(vk_x, vk.gamma_abc[0]); - if(!Pairing.pairingProd4( - proof.a, proof.b, - Pairing.negate(vk_x), vk.gamma, - Pairing.negate(proof.c), vk.delta, - Pairing.negate(vk.alpha), vk.beta)) return 1; - return 0; - } - function verifyTx( - Proof memory proof<%input_argument%> - ) public view returns (bool r) { - uint[] memory inputValues = new uint[](<%vk_input_length%>); - <%input_loop%> - if (verify(inputValues, proof) == 0) { - return true; - } else { - return false; - } - } -} -"#; - const CONTRACT_TEMPLATE: &str = r#" contract Verifier { using Pairing for *; @@ -237,14 +171,8 @@ contract Verifier { return 0; } function verifyTx( - uint[2] memory a, - uint[2][2] memory b, - uint[2] memory c<%input_argument%> + Proof memory proof<%input_argument%> ) public view returns (bool r) { - Proof memory proof; - proof.a = Pairing.G1Point(a[0], a[1]); - proof.b = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); - proof.c = Pairing.G1Point(c[0], c[1]); uint[] memory inputValues = new uint[](<%vk_input_length%>); <%input_loop%> if (verify(inputValues, proof) == 0) { diff --git a/zokrates_core/src/proof_system/scheme/pghr13.rs b/zokrates_core/src/proof_system/scheme/pghr13.rs index a6256b665..5362f245f 100644 --- a/zokrates_core/src/proof_system/scheme/pghr13.rs +++ b/zokrates_core/src/proof_system/scheme/pghr13.rs @@ -1,7 +1,5 @@ use crate::proof_system::scheme::{NonUniversalScheme, Scheme}; -use crate::proof_system::solidity::{ - SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2, -}; +use crate::proof_system::solidity::{SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB}; use crate::proof_system::{G1Affine, G2Affine, SolidityCompatibleField, SolidityCompatibleScheme}; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -42,20 +40,11 @@ impl Scheme for PGHR13 { impl NonUniversalScheme for PGHR13 {} impl SolidityCompatibleScheme for PGHR13 { - fn export_solidity_verifier( - vk: >::VerificationKey, - abi: SolidityAbi, - ) -> String { - let (mut template_text, solidity_pairing_lib) = match abi { - SolidityAbi::V1 => ( - String::from(CONTRACT_TEMPLATE), - String::from(SOLIDITY_PAIRING_LIB), - ), - SolidityAbi::V2 => ( - String::from(CONTRACT_TEMPLATE_V2), - String::from(SOLIDITY_PAIRING_LIB_V2), - ), - }; + fn export_solidity_verifier(vk: >::VerificationKey) -> String { + let (mut template_text, solidity_pairing_lib) = ( + String::from(CONTRACT_TEMPLATE), + String::from(SOLIDITY_PAIRING_LIB), + ); // replace things in template let vk_regex = Regex::new(r#"(<%vk_[^i%]*%>)"#).unwrap(); @@ -156,79 +145,6 @@ impl SolidityCompatibleScheme for PGHR13 { } } -const CONTRACT_TEMPLATE_V2: &str = r#"contract Verifier { - using Pairing for *; - struct VerifyingKey { - Pairing.G2Point a; - Pairing.G1Point b; - Pairing.G2Point c; - Pairing.G2Point gamma; - Pairing.G1Point gamma_beta_1; - Pairing.G2Point gamma_beta_2; - Pairing.G2Point z; - Pairing.G1Point[] ic; - } - struct Proof { - Pairing.G1Point a; - Pairing.G1Point a_p; - Pairing.G2Point b; - Pairing.G1Point b_p; - Pairing.G1Point c; - Pairing.G1Point c_p; - Pairing.G1Point h; - Pairing.G1Point k; - } - function verifyingKey() pure internal returns (VerifyingKey memory vk) { - vk.a = Pairing.G2Point(<%vk_a%>); - vk.b = Pairing.G1Point(<%vk_b%>); - vk.c = Pairing.G2Point(<%vk_c%>); - vk.gamma = Pairing.G2Point(<%vk_g%>); - vk.gamma_beta_1 = Pairing.G1Point(<%vk_gb1%>); - vk.gamma_beta_2 = Pairing.G2Point(<%vk_gb2%>); - vk.z = Pairing.G2Point(<%vk_z%>); - vk.ic = new Pairing.G1Point[](<%vk_ic_length%>); - <%vk_ic_pts%> - } - function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { - uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - VerifyingKey memory vk = verifyingKey(); - require(input.length + 1 == vk.ic.length); - // Compute the linear combination vk_x - Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); - for (uint i = 0; i < input.length; i++) { - require(input[i] < snark_scalar_field); - vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.ic[i + 1], input[i])); - } - vk_x = Pairing.addition(vk_x, vk.ic[0]); - if (!Pairing.pairingProd2(proof.a, vk.a, Pairing.negate(proof.a_p), Pairing.P2())) return 1; - if (!Pairing.pairingProd2(vk.b, proof.b, Pairing.negate(proof.b_p), Pairing.P2())) return 2; - if (!Pairing.pairingProd2(proof.c, vk.c, Pairing.negate(proof.c_p), Pairing.P2())) return 3; - if (!Pairing.pairingProd3( - proof.k, vk.gamma, - Pairing.negate(Pairing.addition(vk_x, Pairing.addition(proof.a, proof.c))), vk.gamma_beta_2, - Pairing.negate(vk.gamma_beta_1), proof.b - )) return 4; - if (!Pairing.pairingProd3( - Pairing.addition(vk_x, proof.a), proof.b, - Pairing.negate(proof.h), vk.z, - Pairing.negate(proof.c), Pairing.P2() - )) return 5; - return 0; - } - function verifyTx( - Proof memory proof<%input_argument%> - ) public view returns (bool r) { - uint[] memory inputValues = new uint[](<%vk_input_length%>); - <%input_loop%> - if (verify(inputValues, proof) == 0) { - return true; - } else { - return false; - } - } -} -"#; - const CONTRACT_TEMPLATE: &str = r#"contract Verifier { using Pairing for *; struct VerifyingKey { @@ -289,24 +205,8 @@ const CONTRACT_TEMPLATE: &str = r#"contract Verifier { return 0; } function verifyTx( - uint[2] memory a, - uint[2] memory a_p, - uint[2][2] memory b, - uint[2] memory b_p, - uint[2] memory c, - uint[2] memory c_p, - uint[2] memory h, - uint[2] memory k<%input_argument%> + Proof memory proof<%input_argument%> ) public view returns (bool r) { - Proof memory proof; - proof.a = Pairing.G1Point(a[0], a[1]); - proof.a_p = Pairing.G1Point(a_p[0], a_p[1]); - proof.b = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); - proof.b_p = Pairing.G1Point(b_p[0], b_p[1]); - proof.c = Pairing.G1Point(c[0], c[1]); - proof.c_p = Pairing.G1Point(c_p[0], c_p[1]); - proof.h = Pairing.G1Point(h[0], h[1]); - proof.k = Pairing.G1Point(k[0], k[1]); uint[] memory inputValues = new uint[](<%vk_input_length%>); <%input_loop%> if (verify(inputValues, proof) == 0) { diff --git a/zokrates_core/src/proof_system/solidity.rs b/zokrates_core/src/proof_system/solidity.rs index 16e54c50e..9c1309e8d 100644 --- a/zokrates_core/src/proof_system/solidity.rs +++ b/zokrates_core/src/proof_system/solidity.rs @@ -5,22 +5,7 @@ pub trait SolidityCompatibleField: Field {} impl SolidityCompatibleField for Bn128Field {} pub trait SolidityCompatibleScheme: Scheme { - fn export_solidity_verifier(vk: Self::VerificationKey, abi: SolidityAbi) -> String; -} - -pub enum SolidityAbi { - V1, - V2, -} - -impl SolidityAbi { - pub fn from(v: &str) -> Result { - match v { - "v1" => Ok(SolidityAbi::V1), - "v2" => Ok(SolidityAbi::V2), - _ => Err("Invalid ABI version"), - } - } + fn export_solidity_verifier(vk: Self::VerificationKey) -> String; } pub const SOLIDITY_G2_ADDITION_LIB: &str = r#"// SPDX-License-Identifier: LGPL-3.0-only @@ -421,155 +406,6 @@ library BN256G2 { } "#; -pub const SOLIDITY_PAIRING_LIB_V2: &str = r#"// This file is MIT Licensed. -// -// Copyright 2017 Christian Reitwiessner -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pragma solidity ^0.8.0; - -library Pairing { - struct G1Point { - uint X; - uint Y; - } - // Encoding of field elements is: X[0] * z + X[1] - struct G2Point { - uint[2] X; - uint[2] Y; - } - /// @return the generator of G1 - function P1() pure internal returns (G1Point memory) { - return G1Point(1, 2); - } - /// @return the generator of G2 - function P2() pure internal returns (G2Point memory) { - return G2Point( - [10857046999023057135944570762232829481370756359578518086990519993285655852781, - 11559732032986387107991004021392285783925812861821192530917403151452391805634], - [8495653923123431417604973247489272438418190587263600148770280649306958101930, - 4082367875863433681332203403145435568316851327593401208105741076214120093531] - ); - } - /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. - function negate(G1Point memory p) pure internal returns (G1Point memory) { - // The prime q in the base field F_q for G1 - uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; - if (p.X == 0 && p.Y == 0) - return G1Point(0, 0); - return G1Point(p.X, q - (p.Y % q)); - } - /// @return r the sum of two points of G1 - function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { - uint[4] memory input; - input[0] = p1.X; - input[1] = p1.Y; - input[2] = p2.X; - input[3] = p2.Y; - bool success; - assembly { - success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } - require(success); - } - /// @return r the sum of two points of G2 - function addition(G2Point memory p1, G2Point memory p2) internal view returns (G2Point memory r) { - (r.X[0], r.X[1], r.Y[0], r.Y[1]) = BN256G2.ECTwistAdd(p1.X[0],p1.X[1],p1.Y[0],p1.Y[1],p2.X[0],p2.X[1],p2.Y[0],p2.Y[1]); - } - /// @return r the product of a point on G1 and a scalar, i.e. - /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. - function scalar_mul(G1Point memory p, uint s) internal view returns (G1Point memory r) { - uint[3] memory input; - input[0] = p.X; - input[1] = p.Y; - input[2] = s; - bool success; - assembly { - success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } - require (success); - } - /// @return the result of computing the pairing check - /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 - /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should - /// return true. - function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) { - require(p1.length == p2.length); - uint elements = p1.length; - uint inputSize = elements * 6; - uint[] memory input = new uint[](inputSize); - for (uint i = 0; i < elements; i++) - { - input[i * 6 + 0] = p1[i].X; - input[i * 6 + 1] = p1[i].Y; - input[i * 6 + 2] = p2[i].X[1]; - input[i * 6 + 3] = p2[i].X[0]; - input[i * 6 + 4] = p2[i].Y[1]; - input[i * 6 + 5] = p2[i].Y[0]; - } - uint[1] memory out; - bool success; - assembly { - success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } - require(success); - return out[0] != 0; - } - /// Convenience method for a pairing check for two pairs. - function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](2); - G2Point[] memory p2 = new G2Point[](2); - p1[0] = a1; - p1[1] = b1; - p2[0] = a2; - p2[1] = b2; - return pairing(p1, p2); - } - /// Convenience method for a pairing check for three pairs. - function pairingProd3( - G1Point memory a1, G2Point memory a2, - G1Point memory b1, G2Point memory b2, - G1Point memory c1, G2Point memory c2 - ) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](3); - G2Point[] memory p2 = new G2Point[](3); - p1[0] = a1; - p1[1] = b1; - p1[2] = c1; - p2[0] = a2; - p2[1] = b2; - p2[2] = c2; - return pairing(p1, p2); - } - /// Convenience method for a pairing check for four pairs. - function pairingProd4( - G1Point memory a1, G2Point memory a2, - G1Point memory b1, G2Point memory b2, - G1Point memory c1, G2Point memory c2, - G1Point memory d1, G2Point memory d2 - ) internal view returns (bool) { - G1Point[] memory p1 = new G1Point[](4); - G2Point[] memory p2 = new G2Point[](4); - p1[0] = a1; - p1[1] = b1; - p1[2] = c1; - p1[3] = d1; - p2[0] = a2; - p2[1] = b2; - p2[2] = c2; - p2[3] = d2; - return pairing(p1, p2); - } -} -"#; - pub const SOLIDITY_PAIRING_LIB: &str = r#"// This file is MIT Licensed. // // Copyright 2017 Christian Reitwiessner diff --git a/zokrates_js/src/lib.rs b/zokrates_js/src/lib.rs index 6be227ae2..bad1275d8 100644 --- a/zokrates_js/src/lib.rs +++ b/zokrates_js/src/lib.rs @@ -13,7 +13,7 @@ use zokrates_core::ir; use zokrates_core::proof_system::bellman::Bellman; use zokrates_core::proof_system::groth16::G16; use zokrates_core::proof_system::{ - Backend, NonUniversalBackend, Proof, Scheme, SolidityAbi, SolidityCompatibleScheme, + Backend, NonUniversalBackend, Proof, Scheme, SolidityCompatibleScheme, }; use zokrates_core::typed_absy::abi::Abi; use zokrates_core::typed_absy::types::ConcreteSignature as Signature; @@ -168,13 +168,9 @@ pub fn setup(program: &[u8]) -> Result { } #[wasm_bindgen] -pub fn export_solidity_verifier(vk: JsValue, abi_version: JsValue) -> Result { - let abi_version = SolidityAbi::from(abi_version.as_string().unwrap().as_str()) - .map_err(|err| JsValue::from_str(err))?; - +pub fn export_solidity_verifier(vk: JsValue) -> Result { let verifier = >::export_solidity_verifier( vk.into_serde().unwrap(), - abi_version, ); Ok(JsValue::from_str(verifier.as_str())) diff --git a/zokrates_js/tests/tests.js b/zokrates_js/tests/tests.js index 469662395..4e8b44a7d 100644 --- a/zokrates_js/tests/tests.js +++ b/zokrates_js/tests/tests.js @@ -104,7 +104,7 @@ describe('tests', function() { const artifacts = this.zokrates.compile(code); const keypair = this.zokrates.setup(artifacts.program); - const verifier = this.zokrates.exportSolidityVerifier(keypair.vk, "v1"); + const verifier = this.zokrates.exportSolidityVerifier(keypair.vk); assert.ok(verifier.length > 0); }); }); From 4e290c77a35919ff52e5a6e4b9b37b3132bc433e Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 16 Jul 2021 12:12:36 +0200 Subject: [PATCH 23/86] Enable Sol optimizer in integration tests --- zokrates_cli/tests/contract/test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zokrates_cli/tests/contract/test.js b/zokrates_cli/tests/contract/test.js index d5b38659e..5d761b555 100644 --- a/zokrates_cli/tests/contract/test.js +++ b/zokrates_cli/tests/contract/test.js @@ -16,6 +16,9 @@ let jsonContractSource = JSON.stringify({ }, }, settings: { + optimizer: { + enabled: true + }, outputSelection: { '*': { '*': ['abi', "evm.bytecode"], From 034fbaf08063dbdf7f3c0914d6097cbcb16347a5 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 16 Jul 2021 12:50:51 +0200 Subject: [PATCH 24/86] Link library properly in integration tests --- zokrates_cli/tests/contract/test.js | 37 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/zokrates_cli/tests/contract/test.js b/zokrates_cli/tests/contract/test.js index 5d761b555..d10eb0bae 100644 --- a/zokrates_cli/tests/contract/test.js +++ b/zokrates_cli/tests/contract/test.js @@ -6,9 +6,8 @@ const proofPath = process.argv[3] const format = process.argv[4] const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); -// -----Compile contract----- const source = fs.readFileSync(contractPath, 'UTF-8'); -let jsonContractSource = JSON.stringify({ +let jsonContractSource = { language: 'Solidity', sources: { [contractPath]: { @@ -20,29 +19,36 @@ let jsonContractSource = JSON.stringify({ enabled: true }, outputSelection: { - '*': { - '*': ['abi', "evm.bytecode"], + [contractPath]: { + "Verifier": ['abi', "evm.bytecode"], }, }, }, -}); +}; -let jsonInterface = JSON.parse(solc.compile(jsonContractSource)); -console.log(jsonInterface); (async () => { const accounts = await web3.eth.getAccounts(); - let abi = jsonInterface.contracts[contractPath]["Verifier"].abi; - let bytecode = jsonInterface.contracts[contractPath]["Verifier"].evm.bytecode; - //There is a solc issue, that for unknown reasons wont link the BN256G2 Library automatically for gm17 v1 and v2 contracts. I dont know why this is happening, - //the contracts compile and deploy without any issue on remix. To fix this, the the BN256G2 Library must be compiled and deployed by itself, after that, - //the library placeholder must be replaced with the library address in the contracts bytecode + // The BN256G2 library needs to be deployed and linked separately + // because it has `public` functions. + // This is not needed for the Pairing library because all its functions + // are `internal` and therefore are compiled into the contract that uses it. if (format == "gm17") { let library = await deployLibrary(); - //replace lib placeholder with lib address in bytecode - bytecode.object = bytecode.object.replace(/\_\_\$[a-f0-9]{34}\$\_\_/g, library["_address"].replace("0x", "")); + jsonContractSource.settings.libraries = { + [contractPath]: { + BN256G2: library["_address"] + } + } } + // -----Compile contract----- + let jsonInterface = JSON.parse(solc.compile(JSON.stringify(jsonContractSource))); + console.log(jsonInterface); + + let abi = jsonInterface.contracts[contractPath]["Verifier"].abi; + let bytecode = jsonInterface.contracts[contractPath]["Verifier"].evm.bytecode; + let contract = new web3.eth.Contract(abi) .deploy({ data: '0x' + bytecode.object @@ -123,6 +129,9 @@ console.log(jsonInterface); }, }, settings: { + optimizer: { + enabled: true + }, outputSelection: { '*': { '*': ['abi', "evm.bytecode"], From 292164c572537b4220c5ae97da7c286f679eb6e2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 16 Jul 2021 13:19:57 +0200 Subject: [PATCH 25/86] refactor --- zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok | 2 +- zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok | 2 +- zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok index 5d764ca7e..20f545909 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -10,7 +10,7 @@ def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): bool[256] dummyblock1 = [true, ...[false; 255]] // Total length of message is 1024 bits: 0b10000000000 - bool[256] dummyblock2 = [...[false; 245], ...[true, ...[false; 10]]] + bool[256] dummyblock2 = [...[false; 245], true, ...[false; 10]] bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok index d23827601..383009e99 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -7,7 +7,7 @@ def main(bool[256] a) -> (bool[256]): // Hash is computed on 256 bits of input // padding fits in the remaining 256 bits of the first block // add dummy block (single "true" followed by "false" + total length) - bool[256] dummyblock1 = [...[true, ...[false; 246]], ...[true, ...[false; 8]]] + bool[256] dummyblock1 = [true, ...[false; 246], true, ...[false; 8]] bool[256] digest = sha256(a, dummyblock1) return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok index 63ecf72e7..b594e691b 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -10,7 +10,7 @@ def main(bool[256] a, bool[256] b) -> (bool[256]): bool[256] dummyblock1 = [true, ...[false; 255]] // Total length of message is 512 bits: 0b1000000000 - bool[256] dummyblock2 = [...[false; 246], ...[true, ...[false; 9]]] + bool[256] dummyblock2 = [...[false; 246], true, ...[false; 9]] bool[256] digest = sha256(a, b, dummyblock1, dummyblock2) return digest \ No newline at end of file From 0ba7d4a3e53d9fe0f16aa2254c529c073b368f1c Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 16 Jul 2021 14:58:22 +0200 Subject: [PATCH 26/86] wip --- .circleci/config.yml | 108 ++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 07ea45d51..633d090a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -149,12 +149,19 @@ jobs: type: executor target: type: string + add-target: + type: boolean + default: false executor: << parameters.os >> steps: - checkout - run: name: Calculate dependencies command: cargo generate-lockfile + - when: + condition: << parameters.add-target >> + steps: + - run: rustup target add << parameters.target >> - run: no_output_timeout: "30m" command: cross build --target << parameters.target >> --release @@ -227,55 +234,70 @@ tag-only: &tag-only workflows: build-test-and-deploy: jobs: - - build - - test - - cpp_format - - wasm_test - - integration_test - - zokrates_js_build - - zokrates_js_test +# - build +# - test +# - cpp_format +# - wasm_test +# - integration_test +# - zokrates_js_build +# - zokrates_js_test +# - cross_build: +# <<: *tag-only +# pre-steps: +# - install_rust +# - install_cross +# matrix: +# alias: cross-build-linux +# parameters: +# os: +# - linux +# target: +# - aarch64-unknown-linux-gnu +# - arm-unknown-linux-gnueabi +# - x86_64-unknown-linux-gnu +# - x86_64-pc-windows-gnu +# - cross_build: +# <<: *tag-only +# pre-steps: +# - install_rust +# - install_cross +# matrix: +# alias: cross-build-macos +# parameters: +# os: +# - macos +# target: +# - x86_64-apple-darwin - cross_build: - <<: *tag-only +# <<: *tag-only pre-steps: - install_rust - install_cross + - run: xcodebuild -showsdks + add-target: true matrix: - alias: cross-build-linux - parameters: - os: - - linux - target: - - aarch64-unknown-linux-gnu - - arm-unknown-linux-gnueabi - - x86_64-unknown-linux-gnu - - x86_64-pc-windows-gnu - - cross_build: - <<: *tag-only - pre-steps: - - install_rust - - install_cross - matrix: - alias: cross-build-macos + alias: cross-build-apple-silicon parameters: os: - macos target: - - x86_64-apple-darwin - - publish_artifacts: - <<: *tag-only - requires: - - cross-build-linux - - cross-build-macos - - deploy: - filters: - branches: - only: - - deploy - requires: - - build - - test - - cpp_format - - wasm_test - - integration_test - - zokrates_js_build - - zokrates_js_test \ No newline at end of file + - aarch64-apple-darwin +# - publish_artifacts: +# <<: *tag-only +# requires: +# - cross-build-linux +# - cross-build-macos +# - cross-build-apple-silicon +# - deploy: +# filters: +# branches: +# only: +# - deploy +# requires: +# - build +# - test +# - cpp_format +# - wasm_test +# - integration_test +# - zokrates_js_build +# - zokrates_js_test \ No newline at end of file From 22e05e6d9c6dc01ef0b491b5f49156eef22b1b77 Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 16 Jul 2021 15:09:22 +0200 Subject: [PATCH 27/86] export env vars --- .circleci/config.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 633d090a8..97ad6a061 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -273,7 +273,10 @@ workflows: pre-steps: - install_rust - install_cross - - run: xcodebuild -showsdks + - run: | + xcodebuild -showsdks + export SDKROOT=$(xcrun -sdk macosx11.1 --show-sdk-path) + export MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx11.1 --show-sdk-platform-version) add-target: true matrix: alias: cross-build-apple-silicon From 51fea62a9ea37da86a1ac75d509f21920d679736 Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 16 Jul 2021 15:30:59 +0200 Subject: [PATCH 28/86] add example, and make it compile, using a DeclarationType for common type detection --- zokrates_cli/examples/structs/generic.zok | 13 +++++ zokrates_core/src/typed_absy/integer.rs | 70 +++++++++++++++++------ 2 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 zokrates_cli/examples/structs/generic.zok diff --git a/zokrates_cli/examples/structs/generic.zok b/zokrates_cli/examples/structs/generic.zok new file mode 100644 index 000000000..12f6d9c80 --- /dev/null +++ b/zokrates_cli/examples/structs/generic.zok @@ -0,0 +1,13 @@ +struct B

{ + field[P] a +} + +struct A { + field[N] a + B b +} + +def main(A<2> a) -> bool: + u32 SIZE = 1 + 1 + A b = A { a: [1, 2], b: B { a: [1, 2] } } + return a == b \ No newline at end of file diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index 4fc6bb169..265452068 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -1,6 +1,6 @@ use crate::typed_absy::types::{ - ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationType, GArrayType, GStructType, - GType, StructMember, StructType, Type, + DeclarationArrayType, DeclarationConstant, DeclarationStructMember, DeclarationStructType, + DeclarationType, GArrayType, GStructType, GType, GenericIdentifier, Type, }; use crate::typed_absy::UBitwidth; use crate::typed_absy::{ @@ -32,28 +32,51 @@ impl<'ast, T: Field> TypedExpressionOrSpread<'ast, T> { } } -fn get_common_type<'a, T: Field>(t: Type<'a, T>, u: Type<'a, T>) -> Result, ()> { +fn get_common_type<'a, T: Field>( + t: Type<'a, T>, + u: Type<'a, T>, +) -> Result, (Type<'a, T>, Type<'a, T>)> { match (t, u) { - (Type::Int, Type::Int) => Err(()), - (Type::Int, u) => Ok(u), - (t, Type::Int) => Ok(t), - (Type::Array(t), Type::Array(u)) => Ok(Type::Array(ArrayType::new( + (Type::Int, Type::Int) => Err((Type::Int, Type::Int)), + (Type::Int, Type::FieldElement) => Ok(DeclarationType::FieldElement), + (Type::Int, Type::Uint(bitwidth)) => Ok(DeclarationType::Uint(bitwidth)), + (Type::FieldElement, Type::Int) => Ok(DeclarationType::FieldElement), + (Type::Uint(bitwidth), Type::Int) => Ok(DeclarationType::Uint(bitwidth)), + (Type::FieldElement, Type::FieldElement) => Ok(DeclarationType::FieldElement), + (Type::Uint(b0), Type::Uint(b1)) => { + if b0 == b1 { + Ok(DeclarationType::Uint(b0)) + } else { + Err((Type::Uint(b0), Type::Uint(b1))) + } + } + (Type::Array(t), Type::Array(u)) => Ok(DeclarationType::Array(DeclarationArrayType::new( get_common_type(*t.ty, *u.ty)?, - t.size, + DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), ))), - (Type::Struct(t), Type::Struct(u)) => Ok(Type::Struct(StructType { + (Type::Struct(t), Type::Struct(u)) => Ok(DeclarationType::Struct(DeclarationStructType { members: t .members .into_iter() .zip(u.members.into_iter()) .map(|(m_t, m_u)| { - get_common_type(*m_t.ty.clone(), *m_u.ty) - .map(|ty| StructMember { ty: box ty, ..m_t }) + get_common_type(*m_t.ty.clone(), *m_u.ty).map(|ty| DeclarationStructMember { + ty: box ty, + id: m_t.id, + }) }) .collect::, _>>()?, - ..t + canonical_location: t.canonical_location, + location: t.location, + generics: t + .generics + .into_iter() + .map(|g| { + g.map(|_| DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY"))) + }) + .collect(), })), - (t, _) => Ok(t), + (t, u) => Err((t, u)), } } @@ -95,11 +118,15 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Array(lhs), Array(rhs)) => { + println!("hey"); + let common_type = get_common_type(lhs.get_type().clone(), rhs.get_type().clone()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; + println!("common type {}", common_type); + let common_type = match common_type { - Type::Array(ty) => ty, + DeclarationType::Array(ty) => ty, _ => unreachable!(), }; @@ -113,14 +140,18 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Struct(lhs), Struct(rhs)) => { + println!("common struct ty"); + let common_type = get_common_type(lhs.get_type(), rhs.get_type()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; let common_type = match common_type { - Type::Struct(ty) => ty, + DeclarationType::Struct(ty) => ty, _ => unreachable!(), }; + println!("ty {}", common_type); + Ok(( StructExpression::try_from_int(lhs.clone(), &common_type) .map_err(|lhs| (lhs.clone(), rhs.clone().into()))? @@ -581,6 +612,8 @@ impl<'ast, T: Field> StructExpression<'ast, T> { struc: Self, target_struct_ty: &GStructType, ) -> Result> { + println!("try from int {}", struc); + let struct_ty = struc.ty().clone(); match struc.into_inner() { @@ -598,10 +631,15 @@ impl<'ast, T: Field> StructExpression<'ast, T> { .members .iter() .zip(target_struct_ty.members.iter()) - .all(|(m, target_m)| *target_m.ty == *m.ty) + .all(|(m, target_m)| { + println!("{:?}", m); + *target_m.ty == *m.ty + }) { + println!("all eq"); Ok(s.annotate(struct_ty.clone())) } else { + println!("not all eq"); Err(s.annotate(struct_ty.clone()).into()) } } From bb9e0f16a2ea2675cbbfaa578f657885a875783d Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 16 Jul 2021 15:21:39 +0200 Subject: [PATCH 29/86] add m1 cross compilation to ci --- .circleci/config.yml | 118 +++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 97ad6a061..12937a6c4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -152,6 +152,9 @@ jobs: add-target: type: boolean default: false + build-with: + type: string + default: cross executor: << parameters.os >> steps: - checkout @@ -163,8 +166,9 @@ jobs: steps: - run: rustup target add << parameters.target >> - run: + name: Build no_output_timeout: "30m" - command: cross build --target << parameters.target >> --release + command: << parameters.build-with >> build --target << parameters.target >> --release - tar_artifacts: target: << parameters.target >> publish_artifacts: @@ -234,49 +238,45 @@ tag-only: &tag-only workflows: build-test-and-deploy: jobs: -# - build -# - test -# - cpp_format -# - wasm_test -# - integration_test -# - zokrates_js_build -# - zokrates_js_test -# - cross_build: -# <<: *tag-only -# pre-steps: -# - install_rust -# - install_cross -# matrix: -# alias: cross-build-linux -# parameters: -# os: -# - linux -# target: -# - aarch64-unknown-linux-gnu -# - arm-unknown-linux-gnueabi -# - x86_64-unknown-linux-gnu -# - x86_64-pc-windows-gnu -# - cross_build: -# <<: *tag-only -# pre-steps: -# - install_rust -# - install_cross -# matrix: -# alias: cross-build-macos -# parameters: -# os: -# - macos -# target: -# - x86_64-apple-darwin + - build + - test + - cpp_format + - wasm_test + - integration_test + - zokrates_js_build + - zokrates_js_test - cross_build: -# <<: *tag-only + <<: *tag-only pre-steps: - install_rust - install_cross - - run: | - xcodebuild -showsdks - export SDKROOT=$(xcrun -sdk macosx11.1 --show-sdk-path) - export MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx11.1 --show-sdk-platform-version) + matrix: + alias: cross-build-linux + parameters: + os: + - linux + target: + - aarch64-unknown-linux-gnu + - arm-unknown-linux-gnueabi + - x86_64-unknown-linux-gnu + - x86_64-pc-windows-gnu + - cross_build: + <<: *tag-only + pre-steps: + - install_rust + build-with: cargo + matrix: + alias: cross-build-macos + parameters: + os: + - macos + target: + - x86_64-apple-darwin + - cross_build: + <<: *tag-only + pre-steps: + - install_rust + build-with: SDKROOT=$(xcrun -sdk macosx11.1 --show-sdk-path) MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx11.1 --show-sdk-platform-version) cargo add-target: true matrix: alias: cross-build-apple-silicon @@ -285,22 +285,22 @@ workflows: - macos target: - aarch64-apple-darwin -# - publish_artifacts: -# <<: *tag-only -# requires: -# - cross-build-linux -# - cross-build-macos -# - cross-build-apple-silicon -# - deploy: -# filters: -# branches: -# only: -# - deploy -# requires: -# - build -# - test -# - cpp_format -# - wasm_test -# - integration_test -# - zokrates_js_build -# - zokrates_js_test \ No newline at end of file + - publish_artifacts: + <<: *tag-only + requires: + - cross-build-linux + - cross-build-macos + - cross-build-apple-silicon + - deploy: + filters: + branches: + only: + - deploy + requires: + - build + - test + - cpp_format + - wasm_test + - integration_test + - zokrates_js_build + - zokrates_js_test \ No newline at end of file From 10b9f4a48bc9d315b2c0aa0b4db9a58b124f9f92 Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 16 Jul 2021 23:19:33 +0200 Subject: [PATCH 30/86] remove remaining references to abi version --- zokrates_js/index.d.ts | 3 +-- zokrates_js/wrapper.js | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zokrates_js/index.d.ts b/zokrates_js/index.d.ts index c49f7938f..b42049cc4 100644 --- a/zokrates_js/index.d.ts +++ b/zokrates_js/index.d.ts @@ -7,7 +7,6 @@ declare module 'zokrates-js' { export type G2Affine = [Fq2, Fq2]; export type ProvingKey = Uint8Array; - export type SolidityAbi = "v1" | "v2"; export type ResolveCallback = (location: string, path: string) => ResolverResult; export interface CompileConfig { @@ -64,7 +63,7 @@ declare module 'zokrates-js' { compile(source: string, options?: CompileOptions): CompilationArtifacts; setup(program: Uint8Array): SetupKeypair; computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult; - exportSolidityVerifier(verificationKey: VerificationKey, abi: SolidityAbi): string; + exportSolidityVerifier(verificationKey: VerificationKey): string; generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): Proof; verify(verificationKey: VerificationKey, proof: Proof): boolean; } diff --git a/zokrates_js/wrapper.js b/zokrates_js/wrapper.js index da3899ac2..636ca2e97 100644 --- a/zokrates_js/wrapper.js +++ b/zokrates_js/wrapper.js @@ -61,8 +61,8 @@ module.exports = (dep) => { const { program, abi } = artifacts; return zokrates.compute_witness(program, abi, JSON.stringify(Array.from(args))); }, - exportSolidityVerifier: (verificationKey, abiVersion) => { - return zokrates.export_solidity_verifier(verificationKey, abiVersion); + exportSolidityVerifier: (verificationKey) => { + return zokrates.export_solidity_verifier(verificationKey); }, generateProof: (program, witness, provingKey) => { return zokrates.generate_proof(program, witness, provingKey); From 03c434994b34a3d889c6d706d4a5408f81db0251 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 19 Jul 2021 09:51:50 +0200 Subject: [PATCH 31/86] add boolean common type case --- zokrates_core/src/typed_absy/integer.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index 265452068..eae35276e 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -37,6 +37,7 @@ fn get_common_type<'a, T: Field>( u: Type<'a, T>, ) -> Result, (Type<'a, T>, Type<'a, T>)> { match (t, u) { + (Type::Boolean, Type::Boolean) => Ok(DeclarationType::Boolean), (Type::Int, Type::Int) => Err((Type::Int, Type::Int)), (Type::Int, Type::FieldElement) => Ok(DeclarationType::FieldElement), (Type::Int, Type::Uint(bitwidth)) => Ok(DeclarationType::Uint(bitwidth)), @@ -118,13 +119,9 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Array(lhs), Array(rhs)) => { - println!("hey"); - let common_type = get_common_type(lhs.get_type().clone(), rhs.get_type().clone()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; - println!("common type {}", common_type); - let common_type = match common_type { DeclarationType::Array(ty) => ty, _ => unreachable!(), From 2b0fd0909f3acbabaa3a50193e8e3ff55863abd0 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 19 Jul 2021 10:08:53 +0200 Subject: [PATCH 32/86] remove logs --- zokrates_core/src/typed_absy/integer.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index eae35276e..bcf41e43b 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -137,8 +137,6 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Struct(lhs), Struct(rhs)) => { - println!("common struct ty"); - let common_type = get_common_type(lhs.get_type(), rhs.get_type()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; @@ -147,8 +145,6 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { _ => unreachable!(), }; - println!("ty {}", common_type); - Ok(( StructExpression::try_from_int(lhs.clone(), &common_type) .map_err(|lhs| (lhs.clone(), rhs.clone().into()))? @@ -609,8 +605,6 @@ impl<'ast, T: Field> StructExpression<'ast, T> { struc: Self, target_struct_ty: &GStructType, ) -> Result> { - println!("try from int {}", struc); - let struct_ty = struc.ty().clone(); match struc.into_inner() { @@ -628,15 +622,10 @@ impl<'ast, T: Field> StructExpression<'ast, T> { .members .iter() .zip(target_struct_ty.members.iter()) - .all(|(m, target_m)| { - println!("{:?}", m); - *target_m.ty == *m.ty - }) + .all(|(m, target_m)| *target_m.ty == *m.ty) { - println!("all eq"); Ok(s.annotate(struct_ty.clone())) } else { - println!("not all eq"); Err(s.annotate(struct_ty.clone()).into()) } } From 497d43d67a5b8f99c29fbe1ea4fac48b342f8d9b Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 20 Jul 2021 15:07:05 +0200 Subject: [PATCH 33/86] use trait for type pattern detection --- zokrates_core/src/typed_absy/integer.rs | 128 ++++++++++++++++-------- 1 file changed, 84 insertions(+), 44 deletions(-) diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index bcf41e43b..f64b14680 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -1,6 +1,7 @@ use crate::typed_absy::types::{ - DeclarationArrayType, DeclarationConstant, DeclarationStructMember, DeclarationStructType, - DeclarationType, GArrayType, GStructType, GType, GenericIdentifier, Type, + ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationStructMember, + DeclarationStructType, DeclarationType, GArrayType, GStructType, GType, GenericIdentifier, + StructType, Type, }; use crate::typed_absy::UBitwidth; use crate::typed_absy::{ @@ -32,52 +33,89 @@ impl<'ast, T: Field> TypedExpressionOrSpread<'ast, T> { } } -fn get_common_type<'a, T: Field>( - t: Type<'a, T>, - u: Type<'a, T>, -) -> Result, (Type<'a, T>, Type<'a, T>)> { - match (t, u) { - (Type::Boolean, Type::Boolean) => Ok(DeclarationType::Boolean), - (Type::Int, Type::Int) => Err((Type::Int, Type::Int)), - (Type::Int, Type::FieldElement) => Ok(DeclarationType::FieldElement), - (Type::Int, Type::Uint(bitwidth)) => Ok(DeclarationType::Uint(bitwidth)), - (Type::FieldElement, Type::Int) => Ok(DeclarationType::FieldElement), - (Type::Uint(bitwidth), Type::Int) => Ok(DeclarationType::Uint(bitwidth)), - (Type::FieldElement, Type::FieldElement) => Ok(DeclarationType::FieldElement), - (Type::Uint(b0), Type::Uint(b1)) => { - if b0 == b1 { - Ok(DeclarationType::Uint(b0)) - } else { - Err((Type::Uint(b0), Type::Uint(b1))) +trait IntegerInference: Sized { + type Pattern; + + fn get_common_pattern(self, other: Self) -> Result; +} + +impl<'ast, T> IntegerInference for Type<'ast, T> { + type Pattern = DeclarationType<'ast>; + + fn get_common_pattern(self, other: Self) -> Result { + match (self, other) { + (Type::Boolean, Type::Boolean) => Ok(DeclarationType::Boolean), + (Type::Int, Type::Int) => Err((Type::Int, Type::Int)), + (Type::Int, Type::FieldElement) => Ok(DeclarationType::FieldElement), + (Type::Int, Type::Uint(bitwidth)) => Ok(DeclarationType::Uint(bitwidth)), + (Type::FieldElement, Type::Int) => Ok(DeclarationType::FieldElement), + (Type::Uint(bitwidth), Type::Int) => Ok(DeclarationType::Uint(bitwidth)), + (Type::FieldElement, Type::FieldElement) => Ok(DeclarationType::FieldElement), + (Type::Uint(b0), Type::Uint(b1)) => { + if b0 == b1 { + Ok(DeclarationType::Uint(b0)) + } else { + Err((Type::Uint(b0), Type::Uint(b1))) + } } + (Type::Array(t), Type::Array(u)) => Ok(DeclarationType::Array( + t.get_common_pattern(u) + .map_err(|(t, u)| (Type::Array(t), Type::Array(u)))?, + )), + (Type::Struct(t), Type::Struct(u)) => Ok(DeclarationType::Struct( + t.get_common_pattern(u) + .map_err(|(t, u)| (Type::Struct(t), Type::Struct(u)))?, + )), + (t, u) => Err((t, u)), } - (Type::Array(t), Type::Array(u)) => Ok(DeclarationType::Array(DeclarationArrayType::new( - get_common_type(*t.ty, *u.ty)?, + } +} + +impl<'ast, T> IntegerInference for ArrayType<'ast, T> { + type Pattern = DeclarationArrayType<'ast>; + + fn get_common_pattern(self, other: Self) -> Result { + let s0 = self.size; + let s1 = other.size; + + Ok(DeclarationArrayType::new( + self.ty + .get_common_pattern(*other.ty) + .map_err(|(t, u)| (ArrayType::new(t, s0), ArrayType::new(u, s1)))?, DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), - ))), - (Type::Struct(t), Type::Struct(u)) => Ok(DeclarationType::Struct(DeclarationStructType { - members: t + )) + } +} + +impl<'ast, T> IntegerInference for StructType<'ast, T> { + type Pattern = DeclarationStructType<'ast>; + + fn get_common_pattern(self, other: Self) -> Result { + Ok(DeclarationStructType { + members: self .members .into_iter() - .zip(u.members.into_iter()) - .map(|(m_t, m_u)| { - get_common_type(*m_t.ty.clone(), *m_u.ty).map(|ty| DeclarationStructMember { + .zip(other.members.into_iter()) + .map(|(m_t, m_u)| match m_t.ty.get_common_pattern(*m_u.ty) { + Ok(ty) => DeclarationStructMember { ty: box ty, id: m_t.id, - }) + }, + Err(..) => unreachable!( + "struct instances of the same struct should always have a common type" + ), }) - .collect::, _>>()?, - canonical_location: t.canonical_location, - location: t.location, - generics: t + .collect::>(), + canonical_location: self.canonical_location, + location: self.location, + generics: self .generics .into_iter() .map(|g| { g.map(|_| DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY"))) }) .collect(), - })), - (t, u) => Err((t, u)), + }) } } @@ -119,7 +157,9 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Array(lhs), Array(rhs)) => { - let common_type = get_common_type(lhs.get_type().clone(), rhs.get_type().clone()) + let common_type = lhs + .get_type() + .get_common_pattern(rhs.get_type()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; let common_type = match common_type { @@ -137,7 +177,9 @@ impl<'ast, T: Field> TypedExpression<'ast, T> { )) } (Struct(lhs), Struct(rhs)) => { - let common_type = get_common_type(lhs.get_type(), rhs.get_type()) + let common_type = lhs + .get_type() + .get_common_pattern(rhs.get_type()) .map_err(|_| (lhs.clone().into(), rhs.clone().into()))?; let common_type = match common_type { @@ -420,7 +462,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { _ => Err(TypedExpression::Uint(e)), }, TypedExpression::Int(e) => { - Self::try_from_int(e.clone(), bitwidth).map_err(|_| TypedExpression::Int(e)) + Self::try_from_int(e, bitwidth).map_err(|e| TypedExpression::Int(e)) } e => Err(e), } @@ -533,8 +575,7 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { target_array_ty: &GArrayType, ) -> Result> { match e { - TypedExpression::Array(e) => Self::try_from_int(e.clone(), target_array_ty) - .map_err(|_| TypedExpression::Array(e)), + TypedExpression::Array(e) => Self::try_from_int(e, target_array_ty), e => Err(e), } } @@ -616,7 +657,7 @@ impl<'ast, T: Field> StructExpression<'ast, T> { }) .collect::, _>>() .map(|v| StructExpressionInner::Value(v).annotate(struct_ty.clone())) - .map_err(|_| unimplemented!()), + .map_err(|(v, _)| v), s => { if struct_ty .members @@ -624,9 +665,9 @@ impl<'ast, T: Field> StructExpression<'ast, T> { .zip(target_struct_ty.members.iter()) .all(|(m, target_m)| *target_m.ty == *m.ty) { - Ok(s.annotate(struct_ty.clone())) + Ok(s.annotate(struct_ty)) } else { - Err(s.annotate(struct_ty.clone()).into()) + Err(s.annotate(struct_ty).into()) } } } @@ -637,8 +678,7 @@ impl<'ast, T: Field> StructExpression<'ast, T> { target_struct_ty: &GStructType, ) -> Result> { match e { - TypedExpression::Struct(e) => Self::try_from_int(e.clone(), target_struct_ty) - .map_err(|_| TypedExpression::Struct(e)), + TypedExpression::Struct(e) => Self::try_from_int(e, target_struct_ty), e => Err(e), } } From eedc4dbe61d887b6509acfa4f50612a0edc2e168 Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 15:46:30 +0200 Subject: [PATCH 34/86] use vec instead of map --- zokrates_abi/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index f828825e5..4102a4288 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -14,14 +14,11 @@ impl> Encode for Inputs { } } -use std::collections::BTreeMap; use std::fmt; use zokrates_core::typed_absy::types::{ConcreteType, UBitwidth}; use zokrates_field::Field; -type Map = BTreeMap; - #[derive(Debug, PartialEq)] pub enum Error { Json(String), @@ -48,7 +45,7 @@ pub enum Value { Field(T), Boolean(bool), Array(Vec>), - Struct(Map>), + Struct(Vec<(String, Value)>), } #[derive(PartialEq, Debug)] From 84f717cd32f03b9328bdc34fef768a87b7dda964 Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 15:51:45 +0200 Subject: [PATCH 35/86] add changelog --- changelogs/unreleased/947-schaeff | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/947-schaeff diff --git a/changelogs/unreleased/947-schaeff b/changelogs/unreleased/947-schaeff new file mode 100644 index 000000000..07e3af350 --- /dev/null +++ b/changelogs/unreleased/947-schaeff @@ -0,0 +1 @@ +Fix abi encoder bug for struct values where the members are encoded in the wrong order \ No newline at end of file From d3621897ed00e74ea29e8d17536735273d98713e Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 16:37:36 +0200 Subject: [PATCH 36/86] fix test --- zokrates_abi/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 4102a4288..b3d13e049 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -325,7 +325,6 @@ pub fn parse_strict(s: &str, types: Vec) -> Result Date: Sun, 25 Jul 2021 16:56:59 +0200 Subject: [PATCH 37/86] add gm17 passing test --- Cargo.lock | 1 + zokrates_abi/src/lib.rs | 42 +++---- .../compile_errors/wrong_member_type.zok | 15 +++ zokrates_core/src/typed_absy/integer.rs | 2 +- .../tests/tests/structs/member_order.json | 20 ++++ .../tests/tests/structs/member_order.zok | 9 ++ zokrates_stdlib/stdlib/snark/gm17.zok | 52 +++++++++ zokrates_stdlib/tests/tests/snark/gm17.json | 103 ++++++++++++++++++ zokrates_stdlib/tests/tests/snark/gm17.zok | 64 +++++++++++ zokrates_test/Cargo.toml | 1 + zokrates_test/src/lib.rs | 56 ++++++++-- 11 files changed, 332 insertions(+), 33 deletions(-) create mode 100644 zokrates_cli/examples/compile_errors/wrong_member_type.zok create mode 100644 zokrates_core_test/tests/tests/structs/member_order.json create mode 100644 zokrates_core_test/tests/tests/structs/member_order.zok create mode 100644 zokrates_stdlib/stdlib/snark/gm17.zok create mode 100644 zokrates_stdlib/tests/tests/snark/gm17.json create mode 100644 zokrates_stdlib/tests/tests/snark/gm17.zok diff --git a/Cargo.lock b/Cargo.lock index c87c18024..85d7dd2d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2490,6 +2490,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "zokrates_abi", "zokrates_core", "zokrates_field", "zokrates_fs_resolver", diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 205af548a..508da06e7 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -299,22 +299,7 @@ pub fn parse_strict(s: &str, types: Vec) -> Result { - if values.len() != types.len() { - return Err(Error::Type(format!( - "Expected {} inputs, found {}", - types.len(), - values.len() - ))); - } - Ok(Values( - types - .into_iter() - .zip(values.into_iter()) - .map(|(ty, v)| parse_value(v, ty)) - .collect::>()?, - )) - } + serde_json::Value::Array(values) => parse_strict_json(values, types), _ => Err(Error::Type(format!( "Expected an array of values, found `{}`", values @@ -322,6 +307,27 @@ pub fn parse_strict(s: &str, types: Vec) -> Result( + values: Vec, + types: Vec, +) -> Result, Error> { + if values.len() != types.len() { + return Err(Error::Type(format!( + "Expected {} inputs, found {}", + types.len(), + values.len() + ))); + } + + Ok(Values( + types + .into_iter() + .zip(values.into_iter()) + .map(|(ty, v)| parse_value(v, ty)) + .collect::>()?, + )) +} + #[cfg(test)] mod tests { use super::*; @@ -428,7 +434,6 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), - vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -450,7 +455,6 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), - vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -468,7 +472,6 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), - vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -486,7 +489,6 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), - vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement diff --git a/zokrates_cli/examples/compile_errors/wrong_member_type.zok b/zokrates_cli/examples/compile_errors/wrong_member_type.zok new file mode 100644 index 000000000..c7644f98a --- /dev/null +++ b/zokrates_cli/examples/compile_errors/wrong_member_type.zok @@ -0,0 +1,15 @@ +struct B { + field a +} + +struct A { + B a +} + +def main(): + A a = A { + a: B { + a: false + } + } + return \ No newline at end of file diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index f64b14680..ff1fe3afc 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -462,7 +462,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { _ => Err(TypedExpression::Uint(e)), }, TypedExpression::Int(e) => { - Self::try_from_int(e, bitwidth).map_err(|e| TypedExpression::Int(e)) + Self::try_from_int(e, bitwidth).map_err(TypedExpression::Int) } e => Err(e), } diff --git a/zokrates_core_test/tests/tests/structs/member_order.json b/zokrates_core_test/tests/tests/structs/member_order.json new file mode 100644 index 000000000..e6aed584d --- /dev/null +++ b/zokrates_core_test/tests/tests/structs/member_order.json @@ -0,0 +1,20 @@ +{ + "entry_point": "./tests/tests/structs/member_order.zok", + "curves": ["Bn128"], + "tests": [ + { + "abi": true, + "input": { + "values": [{ + "a":true, + "b": "3" + }] + }, + "output": { + "Ok": { + "values": [] + } + } + } + ] +} diff --git a/zokrates_core_test/tests/tests/structs/member_order.zok b/zokrates_core_test/tests/tests/structs/member_order.zok new file mode 100644 index 000000000..77a8291d9 --- /dev/null +++ b/zokrates_core_test/tests/tests/structs/member_order.zok @@ -0,0 +1,9 @@ +struct Foo { + field b + bool a +} + +// this tests the abi, checking that the fields of a `Foo` instance get encoded in the right order +// if the the encoder reverses `a` and `b`, the boolean check ends up being done on the field value, which would fail +def main(Foo f): + return \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/snark/gm17.zok b/zokrates_stdlib/stdlib/snark/gm17.zok new file mode 100644 index 000000000..f839f3dba --- /dev/null +++ b/zokrates_stdlib/stdlib/snark/gm17.zok @@ -0,0 +1,52 @@ +#pragma curve bw6_761 +from "EMBED" import snark_verify_bls12_377 as verify + +struct ProofInner { + field[2] a + field[2][2] b + field[2] c +} + +struct Proof { + ProofInner proof + field[N] inputs +} +struct VerificationKey { + field[2][2] h + field[2] g_alpha + field[2][2] h_beta + field[2] g_gamma + field[2][2] h_gamma + field[N][2] query // input length + 1 +} + +def flat(field[N][2] input) -> field[F]: + assert(F == N * 2) + field[F] out = [0; F] + for u32 i in 0..N do + for u32 j in 0..2 do + out[(i * 2) + j] = input[i][j] + endfor + endfor + return out + +def main(Proof proof, VerificationKey vk) -> bool: + assert(Q == N + 1) // query length (Q) should be N + 1 + field[8] flat_proof = [ + ...proof.proof.a, + ...flat::<2, 4>(proof.proof.b), + ...proof.proof.c + ] + + u32 two_Q = 2 * Q + + field[16 + (2 * Q)] flat_vk = [ + ...flat::<2, 4>(vk.h), + ...vk.g_alpha, + ...flat::<2, 4>(vk.h_beta), + ...vk.g_gamma, + ...flat::<2, 4>(vk.h_gamma), + ...flat::(vk.query) + ] + + return verify(proof.inputs, flat_proof, flat_vk) \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/snark/gm17.json b/zokrates_stdlib/tests/tests/snark/gm17.json new file mode 100644 index 000000000..5c85c196f --- /dev/null +++ b/zokrates_stdlib/tests/tests/snark/gm17.json @@ -0,0 +1,103 @@ +{ + "entry_point": "./tests/tests/snark/gm17.zok", + "curves": ["Bw6_761"], + "tests": [ + { + "abi": true, + "input": { + "values": [ +{ + "proof": { + "a": [ + "0x01441e34fd88112583831de068e3bdf67d7a5b020c9650e4dc8e3dd0cf92f62b32668dd4654ddc63fe5293a542756a27", + "0x013d7b6097a6ae8534909cb2f2ec2e39f3ccbe8858db0285e45619131db37f84b1c88fbb257a7b8e8944a926bb41aa66" + ], + "b": [ + [ + "0x00dcf8242e445213da28281aab32bcf47268bf16624dbca7c828cfbb0e8000bad94926272cba0cd5e9a959cf4e969c7c", + "0x00b570276d40ae06ac3feb5db65b37acf1eabd16e1c588d01c553b1a60e5d007d9202a8ad2b6405e521b3eec84772521" + ], + [ + "0x00acbeabed6267316420b73b9eba39e8c51080b8b507857478a54c0fc259b17eec2921253a15445e2ec3c130706398b0", + "0x019b579a061cbc4aed64351d87ba96c071118ef3fd645e630c18986e284de5ffc8a48ea94eeb3bdc8807d62d366e223f" + ] + ], + "c": [ + "0x004c93c20cd43f8b7818fcc4ece38243779bedb8b874702df4d6968b75cbe2e6831ab38475e2f0c7bc170171580198df", + "0x0177a560e5f6ae87f07aeff2dcdb1e0737b4810aeba8a5ba1bc4c5d0e89f268aae142ab5327afbde8e8bad869702aad3" + ] + }, + "inputs": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003" + ] +}, +{ + "h": [ + [ + "0x000a4c42894d5fd7ac23ca05eac034d82299dd9db5fa493812e4852bcf50cd88faf8f3e97cd292678b292d11e173949b", + "0x001ead78f91728b07146e93ee1f21165f25ad88e0fee997f5527076ca84374d3a6d834b59608226b28ab8b8d5ea9a94f" + ], + [ + "0x0087b1837c209351af3b67bbfeaea80ed94f690584847b1aa34cc59a2b451f360fc268b2562ea8015f8f4d71c7bf4675", + "0x015c50d51c8ed463a4e9cc76fc0583634b04dc26b36e10bfac9169d0baebf58b45b687a81a0ca60400427889bcbc6b76" + ] + ], + "g_alpha": [ + "0x004b7af9ab6ef9061adb5ed7ba12e9cd41f508ac758c25c5e629d871a1b980e5242149b522b20c57808fae97cb76b971", + "0x0196c16d89a7cccbb8f15775da22c01d5ec45b384829bcaad91b324a482676558d3d6d41f675966b5d22537f4ed77903" + ], + "h_beta": [ + [ + "0x014d2d0bcfa272334efbc589dc263c3f2a5d2711f9a0d5fbb3c2ad1b7eebe93459aeee6e1c8bc02041945313aec93d8a", + "0x0054800f89ebbbd924328a7782fdbb5260b56059901a06e6ad58c4a7df96018e5ea1c5ffd28ed0dd0139dcced6bde7e8" + ], + [ + "0x00ca4e270e5fe79ff2a5432daf6e9e5aa22aebf6521a7d3c5ef97d981b05ea93043c6307b47e8a3e00ace9c987fb725e", + "0x010cb8f97a5d586777e4f7ca8a0ce4465c0de02951cb8ccca43403b1a669e523c1163ebc9ce7d10edf583894fad70341" + ] + ], + "g_gamma": [ + "0x003fa4d4d1fe1a9bb62e704b5ac76a514e4aaf53cfcbd12cb55aa7afecf2c12ce9346737b5594ee872700178748e9ed1", + "0x018975a2eb9de8a1982d076b56bb86b5214f89cff897d492e16dcdc1eca2a692eb9f0af5183585ba4aee9d78af2ab570" + ], + "h_gamma": [ + [ + "0x000a4c42894d5fd7ac23ca05eac034d82299dd9db5fa493812e4852bcf50cd88faf8f3e97cd292678b292d11e173949b", + "0x001ead78f91728b07146e93ee1f21165f25ad88e0fee997f5527076ca84374d3a6d834b59608226b28ab8b8d5ea9a94f" + ], + [ + "0x0087b1837c209351af3b67bbfeaea80ed94f690584847b1aa34cc59a2b451f360fc268b2562ea8015f8f4d71c7bf4675", + "0x015c50d51c8ed463a4e9cc76fc0583634b04dc26b36e10bfac9169d0baebf58b45b687a81a0ca60400427889bcbc6b76" + ] + ], + "query": [ + [ + "0x00dbcc84391e078ae2fa7b5dc8478651b945e155505332a55e5b7be4de52ce83450bbf94f1da270c012104d394b22fda", + "0x002dc3039f7236d31fceaa6d8e13d33a5850984193f70c0abfe20a1f4540f59987e49cb0cc2722f1dccb47f1012d38c8" + ], + [ + "0x00db1bc3a431619ca74564c8a734592151a5fc2d8bfa750d4ffb94126bdaed83dce86bcdc8f966dca3066f67c61c897c", + "0x00e97f2f6c94a2676dd3c8646a45684cfd66a644644c1fc8ee5cf2ab4e322a5a82a9f9872ec9e8c7f3f1a9ddf38f2e53" + ], + [ + "0x008f4c292ba1ae0fa22613e0afaa075796b21a935e591fb8e8b32fa7c0fe0ecda25d5575e1e2b178d5a4bfb8e89f9d36", + "0x017cb6aca4e2d1027ab429a2a7d6b8f6e13dfeb427b7eaf9b6e3ca22554fae39f45ee0854098c9753cca04b46f3388d0" + ], + [ + "0x0168740e2d9cab168df083dd1d340de23d5055f4eed63c87811e94a5bf9c492658c6c58ccb1a48bb153cbe9aa8d98c8d", + "0x005b7c28b57504562c1d38a5ba9c67a59c696dc2e51b3c50d96e75e2f399f9106f08f6846d553d32e58b8131ad997fc1" + ] + ] +} + ] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} diff --git a/zokrates_stdlib/tests/tests/snark/gm17.zok b/zokrates_stdlib/tests/tests/snark/gm17.zok new file mode 100644 index 000000000..afa72558f --- /dev/null +++ b/zokrates_stdlib/tests/tests/snark/gm17.zok @@ -0,0 +1,64 @@ +// verify a snark +// to reproduce the test cases: +// +// 1. Create a program +// ```zokrates +// def main(field a, field b) -> field: +// return a + b +// ``` +// +// 2. Compile it to bls12_377 +// ```sh +// zokrates compile -i program.zok --curve bls12_377 +// ``` +// +// 3. Run a trusted setup for gm17 +// ```sh +// zokrates setup --proving-scheme gm17 --backend ark +// ``` +// +// 4. Execute the program and generate a proof +// ```sh +// zokrates compute-witness -a 1 2 +// zokrates generate-proof --proving-scheme gm17 --backend ark +// ``` +// +// 5. Generate the test case +// +// ```sh +// rm gm17.json +// touch gm17.json + +// echo '{ +// "entry_point": "./tests/tests/snark/gm17.zok", +// "curves": ["Bw6_761"], +// "tests": [ +// { +// "input": { +// "values": [' >> gm17.json + +// cat proof.json >> gm17.json + +// echo ', ' >> gm17.json + +// cat verification.key >> gm17.json + +// echo ' +// ] +// }, +// "output": { +// "Ok": { +// "values": ["1"] +// } +// } +// } +// ] +// }' >> gm17.json +// ``` +// +// `gm17.json` can then be used as a test for this code file + +from "snark/gm17" import main as verify, Proof, VerificationKey + +def main(Proof<3> proof, VerificationKey<4> vk) -> bool: + return verify::<3, 4>(proof, vk) \ No newline at end of file diff --git a/zokrates_test/Cargo.toml b/zokrates_test/Cargo.toml index 8c299898c..823f6cf38 100644 --- a/zokrates_test/Cargo.toml +++ b/zokrates_test/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" zokrates_field = { version = "0.4", path = "../zokrates_field" } zokrates_core = { version = "0.6", path = "../zokrates_core" } zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver" } +zokrates_abi = { version = "0.1", path = "../zokrates_abi" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/zokrates_test/src/lib.rs b/zokrates_test/src/lib.rs index a9e252a17..ca95920c3 100644 --- a/zokrates_test/src/lib.rs +++ b/zokrates_test/src/lib.rs @@ -5,8 +5,11 @@ use std::fs::File; use std::io::{BufReader, Read}; use std::path::{Path, PathBuf}; -use zokrates_core::compile::{compile, CompileConfig}; use zokrates_core::ir; +use zokrates_core::{ + compile::{compile, CompileConfig}, + typed_absy::ConcreteType, +}; use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Bw6_761Field, Field}; use zokrates_fs_resolver::FileSystemResolver; @@ -34,6 +37,7 @@ struct Input { #[derive(Serialize, Deserialize, Clone)] struct Test { + pub abi: Option, pub input: Input, pub output: TestResult, } @@ -48,11 +52,24 @@ struct Output { values: Vec, } -type Val = String; +type Val = serde_json::Value; -fn parse_val(s: String) -> T { - let radix = if s.starts_with("0x") { 16 } else { 10 }; - T::try_from_str(s.trim_start_matches("0x"), radix).unwrap() +fn try_parse_raw_val(s: serde_json::Value) -> Result { + match s { + serde_json::Value::String(s) => { + let radix = if s.starts_with("0x") { 16 } else { 10 }; + T::try_from_str(s.trim_start_matches("0x"), radix).map_err(|_| ()) + } + _ => Err(()), + } +} + +fn try_parse_abi_val( + s: Vec, + types: Vec, +) -> Result, zokrates_abi::Error> { + use zokrates_abi::Encode; + zokrates_abi::parse_strict_json(s, types).map(|v| v.encode()) } impl From> for ComparableResult { @@ -63,7 +80,12 @@ impl From> for ComparableResult { impl From for ComparableResult { fn from(r: TestResult) -> ComparableResult { - ComparableResult(r.map(|v| v.values.into_iter().map(parse_val).collect())) + ComparableResult(r.map(|v| { + v.values + .into_iter() + .map(|v| try_parse_raw_val(v).unwrap()) + .collect() + })) } } @@ -130,6 +152,7 @@ fn compile_and_run(t: Tests) { let artifacts = compile::(code, entry_point.clone(), Some(&resolver), &config).unwrap(); let bin = artifacts.prog(); + let abi = artifacts.abi(); if let Some(target_count) = t.max_constraint_count { let count = bin.constraint_count(); @@ -148,12 +171,21 @@ fn compile_and_run(t: Tests) { let interpreter = zokrates_core::ir::Interpreter::default(); for test in t.tests.into_iter() { - let input = &test.input.values; - - let output = interpreter.execute( - bin, - &(input.iter().cloned().map(parse_val).collect::>()), - ); + let with_abi = test.abi.unwrap_or(false); + + let input = if with_abi { + try_parse_abi_val(test.input.values, abi.signature().inputs).unwrap() + } else { + test.input + .values + .iter() + .cloned() + .map(try_parse_raw_val) + .collect::, _>>() + .unwrap() + }; + + let output = interpreter.execute(bin, &input); if let Err(e) = compare(output, test.output) { let mut code = File::open(&entry_point).unwrap(); From 6eb5116f55e6b75cf4e96f1370d40dacc7a9b9b5 Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 17:05:09 +0200 Subject: [PATCH 38/86] add changelog --- changelogs/unreleased/948-schaeff | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/948-schaeff diff --git a/changelogs/unreleased/948-schaeff b/changelogs/unreleased/948-schaeff new file mode 100644 index 000000000..15e68c970 --- /dev/null +++ b/changelogs/unreleased/948-schaeff @@ -0,0 +1 @@ +Add gm17 verifier to stdlib for bw6_761 \ No newline at end of file From a98701309d4ca557682e96963bd011aa3e0b7b13 Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 18:31:22 +0200 Subject: [PATCH 39/86] implement fold_program to avoid calling fold_module more than expected --- changelogs/unreleased/949-schaeff | 1 + zokrates_core/src/static_analysis/constant_inliner.rs | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 changelogs/unreleased/949-schaeff diff --git a/changelogs/unreleased/949-schaeff b/changelogs/unreleased/949-schaeff new file mode 100644 index 000000000..146b59230 --- /dev/null +++ b/changelogs/unreleased/949-schaeff @@ -0,0 +1 @@ +Fix state corruption in the constant inliner \ No newline at end of file diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index ad00d292c..26920dcc7 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -67,6 +67,17 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { } impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { + fn fold_program(&mut self, p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { + for (id, _) in p.modules { + self.fold_module_id(id); + } + + TypedProgram { + modules: std::mem::take(&mut self.modules), + ..p + } + } + fn fold_module_id(&mut self, id: OwnedTypedModuleId) -> OwnedTypedModuleId { // anytime we encounter a module id, visit the corresponding module if it hasn't been done yet if !self.treated(&id) { From a94b691c01ffaabfb1c565e0f3377f23850d7366 Mon Sep 17 00:00:00 2001 From: schaeff Date: Sun, 25 Jul 2021 18:42:47 +0200 Subject: [PATCH 40/86] fix abi tests --- zokrates_abi/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 508da06e7..6c07891ed 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -434,6 +434,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -455,6 +456,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -472,6 +474,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement @@ -489,6 +492,7 @@ mod tests { vec![ConcreteType::Struct(ConcreteStructType::new( "".into(), "".into(), + vec![], vec![ConcreteStructMember::new( "a".into(), ConcreteType::FieldElement From c9e4cf1e48019b882697914d0e841fa8fd2e8c4f Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 26 Jul 2021 14:42:13 +0200 Subject: [PATCH 41/86] inline constants starting from main --- zokrates_core/src/static_analysis/constant_inliner.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 26920dcc7..fcee31869 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -68,9 +68,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { fn fold_program(&mut self, p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { - for (id, _) in p.modules { - self.fold_module_id(id); - } + self.fold_module_id(p.main.clone()); TypedProgram { modules: std::mem::take(&mut self.modules), From ecb105fb56d785b994bbc94db7480dde00bdfbc8 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 26 Jul 2021 15:02:37 +0200 Subject: [PATCH 42/86] add test --- zokrates_cli/examples/imports/inliner_state.zok | 12 ++++++++++++ zokrates_cli/examples/imports/inliner_state_aux.zok | 5 +++++ 2 files changed, 17 insertions(+) create mode 100644 zokrates_cli/examples/imports/inliner_state.zok create mode 100644 zokrates_cli/examples/imports/inliner_state_aux.zok diff --git a/zokrates_cli/examples/imports/inliner_state.zok b/zokrates_cli/examples/imports/inliner_state.zok new file mode 100644 index 000000000..321ee5a0b --- /dev/null +++ b/zokrates_cli/examples/imports/inliner_state.zok @@ -0,0 +1,12 @@ +from "./inliner_state_aux" import main as test + +// we check that the constant inliner does not get corrupted +// notice that the constant generic has the same name as the constant `K` +// defined in the `test1.zok` module +def tmp(): + u32 junk = test() + K + return + +// dummy main +def main(): + return \ No newline at end of file diff --git a/zokrates_cli/examples/imports/inliner_state_aux.zok b/zokrates_cli/examples/imports/inliner_state_aux.zok new file mode 100644 index 000000000..f828089da --- /dev/null +++ b/zokrates_cli/examples/imports/inliner_state_aux.zok @@ -0,0 +1,5 @@ +// the issue only shows if `K` is an array, renaming this constant to something else works +const u32[1] K = [1] + +def main() -> u32: + return K[0] \ No newline at end of file From fbd7fddf99f393764e07386691fcaaf346e8db8a Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 28 Jul 2021 00:11:18 +0200 Subject: [PATCH 43/86] update doc, example, fix absy creation --- zokrates_book/src/language/types.md | 2 +- zokrates_cli/examples/book/structs.zok | 12 ++++++------ zokrates_core/src/absy/from_ast.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zokrates_book/src/language/types.md b/zokrates_book/src/language/types.md index e3cad6088..146de1296 100644 --- a/zokrates_book/src/language/types.md +++ b/zokrates_book/src/language/types.md @@ -107,7 +107,7 @@ field[2] b = a[1..3] // initialize an array copying a slice from `a` ``` ### Structs -A struct is a composite datatype representing a named collection of variables. +A struct is a composite datatype representing a named collection of variables. Structs can be generic over constants, in order to wrap arrays of generic size. For more details on generic array sizes, see [constant generics](../language/generics.md) The contained variables can be of any type. The following code shows an example of how to use structs. diff --git a/zokrates_cli/examples/book/structs.zok b/zokrates_cli/examples/book/structs.zok index 7cca57075..9e2ed2e51 100644 --- a/zokrates_cli/examples/book/structs.zok +++ b/zokrates_cli/examples/book/structs.zok @@ -1,14 +1,14 @@ -struct Bar { - field[2] c +struct Bar { + field[N] c bool d } -struct Foo { - Bar a +struct Foo

{ + Bar

a bool b } -def main() -> (Foo): - Foo[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true}] +def main() -> (Foo<2>): + Foo<2>[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true}] f[0].a.c = [42, 43] return f[0] diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 673f627c1..a968b9c29 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -773,7 +773,7 @@ impl<'ast> From> for absy::UnresolvedTypeNode<'ast> { pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), }, pest::BasicOrStructType::Struct(t) => UnresolvedType::User( - t.span.as_str().to_string(), + t.id.span.as_str().to_string(), t.explicit_generics.map(|explicit_generics| { explicit_generics .values From d0622d849c9c80a57ada33cf1fa7e7d23a879761 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 28 Jul 2021 09:37:49 +0200 Subject: [PATCH 44/86] clippy --- zokrates_core/src/typed_absy/integer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index f64b14680..ff1fe3afc 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -462,7 +462,7 @@ impl<'ast, T: Field> UExpression<'ast, T> { _ => Err(TypedExpression::Uint(e)), }, TypedExpression::Int(e) => { - Self::try_from_int(e, bitwidth).map_err(|e| TypedExpression::Int(e)) + Self::try_from_int(e, bitwidth).map_err(TypedExpression::Int) } e => Err(e), } From f92df0fa1abcf39ce05cea5262541344fa03f667 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 28 Jul 2021 12:38:58 +0200 Subject: [PATCH 45/86] add tests, fail gracefully on generic inference attempt and eq generic mismatch --- .../{unused.zok => generic_in_main.zok} | 0 .../generics/generic_inference.zok | 7 ++++ .../generics/struct_generic_mismatch.zok | 6 ++++ .../generics/unused_struct_generic.zok | 4 +++ zokrates_core/src/semantics.rs | 32 ++++++++++++------- .../src/static_analysis/propagation.rs | 18 +++++++++++ zokrates_core/src/typed_absy/abi.rs | 31 ++++++++++-------- 7 files changed, 73 insertions(+), 25 deletions(-) rename zokrates_cli/examples/compile_errors/generics/{unused.zok => generic_in_main.zok} (100%) create mode 100644 zokrates_cli/examples/compile_errors/generics/generic_inference.zok create mode 100644 zokrates_cli/examples/compile_errors/generics/struct_generic_mismatch.zok create mode 100644 zokrates_cli/examples/compile_errors/generics/unused_struct_generic.zok diff --git a/zokrates_cli/examples/compile_errors/generics/unused.zok b/zokrates_cli/examples/compile_errors/generics/generic_in_main.zok similarity index 100% rename from zokrates_cli/examples/compile_errors/generics/unused.zok rename to zokrates_cli/examples/compile_errors/generics/generic_in_main.zok diff --git a/zokrates_cli/examples/compile_errors/generics/generic_inference.zok b/zokrates_cli/examples/compile_errors/generics/generic_inference.zok new file mode 100644 index 000000000..82c95f5f6 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/generic_inference.zok @@ -0,0 +1,7 @@ +struct A { + field[N] a +} + +def main(): + A<_> a = A { a: [1] } + return \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/generics/struct_generic_mismatch.zok b/zokrates_cli/examples/compile_errors/generics/struct_generic_mismatch.zok new file mode 100644 index 000000000..b110cd581 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/struct_generic_mismatch.zok @@ -0,0 +1,6 @@ +struct A { + field[N] a +} + +def main(A<1> a, A<2> b) -> bool: + return a == b \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/generics/unused_struct_generic.zok b/zokrates_cli/examples/compile_errors/generics/unused_struct_generic.zok new file mode 100644 index 000000000..03f97145c --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/unused_struct_generic.zok @@ -0,0 +1,4 @@ +struct A {} + +def main(): + return \ No newline at end of file diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 2a89dc17b..3a2546c70 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1216,18 +1216,26 @@ impl<'ast, T: Field> Checker<'ast, T> { let assignment = GGenericsAssignment(generics .into_iter() .zip(generic_identifiers) - .filter_map(|(e, g)| e.map(|e| { - self - .check_expression(e, module_id, types) - .and_then(|e| { - UExpression::try_from_typed(e, &UBitwidth::B32) - .map(|e| (g, e)) - .map_err(|e| ErrorInner { - pos: Some(pos), - message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), - }) - }) - })) + .map(|(e, g)| match e { + Some(e) => { + self + .check_expression(e, module_id, types) + .and_then(|e| { + UExpression::try_from_typed(e, &UBitwidth::B32) + .map(|e| (g, e)) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!("Expected u32 expression, but got expression of type {}", e.get_type()), + }) + }) + }, + None => Err(ErrorInner { + pos: Some(pos), + message: + "Expected u32 constant or identifier, but found `_`. Generic inference is not supported yet." + .into(), + }) + }) .collect::>()?); // specialize the declared type using the generic assignment diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 5d51a05a1..c5989c217 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -1279,6 +1279,24 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { Ok(BooleanExpression::ArrayEq(box e1, box e2)) } + BooleanExpression::StructEq(box e1, box e2) => { + let e1 = self.fold_struct_expression(e1)?; + let e2 = self.fold_struct_expression(e2)?; + + if let (Ok(t1), Ok(t2)) = ( + ConcreteType::try_from(e1.get_type()), + ConcreteType::try_from(e2.get_type()), + ) { + if t1 != t2 { + return Err(Error::Type(format!( + "Cannot compare {} of type {} to {} of type {}", + e1, t1, e2, t2 + ))); + } + }; + + Ok(BooleanExpression::StructEq(box e1, box e2)) + } BooleanExpression::FieldLt(box e1, box e2) => { let e1 = self.fold_field_expression(e1)?; let e2 = self.fold_field_expression(e2)?; diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index db30311a4..15554a735 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -230,12 +230,15 @@ mod tests { public: true, ty: ConcreteType::Struct(ConcreteStructType::new( "".into(), - "Foo".into(), - vec![], - vec![ - ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement), - ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean), - ], + "Bar".into(), + vec![Some(1usize)], + vec![ConcreteStructMember::new( + String::from("a"), + ConcreteType::Array(ConcreteArrayType::new( + ConcreteType::FieldElement, + 1usize, + )), + )], )), }], outputs: vec![ConcreteType::Struct(ConcreteStructType::new( @@ -259,16 +262,18 @@ mod tests { "public": true, "type": "struct", "components": { - "name": "Foo", - "generics": [], + "name": "Bar", + "generics": [ + 1 + ], "members": [ { "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "bool" + "type": "array", + "components": { + "size": 1, + "type": "field" + } } ] } From dbcd0bd55846f7cba25f5fe4e5bb8d908b3fba21 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 29 Jul 2021 11:13:54 +0200 Subject: [PATCH 46/86] add log to core and env_log to cli --- zokrates_cli/Cargo.toml | 2 + zokrates_cli/src/bin.rs | 2 + zokrates_cli/src/ops/compile.rs | 8 +++ zokrates_core/Cargo.toml | 1 + zokrates_core/src/compile.rs | 28 +++++++-- zokrates_core/src/flatten/mod.rs | 77 +++++++++++------------- zokrates_core/src/imports.rs | 4 +- zokrates_core/src/optimizer/mod.rs | 22 ++++++- zokrates_core/src/static_analysis/mod.rs | 29 ++++++++- 9 files changed, 122 insertions(+), 51 deletions(-) diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index c23bb95f8..5ea922438 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -12,6 +12,8 @@ bellman = ["zokrates_core/bellman"] ark = ["zokrates_core/ark"] [dependencies] +log = "0.4" +env_logger = "0.9.0" cfg-if = "0.1" clap = "2.26.2" bincode = "0.8.0" diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 907c65f40..6ce19365d 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -20,6 +20,8 @@ fn main() { // set a custom panic hook std::panic::set_hook(Box::new(panic_hook)); + env_logger::init(); + cli().unwrap_or_else(|e| { println!("{}", e); std::process::exit(1); diff --git a/zokrates_cli/src/ops/compile.rs b/zokrates_cli/src/ops/compile.rs index ace894b4d..cfe177811 100644 --- a/zokrates_cli/src/ops/compile.rs +++ b/zokrates_cli/src/ops/compile.rs @@ -99,6 +99,8 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { let abi_spec_path = Path::new(sub_matches.value_of("abi-spec").unwrap()); let hr_output_path = bin_output_path.to_path_buf().with_extension("ztf"); + log::debug!("Load entry point file {}", path.display()); + let file = File::open(path.clone()) .map_err(|why| format!("Could not open {}: {}", path.display(), why))?; @@ -131,6 +133,9 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { .isolate_branches(sub_matches.is_present("isolate-branches")); let resolver = FileSystemResolver::with_stdlib_root(stdlib_path); + + log::debug!("Compile"); + let artifacts: CompilationArtifacts = compile(source, path, Some(&resolver), &config) .map_err(|e| { format!( @@ -148,6 +153,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { let num_constraints = program_flattened.constraint_count(); // serialize flattened program and write to binary file + log::debug!("Serialize program"); let bin_output_file = File::create(&bin_output_path) .map_err(|why| format!("Could not create {}: {}", bin_output_path.display(), why))?; @@ -156,6 +162,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { program_flattened.serialize(&mut writer); // serialize ABI spec and write to JSON file + log::debug!("Serialize ABI"); let abi_spec_file = File::create(&abi_spec_path) .map_err(|why| format!("Could not create {}: {}", abi_spec_path.display(), why))?; @@ -173,6 +180,7 @@ fn cli_compile(sub_matches: &ArgMatches) -> Result<(), String> { if sub_matches.is_present("ztf") { // write human-readable output file + log::debug!("Serialize human readable program"); let hr_output_file = File::create(&hr_output_path) .map_err(|why| format!("Could not create {}: {}", hr_output_path.display(), why))?; diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index e81f04fbe..204da4849 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -16,6 +16,7 @@ multicore = ["bellman_ce/multicore"] ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "zokrates_field/ark", "sha2"] [dependencies] +log = "0.4" cfg-if = "0.1" num = { version = "0.1.36", default-features = false } num-bigint = { version = "0.2", default-features = false } diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 093031ec5..81b07f2da 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -192,18 +192,23 @@ pub fn compile>( let (typed_ast, abi) = check_with_arena(source, location, resolver, config, &arena)?; // flatten input program + log::debug!("Flatten"); let program_flattened = Flattener::flatten(typed_ast, config); // analyse (constant propagation after call resolution) + log::debug!("Analyse flat program"); let program_flattened = program_flattened.analyse(); // convert to ir + log::debug!("Convert to IR"); let ir_prog = ir::Prog::from(program_flattened); // optimize + log::debug!("Optimise IR"); let optimized_ir_prog = ir_prog.optimize(); // analyse (check constraints) + log::debug!("Analyse IR"); let optimized_ir_prog = optimized_ir_prog.analyse(); Ok(CompilationArtifacts { @@ -231,7 +236,12 @@ fn check_with_arena<'ast, T: Field, E: Into>( arena: &'ast Arena, ) -> Result<(ZirProgram<'ast, T>, Abi), CompileErrors> { let source = arena.alloc(source); - let compiled = compile_program::(source, location, resolver, &arena)?; + + log::debug!("Parse program with entry file {}", location.display()); + + let compiled = parse_program::(source, location, resolver, &arena)?; + + log::debug!("Check semantics"); // check semantics let typed_ast = Checker::check(compiled) @@ -239,13 +249,15 @@ fn check_with_arena<'ast, T: Field, E: Into>( let main_module = typed_ast.main.clone(); + log::debug!("Run static analysis"); + // analyse (unroll and constant propagation) typed_ast .analyse(config) .map_err(|e| CompileErrors(vec![CompileErrorInner::from(e).in_file(&main_module)])) } -pub fn compile_program<'ast, T: Field, E: Into>( +pub fn parse_program<'ast, T: Field, E: Into>( source: &'ast str, location: FilePath, resolver: Option<&dyn Resolver>, @@ -253,7 +265,7 @@ pub fn compile_program<'ast, T: Field, E: Into>( ) -> Result, CompileErrors> { let mut modules = HashMap::new(); - let main = compile_module::(&source, location.clone(), resolver, &mut modules, &arena)?; + let main = parse_module::(&source, location.clone(), resolver, &mut modules, &arena)?; modules.insert(location.clone(), main); @@ -263,21 +275,29 @@ pub fn compile_program<'ast, T: Field, E: Into>( }) } -pub fn compile_module<'ast, T: Field, E: Into>( +pub fn parse_module<'ast, T: Field, E: Into>( source: &'ast str, location: FilePath, resolver: Option<&dyn Resolver>, modules: &mut HashMap>, arena: &'ast Arena, ) -> Result, CompileErrors> { + log::debug!("Generate pest AST for {}", location.display()); + let ast = pest::generate_ast(&source) .map_err(|e| CompileErrors::from(CompileErrorInner::from(e).in_file(&location)))?; + log::debug!("Process macros for {}", location.display()); + let ast = process_macros::(ast) .map_err(|e| CompileErrors::from(CompileErrorInner::from(e).in_file(&location)))?; + log::debug!("Generate absy for {}", location.display()); + let module_without_imports: Module = Module::from(ast); + log::debug!("Apply imports to absy for {}", location.display()); + Importer::apply_imports::( module_without_imports, location.clone(), diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index dd05f3f32..f04aedcca 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -40,18 +40,18 @@ pub struct Flattener<'ast, T: Field> { } trait FlattenOutput: Sized { - fn flat(&self) -> FlatExpression; + fn flat(self) -> FlatExpression; } impl FlattenOutput for FlatExpression { - fn flat(&self) -> FlatExpression { - self.clone() + fn flat(self) -> FlatExpression { + self } } impl FlattenOutput for FlatUExpression { - fn flat(&self) -> FlatExpression { - self.clone().get_field_unchecked() + fn flat(self) -> FlatExpression { + self.get_field_unchecked() } } @@ -905,8 +905,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { // Y == X * M // 0 == (1-Y) * X - assert!(lhs.metadata.clone().unwrap().should_reduce.to_bool()); - assert!(rhs.metadata.clone().unwrap().should_reduce.to_bool()); + assert!(lhs.metadata.as_ref().unwrap().should_reduce.to_bool()); + assert!(rhs.metadata.as_ref().unwrap().should_reduce.to_bool()); let lhs = self .flatten_uint_expression(statements_flattened, lhs) @@ -924,7 +924,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { ); let eq = self.flatten_boolean_expression( statements_flattened, - BooleanExpression::FieldEq(box lhs.clone(), box rhs.clone()), + BooleanExpression::FieldEq(box lhs, box rhs), ); FlatExpression::Add(box eq, box lt) } @@ -1018,7 +1018,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { ); let eq = self.flatten_boolean_expression( statements_flattened, - BooleanExpression::UintEq(box lhs.clone(), box rhs.clone()), + BooleanExpression::UintEq(box lhs, box rhs), ); FlatExpression::Add(box eq, box lt) } @@ -1045,7 +1045,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { box x.clone(), box FlatExpression::Sub(box y.clone(), box name_x_or_y.into()), ), - FlatExpression::Mult(box x.clone(), box y.clone()), + FlatExpression::Mult(box x, box y), RuntimeError::Or, )); name_x_or_y.into() @@ -1089,9 +1089,9 @@ impl<'ast, T: Field> Flattener<'ast, T> { bitwidth: UBitwidth, ) -> Vec> { let expression = UExpression::try_from(expression).unwrap(); - let from = expression.metadata.clone().unwrap().bitwidth(); + let from = expression.metadata.as_ref().unwrap().bitwidth(); let p = self.flatten_uint_expression(statements_flattened, expression); - self.get_bits(p, from as usize, bitwidth, statements_flattened) + self.get_bits(&p, from as usize, bitwidth, statements_flattened) .into_iter() .map(FlatUExpression::with_field) .collect() @@ -1128,27 +1128,29 @@ impl<'ast, T: Field> Flattener<'ast, T> { statements_flattened: &mut FlatStatements, embed: FlatEmbed, generics: Vec, - param_expressions: Vec>, + mut param_expressions: Vec>, ) -> Vec> { match embed { crate::embed::FlatEmbed::U64ToBits => self.flatten_u_to_bits( statements_flattened, - param_expressions[0].clone(), + param_expressions.pop().unwrap(), 64.into(), ), crate::embed::FlatEmbed::U32ToBits => self.flatten_u_to_bits( statements_flattened, - param_expressions[0].clone(), + param_expressions.pop().unwrap(), 32.into(), ), crate::embed::FlatEmbed::U16ToBits => self.flatten_u_to_bits( statements_flattened, - param_expressions[0].clone(), + param_expressions.pop().unwrap(), 16.into(), ), - crate::embed::FlatEmbed::U8ToBits => { - self.flatten_u_to_bits(statements_flattened, param_expressions[0].clone(), 8.into()) - } + crate::embed::FlatEmbed::U8ToBits => self.flatten_u_to_bits( + statements_flattened, + param_expressions.pop().unwrap(), + 8.into(), + ), crate::embed::FlatEmbed::U64FromBits => { vec![self.flatten_bits_to_u(statements_flattened, param_expressions, 64.into())] } @@ -1293,10 +1295,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { self.define(e, statements_flattened).into() } else if n == T::from(1) { self.define( - FlatExpression::Sub( - box FlatExpression::Number(T::from(1)), - box e.clone(), - ), + FlatExpression::Sub(box FlatExpression::Number(T::from(1)), box e), statements_flattened, ) .into() @@ -1319,8 +1318,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { box FlatExpression::Sub(box y.clone(), box name.into()), ), FlatExpression::Mult( - box FlatExpression::Add(box x.clone(), box x.clone()), - box y.clone(), + box FlatExpression::Add(box x.clone(), box x), + box y, ), RuntimeError::Xor, ), @@ -1391,7 +1390,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // q in range let _ = self.get_bits( - FlatUExpression::with_field(FlatExpression::from(q)), + &FlatUExpression::with_field(FlatExpression::from(q)), target_bitwidth.to_usize(), target_bitwidth, statements_flattened, @@ -1399,7 +1398,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // r in range let _ = self.get_bits( - FlatUExpression::with_field(FlatExpression::from(r)), + &FlatUExpression::with_field(FlatExpression::from(r)), target_bitwidth.to_usize(), target_bitwidth, statements_flattened, @@ -1407,7 +1406,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // r < d <=> r - d + 2**w < 2**w let _ = self.get_bits( - FlatUExpression::with_field(FlatExpression::Add( + &FlatUExpression::with_field(FlatExpression::Add( box FlatExpression::Sub(box r.into(), box d.clone()), box FlatExpression::Number(T::from(2_u128.pow(target_bitwidth.to_usize() as u32))), )), @@ -1514,7 +1513,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { UExpressionInner::Sub(box left, box right) => { // see uint optimizer for the reasoning here let offset = FlatExpression::Number(T::from(2).pow(std::cmp::max( - right.metadata.clone().unwrap().bitwidth() as usize, + right.metadata.as_ref().unwrap().bitwidth() as usize, target_bitwidth as usize, ))); @@ -1818,10 +1817,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { } } (x, y) => self - .define( - FlatExpression::Mult(box x.clone(), box y.clone()), - statements_flattened, - ) + .define(FlatExpression::Mult(box x, box y), statements_flattened) .into(), }) .collect(); @@ -1883,12 +1879,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { let res = match should_reduce { true => { - let bits = self.get_bits( - res.clone(), - actual_bitwidth, - target_bitwidth, - statements_flattened, - ); + let bits = + self.get_bits(&res, actual_bitwidth, target_bitwidth, statements_flattened); let field = if actual_bitwidth > target_bitwidth.to_usize() { bits.iter().enumerate().fold( @@ -1919,7 +1911,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { fn get_bits( &mut self, - e: FlatUExpression, + e: &FlatUExpression, from: usize, to: UBitwidth, statements_flattened: &mut FlatStatements, @@ -1993,7 +1985,8 @@ impl<'ast, T: Field> Flattener<'ast, T> { assert_eq!(bits.len(), to); - self.bits_cache.insert(e.field.unwrap(), bits.clone()); + self.bits_cache + .insert(e.field.clone().unwrap(), bits.clone()); self.bits_cache.insert(sum, bits.clone()); bits @@ -2597,7 +2590,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // to constrain unsigned integer inputs to be in range, we get their bit decomposition. // it will be cached self.get_bits( - FlatUExpression::with_field(FlatExpression::Identifier(variable)), + &FlatUExpression::with_field(FlatExpression::Identifier(variable)), bitwidth.to_usize(), bitwidth, statements_flattened, diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 4578b89db..ad0e475ae 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -5,7 +5,7 @@ //! @date 2018 use crate::absy::*; -use crate::compile::compile_module; +use crate::compile::parse_module; use crate::compile::{CompileErrorInner, CompileErrors}; use crate::embed::FlatEmbed; use crate::parser::Position; @@ -222,7 +222,7 @@ impl Importer { Some(_) => {} None => { let source = arena.alloc(source); - let compiled = compile_module::( + let compiled = parse_module::( source, new_location.clone(), resolver, diff --git a/zokrates_core/src/optimizer/mod.rs b/zokrates_core/src/optimizer/mod.rs index 6fd1088ad..3f2c064a8 100644 --- a/zokrates_core/src/optimizer/mod.rs +++ b/zokrates_core/src/optimizer/mod.rs @@ -21,12 +21,30 @@ use zokrates_field::Field; impl Prog { pub fn optimize(self) -> Self { // remove redefinitions + log::debug!("Constraints: {}", self.constraint_count()); + log::debug!("Optimizer: Remove redefinitions"); let r = RedefinitionOptimizer::optimize(self); + log::debug!("Done"); + // remove constraints that are always satisfied + log::debug!("Constraints: {}", r.constraint_count()); + log::debug!("Optimizer: Remove tautologies"); let r = TautologyOptimizer::optimize(r); - // // deduplicate directives which take the same input + log::debug!("Done"); + + // deduplicate directives which take the same input + log::debug!("Constraints: {}", r.constraint_count()); + log::debug!("Optimizer: Remove duplicate directive"); let r = DirectiveOptimizer::optimize(r); + log::debug!("Done"); + // remove duplicate constraints - DuplicateOptimizer::optimize(r) + log::debug!("Constraints: {}", r.constraint_count()); + log::debug!("Optimizer: Remove duplicate constraints"); + let r = DuplicateOptimizer::optimize(r); + log::debug!("Done"); + + log::debug!("Constraints: {}", r.constraint_count()); + r } } diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index e66f15055..82b9d6fe0 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -73,29 +73,54 @@ impl fmt::Display for Error { impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { // inline user-defined constants + log::debug!("Static analyser: Inline constants"); let r = ConstantInliner::inline(self); + log::trace!("\n{}", r); + // isolate branches let r = if config.isolate_branches { - Isolator::isolate(r) + 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 }; // reduce the program to a single function + log::debug!("Static analyser: Reduce program"); let r = reduce_program(r).map_err(Error::from)?; + log::trace!("\n{}", r); + // generate abi + log::debug!("Static analyser: Generate abi"); let abi = r.abi(); // propagate + log::debug!("Static analyser: Propagate"); let r = Propagator::propagate(r).map_err(Error::from)?; + log::trace!("\n{}", r); + // remove assignment to variable index + log::debug!("Static analyser: Remove variable index"); let r = VariableWriteRemover::apply(r); + log::trace!("\n{}", r); + // detect non constant shifts + log::debug!("Static analyser: Detect non constant shifts"); let r = ShiftChecker::check(r).map_err(Error::from)?; + log::trace!("\n{}", r); + // convert to zir, removing complex types + log::debug!("Static analyser: Convert to zir"); let zir = Flattener::flatten(r); + log::trace!("\n{}", zir); + // optimize uint expressions + log::debug!("Static analyser: Optimize uints"); let zir = UintOptimizer::optimize(zir); + log::trace!("\n{}", zir); Ok((zir, abi)) } @@ -103,12 +128,14 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { impl Analyse for FlatProg { fn analyse(self) -> Self { + log::debug!("Static analyser: Propagate flat"); self.propagate() } } impl Analyse for Prog { fn analyse(self) -> Self { + log::debug!("Static analyser: Detect unconstrained zir"); UnconstrainedVariableDetector::detect(self) } } From 63865f8e01866c76d85248090134c36caa931339 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 29 Jul 2021 11:48:48 +0200 Subject: [PATCH 47/86] add changelog --- Cargo.lock | 65 +++++++++++++++++++++++++++++-- changelogs/unreleased/950-schaeff | 1 + 2 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/950-schaeff diff --git a/Cargo.lock b/Cargo.lock index c87c18024..3204491d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -776,6 +785,19 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex 1.5.4", + "termcolor", +] + [[package]] name = "environment" version = "0.1.1" @@ -1076,6 +1098,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "idna" version = "0.2.3" @@ -1682,13 +1710,24 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" dependencies = [ - "aho-corasick", + "aho-corasick 0.6.10", "memchr", - "regex-syntax", + "regex-syntax 0.5.6", "thread_local", "utf8-ranges", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick 0.7.18", + "memchr", + "regex-syntax 0.6.25", +] + [[package]] name = "regex-automata" version = "0.1.10" @@ -1704,6 +1743,12 @@ dependencies = [ "ucd-util", ] +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1959,6 +2004,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -2336,10 +2390,12 @@ dependencies = [ "cfg-if 0.1.10", "clap", "dirs", + "env_logger", "fs_extra", "glob 0.2.11", "lazy_static", - "regex", + "log", + "regex 0.2.11", "serde_json", "tempdir", "zokrates_abi", @@ -2378,6 +2434,7 @@ dependencies = [ "git2", "hex", "lazy_static", + "log", "num", "num-bigint 0.2.6", "pairing_ce", @@ -2385,7 +2442,7 @@ dependencies = [ "rand 0.4.6", "rand 0.7.3", "reduce", - "regex", + "regex 0.2.11", "serde", "serde_json", "sha2 0.9.5", diff --git a/changelogs/unreleased/950-schaeff b/changelogs/unreleased/950-schaeff new file mode 100644 index 000000000..1b3e2e0da --- /dev/null +++ b/changelogs/unreleased/950-schaeff @@ -0,0 +1 @@ +Add compiler logs \ No newline at end of file From b9f16d30eb44362f5a886dc5a55498e5153549dd Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 2 Aug 2021 12:46:10 +0200 Subject: [PATCH 48/86] flag tutorial tests as ignored --- zokrates_cli/tests/integration.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zokrates_cli/tests/integration.rs b/zokrates_cli/tests/integration.rs index 80b9ad692..4776f9106 100644 --- a/zokrates_cli/tests/integration.rs +++ b/zokrates_cli/tests/integration.rs @@ -392,6 +392,7 @@ mod integration { } #[test] + #[ignore] fn test_compile_and_smtlib2_dir() { let dir = Path::new("./tests/code"); assert!(dir.is_dir()); @@ -407,6 +408,7 @@ mod integration { } #[test] + #[ignore] fn test_rng_tutorial() { let tmp_dir = TempDir::new(".tmp").unwrap(); let tmp_base = tmp_dir.path(); @@ -429,6 +431,7 @@ mod integration { } #[test] + #[ignore] fn test_sha256_tutorial() { let tmp_dir = TempDir::new(".tmp").unwrap(); let tmp_base = tmp_dir.path(); From 3103d17d6f276776d05d58f5d740c2636dd06772 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 3 Aug 2021 00:20:40 +0200 Subject: [PATCH 49/86] add tests, unwrap on infailible semantic check --- .../compile_errors/generics/duplicate_struct_generic.zok | 6 ++++++ .../compile_errors/generics/numerical_struct_generic.zok | 6 ++++++ .../compile_errors/generics/undeclared_struct_generic.zok | 6 ++++++ zokrates_core/src/semantics.rs | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 zokrates_cli/examples/compile_errors/generics/duplicate_struct_generic.zok create mode 100644 zokrates_cli/examples/compile_errors/generics/numerical_struct_generic.zok create mode 100644 zokrates_cli/examples/compile_errors/generics/undeclared_struct_generic.zok diff --git a/zokrates_cli/examples/compile_errors/generics/duplicate_struct_generic.zok b/zokrates_cli/examples/compile_errors/generics/duplicate_struct_generic.zok new file mode 100644 index 000000000..a87dcd163 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/duplicate_struct_generic.zok @@ -0,0 +1,6 @@ +struct A { + field[N] a +} + +def main(): + return \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/generics/numerical_struct_generic.zok b/zokrates_cli/examples/compile_errors/generics/numerical_struct_generic.zok new file mode 100644 index 000000000..ccb789e3c --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/numerical_struct_generic.zok @@ -0,0 +1,6 @@ +struct A<1> { + field[1] a +} + +def main(): + return \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/generics/undeclared_struct_generic.zok b/zokrates_cli/examples/compile_errors/generics/undeclared_struct_generic.zok new file mode 100644 index 000000000..bd1ac03f2 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/generics/undeclared_struct_generic.zok @@ -0,0 +1,6 @@ +struct A { + field[N] a +} + +def main(): + return \ No newline at end of file diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 3a2546c70..02243960c 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1410,7 +1410,7 @@ impl<'ast, T: Field> Checker<'ast, T> { .map(|m| { Ok(DeclarationStructMember { ty: box specialize_declaration_type(*m.ty, &assignment) - .map_err(|_| unimplemented!())?, + .unwrap(), ..m }) }) From 0daf12284096a7ac380dc0ae6446b2bb135cc180 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 3 Aug 2021 00:52:35 +0200 Subject: [PATCH 50/86] better absy fmt, remove tryfrom/from implementations from declaration types to normal types, use function instead --- zokrates_core/src/absy/mod.rs | 15 ++++++------ zokrates_core/src/semantics.rs | 8 ++++--- .../static_analysis/flatten_complex_types.rs | 2 +- zokrates_core/src/static_analysis/mod.rs | 2 -- .../src/static_analysis/propagation.rs | 1 - zokrates_core/src/typed_absy/mod.rs | 2 +- zokrates_core/src/typed_absy/types.rs | 24 ------------------- zokrates_core/src/typed_absy/variable.rs | 20 ++++------------ 8 files changed, 19 insertions(+), 55 deletions(-) diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index d685151e1..70fc76d09 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -205,20 +205,19 @@ pub struct StructDefinition<'ast> { impl<'ast> fmt::Display for StructDefinition<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( + writeln!( f, - "<{}> {{\n {}\n}}", + "<{}> {{", self.generics .iter() .map(|g| g.to_string()) .collect::>() .join(", "), - self.fields - .iter() - .map(|fi| fi.to_string()) - .collect::>() - .join("\n ") - ) + )?; + for field in &self.fields { + writeln!(f, " {}", field)?; + } + write!(f, "}}",) } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 02243960c..937fbf174 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -945,7 +945,9 @@ impl<'ast, T: Field> Checker<'ast, T> { let decl_v = DeclarationVariable::with_id_and_type(arg.id.value.id, decl_ty.clone()); - match self.insert_into_scope(decl_v.clone()) { + match self.insert_into_scope( + crate::typed_absy::variable::try_from_g_variable(decl_v.clone()).unwrap(), + ) { true => {} false => { errors.push(ErrorInner { @@ -3258,9 +3260,9 @@ impl<'ast, T: Field> Checker<'ast, T> { }) } - fn insert_into_scope>>(&mut self, v: U) -> bool { + fn insert_into_scope(&mut self, v: Variable<'ast, T>) -> bool { self.scope.insert(ScopedVariable { - id: v.into(), + id: v, level: self.level, }) } diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index af1825f59..36ae9af3a 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -129,7 +129,7 @@ impl<'ast, T: Field> Flattener { p: typed_absy::DeclarationParameter<'ast>, ) -> Vec> { let private = p.private; - self.fold_variable(p.id.try_into().unwrap()) + self.fold_variable(crate::typed_absy::variable::try_from_g_variable(p.id).unwrap()) .into_iter() .map(|v| zir::Parameter { id: v, private }) .collect() diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 8740f1dc4..e66f15055 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -83,13 +83,11 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { // reduce the program to a single function let r = reduce_program(r).map_err(Error::from)?; - // generate abi let abi = r.abi(); // propagate let r = Propagator::propagate(r).map_err(Error::from)?; - // remove assignment to variable index let r = VariableWriteRemover::apply(r); // detect non constant shifts diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index c5989c217..6f3f6c89c 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -327,7 +327,6 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { // propagation to the defined variable if rhs is a constant TypedStatement::Definition(assignee, expr) => { let expr = self.fold_expression(expr)?; - let assignee = self.fold_assignee(assignee)?; if let (Ok(a), Ok(e)) = ( diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 7b353f451..89f939765 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -14,7 +14,7 @@ mod integer; mod parameter; pub mod types; mod uint; -mod variable; +pub mod variable; pub use self::identifier::CoreIdentifier; pub use self::parameter::{DeclarationParameter, GParameter}; diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index dde96217f..6e9a13dbf 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -263,18 +263,6 @@ impl<'ast, T> From for StructMember<'ast, T> { } } -// impl<'ast> From for DeclarationStructMember<'ast> { -// fn from(t: ConcreteStructMember) -> Self { -// try_from_g_struct_member(t).unwrap() -// } -// } - -// impl<'ast, T> From> for StructMember<'ast, T> { -// fn from(t: DeclarationStructMember<'ast>) -> Self { -// try_from_g_struct_member(t).unwrap() -// } -// } - #[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)] pub struct GArrayType { pub size: S, @@ -354,12 +342,6 @@ impl<'ast> From for DeclarationArrayType<'ast> { } } -impl<'ast, T> From> for ArrayType<'ast, T> { - fn from(t: DeclarationArrayType<'ast>) -> Self { - try_from_g_array_type(t).unwrap() - } -} - #[derive(Debug, Clone, Serialize, Deserialize, PartialOrd, Ord)] pub struct GStructType { #[serde(flatten)] @@ -440,12 +422,6 @@ impl<'ast> From for DeclarationStructType<'ast> { } } -// impl<'ast, T> From> for StructType<'ast, T> { -// fn from(t: DeclarationStructType<'ast>) -> Self { -// try_from_g_struct_type(t).unwrap() -// } -// } - impl GStructType { pub fn new( module: PathBuf, diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index f49a86b90..964da307d 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -25,16 +25,6 @@ impl<'ast, T> TryFrom> for ConcreteVariable<'ast> { } } -// impl<'ast> TryFrom> for ConcreteVariable<'ast> { -// type Error = SpecializationError; - -// fn try_from(v: DeclarationVariable<'ast>) -> Result { -// let _type = v._type.try_into()?; - -// Ok(Self { _type, id: v.id }) -// } -// } - impl<'ast, T> From> for Variable<'ast, T> { fn from(v: ConcreteVariable<'ast>) -> Self { let _type = v._type.into(); @@ -43,12 +33,12 @@ impl<'ast, T> From> for Variable<'ast, T> { } } -impl<'ast, T> From> for Variable<'ast, T> { - fn from(v: DeclarationVariable<'ast>) -> Self { - let _type = crate::typed_absy::types::try_from_g_type(v._type).unwrap(); +pub fn try_from_g_variable<'ast, T: TryInto, U>( + v: GVariable<'ast, T>, +) -> Result, SpecializationError> { + let _type = crate::typed_absy::types::try_from_g_type(v._type)?; - Self { _type, id: v.id } - } + Ok(GVariable { _type, id: v.id }) } impl<'ast, S: Clone> GVariable<'ast, S> { From 1e03f110afcf77aa5fe679a60e9b0bfba7bbe062 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 3 Aug 2021 10:25:42 +0200 Subject: [PATCH 51/86] clippy --- zokrates_core/src/typed_absy/variable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index 964da307d..2d19a95ef 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -33,8 +33,8 @@ impl<'ast, T> From> for Variable<'ast, T> { } } -pub fn try_from_g_variable<'ast, T: TryInto, U>( - v: GVariable<'ast, T>, +pub fn try_from_g_variable, U>( + v: GVariable, ) -> Result, SpecializationError> { let _type = crate::typed_absy::types::try_from_g_type(v._type)?; From bb27d13a2f488f9840205b83ed9378ef4657a722 Mon Sep 17 00:00:00 2001 From: dark64 Date: Tue, 3 Aug 2021 14:48:45 +0200 Subject: [PATCH 52/86] improve test generation script in gm17 snark test --- zokrates_stdlib/tests/tests/snark/gm17.zok | 47 +++++++++------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/zokrates_stdlib/tests/tests/snark/gm17.zok b/zokrates_stdlib/tests/tests/snark/gm17.zok index afa72558f..d09a2473a 100644 --- a/zokrates_stdlib/tests/tests/snark/gm17.zok +++ b/zokrates_stdlib/tests/tests/snark/gm17.zok @@ -26,34 +26,27 @@ // 5. Generate the test case // // ```sh -// rm gm17.json -// touch gm17.json - -// echo '{ -// "entry_point": "./tests/tests/snark/gm17.zok", -// "curves": ["Bw6_761"], -// "tests": [ -// { -// "input": { -// "values": [' >> gm17.json - -// cat proof.json >> gm17.json - -// echo ', ' >> gm17.json - -// cat verification.key >> gm17.json - -// echo ' +// cat > gm17.json << EOT +// { +// "entry_point": "./tests/tests/snark/gm17.zok", +// "curves": ["Bw6_761"], +// "tests": [ +// { +// "abi": true, +// "input": { +// "values": [ +// $(cat proof.json && echo ", " && cat verification.key) // ] -// }, -// "output": { -// "Ok": { -// "values": ["1"] -// } -// } -// } -// ] -// }' >> gm17.json +// }, +// "output": { +// "Ok": { +// "values": ["1"] +// } +// } +// } +// ] +// } +// EOT // ``` // // `gm17.json` can then be used as a test for this code file From b1c9a171f8666bb7994b64895d9b9c46f61eb8cb Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 14:55:17 +0200 Subject: [PATCH 53/86] add bit lt embed, fail on non constant bound, implement safe unpack --- .../compile_errors/variable_constant_lt.zok | 5 + zokrates_core/src/embed.rs | 30 +++++- zokrates_core/src/flatten/mod.rs | 49 ++++++++- zokrates_core/src/imports.rs | 4 + zokrates_core/src/ir/interpreter.rs | 24 ++++- .../constant_argument_checker.rs | 99 +++++++++++++++++++ zokrates_core/src/static_analysis/mod.rs | 14 +-- .../src/static_analysis/propagation.rs | 1 + .../src/static_analysis/shift_checker.rs | 55 ----------- .../utils/pack/bool/nonStrictUnpack256.zok | 4 +- .../stdlib/utils/pack/bool/unpack.zok | 12 +-- .../stdlib/utils/pack/bool/unpack128.zok | 4 +- .../stdlib/utils/pack/bool/unpack256.zok | 7 ++ .../utils/pack/bool/unpack_unchecked.zok | 9 ++ .../tests/utils/pack/bool/unpack256.json | 16 +++ .../tests/tests/utils/pack/bool/unpack256.zok | 24 +++++ 16 files changed, 277 insertions(+), 80 deletions(-) create mode 100644 zokrates_cli/examples/compile_errors/variable_constant_lt.zok create mode 100644 zokrates_core/src/static_analysis/constant_argument_checker.rs delete mode 100644 zokrates_core/src/static_analysis/shift_checker.rs create mode 100644 zokrates_stdlib/stdlib/utils/pack/bool/unpack256.zok create mode 100644 zokrates_stdlib/stdlib/utils/pack/bool/unpack_unchecked.zok create mode 100644 zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json create mode 100644 zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.zok diff --git a/zokrates_cli/examples/compile_errors/variable_constant_lt.zok b/zokrates_cli/examples/compile_errors/variable_constant_lt.zok new file mode 100644 index 000000000..4527bffc5 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/variable_constant_lt.zok @@ -0,0 +1,5 @@ +from "EMBED" import bit_array_le + +// Unpack a field element as N big endian bits +def main(bool[1] a, bool[1] b) -> bool: + return bit_array_le::<1>(a, b) \ No newline at end of file diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 9f87b00e9..d0c34bab5 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -28,6 +28,7 @@ cfg_if::cfg_if! { /// the flattening step when it can be inlined. #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub enum FlatEmbed { + BitArrayLe, U32ToField, Unpack, U8ToBits, @@ -47,6 +48,30 @@ pub enum FlatEmbed { impl FlatEmbed { pub fn signature(&self) -> DeclarationSignature<'static> { match self { + FlatEmbed::BitArrayLe => DeclarationSignature::new() + .generics(vec![Some(DeclarationConstant::Generic( + GenericIdentifier { + name: "N", + index: 0, + }, + ))]) + .inputs(vec![ + DeclarationType::array(( + DeclarationType::Boolean, + GenericIdentifier { + name: "N", + index: 0, + }, + )), + DeclarationType::array(( + DeclarationType::Boolean, + GenericIdentifier { + name: "N", + index: 0, + }, + )), + ]) + .outputs(vec![DeclarationType::Boolean]), FlatEmbed::U32ToField => DeclarationSignature::new() .inputs(vec![DeclarationType::uint(32)]) .outputs(vec![DeclarationType::FieldElement]), @@ -172,6 +197,7 @@ impl FlatEmbed { pub fn id(&self) -> &'static str { match self { + &FlatEmbed::BitArrayLe => "_BIT_ARRAY_LT", FlatEmbed::U32ToField => "_U32_TO_FIELD", FlatEmbed::Unpack => "_UNPACK", FlatEmbed::U8ToBits => "_U8_TO_BITS", @@ -453,10 +479,6 @@ fn use_variable( /// as we decompose over `log_2(p) + 1 bits, some /// elements can have multiple representations: For example, `unpack(0)` is `[0, ..., 0]` but also `unpack(p)` pub fn unpack_to_bitwidth(bit_width: usize) -> FlatFunction { - let nbits = T::get_required_bits(); - - assert!(bit_width <= nbits); - let mut counter = 0; let mut layout = HashMap::new(); diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index dd05f3f32..1d230eae7 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -222,7 +222,6 @@ impl<'ast, T: Field> Flattener<'ast, T> { b: &[bool], ) -> Vec> { let len = b.len(); - assert_eq!(a.len(), T::get_required_bits()); assert_eq!(a.len(), b.len()); let mut is_not_smaller_run = vec![]; @@ -984,7 +983,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { } // check that the decomposition is in the field with a strict `< p` checks - self.constant_le_check( + self.enforce_constant_le_check( statements_flattened, &sub_bits_be, &T::max_value().bit_vector_be(), @@ -1161,6 +1160,52 @@ impl<'ast, T: Field> Flattener<'ast, T> { crate::embed::FlatEmbed::U8FromBits => { vec![self.flatten_bits_to_u(statements_flattened, param_expressions, 8.into())] } + crate::embed::FlatEmbed::BitArrayLe => { + let len = generics[0]; + + let (expressions, constants) = ( + param_expressions[..len as usize].to_vec(), + param_expressions[len as usize..].to_vec(), + ); + + let variables: Vec<_> = expressions + .into_iter() + .map(|e| { + let e = self + .flatten_expression(statements_flattened, e) + .get_field_unchecked(); + self.define(e, statements_flattened) + }) + .collect(); + + let constants: Vec<_> = constants + .into_iter() + .map(|e| { + self.flatten_expression(statements_flattened, e) + .get_field_unchecked() + }) + .map(|e| match e { + FlatExpression::Number(n) => n == T::one(), + _ => unreachable!(), + }) + .collect(); + + let conditions = + self.constant_le_check(statements_flattened, &variables, &constants); + + // return `len(conditions) == sum(conditions)` + vec![FlatUExpression::with_field( + self.eq_check( + statements_flattened, + T::from(conditions.len()).into(), + conditions + .into_iter() + .fold(FlatExpression::Number(T::zero()), |acc, e| { + FlatExpression::Add(box acc, box e) + }), + ), + )] + } funct => { let funct = funct.synthetize(&generics); diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 4578b89db..78d0f180f 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -148,6 +148,10 @@ impl Importer { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::Unpack), }, + "bit_array_le" => SymbolDeclaration { + id: symbol.get_alias(), + symbol: Symbol::Flat(FlatEmbed::BitArrayLe), + }, "u64_to_bits" => SymbolDeclaration { id: symbol.get_alias(), symbol: Symbol::Flat(FlatEmbed::U64ToBits), diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 04f4108ef..c6b75dae6 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -156,10 +156,18 @@ impl Interpreter { ], }, Solver::Bits(bit_width) => { + let padding = bit_width.saturating_sub(T::get_required_bits()); + + let bit_width = bit_width - padding; + let mut num = inputs[0].clone(); let mut res = vec![]; - for i in (0..*bit_width).rev() { + for _ in 0..padding { + res.push(T::zero()); + } + + for i in (0..bit_width).rev() { if T::from(2).pow(i) <= num { num = num - T::from(2).pow(i); res.push(T::one()); @@ -407,4 +415,18 @@ mod tests { assert_eq!(res[248], Bn128Field::from(1)); assert_eq!(res[247], Bn128Field::from(0)); } + + #[test] + fn five_hundred_bits_of_1() { + let inputs = vec![Bn128Field::from(1)]; + let interpreter = Interpreter::default(); + let res = interpreter + .execute_solver(&Solver::Bits(500), &inputs) + .unwrap(); + + let mut expected = vec![Bn128Field::from(0); 500]; + expected[499] = Bn128Field::from(1); + + assert_eq!(res, expected); + } } diff --git a/zokrates_core/src/static_analysis/constant_argument_checker.rs b/zokrates_core/src/static_analysis/constant_argument_checker.rs new file mode 100644 index 000000000..9e9ddb390 --- /dev/null +++ b/zokrates_core/src/static_analysis/constant_argument_checker.rs @@ -0,0 +1,99 @@ +use crate::embed::FlatEmbed; +use crate::typed_absy::TypedProgram; +use crate::typed_absy::{ + result_folder::ResultFolder, + result_folder::{fold_expression_list_inner, fold_uint_expression_inner}, + ArrayExpressionInner, BooleanExpression, TypedExpression, TypedExpressionListInner, + TypedExpressionOrSpread, Types, UBitwidth, UExpressionInner, +}; +use zokrates_field::Field; +pub struct ConstantArgumentChecker; + +impl ConstantArgumentChecker { + pub fn check(p: TypedProgram) -> Result, Error> { + ConstantArgumentChecker.fold_program(p) + } +} + +pub type Error = String; + +impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker { + type Error = Error; + + fn fold_uint_expression_inner( + &mut self, + bitwidth: UBitwidth, + e: UExpressionInner<'ast, T>, + ) -> Result, Error> { + match e { + UExpressionInner::LeftShift(box e, box by) => { + let e = self.fold_uint_expression(e)?; + let by = self.fold_uint_expression(by)?; + + match by.as_inner() { + UExpressionInner::Value(_) => Ok(UExpressionInner::LeftShift(box e, box by)), + by => Err(format!( + "Cannot shift by a variable value, found `{} << {}`", + e, + by.clone().annotate(UBitwidth::B32) + )), + } + } + UExpressionInner::RightShift(box e, box by) => { + let e = self.fold_uint_expression(e)?; + let by = self.fold_uint_expression(by)?; + + match by.as_inner() { + UExpressionInner::Value(_) => Ok(UExpressionInner::RightShift(box e, box by)), + by => Err(format!( + "Cannot shift by a variable value, found `{} >> {}`", + e, + by.clone().annotate(UBitwidth::B32) + )), + } + } + e => fold_uint_expression_inner(self, bitwidth, e), + } + } + + fn fold_expression_list_inner( + &mut self, + tys: &Types<'ast, T>, + l: TypedExpressionListInner<'ast, T>, + ) -> Result, Error> { + match l { + TypedExpressionListInner::EmbedCall(FlatEmbed::BitArrayLe, generics, arguments) => { + let arguments = arguments + .into_iter() + .map(|a| self.fold_expression(a)) + .collect::, _>>()?; + + match arguments[1] { + TypedExpression::Array(ref a) => match a.as_inner() { + ArrayExpressionInner::Value(v) => { + if v.0.iter().all(|v| { + matches!( + v, + TypedExpressionOrSpread::Expression(TypedExpression::Boolean( + BooleanExpression::Value(_) + )) + ) + }) { + Ok(TypedExpressionListInner::EmbedCall( + FlatEmbed::BitArrayLe, + generics, + arguments, + )) + } else { + Err(format!("Cannot compare to a variable value, found `{}`", a)) + } + } + v => Err(format!("Cannot compare to a variable value, found `{}`", v)), + }, + _ => unreachable!(), + } + } + l => fold_expression_list_inner(self, tys, l), + } + } +} diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index e66f15055..bf658118c 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -5,21 +5,21 @@ //! @date 2018 mod branch_isolator; +mod constant_argument_checker; mod constant_inliner; mod flat_propagation; mod flatten_complex_types; mod propagation; mod reducer; -mod shift_checker; mod uint_optimizer; mod unconstrained_vars; mod variable_write_remover; use self::branch_isolator::Isolator; +use self::constant_argument_checker::ConstantArgumentChecker; use self::flatten_complex_types::Flattener; use self::propagation::Propagator; use self::reducer::reduce_program; -use self::shift_checker::ShiftChecker; use self::uint_optimizer::UintOptimizer; use self::unconstrained_vars::UnconstrainedVariableDetector; use self::variable_write_remover::VariableWriteRemover; @@ -39,7 +39,7 @@ pub trait Analyse { pub enum Error { Reducer(self::reducer::Error), Propagation(self::propagation::Error), - NonConstantShift(self::shift_checker::Error), + NonConstantShift(self::constant_argument_checker::Error), } impl From for Error { @@ -54,8 +54,8 @@ impl From for Error { } } -impl From for Error { - fn from(e: shift_checker::Error) -> Self { +impl From for Error { + fn from(e: constant_argument_checker::Error) -> Self { Error::NonConstantShift(e) } } @@ -90,8 +90,8 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { let r = Propagator::propagate(r).map_err(Error::from)?; // remove assignment to variable index let r = VariableWriteRemover::apply(r); - // detect non constant shifts - let r = ShiftChecker::check(r).map_err(Error::from)?; + // detect non constant shifts and constant lt bounds + let r = ConstantArgumentChecker::check(r).map_err(Error::from)?; // convert to zir, removing complex types let zir = Flattener::flatten(r); // optimize uint expressions diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 3799755a4..34a9c3f32 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -502,6 +502,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { true => { let r: Option> = match embed { FlatEmbed::U32ToField => None, // todo + FlatEmbed::BitArrayLe => None, // todo FlatEmbed::U64FromBits => Some(process_u_from_bits( assignees.clone(), arguments.clone(), diff --git a/zokrates_core/src/static_analysis/shift_checker.rs b/zokrates_core/src/static_analysis/shift_checker.rs deleted file mode 100644 index 7e44ea525..000000000 --- a/zokrates_core/src/static_analysis/shift_checker.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::typed_absy::TypedProgram; -use crate::typed_absy::{ - result_folder::fold_uint_expression_inner, result_folder::ResultFolder, UBitwidth, - UExpressionInner, -}; -use zokrates_field::Field; -pub struct ShiftChecker; - -impl ShiftChecker { - pub fn check(p: TypedProgram) -> Result, Error> { - ShiftChecker.fold_program(p) - } -} - -pub type Error = String; - -impl<'ast, T: Field> ResultFolder<'ast, T> for ShiftChecker { - type Error = Error; - - fn fold_uint_expression_inner( - &mut self, - bitwidth: UBitwidth, - e: UExpressionInner<'ast, T>, - ) -> Result, Error> { - match e { - UExpressionInner::LeftShift(box e, box by) => { - let e = self.fold_uint_expression(e)?; - let by = self.fold_uint_expression(by)?; - - match by.as_inner() { - UExpressionInner::Value(_) => Ok(UExpressionInner::LeftShift(box e, box by)), - by => Err(format!( - "Cannot shift by a variable value, found `{} << {}`", - e, - by.clone().annotate(UBitwidth::B32) - )), - } - } - UExpressionInner::RightShift(box e, box by) => { - let e = self.fold_uint_expression(e)?; - let by = self.fold_uint_expression(by)?; - - match by.as_inner() { - UExpressionInner::Value(_) => Ok(UExpressionInner::RightShift(box e, box by)), - by => Err(format!( - "Cannot shift by a variable value, found `{} >> {}`", - e, - by.clone().annotate(UBitwidth::B32) - )), - } - } - e => fold_uint_expression_inner(self, bitwidth, e), - } - } -} diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok b/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok index 4e48909fc..e31dece46 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok @@ -1,12 +1,12 @@ #pragma curve bn128 -import "./unpack" as unpack +import "./unpack_unchecked" // Unpack a field element as 256 big-endian bits // Note: uniqueness of the output is not guaranteed // For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)` def main(field i) -> bool[256]: - bool[254] b = unpack::<254>(i) + bool[254] b = unpack_unchecked::<254>(i) return [false, false, ...b] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/unpack.zok b/zokrates_stdlib/stdlib/utils/pack/bool/unpack.zok index d5b7a5cdf..bc6d22d12 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/unpack.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/unpack.zok @@ -1,12 +1,12 @@ -#pragma curve bn128 - -from "EMBED" import unpack +import "./unpack_unchecked.zok" +from "field" import FIELD_SIZE_IN_BITS +from "EMBED" import bit_array_le // Unpack a field element as N big endian bits def main(field i) -> bool[N]: - - assert(N <= 254) - bool[N] res = unpack(i) + bool[N] res = unpack_unchecked(i) + + assert(if N >= FIELD_SIZE_IN_BITS then bit_array_le(res, [...[false; N - FIELD_SIZE_IN_BITS], ...unpack_unchecked::(-1)]) else true fi) return res \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok b/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok index a24a244b0..8f0b12030 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok @@ -1,9 +1,7 @@ -#pragma curve bn128 - import "./unpack" as unpack // Unpack a field element as 128 big-endian bits -// Precondition: the input is smaller or equal to `2**128 - 1` +// If the input is larger than `2**128 - 1`, the output is truncated. def main(field i) -> bool[128]: bool[128] res = unpack::<128>(i) return res \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/unpack256.zok b/zokrates_stdlib/stdlib/utils/pack/bool/unpack256.zok new file mode 100644 index 000000000..4c3e3e56e --- /dev/null +++ b/zokrates_stdlib/stdlib/utils/pack/bool/unpack256.zok @@ -0,0 +1,7 @@ +import "./unpack" as unpack + +// Unpack a field element as 256 big-endian bits +// If the input is larger than `2**256 - 1`, the output is truncated. +def main(field i) -> bool[256]: + bool[256] res = unpack::<256>(i) + return res \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/unpack_unchecked.zok b/zokrates_stdlib/stdlib/utils/pack/bool/unpack_unchecked.zok new file mode 100644 index 000000000..2b0babbea --- /dev/null +++ b/zokrates_stdlib/stdlib/utils/pack/bool/unpack_unchecked.zok @@ -0,0 +1,9 @@ +from "EMBED" import unpack + +// Unpack a field element as N big endian bits without checking for overflows +// This does *not* guarantee a single output: for example, 0 can be decomposed as 0 or as P and this function does not enforce either +def main(field i) -> bool[N]: + + bool[N] res = unpack(i) + + return res \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json new file mode 100644 index 000000000..5739811a3 --- /dev/null +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/utils/pack/bool/unpack256.zok", + "curves": ["Bn128"], + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": [] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.zok b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.zok new file mode 100644 index 000000000..921ccb024 --- /dev/null +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.zok @@ -0,0 +1,24 @@ +import "utils/pack/bool/unpack256" as unpack256 + +def testFive() -> bool: + + bool[256] b = unpack256(5) + + assert(b == [...[false; 253], true, false, true]) + + return true + +def testZero() -> bool: + + bool[256] b = unpack256(0) + + assert(b == [false; 256]) + + return true + + def main(): + + assert(testFive()) + assert(testZero()) + + return From 2d2387a4b8933597e8234448abcc42f67a6fd376 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 15:06:57 +0200 Subject: [PATCH 54/86] enforce constant range check in uint lt check --- zokrates_core/src/flatten/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index dd05f3f32..664ce70fc 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -984,7 +984,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { } // check that the decomposition is in the field with a strict `< p` checks - self.constant_le_check( + self.enforce_constant_le_check( statements_flattened, &sub_bits_be, &T::max_value().bit_vector_be(), From d771b453f9b53d34af5a58fd1b86b1de7be89946 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 15:10:38 +0200 Subject: [PATCH 55/86] changelog --- changelogs/unreleased/954-schaeff | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/954-schaeff diff --git a/changelogs/unreleased/954-schaeff b/changelogs/unreleased/954-schaeff new file mode 100644 index 000000000..9151cc062 --- /dev/null +++ b/changelogs/unreleased/954-schaeff @@ -0,0 +1 @@ +Fix constant range check in uint lt check \ No newline at end of file From dc0ef3586170c8f45db626f2dff14dda497a8cb2 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 16:53:41 +0200 Subject: [PATCH 56/86] add must_use to prevent this happening --- zokrates_core/src/flatten/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 664ce70fc..efc538d5e 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -215,6 +215,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// **true => a -> 0 /// sizeUnkown * /// **false => a -> {0,1} + #[must_use] fn constant_le_check( &mut self, statements_flattened: &mut FlatStatements, From 6fa722de05de56171e913b027e36463c90592506 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 17:30:16 +0200 Subject: [PATCH 57/86] add commentt on dummy generic variable --- zokrates_core/src/typed_absy/integer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index ff1fe3afc..59589df21 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -82,7 +82,7 @@ impl<'ast, T> IntegerInference for ArrayType<'ast, T> { self.ty .get_common_pattern(*other.ty) .map_err(|(t, u)| (ArrayType::new(t, s0), ArrayType::new(u, s1)))?, - DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), + DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), // sizes are not checked at this stage, therefore we insert a dummy generic variable which will be equal to all possible sizes )) } } From ca6a3f09e8bc338e47657381fd581fec1df87080 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 20:08:23 +0200 Subject: [PATCH 58/86] apply more aggressive propagation to array values --- .../src/static_analysis/propagation.rs | 28 +++++++++++++++++++ zokrates_core/src/typed_absy/mod.rs | 4 +-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 34a9c3f32..384619b46 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -1174,6 +1174,34 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { }, None => Ok(ArrayExpressionInner::Identifier(id)), }, + ArrayExpressionInner::Value(exprs) => { + Ok(ArrayExpressionInner::Value( + exprs + .into_iter() + .map(|e| self.fold_expression_or_spread(e)) + .collect::, _>>()? + .into_iter() + .flat_map(|e| { + match e { + // simplify `...[a, b]` to `a, b` + TypedExpressionOrSpread::Spread(TypedSpread { + array: + ArrayExpression { + ty: _, + inner: ArrayExpressionInner::Value(v), + }, + }) => v.0, + e => vec![e], + } + }) + // ignore spreads over empty arrays + .filter_map(|e| match e { + TypedExpressionOrSpread::Spread(s) if s.array.size() == 0 => None, + e => Some(e), + }) + .collect(), + )) + } e => fold_array_expression_inner(self, ty, e), } } diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index eb4f272e0..07ce3c016 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -1019,8 +1019,8 @@ impl<'ast, T> From for BooleanExpression<'ast, T> { /// type checking #[derive(Clone, PartialEq, Debug, Hash, Eq)] pub struct ArrayExpression<'ast, T> { - ty: Box>, - inner: ArrayExpressionInner<'ast, T>, + pub ty: Box>, + pub inner: ArrayExpressionInner<'ast, T>, } #[derive(Debug, PartialEq, Eq, Hash, Clone)] From eb8e55e137751b49dcaed43a3641dc3dd91d4b8e Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 20:33:10 +0200 Subject: [PATCH 59/86] adjust test --- .../src/static_analysis/reducer/mod.rs | 68 ------------------- 1 file changed, 68 deletions(-) diff --git a/zokrates_core/src/static_analysis/reducer/mod.rs b/zokrates_core/src/static_analysis/reducer/mod.rs index ae26d6cde..84790f29b 100644 --- a/zokrates_core/src/static_analysis/reducer/mod.rs +++ b/zokrates_core/src/static_analysis/reducer/mod.rs @@ -1273,13 +1273,8 @@ mod tests { // def main(): // # PUSH CALL to foo::<1> // # PUSH CALL to bar::<2> - // field[2] a_1 = [...[1]], 0] - // field[2] #RET_0_1 = a_1 // # POP CALL - // field[1] ret := #RET_0_1[0..1] - // field[1] #RET_0 = ret // # POP CALL - // field[1] b_0 := #RET_0 // return let foo_signature = DeclarationSignature::new() @@ -1452,71 +1447,8 @@ mod tests { .collect(), ), ), - TypedStatement::Definition( - Variable::array(Identifier::from("a").version(1), Type::FieldElement, 2u32) - .into(), - ArrayExpressionInner::Value( - vec![ - TypedExpressionOrSpread::Spread( - ArrayExpressionInner::Value( - vec![TypedExpressionOrSpread::Expression( - FieldElementExpression::Number(Bn128Field::from(1)).into(), - )] - .into(), - ) - .annotate(Type::FieldElement, 1u32) - .into(), - ), - FieldElementExpression::Number(Bn128Field::from(0)).into(), - ] - .into(), - ) - .annotate(Type::FieldElement, 2u32) - .into(), - ), - TypedStatement::Definition( - Variable::array( - Identifier::from(CoreIdentifier::Call(0)).version(1), - Type::FieldElement, - 2u32, - ) - .into(), - ArrayExpressionInner::Identifier(Identifier::from("a").version(1)) - .annotate(Type::FieldElement, 2u32) - .into(), - ), TypedStatement::PopCallLog, - TypedStatement::Definition( - Variable::array("ret", Type::FieldElement, 1u32).into(), - ArrayExpressionInner::Slice( - box ArrayExpressionInner::Identifier( - Identifier::from(CoreIdentifier::Call(0)).version(1), - ) - .annotate(Type::FieldElement, 2u32), - box 0u32.into(), - box 1u32.into(), - ) - .annotate(Type::FieldElement, 1u32) - .into(), - ), - TypedStatement::Definition( - Variable::array( - Identifier::from(CoreIdentifier::Call(0)), - Type::FieldElement, - 1u32, - ) - .into(), - ArrayExpressionInner::Identifier("ret".into()) - .annotate(Type::FieldElement, 1u32) - .into(), - ), TypedStatement::PopCallLog, - TypedStatement::Definition( - Variable::array("b", Type::FieldElement, 1u32).into(), - ArrayExpressionInner::Identifier(Identifier::from(CoreIdentifier::Call(0))) - .annotate(Type::FieldElement, 1u32) - .into(), - ), TypedStatement::Return(vec![]), ], signature: DeclarationSignature::new(), From 1ca0b3b9e657cee599ca08d9823a0044e6114072 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 20:59:58 +0200 Subject: [PATCH 60/86] changelog, clean --- changelogs/unreleased/955-schaeff | 1 + zokrates_core/src/embed.rs | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/955-schaeff diff --git a/changelogs/unreleased/955-schaeff b/changelogs/unreleased/955-schaeff new file mode 100644 index 000000000..fff1c6e23 --- /dev/null +++ b/changelogs/unreleased/955-schaeff @@ -0,0 +1 @@ +Make the stdlib `unpack` function safe against overflows of bit decompositions for any size of output, introduce `unpack_unchecked` for cases that do not require determinism \ No newline at end of file diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index d0c34bab5..3ee07660d 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -197,7 +197,7 @@ impl FlatEmbed { pub fn id(&self) -> &'static str { match self { - &FlatEmbed::BitArrayLe => "_BIT_ARRAY_LT", + FlatEmbed::BitArrayLe => "_BIT_ARRAY_LT", FlatEmbed::U32ToField => "_U32_TO_FIELD", FlatEmbed::Unpack => "_UNPACK", FlatEmbed::U8ToBits => "_U8_TO_BITS", @@ -475,9 +475,8 @@ fn use_variable( /// * bit_width the number of bits we want to decompose to /// /// # Remarks -/// * the return value of the `FlatFunction` is not deterministic if `bit_width == T::get_required_bits()` -/// as we decompose over `log_2(p) + 1 bits, some -/// elements can have multiple representations: For example, `unpack(0)` is `[0, ..., 0]` but also `unpack(p)` +/// * the return value of the `FlatFunction` is not deterministic if `bit_width >= T::get_required_bits()` +/// as some elements can have multiple representations: For example, `unpack(0)` is `[0, ..., 0]` but also `unpack(p)` pub fn unpack_to_bitwidth(bit_width: usize) -> FlatFunction { let mut counter = 0; From 7c9e31f40b6f00c2aa5efe9d3cd5c3896cb064e2 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 21:20:45 +0200 Subject: [PATCH 61/86] inline repeats of constants --- .../src/static_analysis/propagation.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 384619b46..a4bc85b06 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -1187,10 +1187,27 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { TypedExpressionOrSpread::Spread(TypedSpread { array: ArrayExpression { - ty: _, inner: ArrayExpressionInner::Value(v), + .. }, }) => v.0, + // simplify ...[a; N] to [a, ..., a] if a is constant + TypedExpressionOrSpread::Spread(TypedSpread { + array: + ArrayExpression { + inner: + ArrayExpressionInner::Repeat( + box v, + box UExpression { + inner: UExpressionInner::Value(count), + .. + }, + ), + .. + }, + }) if is_constant(&v) => { + vec![TypedExpressionOrSpread::Expression(v); count as usize] + } e => vec![e], } }) From dd126b63e0c96705fa21407daa2ad80c4f388aac Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 22:54:43 +0200 Subject: [PATCH 62/86] refactor is_constant to trait, move to typed_absy --- .../constant_argument_checker.rs | 37 ++-- .../src/static_analysis/propagation.rs | 147 +------------- zokrates_core/src/typed_absy/mod.rs | 191 ++++++++++++++++++ 3 files changed, 208 insertions(+), 167 deletions(-) diff --git a/zokrates_core/src/static_analysis/constant_argument_checker.rs b/zokrates_core/src/static_analysis/constant_argument_checker.rs index 9e9ddb390..91ec166ef 100644 --- a/zokrates_core/src/static_analysis/constant_argument_checker.rs +++ b/zokrates_core/src/static_analysis/constant_argument_checker.rs @@ -3,8 +3,7 @@ use crate::typed_absy::TypedProgram; use crate::typed_absy::{ result_folder::ResultFolder, result_folder::{fold_expression_list_inner, fold_uint_expression_inner}, - ArrayExpressionInner, BooleanExpression, TypedExpression, TypedExpressionListInner, - TypedExpressionOrSpread, Types, UBitwidth, UExpressionInner, + Constant, TypedExpressionListInner, Types, UBitwidth, UExpressionInner, }; use zokrates_field::Field; pub struct ConstantArgumentChecker; @@ -68,29 +67,17 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker { .map(|a| self.fold_expression(a)) .collect::, _>>()?; - match arguments[1] { - TypedExpression::Array(ref a) => match a.as_inner() { - ArrayExpressionInner::Value(v) => { - if v.0.iter().all(|v| { - matches!( - v, - TypedExpressionOrSpread::Expression(TypedExpression::Boolean( - BooleanExpression::Value(_) - )) - ) - }) { - Ok(TypedExpressionListInner::EmbedCall( - FlatEmbed::BitArrayLe, - generics, - arguments, - )) - } else { - Err(format!("Cannot compare to a variable value, found `{}`", a)) - } - } - v => Err(format!("Cannot compare to a variable value, found `{}`", v)), - }, - _ => unreachable!(), + if arguments[1].is_constant() { + Ok(TypedExpressionListInner::EmbedCall( + FlatEmbed::BitArrayLe, + generics, + arguments, + )) + } else { + Err(format!( + "Cannot compare to a variable value, found `{}`", + arguments[1] + )) } } l => fold_expression_list_inner(self, tys, l), diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index a4bc85b06..cbb2c4279 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -124,126 +124,6 @@ impl<'ast, 'a, T: Field> Propagator<'ast, 'a, T> { } } -fn is_constant(e: &TypedExpression) -> bool { - match e { - TypedExpression::FieldElement(FieldElementExpression::Number(..)) => true, - TypedExpression::Boolean(BooleanExpression::Value(..)) => true, - TypedExpression::Array(a) => match a.as_inner() { - ArrayExpressionInner::Value(v) => v.0.iter().all(|e| match e { - TypedExpressionOrSpread::Expression(e) => is_constant(e), - _ => false, - }), - ArrayExpressionInner::Slice(box a, box from, box to) => { - is_constant(&from.clone().into()) - && is_constant(&to.clone().into()) - && is_constant(&a.clone().into()) - } - ArrayExpressionInner::Repeat(box e, box count) => { - is_constant(&count.clone().into()) && is_constant(&e) - } - _ => false, - }, - TypedExpression::Struct(a) => match a.as_inner() { - StructExpressionInner::Value(v) => v.iter().all(|e| is_constant(e)), - _ => false, - }, - TypedExpression::Uint(a) => matches!(a.as_inner(), UExpressionInner::Value(..)), - _ => false, - } -} - -// in the constant map, we only want canonical constants: [0; 3] -> [0, 0, 0], [...[1], 2] -> [1, 2], etc -fn to_canonical_constant(e: TypedExpression) -> TypedExpression { - fn to_canonical_constant_aux( - e: TypedExpressionOrSpread, - ) -> Vec> { - match e { - TypedExpressionOrSpread::Expression(e) => vec![e], - TypedExpressionOrSpread::Spread(s) => match s.array.into_inner() { - ArrayExpressionInner::Value(v) => { - v.into_iter().flat_map(to_canonical_constant_aux).collect() - } - _ => unimplemented!(), - }, - } - } - - match e { - TypedExpression::Array(a) => { - let array_ty = a.ty(); - - match a.into_inner() { - ArrayExpressionInner::Value(v) => ArrayExpressionInner::Value( - v.into_iter() - .flat_map(to_canonical_constant_aux) - .map(|e| e.into()) - .collect::>() - .into(), - ) - .annotate(*array_ty.ty, array_ty.size) - .into(), - ArrayExpressionInner::Slice(box a, box from, box to) => { - let from = match from.into_inner() { - UExpressionInner::Value(from) => from as usize, - _ => unreachable!("should be a uint value"), - }; - - let to = match to.into_inner() { - UExpressionInner::Value(to) => to as usize, - _ => unreachable!("should be a uint value"), - }; - - let v = match a.into_inner() { - ArrayExpressionInner::Value(v) => v, - _ => unreachable!("should be an array value"), - }; - - ArrayExpressionInner::Value( - v.into_iter() - .flat_map(to_canonical_constant_aux) - .map(|e| e.into()) - .enumerate() - .filter(|(index, _)| index >= &from && index < &to) - .map(|(_, e)| e) - .collect::>() - .into(), - ) - .annotate(*array_ty.ty, array_ty.size) - .into() - } - ArrayExpressionInner::Repeat(box e, box count) => { - let count = match count.into_inner() { - UExpressionInner::Value(from) => from as usize, - _ => unreachable!("should be a uint value"), - }; - - let e = to_canonical_constant(e); - - ArrayExpressionInner::Value( - vec![TypedExpressionOrSpread::Expression(e); count].into(), - ) - .annotate(*array_ty.ty, array_ty.size) - .into() - } - _ => unreachable!(), - } - } - TypedExpression::Struct(s) => { - let struct_ty = s.ty().clone(); - - match s.into_inner() { - StructExpressionInner::Value(expressions) => StructExpressionInner::Value( - expressions.into_iter().map(to_canonical_constant).collect(), - ) - .annotate(struct_ty) - .into(), - _ => unreachable!(), - } - } - e => e, - } -} - impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { type Error = Error; @@ -341,10 +221,10 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { } }; - if is_constant(&expr) { + if expr.is_constant() { match assignee { TypedAssignee::Identifier(var) => { - let expr = to_canonical_constant(expr); + let expr = expr.into_canonical_constant(); assert!(self.constants.insert(var.id, expr).is_none()); @@ -352,7 +232,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { } assignee => match self.try_get_constant_mut(&assignee) { Ok((_, c)) => { - *c = to_canonical_constant(expr); + *c = expr.into_canonical_constant(); Ok(vec![]) } Err(v) => match self.constants.remove(&v.id) { @@ -423,7 +303,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { let argument = arguments.pop().unwrap(); - let argument = to_canonical_constant(argument); + let argument = argument.into_canonical_constant(); match ArrayExpression::try_from(argument) .unwrap() @@ -498,7 +378,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { } } - match arguments.iter().all(|a| is_constant(a)) { + match arguments.iter().all(|a| a.is_constant()) { true => { let r: Option> = match embed { FlatEmbed::U32ToField => None, // todo @@ -1191,23 +1071,6 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { .. }, }) => v.0, - // simplify ...[a; N] to [a, ..., a] if a is constant - TypedExpressionOrSpread::Spread(TypedSpread { - array: - ArrayExpression { - inner: - ArrayExpressionInner::Repeat( - box v, - box UExpression { - inner: UExpressionInner::Value(count), - .. - }, - ), - .. - }, - }) if is_constant(&v) => { - vec![TypedExpressionOrSpread::Expression(v); count as usize] - } e => vec![e], } }) diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 07ce3c016..e4f500b5a 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -1970,3 +1970,194 @@ impl<'ast, T: Field> Block<'ast, T> for StructExpression<'ast, T> { StructExpressionInner::Block(BlockExpression::new(statements, value)).annotate(struct_ty) } } + +pub trait Constant: Sized { + fn is_constant(&self) -> bool; + + fn into_canonical_constant(self) -> Self { + self + } +} + +impl<'ast, T: Field> Constant for FieldElementExpression<'ast, T> { + fn is_constant(&self) -> bool { + matches!(self, FieldElementExpression::Number(..)) + } +} + +impl<'ast, T: Field> Constant for BooleanExpression<'ast, T> { + fn is_constant(&self) -> bool { + matches!(self, BooleanExpression::Value(..)) + } +} + +impl<'ast, T: Field> Constant for UExpression<'ast, T> { + fn is_constant(&self) -> bool { + matches!(self.as_inner(), UExpressionInner::Value(..)) + } +} + +impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { + fn is_constant(&self) -> bool { + match self.as_inner() { + ArrayExpressionInner::Value(v) => v.0.iter().all(|e| match e { + TypedExpressionOrSpread::Expression(e) => e.is_constant(), + TypedExpressionOrSpread::Spread(s) => s.array.is_constant(), + }), + ArrayExpressionInner::Slice(box a, box from, box to) => { + from.is_constant() && to.is_constant() && a.is_constant() + } + ArrayExpressionInner::Repeat(box e, box count) => { + count.is_constant() && e.is_constant() + } + _ => false, + } + } + + fn into_canonical_constant(self) -> Self { + fn into_canonical_constant_aux( + e: TypedExpressionOrSpread, + ) -> Vec> { + match e { + TypedExpressionOrSpread::Expression(e) => vec![e], + TypedExpressionOrSpread::Spread(s) => match s.array.into_inner() { + ArrayExpressionInner::Value(v) => v + .into_iter() + .flat_map(into_canonical_constant_aux) + .collect(), + ArrayExpressionInner::Slice(box v, box from, box to) => { + let from = match from.into_inner() { + UExpressionInner::Value(v) => v, + _ => unreachable!(), + }; + + let to = match to.into_inner() { + UExpressionInner::Value(v) => v, + _ => unreachable!(), + }; + + let v = match v.into_inner() { + ArrayExpressionInner::Value(v) => v, + _ => unreachable!(), + }; + + v.into_iter() + .flat_map(into_canonical_constant_aux) + .skip(from as usize) + .take(to as usize - from as usize) + .collect() + } + a => unreachable!("{}", a), + }, + } + } + + let array_ty = self.ty(); + + match self.into_inner() { + ArrayExpressionInner::Value(v) => ArrayExpressionInner::Value( + v.into_iter() + .flat_map(into_canonical_constant_aux) + .map(|e| e.into()) + .collect::>() + .into(), + ) + .annotate(*array_ty.ty, array_ty.size) + .into(), + ArrayExpressionInner::Slice(box a, box from, box to) => { + let from = match from.into_inner() { + UExpressionInner::Value(from) => from as usize, + _ => unreachable!("should be a uint value"), + }; + + let to = match to.into_inner() { + UExpressionInner::Value(to) => to as usize, + _ => unreachable!("should be a uint value"), + }; + + let v = match a.into_inner() { + ArrayExpressionInner::Value(v) => v, + _ => unreachable!("should be an array value"), + }; + + ArrayExpressionInner::Value( + v.into_iter() + .flat_map(into_canonical_constant_aux) + .map(|e| e.into()) + .enumerate() + .filter(|(index, _)| index >= &from && index < &to) + .map(|(_, e)| e) + .collect::>() + .into(), + ) + .annotate(*array_ty.ty, array_ty.size) + .into() + } + ArrayExpressionInner::Repeat(box e, box count) => { + let count = match count.into_inner() { + UExpressionInner::Value(from) => from as usize, + _ => unreachable!("should be a uint value"), + }; + + let e = e.into_canonical_constant(); + + ArrayExpressionInner::Value( + vec![TypedExpressionOrSpread::Expression(e); count].into(), + ) + .annotate(*array_ty.ty, array_ty.size) + .into() + } + _ => unreachable!(), + } + } +} + +impl<'ast, T: Field> Constant for StructExpression<'ast, T> { + fn is_constant(&self) -> bool { + match self.as_inner() { + StructExpressionInner::Value(v) => v.iter().all(|e| e.is_constant()), + _ => false, + } + } + + fn into_canonical_constant(self) -> Self { + let struct_ty = self.ty().clone(); + + match self.into_inner() { + StructExpressionInner::Value(expressions) => StructExpressionInner::Value( + expressions + .into_iter() + .map(|e| e.into_canonical_constant()) + .collect(), + ) + .annotate(struct_ty) + .into(), + _ => unreachable!(), + } + } +} + +impl<'ast, T: Field> Constant for TypedExpression<'ast, T> { + fn is_constant(&self) -> bool { + match self { + TypedExpression::FieldElement(e) => e.is_constant(), + TypedExpression::Boolean(e) => e.is_constant(), + TypedExpression::Array(e) => e.is_constant(), + TypedExpression::Struct(e) => e.is_constant(), + TypedExpression::Uint(e) => e.is_constant(), + _ => unreachable!(), + } + } + + // in the constant map, we only want canonical constants: [0; 3] -> [0, 0, 0], [...[1], 2] -> [1, 2], etc + fn into_canonical_constant(self) -> Self { + match self { + TypedExpression::FieldElement(e) => e.into_canonical_constant().into(), + TypedExpression::Boolean(e) => e.into_canonical_constant().into(), + TypedExpression::Array(e) => e.into_canonical_constant().into(), + TypedExpression::Struct(e) => e.into_canonical_constant().into(), + TypedExpression::Uint(e) => e.into_canonical_constant().into(), + _ => unreachable!(), + } + } +} From ea0594035a495be61a9f357df2a61b548667cbe4 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 23:00:10 +0200 Subject: [PATCH 63/86] clippy --- zokrates_core/src/static_analysis/uint_optimizer.rs | 4 ++-- zokrates_core/src/typed_absy/mod.rs | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/zokrates_core/src/static_analysis/uint_optimizer.rs b/zokrates_core/src/static_analysis/uint_optimizer.rs index ecca499a0..232c44249 100644 --- a/zokrates_core/src/static_analysis/uint_optimizer.rs +++ b/zokrates_core/src/static_analysis/uint_optimizer.rs @@ -738,7 +738,7 @@ mod tests { assert_eq!( UintOptimizer::new() - .fold_uint_expression(UExpression::right_shift(left.clone(), right.clone())), + .fold_uint_expression(UExpression::right_shift(left.clone(), right)), UExpression::right_shift(left_expected, right_expected).with_max(output_max) ); } @@ -761,7 +761,7 @@ mod tests { assert_eq!( UintOptimizer::new() - .fold_uint_expression(UExpression::left_shift(left.clone(), right.clone())), + .fold_uint_expression(UExpression::left_shift(left.clone(), right)), UExpression::left_shift(left_expected, right_expected).with_max(output_max) ); } diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index e4f500b5a..07f18a63d 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -2062,8 +2062,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { .collect::>() .into(), ) - .annotate(*array_ty.ty, array_ty.size) - .into(), + .annotate(*array_ty.ty, array_ty.size), ArrayExpressionInner::Slice(box a, box from, box to) => { let from = match from.into_inner() { UExpressionInner::Value(from) => from as usize, @@ -2091,7 +2090,6 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { .into(), ) .annotate(*array_ty.ty, array_ty.size) - .into() } ArrayExpressionInner::Repeat(box e, box count) => { let count = match count.into_inner() { @@ -2105,7 +2103,6 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { vec![TypedExpressionOrSpread::Expression(e); count].into(), ) .annotate(*array_ty.ty, array_ty.size) - .into() } _ => unreachable!(), } @@ -2130,8 +2127,7 @@ impl<'ast, T: Field> Constant for StructExpression<'ast, T> { .map(|e| e.into_canonical_constant()) .collect(), ) - .annotate(struct_ty) - .into(), + .annotate(struct_ty), _ => unreachable!(), } } From 8663ea2bcaac955006c2d701861fdb895c399e62 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 4 Aug 2021 23:52:02 +0200 Subject: [PATCH 64/86] implement repeat case --- zokrates_core/src/typed_absy/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 07f18a63d..d262df05b 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -2047,6 +2047,14 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { .take(to as usize - from as usize) .collect() } + ArrayExpressionInner::Repeat(box e, box count) => { + let count = match count.into_inner() { + UExpressionInner::Value(count) => count, + _ => unreachable!(), + }; + + vec![e; count as usize] + } a => unreachable!("{}", a), }, } From 6e19e7754c4b2b95c8b1e17a0cf540a24b1b4f79 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 11:46:07 +0200 Subject: [PATCH 65/86] clean typed_absy, move common impl to expr trait --- .../static_analysis/flatten_complex_types.rs | 2 +- zokrates_core/src/typed_absy/integer.rs | 4 +- zokrates_core/src/typed_absy/mod.rs | 112 +++++++++++------- 3 files changed, 71 insertions(+), 47 deletions(-) diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index 4e2294af1..ea024055e 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -570,7 +570,7 @@ fn fold_select_expression<'ast, T: Field, E>( statements_buffer: &mut Vec>, select: typed_absy::SelectExpression<'ast, T, E>, ) -> Vec> { - let size = typed_absy::types::ConcreteType::try_from(*select.array.ty().ty) + let size = typed_absy::types::ConcreteType::try_from(*select.array.ty().clone().ty) .unwrap() .get_primitive_count(); diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index 851acf7a2..87ea87d2e 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -1,7 +1,7 @@ use crate::typed_absy::types::{ArrayType, Type}; use crate::typed_absy::UBitwidth; use crate::typed_absy::{ - ArrayExpression, ArrayExpressionInner, BooleanExpression, FieldElementExpression, IfElse, + ArrayExpression, ArrayExpressionInner, BooleanExpression, Expr, FieldElementExpression, IfElse, IfElseExpression, Select, SelectExpression, StructExpression, Typed, TypedExpression, TypedExpressionOrSpread, TypedSpread, UExpression, UExpressionInner, }; @@ -477,7 +477,7 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { array: Self, target_inner_ty: Type<'ast, T>, ) -> Result> { - let array_ty = array.ty(); + let array_ty = array.ty().clone(); // elements must fit in the target type match array.into_inner() { diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index d262df05b..07220a222 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -1139,25 +1139,6 @@ impl<'ast, T: Clone> ArrayExpression<'ast, T> { pub fn size(&self) -> UExpression<'ast, T> { self.ty.size.clone() } - - pub fn as_inner(&self) -> &ArrayExpressionInner<'ast, T> { - &self.inner - } - - pub fn as_inner_mut(&mut self) -> &mut ArrayExpressionInner<'ast, T> { - &mut self.inner - } - - pub fn into_inner(self) -> ArrayExpressionInner<'ast, T> { - self.inner - } - - pub fn ty(&self) -> ArrayType<'ast, T> { - ArrayType { - size: self.size(), - ty: box self.inner_type().clone(), - } - } } #[derive(Clone, PartialEq, Debug, Hash, Eq)] @@ -1184,24 +1165,6 @@ impl<'ast, T: Field> StructExpression<'ast, T> { } } -impl<'ast, T> StructExpression<'ast, T> { - pub fn ty(&self) -> &StructType<'ast, T> { - &self.ty - } - - pub fn as_inner(&self) -> &StructExpressionInner<'ast, T> { - &self.inner - } - - pub fn as_inner_mut(&mut self) -> &mut StructExpressionInner<'ast, T> { - &mut self.inner - } - - pub fn into_inner(self) -> StructExpressionInner<'ast, T> { - self.inner - } -} - #[derive(Clone, PartialEq, Debug, Hash, Eq)] pub enum StructExpressionInner<'ast, T> { Block(BlockExpression<'ast, T, StructExpression<'ast, T>>), @@ -1503,15 +1466,23 @@ pub trait Expr<'ast, T>: From> { type Inner; type Ty: Clone + IntoTypes<'ast, T>; + fn ty(&self) -> &Self::Ty; + fn into_inner(self) -> Self::Inner; fn as_inner(&self) -> &Self::Inner; + + fn as_inner_mut(&mut self) -> &mut Self::Inner; } impl<'ast, T: Clone> Expr<'ast, T> for FieldElementExpression<'ast, T> { type Inner = Self; type Ty = Type<'ast, T>; + fn ty(&self) -> &Self::Ty { + &Type::FieldElement + } + fn into_inner(self) -> Self::Inner { self } @@ -1519,12 +1490,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for FieldElementExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + self + } } impl<'ast, T: Clone> Expr<'ast, T> for BooleanExpression<'ast, T> { type Inner = Self; type Ty = Type<'ast, T>; + fn ty(&self) -> &Self::Ty { + &Type::Boolean + } + fn into_inner(self) -> Self::Inner { self } @@ -1532,12 +1511,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for BooleanExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + self + } } impl<'ast, T: Clone> Expr<'ast, T> for UExpression<'ast, T> { type Inner = UExpressionInner<'ast, T>; type Ty = UBitwidth; + fn ty(&self) -> &Self::Ty { + &self.bitwidth + } + fn into_inner(self) -> Self::Inner { self.inner } @@ -1545,12 +1532,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for UExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self.inner } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + &mut self.inner + } } impl<'ast, T: Clone> Expr<'ast, T> for StructExpression<'ast, T> { type Inner = StructExpressionInner<'ast, T>; type Ty = StructType<'ast, T>; + fn ty(&self) -> &Self::Ty { + &self.ty + } + fn into_inner(self) -> Self::Inner { self.inner } @@ -1558,12 +1553,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for StructExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self.inner } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + &mut self.inner + } } impl<'ast, T: Clone> Expr<'ast, T> for ArrayExpression<'ast, T> { type Inner = ArrayExpressionInner<'ast, T>; type Ty = ArrayType<'ast, T>; + fn ty(&self) -> &Self::Ty { + &self.ty + } + fn into_inner(self) -> Self::Inner { self.inner } @@ -1571,12 +1574,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for ArrayExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self.inner } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + &mut self.inner + } } impl<'ast, T: Clone> Expr<'ast, T> for IntExpression<'ast, T> { type Inner = Self; type Ty = Type<'ast, T>; + fn ty(&self) -> &Self::Ty { + &Type::Int + } + fn into_inner(self) -> Self::Inner { self } @@ -1584,12 +1595,20 @@ impl<'ast, T: Clone> Expr<'ast, T> for IntExpression<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + self + } } impl<'ast, T: Clone> Expr<'ast, T> for TypedExpressionList<'ast, T> { type Inner = TypedExpressionListInner<'ast, T>; type Ty = Types<'ast, T>; + fn ty(&self) -> &Self::Ty { + &self.types + } + fn into_inner(self) -> Self::Inner { self.inner } @@ -1597,6 +1616,10 @@ impl<'ast, T: Clone> Expr<'ast, T> for TypedExpressionList<'ast, T> { fn as_inner(&self) -> &Self::Inner { &self.inner } + + fn as_inner_mut(&mut self) -> &mut Self::Inner { + &mut self.inner + } } // Enums types to enable returning e.g a member expression OR another type of expression of this type @@ -1777,7 +1800,7 @@ impl<'ast, T> Member<'ast, T> for BooleanExpression<'ast, T> { } } -impl<'ast, T> Member<'ast, T> for UExpression<'ast, T> { +impl<'ast, T: Clone> Member<'ast, T> for UExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let bitwidth = match ty { @@ -1957,7 +1980,7 @@ impl<'ast, T: Field> Block<'ast, T> for UExpression<'ast, T> { impl<'ast, T: Field> Block<'ast, T> for ArrayExpression<'ast, T> { fn block(statements: Vec>, value: Self) -> Self { - let array_ty = value.ty(); + let array_ty = value.ty().clone(); ArrayExpressionInner::Block(BlockExpression::new(statements, value)) .annotate(*array_ty.ty, array_ty.size) } @@ -1972,8 +1995,11 @@ impl<'ast, T: Field> Block<'ast, T> for StructExpression<'ast, T> { } pub trait Constant: Sized { + // return whether this is constant fn is_constant(&self) -> bool; + // canonicalize an expression *that we know to be constant* + // for example for [0; 3] -> [0, 0, 0], [...[1], 2] -> [1, 2], etc fn into_canonical_constant(self) -> Self { self } @@ -2060,7 +2086,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { } } - let array_ty = self.ty(); + let array_ty = self.ty().clone(); match self.into_inner() { ArrayExpressionInner::Value(v) => ArrayExpressionInner::Value( @@ -2091,9 +2117,8 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { v.into_iter() .flat_map(into_canonical_constant_aux) .map(|e| e.into()) - .enumerate() - .filter(|(index, _)| index >= &from && index < &to) - .map(|(_, e)| e) + .skip(from) + .take(to - from) .collect::>() .into(), ) @@ -2153,7 +2178,6 @@ impl<'ast, T: Field> Constant for TypedExpression<'ast, T> { } } - // in the constant map, we only want canonical constants: [0; 3] -> [0, 0, 0], [...[1], 2] -> [1, 2], etc fn into_canonical_constant(self) -> Self { match self { TypedExpression::FieldElement(e) => e.into_canonical_constant().into(), From 33c8fba1e1bce86ef85c1f64b9678f75d0140d60 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 13:36:48 +0200 Subject: [PATCH 66/86] add comments, use iterators --- zokrates_core/src/flatten/mod.rs | 8 +++++++- zokrates_core/src/ir/interpreter.rs | 29 +++++++++++++---------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 1d230eae7..e096f9b2d 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -1161,13 +1161,16 @@ impl<'ast, T: Field> Flattener<'ast, T> { vec![self.flatten_bits_to_u(statements_flattened, param_expressions, 8.into())] } crate::embed::FlatEmbed::BitArrayLe => { + // get the length of the bit arrays let len = generics[0]; + // split the arguments into the two bit arrays of size `len` let (expressions, constants) = ( param_expressions[..len as usize].to_vec(), param_expressions[len as usize..].to_vec(), ); + // define variables for the variable bits let variables: Vec<_> = expressions .into_iter() .map(|e| { @@ -1178,6 +1181,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { }) .collect(); + // get constants for the constant bits let constants: Vec<_> = constants .into_iter() .map(|e| { @@ -1185,11 +1189,13 @@ impl<'ast, T: Field> Flattener<'ast, T> { .get_field_unchecked() }) .map(|e| match e { - FlatExpression::Number(n) => n == T::one(), + FlatExpression::Number(n) if n == T::one() => true, + FlatExpression::Number(n) if n == T::zero() => false, _ => unreachable!(), }) .collect(); + // get the list of conditions which must hold iff the `<=` relation holds let conditions = self.constant_le_check(statements_flattened, &variables, &constants); diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index c6b75dae6..b68574f35 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -160,22 +160,19 @@ impl Interpreter { let bit_width = bit_width - padding; - let mut num = inputs[0].clone(); - let mut res = vec![]; - - for _ in 0..padding { - res.push(T::zero()); - } - - for i in (0..bit_width).rev() { - if T::from(2).pow(i) <= num { - num = num - T::from(2).pow(i); - res.push(T::one()); - } else { - res.push(T::zero()); - } - } - res + let num = inputs[0].clone(); + + (0..padding) + .map(|_| T::zero()) + .chain((0..bit_width).rev().scan(num, |state, i| { + if T::from(2).pow(i) <= *state { + *state = (*state).clone() - T::from(2).pow(i); + Some(T::one()) + } else { + Some(T::zero()) + } + })) + .collect() } Solver::Xor => { let x = inputs[0].clone(); From 63be983d745a8551b28642367dcd71319291223f Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 15:22:46 +0200 Subject: [PATCH 67/86] add tests, tweak out of range interpreter --- Cargo.lock | 1 + zokrates_core/Cargo.toml | 1 + zokrates_core/src/ir/interpreter.rs | 49 +++++----- zokrates_core/src/static_analysis/mod.rs | 6 +- zokrates_core/tests/out_of_range.rs | 117 ++++++++++++++++++++++- zokrates_fs_resolver/src/lib.rs | 13 ++- 6 files changed, 150 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c87c18024..cf5b77b4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2394,6 +2394,7 @@ dependencies = [ "zokrates_common", "zokrates_embed", "zokrates_field", + "zokrates_fs_resolver", "zokrates_pest_ast", ] diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index e81f04fbe..91b31714e 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -59,6 +59,7 @@ sha2 = { version = "0.9.3", optional = true } [dev-dependencies] wasm-bindgen-test = "^0.3.0" pretty_assertions = "0.6.1" +zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"} [build-dependencies] cc = { version = "1.0", features = ["parallel"], optional = true } diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index b68574f35..ef344e91e 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -65,33 +65,27 @@ impl Interpreter { } } }, - Statement::Directive(ref d) => { - match (&d.solver, &d.inputs, self.should_try_out_of_range) { - (Solver::Bits(bitwidth), inputs, true) - if inputs[0].left.0.len() > 1 - || inputs[0].right.0.len() > 1 - && *bitwidth == T::get_required_bits() => - { - Self::try_solve_out_of_range(&d, &mut witness) - } - _ => { - let inputs: Vec<_> = d - .inputs - .iter() - .map(|i| i.evaluate(&witness).unwrap()) - .collect(); - match self.execute_solver(&d.solver, &inputs) { - Ok(res) => { - for (i, o) in d.outputs.iter().enumerate() { - witness.insert(*o, res[i].clone()); - } - continue; + Statement::Directive(ref d) => match (&d.solver, self.should_try_out_of_range) { + (Solver::Bits(bitwidth), true) if *bitwidth >= T::get_required_bits() => { + Self::try_solve_out_of_range(&d, &mut witness) + } + _ => { + let inputs: Vec<_> = d + .inputs + .iter() + .map(|i| i.evaluate(&witness).unwrap()) + .collect(); + match self.execute_solver(&d.solver, &inputs) { + Ok(res) => { + for (i, o) in d.outputs.iter().enumerate() { + witness.insert(*o, res[i].clone()); } - Err(_) => return Err(Error::Solver), - }; - } + continue; + } + Err(_) => return Err(Error::Solver), + }; } - } + }, } } @@ -104,7 +98,9 @@ impl Interpreter { // we target the `2a - 2b` part of the `<` check by only returning out-of-range results // when the input is not a single summand let value = d.inputs[0].evaluate(&witness).unwrap(); + let candidate = value.to_biguint() + T::max_value().to_biguint() + T::from(1).to_biguint(); + let input = if candidate < T::from(2).to_biguint().pow(T::get_required_bits()) { candidate } else { @@ -123,6 +119,9 @@ impl Interpreter { } } assert_eq!(num, T::zero().to_biguint()); + + println!("RES {:?}", res); + for (i, o) in d.outputs.iter().enumerate() { witness.insert(*o, res[i].clone()); } diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index bf658118c..b2dab63e7 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -39,7 +39,7 @@ pub trait Analyse { pub enum Error { Reducer(self::reducer::Error), Propagation(self::propagation::Error), - NonConstantShift(self::constant_argument_checker::Error), + NonConstantArgument(self::constant_argument_checker::Error), } impl From for Error { @@ -56,7 +56,7 @@ impl From for Error { impl From for Error { fn from(e: constant_argument_checker::Error) -> Self { - Error::NonConstantShift(e) + Error::NonConstantArgument(e) } } @@ -65,7 +65,7 @@ impl fmt::Display for Error { match self { Error::Reducer(e) => write!(f, "{}", e), Error::Propagation(e) => write!(f, "{}", e), - Error::NonConstantShift(e) => write!(f, "{}", e), + Error::NonConstantArgument(e) => write!(f, "{}", e), } } } diff --git a/zokrates_core/tests/out_of_range.rs b/zokrates_core/tests/out_of_range.rs index 6d2f19ab9..95fd54977 100644 --- a/zokrates_core/tests/out_of_range.rs +++ b/zokrates_core/tests/out_of_range.rs @@ -10,9 +10,10 @@ use zokrates_core::{ ir::Interpreter, }; use zokrates_field::Bn128Field; +use zokrates_fs_resolver::FileSystemResolver; #[test] -fn out_of_range() { +fn lt_field() { let source = r#" def main(private field a, private field b) -> field: field x = if a < b then 3333 else 4444 fi @@ -21,7 +22,7 @@ fn out_of_range() { "# .to_string(); - // let's try to prove that "10000 < 5555" is true by exploiting + // let's try to prove that "10000f < 5555f" is true by exploiting // the fact that `2*10000 - 2*5555` has two distinct bit decompositions // we chose the one which is out of range, ie the sum check features an overflow @@ -42,3 +43,115 @@ fn out_of_range() { ) .is_err()); } + +#[test] +fn lt_uint() { + let source = r#" + def main(private u32 a, private u32 b): + field x = if a < b then 3333 else 4444 fi + assert(x == 3333) + return + "# + .to_string(); + + // let's try to prove that "10000u32 < 5555u32" is true by exploiting + // the fact that `2*10000 - 2*5555` has two distinct bit decompositions + // we chose the one which is out of range, ie the sum check features an overflow + + let res: CompilationArtifacts = compile( + source, + "./path/to/file".into(), + None::<&dyn Resolver>, + &CompileConfig::default(), + ) + .unwrap(); + + let interpreter = Interpreter::try_out_of_range(); + + assert!(interpreter + .execute( + &res.prog(), + &[Bn128Field::from(10000), Bn128Field::from(5555)] + ) + .is_err()); +} + +#[test] +fn unpack256() { + let source = r#" + import "utils/pack/bool/unpack256" + + def main(private field a): + bool[256] bits = unpack256(a) + assert(bits[255]) + return + "# + .to_string(); + + // let's try to prove that the least significant bit of 0 is 1 + // we exploit the fact that the bits of 0 are the bits of p, and p is even + // we want this to still fail + + let stdlib_path = std::fs::canonicalize( + std::env::current_dir() + .unwrap() + .join("../zokrates_stdlib/stdlib"), + ) + .unwrap(); + + let res: CompilationArtifacts = compile( + source, + "./path/to/file".into(), + Some(&FileSystemResolver::with_stdlib_root( + stdlib_path.to_str().unwrap(), + )), + &CompileConfig::default(), + ) + .unwrap(); + + let interpreter = Interpreter::try_out_of_range(); + + assert!(interpreter + .execute(&res.prog(), &[Bn128Field::from(0)]) + .is_err()); +} + +#[test] +fn unpack256_unchecked() { + let source = r#" + import "utils/pack/bool/nonStrictUnpack256" + + def main(private field a): + bool[256] bits = nonStrictUnpack256(a) + assert(bits[255]) + return + "# + .to_string(); + + // let's try to prove that the least significant bit of 0 is 1 + // we exploit the fact that the bits of 0 are the bits of p, and p is even + // we want this to succeed as the non strict version does not enforce the bits to be in range + + let stdlib_path = std::fs::canonicalize( + std::env::current_dir() + .unwrap() + .join("../zokrates_stdlib/stdlib"), + ) + .unwrap(); + + let res: CompilationArtifacts = compile( + source, + "./path/to/file".into(), + Some(&FileSystemResolver::with_stdlib_root( + stdlib_path.to_str().unwrap(), + )), + &CompileConfig::default(), + ) + .unwrap(); + + let interpreter = Interpreter::try_out_of_range(); + + assert!(interpreter + .execute(&res.prog(), &[Bn128Field::from(0)]) + .is_ok()); +} diff --git a/zokrates_fs_resolver/src/lib.rs b/zokrates_fs_resolver/src/lib.rs index b38a0b17c..1289bbe3a 100644 --- a/zokrates_fs_resolver/src/lib.rs +++ b/zokrates_fs_resolver/src/lib.rs @@ -26,17 +26,16 @@ impl<'a> Resolver for FileSystemResolver<'a> { ) -> Result<(String, PathBuf), io::Error> { let source = Path::new(&import_location); - if !current_location.is_file() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("{} was expected to be a file", current_location.display()), - )); - } - // paths starting with `./` or `../` are interpreted relative to the current file // other paths `abc/def` are interpreted relative to the standard library root path let base = match source.components().next() { Some(Component::CurDir) | Some(Component::ParentDir) => { + if !current_location.is_file() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("{} was expected to be a file", current_location.display()), + )); + } current_location.parent().unwrap().into() } _ => PathBuf::from(self.stdlib_root_path.unwrap_or("")), From 78516e8a30e78c612a95ae2a7e4a5e32d5b06507 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 15:31:33 +0200 Subject: [PATCH 68/86] add test using out of range interpreter --- zokrates_core/tests/out_of_range.rs | 36 +++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/zokrates_core/tests/out_of_range.rs b/zokrates_core/tests/out_of_range.rs index 6d2f19ab9..2152e45ce 100644 --- a/zokrates_core/tests/out_of_range.rs +++ b/zokrates_core/tests/out_of_range.rs @@ -12,7 +12,7 @@ use zokrates_core::{ use zokrates_field::Bn128Field; #[test] -fn out_of_range() { +fn lt_field() { let source = r#" def main(private field a, private field b) -> field: field x = if a < b then 3333 else 4444 fi @@ -21,7 +21,39 @@ fn out_of_range() { "# .to_string(); - // let's try to prove that "10000 < 5555" is true by exploiting + // let's try to prove that "10000f < 5555f" is true by exploiting + // the fact that `2*10000 - 2*5555` has two distinct bit decompositions + // we chose the one which is out of range, ie the sum check features an overflow + + let res: CompilationArtifacts = compile( + source, + "./path/to/file".into(), + None::<&dyn Resolver>, + &CompileConfig::default(), + ) + .unwrap(); + + let interpreter = Interpreter::try_out_of_range(); + + assert!(interpreter + .execute( + &res.prog(), + &[Bn128Field::from(10000), Bn128Field::from(5555)] + ) + .is_err()); +} + +#[test] +fn lt_uint() { + let source = r#" + def main(private u32 a, private u32 b): + field x = if a < b then 3333 else 4444 fi + assert(x == 3333) + return + "# + .to_string(); + + // let's try to prove that "10000u32 < 5555u32" is true by exploiting // the fact that `2*10000 - 2*5555` has two distinct bit decompositions // we chose the one which is out of range, ie the sum check features an overflow From 7f76505a86771ad3f131c7651d11ab8c205376a4 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 16:03:57 +0200 Subject: [PATCH 69/86] refactor out of range interpreter, accept any size of output --- zokrates_core/src/flatten/mod.rs | 3 +- zokrates_core/src/ir/interpreter.rs | 88 +++++++++------------ zokrates_core/src/optimizer/redefinition.rs | 4 +- zokrates_core/tests/out_of_range.rs | 2 +- 4 files changed, 41 insertions(+), 56 deletions(-) diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index e096f9b2d..f44c53640 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -1982,8 +1982,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // constants do not require directives if let Some(FlatExpression::Number(ref x)) = e.field { - let bits: Vec<_> = Interpreter::default() - .execute_solver(&Solver::bits(to), &[x.clone()]) + let bits: Vec<_> = Interpreter::execute_solver(&Solver::bits(to), &[x.clone()]) .unwrap() .into_iter() .map(FlatExpression::Number) diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index ef344e91e..510c89b25 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -1,5 +1,4 @@ use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::Directive; use crate::ir::{LinComb, Prog, QuadComb, Statement, Witness}; use crate::solvers::Solver; use serde::{Deserialize, Serialize}; @@ -65,66 +64,59 @@ impl Interpreter { } } }, - Statement::Directive(ref d) => match (&d.solver, self.should_try_out_of_range) { - (Solver::Bits(bitwidth), true) if *bitwidth >= T::get_required_bits() => { - Self::try_solve_out_of_range(&d, &mut witness) + Statement::Directive(ref d) => { + let mut inputs: Vec<_> = d + .inputs + .iter() + .map(|i| i.evaluate(&witness).unwrap()) + .collect(); + + let res = match (&d.solver, self.should_try_out_of_range) { + (Solver::Bits(bitwidth), true) if *bitwidth >= T::get_required_bits() => { + Ok(Self::try_solve_with_out_of_range_bits( + *bitwidth, + inputs.pop().unwrap(), + )) + } + _ => Self::execute_solver(&d.solver, &inputs), } - _ => { - let inputs: Vec<_> = d - .inputs - .iter() - .map(|i| i.evaluate(&witness).unwrap()) - .collect(); - match self.execute_solver(&d.solver, &inputs) { - Ok(res) => { - for (i, o) in d.outputs.iter().enumerate() { - witness.insert(*o, res[i].clone()); - } - continue; - } - Err(_) => return Err(Error::Solver), - }; + .map_err(|_| Error::Solver)?; + + for (i, o) in d.outputs.iter().enumerate() { + witness.insert(*o, res[i].clone()); } - }, + } } } Ok(Witness(witness)) } - fn try_solve_out_of_range(d: &Directive, witness: &mut BTreeMap) { + fn try_solve_with_out_of_range_bits(bit_width: usize, input: T) -> Vec { use num::traits::Pow; + use num_bigint::BigUint; - // we target the `2a - 2b` part of the `<` check by only returning out-of-range results - // when the input is not a single summand - let value = d.inputs[0].evaluate(&witness).unwrap(); - - let candidate = value.to_biguint() + T::max_value().to_biguint() + T::from(1).to_biguint(); + let candidate = input.to_biguint() + T::max_value().to_biguint() + T::from(1).to_biguint(); let input = if candidate < T::from(2).to_biguint().pow(T::get_required_bits()) { candidate } else { - value.to_biguint() + input.to_biguint() }; - let mut num = input; - let mut res = vec![]; - let bits = T::get_required_bits(); - for i in (0..bits).rev() { - if T::from(2).to_biguint().pow(i as usize) <= num { - num -= T::from(2).to_biguint().pow(i as usize); - res.push(T::one()); - } else { - res.push(T::zero()); - } - } - assert_eq!(num, T::zero().to_biguint()); - - println!("RES {:?}", res); - - for (i, o) in d.outputs.iter().enumerate() { - witness.insert(*o, res[i].clone()); - } + let padding = bit_width - T::get_required_bits(); + + (0..padding) + .map(|_| T::zero()) + .chain((0..T::get_required_bits()).rev().scan(input, |state, i| { + if BigUint::from(2usize).pow(i) <= *state { + *state = (*state).clone() - BigUint::from(2usize).pow(i); + Some(T::one()) + } else { + Some(T::zero()) + } + })) + .collect() } fn check_inputs(&self, program: &Prog, inputs: &[U]) -> Result<(), Error> { @@ -138,11 +130,7 @@ impl Interpreter { } } - pub fn execute_solver( - &self, - solver: &Solver, - inputs: &[T], - ) -> Result, String> { + pub fn execute_solver(solver: &Solver, inputs: &[T]) -> Result, String> { let (expected_input_count, expected_output_count) = solver.get_signature(); assert_eq!(inputs.len(), expected_input_count); diff --git a/zokrates_core/src/optimizer/redefinition.rs b/zokrates_core/src/optimizer/redefinition.rs index 6b197b1e5..4222281c0 100644 --- a/zokrates_core/src/optimizer/redefinition.rs +++ b/zokrates_core/src/optimizer/redefinition.rs @@ -140,9 +140,7 @@ impl Folder for RedefinitionOptimizer { // unwrap inputs to their constant value let inputs: Vec<_> = inputs.into_iter().map(|i| i.unwrap()).collect(); // run the solver - let outputs = Interpreter::default() - .execute_solver(&d.solver, &inputs) - .unwrap(); + let outputs = Interpreter::execute_solver(&d.solver, &inputs).unwrap(); assert_eq!(outputs.len(), d.outputs.len()); // insert the results in the substitution diff --git a/zokrates_core/tests/out_of_range.rs b/zokrates_core/tests/out_of_range.rs index 95fd54977..c27e23614 100644 --- a/zokrates_core/tests/out_of_range.rs +++ b/zokrates_core/tests/out_of_range.rs @@ -129,7 +129,7 @@ fn unpack256_unchecked() { .to_string(); // let's try to prove that the least significant bit of 0 is 1 - // we exploit the fact that the bits of 0 are the bits of p, and p is even + // we exploit the fact that the bits of 0 are the bits of p, and p is odd // we want this to succeed as the non strict version does not enforce the bits to be in range let stdlib_path = std::fs::canonicalize( From a7cff74ea8a82470c4fc7f5327b6431a573d92f3 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 5 Aug 2021 16:13:15 +0200 Subject: [PATCH 70/86] fix tests --- zokrates_core/src/ir/interpreter.rs | 55 ++++++++++++----------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 510c89b25..580e5ee89 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -338,16 +338,14 @@ mod tests { fn execute() { let cond_eq = Solver::ConditionEq; let inputs = vec![0]; - let interpreter = Interpreter::default(); - let r = interpreter - .execute_solver( - &cond_eq, - &inputs - .iter() - .map(|&i| Bn128Field::from(i)) - .collect::>(), - ) - .unwrap(); + let r = Interpreter::execute_solver( + &cond_eq, + &inputs + .iter() + .map(|&i| Bn128Field::from(i)) + .collect::>(), + ) + .unwrap(); let res: Vec = vec![0, 1].iter().map(|&i| Bn128Field::from(i)).collect(); assert_eq!(r, &res[..]); } @@ -356,16 +354,14 @@ mod tests { fn execute_non_eq() { let cond_eq = Solver::ConditionEq; let inputs = vec![1]; - let interpreter = Interpreter::default(); - let r = interpreter - .execute_solver( - &cond_eq, - &inputs - .iter() - .map(|&i| Bn128Field::from(i)) - .collect::>(), - ) - .unwrap(); + let r = Interpreter::execute_solver( + &cond_eq, + &inputs + .iter() + .map(|&i| Bn128Field::from(i)) + .collect::>(), + ) + .unwrap(); let res: Vec = vec![1, 1].iter().map(|&i| Bn128Field::from(i)).collect(); assert_eq!(r, &res[..]); } @@ -374,10 +370,9 @@ mod tests { #[test] fn bits_of_one() { let inputs = vec![Bn128Field::from(1)]; - let interpreter = Interpreter::default(); - let res = interpreter - .execute_solver(&Solver::Bits(Bn128Field::get_required_bits()), &inputs) - .unwrap(); + let res = + Interpreter::execute_solver(&Solver::Bits(Bn128Field::get_required_bits()), &inputs) + .unwrap(); assert_eq!(res[253], Bn128Field::from(1)); for r in &res[0..253] { assert_eq!(*r, Bn128Field::from(0)); @@ -387,10 +382,9 @@ mod tests { #[test] fn bits_of_42() { let inputs = vec![Bn128Field::from(42)]; - let interpreter = Interpreter::default(); - let res = interpreter - .execute_solver(&Solver::Bits(Bn128Field::get_required_bits()), &inputs) - .unwrap(); + let res = + Interpreter::execute_solver(&Solver::Bits(Bn128Field::get_required_bits()), &inputs) + .unwrap(); assert_eq!(res[253], Bn128Field::from(0)); assert_eq!(res[252], Bn128Field::from(1)); assert_eq!(res[251], Bn128Field::from(0)); @@ -403,10 +397,7 @@ mod tests { #[test] fn five_hundred_bits_of_1() { let inputs = vec![Bn128Field::from(1)]; - let interpreter = Interpreter::default(); - let res = interpreter - .execute_solver(&Solver::Bits(500), &inputs) - .unwrap(); + let res = Interpreter::execute_solver(&Solver::Bits(500), &inputs).unwrap(); let mut expected = vec![Bn128Field::from(0); 500]; expected[499] = Bn128Field::from(1); From fee8535bcee04ce07df3a9e368c322a6567e7cb8 Mon Sep 17 00:00:00 2001 From: dark64 Date: Thu, 5 Aug 2021 16:25:54 +0200 Subject: [PATCH 71/86] fix glob pattern --- zokrates_cli/src/bin.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index ad957483f..ec923044b 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -124,13 +124,18 @@ mod tests { builder .spawn(|| { - for p in glob("./examples/**/*.zok").expect("Failed to read glob pattern") { + for p in glob("./examples/**/!(*.sh)").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), }; + if !path.is_file() { + continue; + } + println!("Testing {:?}", path); + assert_eq!(path.extension().expect("extension expected"), "zok"); let should_error = path.to_str().unwrap().contains("compile_errors"); @@ -165,7 +170,9 @@ mod tests { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), }; + println!("Testing {:?}", path); + assert_eq!(path.extension().expect("extension expected"), "zok"); let file = File::open(path.clone()).unwrap(); @@ -190,12 +197,14 @@ mod tests { #[test] fn execute_examples_err() { //these examples should compile but not run - for p in glob("./examples/runtime_errors/*.zok").expect("Failed to read glob pattern") { + for p in glob("./examples/runtime_errors/*").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), }; + println!("Testing {:?}", path); + assert_eq!(path.extension().expect("extension expected"), "zok"); let file = File::open(path.clone()).unwrap(); From dbc1647c56d626728fb2ad82574c2c6a5d2bd9f2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 9 Aug 2021 10:44:15 +0200 Subject: [PATCH 72/86] refactor mimcSponge --- .../stdlib/hashes/mimcSponge/mimcSponge.zok | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok index e30b74e55..27ff5f0ca 100644 --- a/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok +++ b/zokrates_stdlib/stdlib/hashes/mimcSponge/mimcSponge.zok @@ -1,19 +1,19 @@ import "./mimcFeistel" as MiMCFeistel -def main(field[N] ins, field k) -> field[P]: - field[N + P - 1][2] S = [[0; 2]; N + P - 1] - field[P] outs = [0; P] +def main(field[nInputs] ins, field k) -> field[nOutputs]: + field[nInputs + nOutputs - 1][2] S = [[0; 2]; nInputs + nOutputs - 1] + field[nOutputs] outs = [0; nOutputs] - for u32 i in 0..N do + for u32 i in 0..nInputs do u32 j = if i == 0 then 0 else i - 1 fi S[i] = if i == 0 then MiMCFeistel(ins[0], 0, k) else MiMCFeistel(S[j][0] + ins[i], S[j][1], k) fi endfor - outs[0] = S[N - 1][0] + outs[0] = S[nInputs - 1][0] - for u32 i in 0..(P - 1) do - S[N + i] = MiMCFeistel(S[N + i - 1][0], S[N + i - 1][1], k) - outs[i + 1] = S[N + i][0] + for u32 i in 0..(nOutputs - 1) do + S[nInputs + i] = MiMCFeistel(S[nInputs + i - 1][0], S[nInputs + i - 1][1], k) + outs[i + 1] = S[nInputs + i][0] endfor return outs From de50a7a0d1171efa3a194c37e3f1ea436ecba357 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 9 Aug 2021 12:02:50 +0200 Subject: [PATCH 73/86] fix test --- zokrates_core/tests/out_of_range.rs | 32 ----------------------------- 1 file changed, 32 deletions(-) diff --git a/zokrates_core/tests/out_of_range.rs b/zokrates_core/tests/out_of_range.rs index 14208d71a..c27e23614 100644 --- a/zokrates_core/tests/out_of_range.rs +++ b/zokrates_core/tests/out_of_range.rs @@ -76,38 +76,6 @@ fn lt_uint() { .is_err()); } -#[test] -fn lt_uint() { - let source = r#" - def main(private u32 a, private u32 b): - field x = if a < b then 3333 else 4444 fi - assert(x == 3333) - return - "# - .to_string(); - - // let's try to prove that "10000u32 < 5555u32" is true by exploiting - // the fact that `2*10000 - 2*5555` has two distinct bit decompositions - // we chose the one which is out of range, ie the sum check features an overflow - - let res: CompilationArtifacts = compile( - source, - "./path/to/file".into(), - None::<&dyn Resolver>, - &CompileConfig::default(), - ) - .unwrap(); - - let interpreter = Interpreter::try_out_of_range(); - - assert!(interpreter - .execute( - &res.prog(), - &[Bn128Field::from(10000), Bn128Field::from(5555)] - ) - .is_err()); -} - #[test] fn unpack256() { let source = r#" From 49a25d926959a2e10bbb7ebceddc5ab9460b9b15 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 9 Aug 2021 15:09:38 +0200 Subject: [PATCH 74/86] add changelog --- changelogs/unreleased/942-dark64 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/942-dark64 diff --git a/changelogs/unreleased/942-dark64 b/changelogs/unreleased/942-dark64 new file mode 100644 index 000000000..798559535 --- /dev/null +++ b/changelogs/unreleased/942-dark64 @@ -0,0 +1 @@ +Use constants in the standard library, make `mimcSponge` implementation generic From 0c6847727546596f77ed423726cc3e5bb0f6e40a Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 10 Aug 2021 15:58:51 +0200 Subject: [PATCH 75/86] add docs --- zokrates_book/src/language/functions.md | 8 +++++++- .../examples/book/explicit_generic_parameters.zok | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 zokrates_cli/examples/book/explicit_generic_parameters.zok diff --git a/zokrates_book/src/language/functions.md b/zokrates_book/src/language/functions.md index 8282b68e9..4e0bfc59d 100644 --- a/zokrates_book/src/language/functions.md +++ b/zokrates_book/src/language/functions.md @@ -14,13 +14,19 @@ A function can be generic over any number of values of type `u32`. {{#include ../../../zokrates_cli/examples/book/generic_function_declaration.zok}} ``` +The generic parameters can be provided explicitly, especially when they cannot be infered. + +```zokrates +{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}} +``` + Functions can return multiple values by providing them as a comma-separated list. ```zokrates {{#include ../../../zokrates_cli/examples/book/multi_return.zok}} ``` -### Inference +### Variable declaration When defining a variable as the return value of a function, types are provided when the variable needs to be declared: diff --git a/zokrates_cli/examples/book/explicit_generic_parameters.zok b/zokrates_cli/examples/book/explicit_generic_parameters.zok new file mode 100644 index 000000000..9b439d990 --- /dev/null +++ b/zokrates_cli/examples/book/explicit_generic_parameters.zok @@ -0,0 +1,11 @@ +// a function to sum the N first powers of a field element +def sum_powers(field a) -> field: + field res = 0 + for u32 i in 0..N do + res = res + a ** i + endfor + return res + +def main(field a) -> field: + // call `sum_powers` providing the explicit generic parameter `N := 5` + return sum_powers::<5>(a) \ No newline at end of file From a713c43e04a6233e890c65ec37f947196443354f Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 11 Aug 2021 14:41:02 +0200 Subject: [PATCH 76/86] fix typo, add changelog --- changelogs/unreleased/962-schaeff | 1 + zokrates_book/src/language/functions.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/962-schaeff diff --git a/changelogs/unreleased/962-schaeff b/changelogs/unreleased/962-schaeff new file mode 100644 index 000000000..43053216b --- /dev/null +++ b/changelogs/unreleased/962-schaeff @@ -0,0 +1 @@ +Add explicit function generic parameters to docs \ No newline at end of file diff --git a/zokrates_book/src/language/functions.md b/zokrates_book/src/language/functions.md index 4e0bfc59d..ea8952aa4 100644 --- a/zokrates_book/src/language/functions.md +++ b/zokrates_book/src/language/functions.md @@ -14,7 +14,7 @@ A function can be generic over any number of values of type `u32`. {{#include ../../../zokrates_cli/examples/book/generic_function_declaration.zok}} ``` -The generic parameters can be provided explicitly, especially when they cannot be infered. +The generic parameters can be provided explicitly, especially when they cannot be inferred. ```zokrates {{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}} From 9ce5827596cfa634d181812860487e25656e9fdc Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 12 Aug 2021 21:14:24 +0200 Subject: [PATCH 77/86] remove left out commented out conflicts --- zokrates_core/src/typed_absy/mod.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index cb9d2537c..b31dfeee1 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -1157,23 +1157,6 @@ pub struct StructExpression<'ast, T> { inner: StructExpressionInner<'ast, T>, } -// <<<<<<< HEAD -// impl<'ast, T: Field> StructExpression<'ast, T> { -// pub fn try_from_typed( -// e: TypedExpression<'ast, T>, -// target_struct_ty: StructType<'ast, T>, -// ) -> Result> { -// match e { -// TypedExpression::Struct(e) => { -// if e.ty() == &target_struct_ty { -// Ok(e) -// } else { -// Err(TypedExpression::Struct(e)) -// } -// } -// e => Err(e), -// } -// ======= impl<'ast, T> StructExpression<'ast, T> { pub fn ty(&self) -> &StructType<'ast, T> { &self.ty @@ -1189,7 +1172,6 @@ impl<'ast, T> StructExpression<'ast, T> { pub fn into_inner(self) -> StructExpressionInner<'ast, T> { self.inner - // >>>>>>> 5a02186fc1d5c8f438a9663112f444497e752ea6 } } From d8ae907030894d8517d3082f457d3bf31f56ade3 Mon Sep 17 00:00:00 2001 From: Thibaut Schaeffer Date: Mon, 16 Aug 2021 10:44:00 +0200 Subject: [PATCH 78/86] Fix constant in struct type (#965) * add breaking test * implement from constant for uint * tweak * tweak * revert and add breaking test * implement from --- zokrates_cli/examples/structs/constant_in_member.zok | 11 +++++++++++ zokrates_cli/src/bin.rs | 6 +++++- zokrates_core/src/typed_absy/types.rs | 9 +++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 zokrates_cli/examples/structs/constant_in_member.zok diff --git a/zokrates_cli/examples/structs/constant_in_member.zok b/zokrates_cli/examples/structs/constant_in_member.zok new file mode 100644 index 000000000..95ea57120 --- /dev/null +++ b/zokrates_cli/examples/structs/constant_in_member.zok @@ -0,0 +1,11 @@ +const u32 SIZE = 42 + +struct Foo { + field[SIZE] foo +} + +def main(): + Foo f = Foo { + foo: [42; SIZE] + } + return \ No newline at end of file diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 767571a7d..c3bb2e051 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -126,7 +126,7 @@ mod tests { builder .spawn(|| { - for p in glob("./examples/**/!(*.sh)").expect("Failed to read glob pattern") { + for p in glob("./examples/**/*").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, Err(why) => panic!("Error: {:?}", why), @@ -136,6 +136,10 @@ mod tests { continue; } + if path.extension().expect("extension expected") == "sh" { + continue; + } + println!("Testing {:?}", path); assert_eq!(path.extension().expect("extension expected"), "zok"); diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 6e9a13dbf..24d125c4d 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -969,8 +969,13 @@ pub fn check_type<'ast, S: Clone + PartialEq + PartialEq>( } impl<'ast, T> From> for UExpression<'ast, T> { - fn from(_: CanonicalConstantIdentifier<'ast>) -> Self { - unreachable!("constants should have been removed in constant inlining") + fn from(c: CanonicalConstantIdentifier<'ast>) -> Self { + let bitwidth = match *c.ty { + DeclarationType::Uint(bitwidth) => bitwidth, + _ => unreachable!(), + }; + + UExpressionInner::Identifier(Identifier::from(c.id)).annotate(bitwidth) } } From 34abb618e5a6c92e25e8d850a8cee83fda708b4e Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 16 Aug 2021 15:27:37 +0200 Subject: [PATCH 79/86] use biguint in uint optimizer max calculations to avoid overflows --- .../src/static_analysis/uint_optimizer.rs | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/zokrates_core/src/static_analysis/uint_optimizer.rs b/zokrates_core/src/static_analysis/uint_optimizer.rs index ecca499a0..e79b51521 100644 --- a/zokrates_core/src/static_analysis/uint_optimizer.rs +++ b/zokrates_core/src/static_analysis/uint_optimizer.rs @@ -2,6 +2,7 @@ use crate::embed::FlatEmbed; use crate::zir::folder::*; use crate::zir::*; use std::collections::HashMap; +use std::ops::{BitAnd, Shl, Shr}; use zokrates_field::Field; #[derive(Default)] @@ -366,16 +367,12 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> { // reduce both terms let e = self.fold_uint_expression(e); - let e_max: u128 = e - .metadata - .clone() - .unwrap() - .max - .to_dec_string() - .parse() - .unwrap(); + let e_max: num_bigint::BigUint = e.metadata.clone().unwrap().max.to_biguint(); + let max = e_max + .shl(by as usize) + .bitand(&(2_u128.pow(range as u32) - 1).into()); - let max = T::from((e_max << by) & (2_u128.pow(range as u32) - 1)); + let max = T::try_from(max).unwrap(); UExpression::left_shift(force_reduce(e), by).with_max(max) } @@ -383,18 +380,12 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> { // reduce both terms let e = self.fold_uint_expression(e); - let e_max: u128 = e - .metadata - .clone() - .unwrap() - .max - .to_dec_string() - .parse() - .unwrap(); + let e_max: num_bigint::BigUint = e.metadata.clone().unwrap().max.to_biguint(); + let max = e_max + .bitand(&(2_u128.pow(range as u32) - 1).into()) + .shr(by as usize); - let max = (e_max & (2_u128.pow(range as u32) - 1)) >> by; - - let max = T::from(max); + let max = T::try_from(max).unwrap(); UExpression::right_shift(force_reduce(e), by).with_max(max) } From b6066b33b0ba34fc9f54294b23874a8fa46fde27 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 16 Aug 2021 15:50:31 +0200 Subject: [PATCH 80/86] use ref instead of cloning --- zokrates_core/src/static_analysis/uint_optimizer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zokrates_core/src/static_analysis/uint_optimizer.rs b/zokrates_core/src/static_analysis/uint_optimizer.rs index e79b51521..f770781d7 100644 --- a/zokrates_core/src/static_analysis/uint_optimizer.rs +++ b/zokrates_core/src/static_analysis/uint_optimizer.rs @@ -367,7 +367,7 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> { // reduce both terms let e = self.fold_uint_expression(e); - let e_max: num_bigint::BigUint = e.metadata.clone().unwrap().max.to_biguint(); + let e_max: num_bigint::BigUint = e.metadata.as_ref().unwrap().max.to_biguint(); let max = e_max .shl(by as usize) .bitand(&(2_u128.pow(range as u32) - 1).into()); @@ -380,7 +380,7 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> { // reduce both terms let e = self.fold_uint_expression(e); - let e_max: num_bigint::BigUint = e.metadata.clone().unwrap().max.to_biguint(); + let e_max: num_bigint::BigUint = e.metadata.as_ref().unwrap().max.to_biguint(); let max = e_max .bitand(&(2_u128.pow(range as u32) - 1).into()) .shr(by as usize); From 79dea12a3e450e9d40cbc73789ddad15f767b3ef Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 16 Aug 2021 16:52:43 +0200 Subject: [PATCH 81/86] use binary tree to limit ast depth --- .../examples/arrays/large_equality.zok | 4 + .../static_analysis/flatten_complex_types.rs | 78 +++++++++---------- 2 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 zokrates_cli/examples/arrays/large_equality.zok diff --git a/zokrates_cli/examples/arrays/large_equality.zok b/zokrates_cli/examples/arrays/large_equality.zok new file mode 100644 index 000000000..8259f807b --- /dev/null +++ b/zokrates_cli/examples/arrays/large_equality.zok @@ -0,0 +1,4 @@ +const u32 SIZE = 10 +def main(private field[SIZE][SIZE] a): + assert(a == [[0; SIZE]; SIZE]) + return \ No newline at end of file diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index 36ae9af3a..797504897 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -765,6 +765,40 @@ fn fold_field_expression<'ast, T: Field>( } } +// util function to output a boolean expression representing the equality of two lists of ZirExpression. +// the two list are checked to have the same size +// we build a binary tree with internal nodes `And(left, right)` and leaves `Eq(left, right)` +fn conjunction_tree<'ast, T: Field>( + v: &[zir::ZirExpression<'ast, T>], + w: &[zir::ZirExpression<'ast, T>], +) -> zir::BooleanExpression<'ast, T> { + assert_eq!(v.len(), w.len()); + + match v.len() { + 0 => zir::BooleanExpression::Value(true), + 1 => match (v[0].clone(), w[0].clone()) { + (zir::ZirExpression::Boolean(v), zir::ZirExpression::Boolean(w)) => { + zir::BooleanExpression::BoolEq(box v, box w) + } + (zir::ZirExpression::FieldElement(v), zir::ZirExpression::FieldElement(w)) => { + zir::BooleanExpression::FieldEq(box v, box w) + } + (zir::ZirExpression::Uint(v), zir::ZirExpression::Uint(w)) => { + zir::BooleanExpression::UintEq(box v, box w) + } + _ => unreachable!(), + }, + n => { + let (x0, y0) = v.split_at(n / 2); + let (x1, y1) = w.split_at(n / 2); + zir::BooleanExpression::And( + box conjunction_tree::(x0, x1), + box conjunction_tree::(y0, y1), + ) + } + } +} + fn fold_boolean_expression<'ast, T: Field>( f: &mut Flattener, statements_buffer: &mut Vec>, @@ -801,27 +835,7 @@ fn fold_boolean_expression<'ast, T: Field>( assert_eq!(e1.len(), e2.len()); - e1.into_iter().zip(e2.into_iter()).fold( - zir::BooleanExpression::Value(true), - |acc, (e1, e2)| { - zir::BooleanExpression::And( - box acc, - box match (e1, e2) { - ( - zir::ZirExpression::FieldElement(e1), - zir::ZirExpression::FieldElement(e2), - ) => zir::BooleanExpression::FieldEq(box e1, box e2), - (zir::ZirExpression::Boolean(e1), zir::ZirExpression::Boolean(e2)) => { - zir::BooleanExpression::BoolEq(box e1, box e2) - } - (zir::ZirExpression::Uint(e1), zir::ZirExpression::Uint(e2)) => { - zir::BooleanExpression::UintEq(box e1, box e2) - } - _ => unreachable!(), - }, - ) - }, - ) + conjunction_tree(&e1, &e2) } typed_absy::BooleanExpression::StructEq(box e1, box e2) => { let e1 = f.fold_struct_expression(statements_buffer, e1); @@ -829,27 +843,7 @@ fn fold_boolean_expression<'ast, T: Field>( assert_eq!(e1.len(), e2.len()); - e1.into_iter().zip(e2.into_iter()).fold( - zir::BooleanExpression::Value(true), - |acc, (e1, e2)| { - zir::BooleanExpression::And( - box acc, - box match (e1, e2) { - ( - zir::ZirExpression::FieldElement(e1), - zir::ZirExpression::FieldElement(e2), - ) => zir::BooleanExpression::FieldEq(box e1, box e2), - (zir::ZirExpression::Boolean(e1), zir::ZirExpression::Boolean(e2)) => { - zir::BooleanExpression::BoolEq(box e1, box e2) - } - (zir::ZirExpression::Uint(e1), zir::ZirExpression::Uint(e2)) => { - zir::BooleanExpression::UintEq(box e1, box e2) - } - _ => unreachable!(), - }, - ) - }, - ) + conjunction_tree(&e1, &e2) } typed_absy::BooleanExpression::UintEq(box e1, box e2) => { let e1 = f.fold_uint_expression(statements_buffer, e1); From e5ae49831e257a297d6a05ca4e15167054115980 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 16 Aug 2021 16:55:17 +0200 Subject: [PATCH 82/86] add changelog, make test bigger --- changelogs/unreleased/969-schaeff | 1 + zokrates_cli/examples/arrays/large_equality.zok | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/969-schaeff diff --git a/changelogs/unreleased/969-schaeff b/changelogs/unreleased/969-schaeff new file mode 100644 index 000000000..770af0433 --- /dev/null +++ b/changelogs/unreleased/969-schaeff @@ -0,0 +1 @@ +Fix stack overflow when testing equality on large arrays \ No newline at end of file diff --git a/zokrates_cli/examples/arrays/large_equality.zok b/zokrates_cli/examples/arrays/large_equality.zok index 8259f807b..93c8d8341 100644 --- a/zokrates_cli/examples/arrays/large_equality.zok +++ b/zokrates_cli/examples/arrays/large_equality.zok @@ -1,4 +1,4 @@ -const u32 SIZE = 10 +const u32 SIZE = 100 def main(private field[SIZE][SIZE] a): assert(a == [[0; SIZE]; SIZE]) return \ No newline at end of file From 10988bfdad79c7dd98cf1f521056bdec20fcc695 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 16 Aug 2021 17:05:12 +0200 Subject: [PATCH 83/86] remove explicit genereic --- zokrates_core/src/static_analysis/flatten_complex_types.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index 797504897..6c9b3c197 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -791,10 +791,7 @@ fn conjunction_tree<'ast, T: Field>( n => { let (x0, y0) = v.split_at(n / 2); let (x1, y1) = w.split_at(n / 2); - zir::BooleanExpression::And( - box conjunction_tree::(x0, x1), - box conjunction_tree::(y0, y1), - ) + zir::BooleanExpression::And(box conjunction_tree(x0, x1), box conjunction_tree(y0, y1)) } } } From dfd3d5a7ab0965e2420a86a399f576cb9060327e Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 16 Aug 2021 19:02:42 +0200 Subject: [PATCH 84/86] bump versions, update changelog --- CHANGELOG.md | 17 +++++++++++++++++ Cargo.lock | 16 ++++++++-------- changelogs/unreleased/844-leonardoalt | 1 - changelogs/unreleased/942-dark64 | 1 - changelogs/unreleased/945-schaeff | 1 - changelogs/unreleased/947-schaeff | 1 - changelogs/unreleased/948-schaeff | 1 - changelogs/unreleased/949-schaeff | 1 - changelogs/unreleased/950-schaeff | 1 - changelogs/unreleased/954-schaeff | 1 - changelogs/unreleased/955-schaeff | 1 - changelogs/unreleased/962-schaeff | 1 - zokrates_cli/Cargo.toml | 2 +- zokrates_core/Cargo.toml | 2 +- zokrates_core_test/Cargo.toml | 2 +- zokrates_fs_resolver/Cargo.toml | 2 +- zokrates_js/Cargo.toml | 2 +- zokrates_js/package.json | 2 +- zokrates_parser/Cargo.toml | 2 +- zokrates_pest_ast/Cargo.toml | 2 +- zokrates_stdlib/Cargo.toml | 2 +- zokrates_test/Cargo.toml | 2 +- 22 files changed, 35 insertions(+), 28 deletions(-) delete mode 100644 changelogs/unreleased/844-leonardoalt delete mode 100644 changelogs/unreleased/942-dark64 delete mode 100644 changelogs/unreleased/945-schaeff delete mode 100644 changelogs/unreleased/947-schaeff delete mode 100644 changelogs/unreleased/948-schaeff delete mode 100644 changelogs/unreleased/949-schaeff delete mode 100644 changelogs/unreleased/950-schaeff delete mode 100644 changelogs/unreleased/954-schaeff delete mode 100644 changelogs/unreleased/955-schaeff delete mode 100644 changelogs/unreleased/962-schaeff diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cc0c6545..0a222f4bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. ## [Unreleased] https://github.com/Zokrates/ZoKrates/compare/latest...develop +## [0.7.6] - 2021-08-16 + +### Release +- https://github.com/Zokrates/ZoKrates/releases/tag/0.7.6 + +### Changes +- Make the stdlib `unpack` function safe against overflows of bit decompositions for any size of output, introduce `unpack_unchecked` for cases that do not require determinism (#955, @schaeff) +- Add explicit function generic parameters to docs (#962, @schaeff) +- Add gm17 verifier to stdlib for bw6_761 (#948, @schaeff) +- Enable constant generics on structs (#945, @schaeff) +- Use constants in the standard library, make `mimcSponge` implementation generic (#942, @dark64) +- Fix constant range check in uint lt check (#954, @schaeff) +- Add compiler logs (#950, @schaeff) +- Fix state corruption in the constant inliner (#949, @schaeff) +- Fix abi encoder bug for struct values where the members are encoded in the wrong order (#947, @schaeff) +- Bump Solidity version to latest breaking release and use Solidity's ABI v2. This means that the `export-verifier` CLI flag to choose the ABI coder was removed. (#844, @leonardoalt) + ## [0.7.5] - 2021-07-10 ### Release diff --git a/Cargo.lock b/Cargo.lock index a26a52d77..17e4488a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2383,7 +2383,7 @@ dependencies = [ [[package]] name = "zokrates_cli" -version = "0.7.5" +version = "0.7.6" dependencies = [ "assert_cli", "bincode", @@ -2410,7 +2410,7 @@ version = "0.1.0" [[package]] name = "zokrates_core" -version = "0.6.5" +version = "0.6.6" dependencies = [ "ark-bls12-377", "ark-bn254", @@ -2457,7 +2457,7 @@ dependencies = [ [[package]] name = "zokrates_core_test" -version = "0.2.3" +version = "0.2.4" dependencies = [ "zokrates_test", "zokrates_test_derive", @@ -2505,7 +2505,7 @@ dependencies = [ [[package]] name = "zokrates_fs_resolver" -version = "0.5.1" +version = "0.5.2" dependencies = [ "tempfile", "zokrates_common", @@ -2513,7 +2513,7 @@ dependencies = [ [[package]] name = "zokrates_parser" -version = "0.2.3" +version = "0.2.4" dependencies = [ "glob 0.2.11", "pest", @@ -2522,7 +2522,7 @@ dependencies = [ [[package]] name = "zokrates_pest_ast" -version = "0.2.2" +version = "0.2.3" dependencies = [ "from-pest", "glob 0.2.11", @@ -2534,7 +2534,7 @@ dependencies = [ [[package]] name = "zokrates_stdlib" -version = "0.2.3" +version = "0.2.4" dependencies = [ "fs_extra", "zokrates_test", @@ -2543,7 +2543,7 @@ dependencies = [ [[package]] name = "zokrates_test" -version = "0.1.6" +version = "0.1.7" dependencies = [ "serde", "serde_derive", diff --git a/changelogs/unreleased/844-leonardoalt b/changelogs/unreleased/844-leonardoalt deleted file mode 100644 index f4cd44d5d..000000000 --- a/changelogs/unreleased/844-leonardoalt +++ /dev/null @@ -1 +0,0 @@ -Bump Solidity version to latest breaking release and use Solidity's ABI v2. This means that the `export-verifier` CLI flag to choose the ABI coder was removed. diff --git a/changelogs/unreleased/942-dark64 b/changelogs/unreleased/942-dark64 deleted file mode 100644 index 798559535..000000000 --- a/changelogs/unreleased/942-dark64 +++ /dev/null @@ -1 +0,0 @@ -Use constants in the standard library, make `mimcSponge` implementation generic diff --git a/changelogs/unreleased/945-schaeff b/changelogs/unreleased/945-schaeff deleted file mode 100644 index 6a5a97b40..000000000 --- a/changelogs/unreleased/945-schaeff +++ /dev/null @@ -1 +0,0 @@ -Enable constant generics on structs \ No newline at end of file diff --git a/changelogs/unreleased/947-schaeff b/changelogs/unreleased/947-schaeff deleted file mode 100644 index 07e3af350..000000000 --- a/changelogs/unreleased/947-schaeff +++ /dev/null @@ -1 +0,0 @@ -Fix abi encoder bug for struct values where the members are encoded in the wrong order \ No newline at end of file diff --git a/changelogs/unreleased/948-schaeff b/changelogs/unreleased/948-schaeff deleted file mode 100644 index 15e68c970..000000000 --- a/changelogs/unreleased/948-schaeff +++ /dev/null @@ -1 +0,0 @@ -Add gm17 verifier to stdlib for bw6_761 \ No newline at end of file diff --git a/changelogs/unreleased/949-schaeff b/changelogs/unreleased/949-schaeff deleted file mode 100644 index 146b59230..000000000 --- a/changelogs/unreleased/949-schaeff +++ /dev/null @@ -1 +0,0 @@ -Fix state corruption in the constant inliner \ No newline at end of file diff --git a/changelogs/unreleased/950-schaeff b/changelogs/unreleased/950-schaeff deleted file mode 100644 index 1b3e2e0da..000000000 --- a/changelogs/unreleased/950-schaeff +++ /dev/null @@ -1 +0,0 @@ -Add compiler logs \ No newline at end of file diff --git a/changelogs/unreleased/954-schaeff b/changelogs/unreleased/954-schaeff deleted file mode 100644 index 9151cc062..000000000 --- a/changelogs/unreleased/954-schaeff +++ /dev/null @@ -1 +0,0 @@ -Fix constant range check in uint lt check \ No newline at end of file diff --git a/changelogs/unreleased/955-schaeff b/changelogs/unreleased/955-schaeff deleted file mode 100644 index fff1c6e23..000000000 --- a/changelogs/unreleased/955-schaeff +++ /dev/null @@ -1 +0,0 @@ -Make the stdlib `unpack` function safe against overflows of bit decompositions for any size of output, introduce `unpack_unchecked` for cases that do not require determinism \ No newline at end of file diff --git a/changelogs/unreleased/962-schaeff b/changelogs/unreleased/962-schaeff deleted file mode 100644 index 43053216b..000000000 --- a/changelogs/unreleased/962-schaeff +++ /dev/null @@ -1 +0,0 @@ -Add explicit function generic parameters to docs \ No newline at end of file diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml index 5ea922438..177892a99 100644 --- a/zokrates_cli/Cargo.toml +++ b/zokrates_cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_cli" -version = "0.7.5" +version = "0.7.6" authors = ["Jacob Eberhardt ", "Dennis Kuhnert ", "Thibaut Schaeffer "] repository = "https://github.com/Zokrates/ZoKrates.git" edition = "2018" diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 3c1b886fa..41bc7f170 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_core" -version = "0.6.5" +version = "0.6.6" edition = "2018" authors = ["Jacob Eberhardt ", "Dennis Kuhnert "] repository = "https://github.com/Zokrates/ZoKrates" diff --git a/zokrates_core_test/Cargo.toml b/zokrates_core_test/Cargo.toml index e366016fd..c7ee35856 100644 --- a/zokrates_core_test/Cargo.toml +++ b/zokrates_core_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_core_test" -version = "0.2.3" +version = "0.2.4" authors = ["schaeff "] edition = "2018" diff --git a/zokrates_fs_resolver/Cargo.toml b/zokrates_fs_resolver/Cargo.toml index 06c864c31..7302e8e1b 100644 --- a/zokrates_fs_resolver/Cargo.toml +++ b/zokrates_fs_resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_fs_resolver" -version = "0.5.1" +version = "0.5.2" authors = ["Thibaut Schaeffer "] repository = "https://github.com/JacobEberhardt/ZoKrates.git" edition = "2018" diff --git a/zokrates_js/Cargo.toml b/zokrates_js/Cargo.toml index 6a8ec711a..c2cb7e1c4 100644 --- a/zokrates_js/Cargo.toml +++ b/zokrates_js/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_js" -version = "1.0.34" +version = "1.0.35" authors = ["Darko Macesic"] edition = "2018" diff --git a/zokrates_js/package.json b/zokrates_js/package.json index 5e58106d6..de98ffe14 100644 --- a/zokrates_js/package.json +++ b/zokrates_js/package.json @@ -2,7 +2,7 @@ "name": "zokrates-js", "main": "index.js", "author": "Darko Macesic ", - "version": "1.0.34", + "version": "1.0.35", "keywords": [ "zokrates", "wasm-bindgen", diff --git a/zokrates_parser/Cargo.toml b/zokrates_parser/Cargo.toml index 4dd48ef99..fbfd76d8b 100644 --- a/zokrates_parser/Cargo.toml +++ b/zokrates_parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_parser" -version = "0.2.3" +version = "0.2.4" authors = ["JacobEberhardt "] edition = "2018" diff --git a/zokrates_pest_ast/Cargo.toml b/zokrates_pest_ast/Cargo.toml index aee4bad6e..6b476c83e 100644 --- a/zokrates_pest_ast/Cargo.toml +++ b/zokrates_pest_ast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_pest_ast" -version = "0.2.2" +version = "0.2.3" authors = ["schaeff "] edition = "2018" diff --git a/zokrates_stdlib/Cargo.toml b/zokrates_stdlib/Cargo.toml index 0ec18e8cc..57116d409 100644 --- a/zokrates_stdlib/Cargo.toml +++ b/zokrates_stdlib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_stdlib" -version = "0.2.3" +version = "0.2.4" authors = ["Stefan Deml ", "schaeff "] edition = "2018" diff --git a/zokrates_test/Cargo.toml b/zokrates_test/Cargo.toml index 823f6cf38..7444ff2a0 100644 --- a/zokrates_test/Cargo.toml +++ b/zokrates_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zokrates_test" -version = "0.1.6" +version = "0.1.7" authors = ["schaeff "] edition = "2018" From 2ca6d59f83e149032c7cfacd164c20e6d33fce68 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 16 Aug 2021 19:31:55 +0200 Subject: [PATCH 85/86] test shl/shr on large max --- zokrates_core/src/static_analysis/uint_optimizer.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zokrates_core/src/static_analysis/uint_optimizer.rs b/zokrates_core/src/static_analysis/uint_optimizer.rs index f770781d7..50b0de8f8 100644 --- a/zokrates_core/src/static_analysis/uint_optimizer.rs +++ b/zokrates_core/src/static_analysis/uint_optimizer.rs @@ -718,7 +718,7 @@ mod tests { #[test] fn right_shift() { - fn right_shift_test(e_max: u128, by: u32, output_max: u32) { + fn right_shift_test>(e_max: U, by: u32, output_max: u32) { let left = e_with_max(e_max); let right = by; @@ -736,12 +736,12 @@ mod tests { right_shift_test(0xff_u128, 2, 0xff >> 2); right_shift_test(2, 2, 2 >> 2); - right_shift_test(0xffffffffffff_u128, 2, 0xffffffff >> 2); + right_shift_test(Bn128Field::max_unique_value(), 2, 0xffffffff >> 2); } #[test] fn left_shift() { - fn left_shift_test(e_max: u128, by: u32, output_max: u32) { + fn left_shift_test>(e_max: U, by: u32, output_max: u32) { let left = e_with_max(e_max); let right = by; @@ -759,7 +759,7 @@ mod tests { left_shift_test(0xff_u128, 2, 0xff << 2); left_shift_test(2, 2, 2 << 2); - left_shift_test(0xffffffffffff_u128, 2, 0xffffffff << 2); + left_shift_test(Bn128Field::max_unique_value(), 2, 0xffffffff << 2); } #[test] From 9f469e5740d6346fa9ea870448dabd68f8f18c63 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 17 Aug 2021 16:59:44 +0200 Subject: [PATCH 86/86] merge dev, update changelog --- CHANGELOG.md | 1 + changelogs/unreleased/969-schaeff | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 changelogs/unreleased/969-schaeff diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a222f4bc..418767fc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ https://github.com/Zokrates/ZoKrates/compare/latest...develop - https://github.com/Zokrates/ZoKrates/releases/tag/0.7.6 ### Changes +- Fix stack overflow when testing equality on large arrays (#969, @schaeff) - Make the stdlib `unpack` function safe against overflows of bit decompositions for any size of output, introduce `unpack_unchecked` for cases that do not require determinism (#955, @schaeff) - Add explicit function generic parameters to docs (#962, @schaeff) - Add gm17 verifier to stdlib for bw6_761 (#948, @schaeff) diff --git a/changelogs/unreleased/969-schaeff b/changelogs/unreleased/969-schaeff deleted file mode 100644 index 770af0433..000000000 --- a/changelogs/unreleased/969-schaeff +++ /dev/null @@ -1 +0,0 @@ -Fix stack overflow when testing equality on large arrays \ No newline at end of file