From 6951dfb07174f6386bab60939b449f9f5aec98d3 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Wed, 6 Mar 2024 17:05:58 -0500 Subject: [PATCH 01/26] wip separating out array and slice types in the AST --- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 14 ++- compiler/noirc_frontend/src/ast/expression.rs | 19 ++++ compiler/noirc_frontend/src/ast/mod.rs | 9 +- .../src/hir/resolution/resolver.rs | 66 ++++++------ .../src/hir/type_check/errors.rs | 5 +- .../noirc_frontend/src/hir/type_check/expr.rs | 101 +++++++++++------- compiler/noirc_frontend/src/hir_def/expr.rs | 1 + compiler/noirc_frontend/src/hir_def/types.rs | 91 +++++++--------- .../src/monomorphization/ast.rs | 1 + .../src/monomorphization/mod.rs | 35 ++++-- .../src/monomorphization/printer.rs | 5 + compiler/noirc_frontend/src/node_interner.rs | 3 +- compiler/noirc_frontend/src/parser/parser.rs | 67 +++++++++++- .../noirc_frontend/src/parser/parser/types.rs | 13 ++- compiler/noirc_printable_type/src/lib.rs | 38 +++++-- tooling/nargo/src/artifacts/debug_vars.rs | 18 ++-- tooling/nargo_fmt/src/rewrite/array.rs | 9 +- tooling/nargo_fmt/src/rewrite/expr.rs | 11 +- tooling/nargo_fmt/src/rewrite/typ.rs | 12 +-- tooling/noirc_abi/src/lib.rs | 2 +- 20 files changed, 353 insertions(+), 167 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index d95295ae3c9..39013fa6e12 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -194,6 +194,18 @@ impl<'a> FunctionContext<'a> { ast::Type::Array(_, _) => { self.codegen_array_checked(elements, typ[0].clone())? } + _ => unreachable!( + "ICE: unexpected array literal type, got {}", + array.typ + ), + }) + } + ast::Literal::Slice(array) => { + let elements = + try_vecmap(&array.contents, |element| self.codegen_expression(element))?; + + let typ = Self::convert_type(&array.typ).flatten(); + Ok(match array.typ { ast::Type::Slice(_) => { let slice_length = self.builder.length_constant(array.contents.len() as u128); @@ -202,7 +214,7 @@ impl<'a> FunctionContext<'a> { Tree::Branch(vec![slice_length.into(), slice_contents]) } _ => unreachable!( - "ICE: array literal type must be an array or a slice, but got {}", + "ICE: unexpected slice literal type, got {}", array.typ ), }) diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index 2a252633a29..4110287c480 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -70,6 +70,17 @@ impl ExpressionKind { })) } + pub fn slice(contents: Vec) -> ExpressionKind { + ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Standard(contents))) + } + + pub fn repeated_slice(repeated_element: Expression, length: Expression) -> ExpressionKind { + ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Repeated { + repeated_element: Box::new(repeated_element), + length: Box::new(length), + })) + } + pub fn integer(contents: FieldElement) -> ExpressionKind { ExpressionKind::Literal(Literal::Integer(contents, false)) } @@ -319,6 +330,7 @@ impl UnaryOp { #[derive(Debug, PartialEq, Eq, Clone)] pub enum Literal { Array(ArrayLiteral), + Slice(ArrayLiteral), Bool(bool), Integer(FieldElement, /*sign*/ bool), // false for positive integer and true for negative Str(String), @@ -515,6 +527,13 @@ impl Display for Literal { Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { write!(f, "[{repeated_element}; {length}]") } + Literal::Slice(ArrayLiteral::Standard(elements)) => { + let contents = vecmap(elements, ToString::to_string); + write!(f, "&[{}]", contents.join(", ")) + } + Literal::Slice(ArrayLiteral::Repeated { repeated_element, length }) => { + write!(f, "&[{repeated_element}; {length}]") + } Literal::Bool(boolean) => write!(f, "{}", if *boolean { "true" } else { "false" }), Literal::Integer(integer, sign) => { if *sign { diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 29edbaca594..4406fdfb5df 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -83,7 +83,8 @@ impl core::fmt::Display for IntegerBitSize { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum UnresolvedTypeData { FieldElement, - Array(Option, Box), // [4]Witness = Array(4, Witness) + Array(UnresolvedTypeExpression, Box), // [4]Witness = Array(4, Witness) + Slice(Box), Integer(Signedness, IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, Expression(UnresolvedTypeExpression), @@ -151,10 +152,8 @@ impl std::fmt::Display for UnresolvedTypeData { use UnresolvedTypeData::*; match self { FieldElement => write!(f, "Field"), - Array(len, typ) => match len { - None => write!(f, "[{typ}]"), - Some(len) => write!(f, "[{typ}; {len}]"), - }, + Array(len, typ) => write!(f, "[{typ}; {len}]"), + Slice(typ) => write!(f, "[{typ}]"), Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), Signedness::Unsigned => write!(f, "u{num_bits}"), diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 7f9e48353a7..96fcc1a43d4 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -468,13 +468,13 @@ impl<'a> Resolver<'a> { FieldElement => Type::FieldElement, Array(size, elem) => { let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); - let size = if size.is_none() { - Type::NotConstant - } else { - self.resolve_array_size(size, new_variables) - }; + let size = self.resolve_array_size(Some(size), new_variables); Type::Array(Box::new(size), elem) } + Slice(elem) => { + let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); + Type::Slice(elem) + } Expression(expr) => self.convert_expression_type(expr), Integer(sign, bits) => Type::Integer(sign, bits), Bool => Type::Bool, @@ -1090,7 +1090,6 @@ impl<'a> Resolver<'a> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::NotConstant | Type::TraitAsType(..) | Type::Forall(_, _) => (), @@ -1101,6 +1100,10 @@ impl<'a> Resolver<'a> { Self::find_numeric_generics_in_type(element_type, found); } + Type::Slice(element_type) => { + Self::find_numeric_generics_in_type(element_type, found); + } + Type::Tuple(fields) => { for field in fields { Self::find_numeric_generics_in_type(field, found); @@ -1392,28 +1395,35 @@ impl<'a> Resolver<'a> { } } + fn resolve_array_literal(&mut self, array_literal: ArrayLiteral) -> HirArrayLiteral { + match array_literal { + ArrayLiteral::Standard(elements) => { + let elements = vecmap(elements, |elem| self.resolve_expression(elem)); + HirArrayLiteral::Standard(elements) + }, + ArrayLiteral::Repeated { repeated_element, length } => { + let span = length.span; + let length = UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else( + |error| { + self.errors.push(ResolverError::ParserError(Box::new(error))); + UnresolvedTypeExpression::Constant(0, span) + }, + ); + + let length = self.convert_expression_type(length); + let repeated_element = self.resolve_expression(*repeated_element); + + HirArrayLiteral::Repeated { repeated_element, length } + }, + } + } + pub fn resolve_expression(&mut self, expr: Expression) -> ExprId { let hir_expr = match expr.kind { ExpressionKind::Literal(literal) => HirExpression::Literal(match literal { Literal::Bool(b) => HirLiteral::Bool(b), - Literal::Array(ArrayLiteral::Standard(elements)) => { - let elements = vecmap(elements, |elem| self.resolve_expression(elem)); - HirLiteral::Array(HirArrayLiteral::Standard(elements)) - } - Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { - let span = length.span; - let length = UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else( - |error| { - self.errors.push(ResolverError::ParserError(Box::new(error))); - UnresolvedTypeExpression::Constant(0, span) - }, - ); - - let length = self.convert_expression_type(length); - let repeated_element = self.resolve_expression(*repeated_element); - - HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) - } + Literal::Array(array_literal) => HirLiteral::Array(self.resolve_array_literal(array_literal)), + Literal::Slice(array_literal) => HirLiteral::Slice(self.resolve_array_literal(array_literal)), Literal::Integer(integer, sign) => HirLiteral::Integer(integer, sign), Literal::Str(str) => HirLiteral::Str(str), Literal::RawStr(str, _) => HirLiteral::Str(str), @@ -2015,18 +2025,14 @@ impl<'a> Resolver<'a> { | UnresolvedTypeData::Function(_, _, _) | UnresolvedTypeData::FormatString(_, _) | UnresolvedTypeData::TraitAsType(..) + | UnresolvedTypeData::Slice(_) | UnresolvedTypeData::Unspecified => { let span = typ.span.expect("Function parameters should always have spans"); self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); } UnresolvedTypeData::Array(length, element) => { - if let Some(length) = length { - self.verify_type_expression_valid_for_program_input(length); - } else { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } + self.verify_type_expression_valid_for_program_input(length); self.verify_type_valid_for_program_input(element); } UnresolvedTypeData::Expression(expression) => { diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index 96d30100d8b..c1eabc76b5c 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -122,6 +122,8 @@ pub enum TypeCheckError { ConstrainedReferenceToUnconstrained { span: Span }, #[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")] UnconstrainedSliceReturnToConstrained { span: Span }, + #[error("Slices must have constant length")] + NonConstantSliceLength { span: Span }, } impl TypeCheckError { @@ -211,7 +213,8 @@ impl From for Diagnostic { | TypeCheckError::OverflowingAssignment { span, .. } | TypeCheckError::FieldModulo { span } | TypeCheckError::ConstrainedReferenceToUnconstrained { span } - | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } => { + | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } + | TypeCheckError::NonConstantSliceLength { span } => { Diagnostic::simple_error(error.to_string(), String::new(), span) } TypeCheckError::PublicReturnType { typ, span } => Diagnostic::simple_error( diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 7b854e58fca..900571cd972 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -48,6 +48,51 @@ impl<'interner> TypeChecker<'interner> { false } + fn check_hir_array_literal(&mut self, hir_array_literal: HirArrayLiteral) -> (Result, u64>, Box) { + match hir_array_literal { + HirArrayLiteral::Standard(arr) => { + let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); + + let first_elem_type = elem_types + .first() + .cloned() + .unwrap_or_else(|| self.interner.next_type_variable()); + + // Check if the array is homogeneous + for (index, elem_type) in elem_types.iter().enumerate().skip(1) { + let location = self.interner.expr_location(&arr[index]); + + elem_type.unify(&first_elem_type, &mut self.errors, || { + TypeCheckError::NonHomogeneousArray { + first_span: self.interner.expr_location(&arr[0]).span, + first_type: first_elem_type.to_string(), + first_index: index, + second_span: location.span, + second_type: elem_type.to_string(), + second_index: index + 1, + } + .add_context("elements in an array must have the same type") + }); + } + + ( + Err(arr.len() as u64), + Box::new(first_elem_type.clone()) + ) + }, + HirArrayLiteral::Repeated { repeated_element, length } => { + let elem_type = self.check_expression(&repeated_element); + let length = match length { + Type::Constant(length) => { + Err(length) + } + other => Ok(Box::new(other)), + }; + (length, Box::new(elem_type)) + }, + } + } + /// Infers a type for a given expression, and return this type. /// As a side-effect, this function will also remember this type in the NodeInterner /// for the given expr_id key. @@ -61,48 +106,22 @@ impl<'interner> TypeChecker<'interner> { HirExpression::Ident(ident) => self.check_ident(ident, expr_id), HirExpression::Literal(literal) => { match literal { - HirLiteral::Array(HirArrayLiteral::Standard(arr)) => { - let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); - - let first_elem_type = elem_types - .first() - .cloned() - .unwrap_or_else(|| self.interner.next_type_variable()); - - let arr_type = Type::Array( - Box::new(Type::constant_variable(arr.len() as u64, self.interner)), - Box::new(first_elem_type.clone()), - ); - - // Check if the array is homogeneous - for (index, elem_type) in elem_types.iter().enumerate().skip(1) { - let location = self.interner.expr_location(&arr[index]); - - elem_type.unify(&first_elem_type, &mut self.errors, || { - TypeCheckError::NonHomogeneousArray { - first_span: self.interner.expr_location(&arr[0]).span, - first_type: first_elem_type.to_string(), - first_index: index, - second_span: location.span, - second_type: elem_type.to_string(), - second_index: index + 1, - } - .add_context("elements in an array must have the same type") - }); + HirLiteral::Array(hir_array_literal) => { + let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); + Type::Array(elem_type, length.unwrap_or_else(|constant| Box::new(Type::constant_variable(constant, self.interner)))) + }, + HirLiteral::Slice(hir_array_literal) => { + let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); + match length_type { + Ok(_non_constant) => { + self.errors.push(TypeCheckError::NonConstantSliceLength { + span: self.interner.expr_span(expr_id), + }); + Type::Error + }, + Err(_length) => Type::Slice(elem_type), } - - arr_type - } - HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) => { - let elem_type = self.check_expression(&repeated_element); - let length = match length { - Type::Constant(length) => { - Type::constant_variable(length, self.interner) - } - other => other, - }; - Type::Array(Box::new(length), Box::new(elem_type)) - } + }, HirLiteral::Bool(_) => Type::Bool, HirLiteral::Integer(_, _) => Type::polymorphic_integer_or_field(self.interner), HirLiteral::Str(string) => { diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index b4c590de491..6a1b4385f0d 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -99,6 +99,7 @@ impl HirBinaryOp { #[derive(Debug, Clone)] pub enum HirLiteral { Array(HirArrayLiteral), + Slice(HirArrayLiteral), Bool(bool), Integer(FieldElement, bool), //true for negative integer and false for positive Str(String), diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index b70aa43701c..6e6b24296cb 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -27,6 +27,9 @@ pub enum Type { /// is either a type variable of some kind or a Type::Constant. Array(Box, Box), + /// Slice(E) is a slice of elements of type E. + Slice(Box), + /// A primitive integer type with the given sign and bit count. /// E.g. `u32` would be `Integer(Unsigned, ThirtyTwo)` Integer(Signedness, IntegerBitSize), @@ -98,11 +101,6 @@ pub enum Type { /// bind to an integer without special checks to bind it to a non-type. Constant(u64), - /// The type of a slice is an array of size NotConstant. - /// The size of an array literal is resolved to this if it ever uses operations - /// involving slices. - NotConstant, - /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with /// an invalid type would otherwise issue a new error each time it is called @@ -150,19 +148,16 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) | Type::Constant(_) - | Type::NotConstant + | Type::Slice(_) | Type::Error => unreachable!("This type cannot exist as a parameter to main"), } } pub(crate) fn is_nested_slice(&self) -> bool { match self { - Type::Array(size, elem) => { - if let Type::NotConstant = size.as_ref() { - elem.as_ref().contains_slice() - } else { - false - } + Type::Slice(_) => true, + Type::Array(_, elem) => { + elem.as_ref().contains_slice() } _ => false, } @@ -170,7 +165,7 @@ impl Type { pub(crate) fn contains_slice(&self) -> bool { match self { - Type::Array(size, _) => matches!(size.as_ref(), Type::NotConstant), + Type::Slice(_) => true, Type::Struct(struct_typ, generics) => { let fields = struct_typ.borrow().get_fields(generics); for field in fields.iter() { @@ -457,7 +452,7 @@ pub enum TypeVariableKind { /// that can only be bound to Type::Integer, or other polymorphic integers. Integer, - /// A potentially constant array size. This will only bind to itself, Type::NotConstant, or + /// A potentially constant array size. This will only bind to itself or /// Type::Constant(n) with a matching size. This defaults to Type::Constant(n) if still unbound /// during monomorphization. Constant(u64), @@ -635,14 +630,15 @@ impl Type { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::NotConstant | Type::Forall(_, _) | Type::TraitAsType(..) => false, Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) } - + Type::Slice(elem) => { + elem.contains_numeric_typevar(target_id) + } Type::Tuple(fields) => { fields.iter().any(|field| field.contains_numeric_typevar(target_id)) } @@ -700,8 +696,8 @@ impl Type { | Type::Function(_, _, _) | Type::MutableReference(_) | Type::Forall(_, _) - | Type::TraitAsType(..) - | Type::NotConstant => false, + | Type::Slice(_) + | Type::TraitAsType(..) => false, // This function is called during name resolution before we've verified aliases // are not cyclic. As a result, it wouldn't be safe to check this alias' definition @@ -770,11 +766,10 @@ impl std::fmt::Display for Type { write!(f, "Field") } Type::Array(len, typ) => { - if matches!(len.follow_bindings(), Type::NotConstant) { - write!(f, "[{typ}]") - } else { - write!(f, "[{typ}; {len}]") - } + write!(f, "[{typ}; {len}]") + } + Type::Slice(typ) => { + write!(f, "[{typ}]") } Type::Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), @@ -864,7 +859,6 @@ impl std::fmt::Display for Type { Type::MutableReference(element) => { write!(f, "&mut {element}") } - Type::NotConstant => write!(f, "_"), } } } @@ -920,10 +914,6 @@ impl Type { bindings.insert(target_id, (var.clone(), this)); Ok(()) } - Type::NotConstant => { - bindings.insert(target_id, (var.clone(), Type::NotConstant)); - Ok(()) - } // A TypeVariable is less specific than a MaybeConstant, so we bind // to the other type variable instead. Type::TypeVariable(new_var, kind) => { @@ -951,14 +941,8 @@ impl Type { bindings.insert(*new_target_id, (new_var.clone(), clone)); Ok(()) } - // The lengths don't match, but neither are set in stone so we can - // just set them both to NotConstant. See issue 2370 - TypeVariableKind::Constant(_) => { - // *length != target_length - bindings.insert(target_id, (var.clone(), Type::NotConstant)); - bindings.insert(*new_target_id, (new_var.clone(), Type::NotConstant)); - Ok(()) - } + // *length != target_length + TypeVariableKind::Constant(_) => Err(UnificationError), TypeVariableKind::IntegerOrField => Err(UnificationError), TypeVariableKind::Integer => Err(UnificationError), }, @@ -1312,12 +1296,11 @@ impl Type { let this = self.follow_bindings(); let target = target.follow_bindings(); - if let (Type::Array(size1, element1), Type::Array(size2, element2)) = (&this, &target) { - let size1 = size1.follow_bindings(); - let size2 = size2.follow_bindings(); + if let (Type::Array(size, element1), Type::Slice(element2)) = (&this, &target) { + let length = size.follow_bindings(); // If we have an array and our target is a slice - if matches!(size1, Type::Constant(_)) && matches!(size2, Type::NotConstant) { + if matches!(length, Type::Constant(_)) { // Still have to ensure the element types match. // Don't need to issue an error here if not, it will be done in unify_with_coercions let mut bindings = TypeBindings::new(); @@ -1493,6 +1476,10 @@ impl Type { let element = element.substitute_helper(type_bindings, substitute_bound_typevars); Type::Array(Box::new(size), Box::new(element)) } + Type::Slice(element) => { + let element = element.substitute_helper(type_bindings, substitute_bound_typevars); + Type::Slice(Box::new(element)) + } Type::String(size) => { let size = size.substitute_helper(type_bindings, substitute_bound_typevars); Type::String(Box::new(size)) @@ -1552,7 +1539,6 @@ impl Type { | Type::Constant(_) | Type::TraitAsType(..) | Type::Error - | Type::NotConstant | Type::Unit => self.clone(), } } @@ -1561,6 +1547,7 @@ impl Type { pub fn occurs(&self, target_id: TypeVariableId) -> bool { match self { Type::Array(len, elem) => len.occurs(target_id) || elem.occurs(target_id), + Type::Slice(elem) => elem.occurs(target_id), Type::String(len) => len.occurs(target_id), Type::FmtString(len, fields) => { let len_occurs = len.occurs(target_id); @@ -1593,7 +1580,6 @@ impl Type { | Type::Constant(_) | Type::TraitAsType(..) | Type::Error - | Type::NotConstant | Type::Unit => false, } } @@ -1610,6 +1596,9 @@ impl Type { Array(size, elem) => { Array(Box::new(size.follow_bindings()), Box::new(elem.follow_bindings())) } + Slice(elem) => { + Slice(Box::new(elem.follow_bindings())) + } String(size) => String(Box::new(size.follow_bindings())), FmtString(size, args) => { let size = Box::new(size.follow_bindings()); @@ -1650,8 +1639,7 @@ impl Type { | Bool | Constant(_) | Unit - | Error - | NotConstant => self.clone(), + | Error => self.clone(), } } @@ -1731,6 +1719,10 @@ impl From<&Type> for PrintableType { let typ = typ.as_ref(); PrintableType::Array { length, typ: Box::new(typ.into()) } } + Type::Slice(typ) => { + let typ = typ.as_ref(); + PrintableType::Slice{ typ: Box::new(typ.into()) } + } Type::Integer(sign, bit_width) => match sign { Signedness::Unsigned => { PrintableType::UnsignedInteger { width: (*bit_width).into() } @@ -1774,7 +1766,6 @@ impl From<&Type> for PrintableType { Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } - Type::NotConstant => unreachable!(), } } } @@ -1786,11 +1777,10 @@ impl std::fmt::Debug for Type { write!(f, "Field") } Type::Array(len, typ) => { - if matches!(len.follow_bindings(), Type::NotConstant) { - write!(f, "[{typ:?}]") - } else { - write!(f, "[{typ:?}; {len:?}]") - } + write!(f, "[{typ:?}; {len:?}]") + } + Type::Slice(typ) => { + write!(f, "[{typ:?}]") } Type::Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), @@ -1860,7 +1850,6 @@ impl std::fmt::Debug for Type { Type::MutableReference(element) => { write!(f, "&mut {element:?}") } - Type::NotConstant => write!(f, "NotConstant"), } } } diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index e4e619d5d92..978430bc068 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -87,6 +87,7 @@ pub struct For { #[derive(Debug, Clone, Hash)] pub enum Literal { Array(ArrayLiteral), + Slice(ArrayLiteral), Integer(FieldElement, Type, Location), Bool(bool), Str(String), diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index ce880401d77..a62a041ecd3 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -417,9 +417,15 @@ impl<'interner> Monomorphizer<'interner> { } } HirExpression::Literal(HirLiteral::Array(array)) => match array { - HirArrayLiteral::Standard(array) => self.standard_array(expr, array)?, + HirArrayLiteral::Standard(array) => self.standard_array(expr, array, false)?, HirArrayLiteral::Repeated { repeated_element, length } => { - self.repeated_array(expr, repeated_element, length)? + self.repeated_array(expr, repeated_element, length, false)? + } + }, + HirExpression::Literal(HirLiteral::Slice(array)) => match array { + HirArrayLiteral::Standard(array) => self.standard_array(expr, array, true)?, + HirArrayLiteral::Repeated { repeated_element, length } => { + self.repeated_array(expr, repeated_element, length, true)? } }, HirExpression::Literal(HirLiteral::Unit) => ast::Expression::Block(vec![]), @@ -518,10 +524,15 @@ impl<'interner> Monomorphizer<'interner> { &mut self, array: node_interner::ExprId, array_elements: Vec, + is_slice: bool, ) -> Result { let typ = self.convert_type(&self.interner.id_type(array)); let contents = try_vecmap(array_elements, |id| self.expr(id))?; - Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + if is_slice { + Ok(ast::Expression::Literal(ast::Literal::Slice(ast::ArrayLiteral { contents, typ }))) + } else { + Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + } } fn repeated_array( @@ -529,6 +540,7 @@ impl<'interner> Monomorphizer<'interner> { array: node_interner::ExprId, repeated_element: node_interner::ExprId, length: HirType, + is_slice: bool, ) -> Result { let typ = self.convert_type(&self.interner.id_type(array)); @@ -538,7 +550,11 @@ impl<'interner> Monomorphizer<'interner> { })?; let contents = try_vecmap(0..length, |_| self.expr(repeated_element))?; - Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + if is_slice { + Ok(ast::Expression::Literal(ast::Literal::Slice(ast::ArrayLiteral { contents, typ }))) + } else { + Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + } } fn index( @@ -858,6 +874,10 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::Slice(element) } } + HirType::Slice(element) => { + let element = Box::new(self.convert_type(element.as_ref())); + ast::Type::Slice(element) + } HirType::TraitAsType(..) => { unreachable!("All TraitAsType should be replaced before calling convert_type"); } @@ -933,7 +953,6 @@ impl<'interner> Monomorphizer<'interner> { HirType::Forall(_, _) | HirType::Constant(_) - | HirType::NotConstant | HirType::Error => { unreachable!("Unexpected type {} found", typ) } @@ -1149,11 +1168,7 @@ impl<'interner> Monomorphizer<'interner> { fn append_printable_type_info_inner(typ: &Type, arguments: &mut Vec) { // Disallow printing slices and mutable references for consistency, // since they cannot be passed from ACIR into Brillig - if let HirType::Array(size, _) = typ { - if let HirType::NotConstant = **size { - unreachable!("println and format strings do not support slices. Convert the slice to an array before passing it to println"); - } - } else if matches!(typ, HirType::MutableReference(_)) { + if matches!(typ, HirType::MutableReference(_)) { unreachable!("println and format strings do not support mutable references."); } diff --git a/compiler/noirc_frontend/src/monomorphization/printer.rs b/compiler/noirc_frontend/src/monomorphization/printer.rs index 7aec2193494..2531dc6574e 100644 --- a/compiler/noirc_frontend/src/monomorphization/printer.rs +++ b/compiler/noirc_frontend/src/monomorphization/printer.rs @@ -95,6 +95,11 @@ impl AstPrinter { self.print_comma_separated(&array.contents, f)?; write!(f, "]") } + super::ast::Literal::Slice(array) => { + write!(f, "&[")?; + self.print_comma_separated(&array.contents, f)?; + write!(f, "]") + } super::ast::Literal::Integer(x, _, _) => x.fmt(f), super::ast::Literal::Bool(x) => x.fmt(f), super::ast::Literal::Str(s) => s.fmt(f), diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 5de43e59254..1ee8610ccf2 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1681,6 +1681,7 @@ enum TypeMethodKey { /// accept only fields or integers, it is just that their names may not clash. FieldOrInt, Array, + Slice, Bool, String, FmtString, @@ -1696,6 +1697,7 @@ fn get_type_method_key(typ: &Type) -> Option { match &typ { Type::FieldElement => Some(FieldOrInt), Type::Array(_, _) => Some(Array), + Type::Slice(_) => Some(Slice), Type::Integer(_, _) => Some(FieldOrInt), Type::TypeVariable(_, TypeVariableKind::IntegerOrField) => Some(FieldOrInt), Type::TypeVariable(_, TypeVariableKind::Integer) => Some(FieldOrInt), @@ -1714,7 +1716,6 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Forall(_, _) | Type::Constant(_) | Type::Error - | Type::NotConstant | Type::Struct(_, _) | Type::TraitAsType(..) => None, } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 75f4a6359bf..ec6d613b85f 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -563,6 +563,7 @@ fn parse_type_inner( format_string_type(recursive_type_parser.clone()), named_type(recursive_type_parser.clone()), named_trait(recursive_type_parser.clone()), + slice_type(recursive_type_parser.clone()), array_type(recursive_type_parser.clone()), parenthesized_type(recursive_type_parser.clone()), tuple_type(recursive_type_parser.clone()), @@ -699,13 +700,22 @@ fn generic_type_args( fn array_type(type_parser: impl NoirParser) -> impl NoirParser { just(Token::LeftBracket) .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression()).or_not()) + .then(just(Token::Semicolon).ignore_then(type_expression())) .then_ignore(just(Token::RightBracket)) .map_with_span(|(element_type, size), span| { UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) }) } +fn slice_type(type_parser: impl NoirParser) -> impl NoirParser { + just(Token::LeftBracket) + .ignore_then(type_parser) + .then_ignore(just(Token::RightBracket)) + .map_with_span(|element_type, span| { + UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) + }) +} + fn type_expression() -> impl NoirParser { recursive(|expr| { expression_with_precedence( @@ -1067,6 +1077,14 @@ where .map(|(lhs, count)| ExpressionKind::repeated_array(lhs, count)) } +/// &[array_expr] +fn slice_expr

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + just(Token::Ampersand).ignore_then(array_expr(expr_parser)) +} + fn expression_list

(expr_parser: P) -> impl NoirParser> where P: ExprParser, @@ -1090,6 +1108,7 @@ where { choice(( if_expr(expr_no_constructors, statement.clone()), + slice_expr(expr_parser.clone()), array_expr(expr_parser.clone()), if allow_constructors { constructor(expr_parser.clone()).boxed() @@ -1168,7 +1187,7 @@ where mod test { use super::test_helpers::*; use super::*; - use crate::{ArrayLiteral, Literal}; + use crate::{ArrayLiteral, SliceLiteral, Literal}; #[test] fn parse_infix() { @@ -1281,6 +1300,50 @@ mod test { parse_all_failing(array_expr(expression()), invalid); } + fn expr_to_slice(expr: ExpressionKind) -> SliceLiteral { + let lit = match expr { + ExpressionKind::Literal(literal) => literal, + _ => unreachable!("expected a literal"), + }; + + match lit { + Literal::Slice(arr) => arr, + _ => unreachable!("expected an slice"), + } + } + + #[test] + fn parse_slice() { + let valid = vec![ + "&[0, 1, 2,3, 4]", + "&[0,1,2,3,4,]", // Trailing commas are valid syntax + "&[0;5]", + ]; + + for expr in parse_all(slice_expr(expression()), valid) { + match expr_to_slice(expr) { + SliceLiteral::Standard(elements) => assert_eq!(elements.len(), 5), + SliceLiteral::Repeated { length, .. } => { + assert_eq!(length.kind, ExpressionKind::integer(5i128.into())); + } + } + } + + parse_all_failing( + slice_expr(expression()), + vec!["0,1,2,3,4]", "&[[0,1,2,3,4]", "&[0,1,2,,]", "&[0,1,2,3,4"], + ); + } + + #[test] + fn parse_slice_sugar() { + let valid = vec!["&[0;7]", "&[(1, 2); 4]", "&[0;Four]", "&[2;1+3-a]"]; + parse_all(slice_expr(expression()), valid); + + let invalid = vec!["&[0;;4]", "&[1, 2; 3]"]; + parse_all_failing(slice_expr(expression()), invalid); + } + #[test] fn parse_block() { parse_with(block(fresh_statement()), "{ [0,1,2,3,4] }").unwrap(); diff --git a/compiler/noirc_frontend/src/parser/parser/types.rs b/compiler/noirc_frontend/src/parser/parser/types.rs index 572397d6527..d8a63d161b9 100644 --- a/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/compiler/noirc_frontend/src/parser/parser/types.rs @@ -88,13 +88,24 @@ pub(super) fn array_type( ) -> impl NoirParser { just(Token::LeftBracket) .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression()).or_not()) + .then(just(Token::Semicolon).ignore_then(type_expression())) .then_ignore(just(Token::RightBracket)) .map_with_span(|(element_type, size), span| { UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) }) } +pub(super) fn slice_type( + type_parser: impl NoirParser, +) -> impl NoirParser { + just(Token::LeftBracket) + .ignore_then(type_parser) + .then_ignore(just(Token::RightBracket)) + .map_with_span(|element_type, span| { + UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) + }) +} + pub(super) fn type_expression() -> impl NoirParser { recursive(|expr| { expression_with_precedence( diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 24f4f275a14..9abc993606b 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -15,6 +15,10 @@ pub enum PrintableType { #[serde(rename = "type")] typ: Box, }, + Slice { + #[serde(rename = "type")] + typ: Box, + }, Tuple { types: Vec, }, @@ -48,7 +52,10 @@ pub enum PrintableType { pub enum PrintableValue { Field(FieldElement), String(String), - Vec(Vec), + Vec { + array_elements: Vec, + is_slice: bool, + }, Struct(BTreeMap), Other, } @@ -182,9 +189,12 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { (_, PrintableType::MutableReference { .. }) => { output.push_str("<>"); } - (PrintableValue::Vec(vector), PrintableType::Array { typ, .. }) => { + (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Array { typ, .. }) => { + if *is_slice { + output.push('&') + } output.push('['); - let mut values = vector.iter().peekable(); + let mut values = array_elements.iter().peekable(); while let Some(value) = values.next() { output.push_str(&format!( "{}", @@ -219,9 +229,9 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str(" }"); } - (PrintableValue::Vec(values), PrintableType::Tuple { types }) => { + (PrintableValue::Vec { array_elements, .. }, PrintableType::Tuple { types }) => { output.push('('); - let mut elems = values.iter().zip(types).peekable(); + let mut elems = array_elements.iter().zip(types).peekable(); while let Some((value, typ)) = elems.next() { output.push_str( &PrintableValueDisplay::Plain(value.clone(), typ.clone()).to_string(), @@ -320,7 +330,7 @@ pub fn decode_value( array_elements.push(decode_value(field_iterator, typ)); } - PrintableValue::Vec(array_elements) + PrintableValue::Vec { array_elements, is_slice: false } } PrintableType::Array { length: Some(length), typ } => { let length = *length as usize; @@ -329,10 +339,22 @@ pub fn decode_value( array_elements.push(decode_value(field_iterator, typ)); } - PrintableValue::Vec(array_elements) + PrintableValue::Vec { array_elements, is_slice: false } + } + PrintableType::Slice { typ } => { + let length = field_iterator + .next() + .expect("not enough data to decode variable array length") + .to_u128() as usize; + let mut array_elements = Vec::with_capacity(length); + for _ in 0..length { + array_elements.push(decode_value(field_iterator, typ)); + } + + PrintableValue::Vec { array_elements, is_slice: true } } PrintableType::Tuple { types } => { - PrintableValue::Vec(vecmap(types, |typ| decode_value(field_iterator, typ))) + PrintableValue::Vec { array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), is_slice: false } } PrintableType::String { length } => { let field_elements: Vec = field_iterator.take(*length as usize).collect(); diff --git a/tooling/nargo/src/artifacts/debug_vars.rs b/tooling/nargo/src/artifacts/debug_vars.rs index 20f2637f7d6..0921dbd3e7c 100644 --- a/tooling/nargo/src/artifacts/debug_vars.rs +++ b/tooling/nargo/src/artifacts/debug_vars.rs @@ -62,16 +62,21 @@ impl DebugVars { .unwrap_or_else(|| panic!("type unavailable for type id {cursor_type_id:?}")); for index in indexes.iter() { (cursor, cursor_type) = match (cursor, cursor_type) { - (PrintableValue::Vec(array), PrintableType::Array { length, typ }) => { + (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Array { length, typ }) => { + assert!(!*is_slice, "slice has array type"); if let Some(len) = length { if *index as u64 >= *len { panic!("unexpected field index past array length") } - if *len != array.len() as u64 { + if *len != array_elements.len() as u64 { panic!("type/array length mismatch") } } - (array.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) + (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) + } + (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Slice { typ }) => { + assert!(*is_slice, "array has slice type"); + (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) } ( PrintableValue::Struct(field_map), @@ -83,18 +88,19 @@ impl DebugVars { let (key, typ) = fields.get(*index as usize).unwrap(); (field_map.get_mut(key).unwrap(), typ) } - (PrintableValue::Vec(array), PrintableType::Tuple { types }) => { + (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Tuple { types }) => { + assert!(!*is_slice, "slice has tuple type"); if *index >= types.len() as u32 { panic!( "unexpected field index ({index}) past tuple length ({})", types.len() ); } - if types.len() != array.len() { + if types.len() != array_elements.len() { panic!("type/array length mismatch") } let typ = types.get(*index as usize).unwrap(); - (array.get_mut(*index as usize).unwrap(), typ) + (array_elements.get_mut(*index as usize).unwrap(), typ) } _ => { panic!("unexpected assign field of {cursor_type:?} type"); diff --git a/tooling/nargo_fmt/src/rewrite/array.rs b/tooling/nargo_fmt/src/rewrite/array.rs index 77e5e756f19..4499760c1a4 100644 --- a/tooling/nargo_fmt/src/rewrite/array.rs +++ b/tooling/nargo_fmt/src/rewrite/array.rs @@ -6,7 +6,7 @@ use crate::{ visitor::{expr::NewlineMode, FmtVisitor}, }; -pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span) -> String { +pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span, is_slice: bool) -> String { let pattern: &[_] = &[' ', '\t']; visitor.indent.block_indent(visitor.config); @@ -75,8 +75,13 @@ pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_spa } } + let open_bracket = if is_slice { + "&[" + } else { + "[" + }; crate::visitor::expr::wrap_exprs( - "[", + open_bracket, "]", items_str.trim().into(), nested_indent, diff --git a/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs index 32d104f559b..ffb8dea5a9d 100644 --- a/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/tooling/nargo_fmt/src/rewrite/expr.rs @@ -122,7 +122,16 @@ pub(crate) fn rewrite( format!("[{repeated}; {length}]") } Literal::Array(ArrayLiteral::Standard(exprs)) => { - super::array(visitor.fork(), exprs, span) + super::array(visitor.fork(), exprs, span, false) + } + Literal::Slice(ArrayLiteral::Repeated { repeated_element, length }) => { + let repeated = rewrite_sub_expr(visitor, shape, *repeated_element); + let length = rewrite_sub_expr(visitor, shape, *length); + + format!("&[{repeated}; {length}]") + } + Literal::Slice(ArrayLiteral::Standard(exprs)) => { + super::array(visitor.fork(), exprs, span, true) } Literal::Unit => "()".to_string(), }, diff --git a/tooling/nargo_fmt/src/rewrite/typ.rs b/tooling/nargo_fmt/src/rewrite/typ.rs index aaa77b0bea5..922337cdb74 100644 --- a/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/tooling/nargo_fmt/src/rewrite/typ.rs @@ -9,12 +9,12 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) match typ.typ { UnresolvedTypeData::Array(length, element) => { let typ = rewrite(visitor, _shape, *element); - if let Some(length) = length { - let length = visitor.slice(length.span()); - format!("[{typ}; {length}]") - } else { - format!("[{typ}]") - } + let length = visitor.slice(length.span()); + format!("[{typ}; {length}]") + } + UnresolvedTypeData::Slice(element) => { + let typ = rewrite(visitor, _shape, *element); + format!("[{typ}]") } UnresolvedTypeData::Parenthesized(typ) => { let typ = rewrite(visitor, _shape, *typ); diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 26feab65d83..26edb7a2af6 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -178,7 +178,7 @@ impl AbiType { | Type::TypeVariable(_, _) | Type::NamedGeneric(..) | Type::Forall(..) - | Type::NotConstant + | Type::Slice(_) | Type::Function(_, _, _) => unreachable!("Type cannot be used in the abi"), Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), From 2f93bedbfa777607032f702bf1758e53e472204b Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 7 Mar 2024 12:53:01 -0600 Subject: [PATCH 02/26] Update ordering of Type::Array construction in type_check/expr.rs --- compiler/noirc_frontend/src/hir/type_check/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 900571cd972..7c143ff433c 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -108,7 +108,7 @@ impl<'interner> TypeChecker<'interner> { match literal { HirLiteral::Array(hir_array_literal) => { let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); - Type::Array(elem_type, length.unwrap_or_else(|constant| Box::new(Type::constant_variable(constant, self.interner)))) + Type::Array(length.unwrap_or_else(|constant| Box::new(Type::constant_variable(constant, self.interner))), elem_type) }, HirLiteral::Slice(hir_array_literal) => { let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); From 654732a27392269f9166799280ff4910ce5ba460 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 8 Mar 2024 13:31:26 -0500 Subject: [PATCH 03/26] wip debugging and updating tests: fix parser and parser tests for ampersand, updating stdlib, fixed nested slice for new type, found missing unification case, added more specific error for missing array length, debugging slice parser, added noirc_frontend test for slices, debugging stdlib failing to build --- .../src/hir/def_collector/dc_crate.rs | 2 +- .../src/hir/def_collector/errors.rs | 4 +-- compiler/noirc_frontend/src/hir_def/types.rs | 6 +++- .../src/monomorphization/mod.rs | 15 ++++---- compiler/noirc_frontend/src/parser/parser.rs | 35 +++++++++++++++---- compiler/noirc_frontend/src/tests.rs | 15 ++++++++ noir_stdlib/src/bigint.nr | 8 ++--- 7 files changed, 64 insertions(+), 21 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 7f36af5b30e..6074095714b 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -136,7 +136,7 @@ pub struct DefCollector { pub(crate) type ImplMap = HashMap<(UnresolvedType, LocalModuleId), Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>>; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CompilationError { ParseError(ParserError), DefinitionError(DefCollectorErrorKind), diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index de45be48c4e..2ffc78d800e 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -23,7 +23,7 @@ pub enum DuplicateType { TraitAssociatedFunction, } -#[derive(Error, Debug, Clone)] +#[derive(Error, Debug, Clone, PartialEq)] pub enum DefCollectorErrorKind { #[error("duplicate {typ} found in namespace")] Duplicate { typ: DuplicateType, first_def: Ident, second_def: Ident }, @@ -78,7 +78,7 @@ pub enum DefCollectorErrorKind { } /// An error struct that macro processors can return. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct MacroError { pub primary_message: String, pub secondary_message: Option, diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 6e6b24296cb..3f7eba598db 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -155,7 +155,7 @@ impl Type { pub(crate) fn is_nested_slice(&self) -> bool { match self { - Type::Slice(_) => true, + Type::Slice(elem) => elem.as_ref().contains_slice(), Type::Array(_, elem) => { elem.as_ref().contains_slice() } @@ -1152,6 +1152,10 @@ impl Type { elem_a.try_unify(elem_b, bindings) } + (Slice(elem_a), Slice(elem_b)) => { + elem_a.try_unify(elem_b, bindings) + } + (String(len_a), String(len_b)) => len_a.try_unify(len_b, bindings), (FmtString(len_a, elements_a), FmtString(len_b, elements_b)) => { diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index a62a041ecd3..5a8af4c699f 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -867,12 +867,11 @@ impl<'interner> Monomorphizer<'interner> { HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { let element = Box::new(self.convert_type(element.as_ref())); - - if let Some(length) = length.evaluate_to_u64() { - ast::Type::Array(length, element) - } else { - ast::Type::Slice(element) - } + // TODO: convert to MonomorphizationError + let length = length.evaluate_to_u64().unwrap_or_else(|| { + panic!("Length of generic array could not be determined.") + }); + ast::Type::Array(length, element) } HirType::Slice(element) => { let element = Box::new(self.convert_type(element.as_ref())); @@ -1236,6 +1235,10 @@ impl<'interner> Monomorphizer<'interner> { location: Location, ) -> ast::Expression { use ast::*; + + // TODO: remove + println!("modulus_array_literal: {:?}, {:?}, {:?}", bytes, arr_elem_bits, location); + let int_type = Type::Integer(crate::Signedness::Unsigned, arr_elem_bits); let bytes_as_expr = vecmap(bytes, |byte| { diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index ec6d613b85f..30948267384 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -1077,12 +1077,33 @@ where .map(|(lhs, count)| ExpressionKind::repeated_array(lhs, count)) } -/// &[array_expr] fn slice_expr

(expr_parser: P) -> impl NoirParser where P: ExprParser, { - just(Token::Ampersand).ignore_then(array_expr(expr_parser)) + just(Token::Ampersand).ignore_then(standard_slice(expr_parser.clone()).or(slice_sugar(expr_parser))) +} + +/// &[a, b, c, ...] +fn standard_slice

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + expression_list(expr_parser) + .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) + .validate(|elements, _span, _emit| ExpressionKind::slice(elements)) +} + +/// &[a; N] +fn slice_sugar

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + expr_parser + .clone() + .then(just(Token::Semicolon).ignore_then(expr_parser)) + .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) + .map(|(lhs, count)| ExpressionKind::repeated_slice(lhs, count)) } fn expression_list

(expr_parser: P) -> impl NoirParser> @@ -1187,7 +1208,7 @@ where mod test { use super::test_helpers::*; use super::*; - use crate::{ArrayLiteral, SliceLiteral, Literal}; + use crate::{ArrayLiteral, Literal}; #[test] fn parse_infix() { @@ -1300,7 +1321,7 @@ mod test { parse_all_failing(array_expr(expression()), invalid); } - fn expr_to_slice(expr: ExpressionKind) -> SliceLiteral { + fn expr_to_slice(expr: ExpressionKind) -> ArrayLiteral { let lit = match expr { ExpressionKind::Literal(literal) => literal, _ => unreachable!("expected a literal"), @@ -1308,7 +1329,7 @@ mod test { match lit { Literal::Slice(arr) => arr, - _ => unreachable!("expected an slice"), + _ => unreachable!("expected a slice: {:?}", lit), } } @@ -1322,8 +1343,8 @@ mod test { for expr in parse_all(slice_expr(expression()), valid) { match expr_to_slice(expr) { - SliceLiteral::Standard(elements) => assert_eq!(elements.len(), 5), - SliceLiteral::Repeated { length, .. } => { + ArrayLiteral::Standard(elements) => assert_eq!(elements.len(), 5), + ArrayLiteral::Repeated { length, .. } => { assert_eq!(length.kind, ExpressionKind::integer(5i128.into())); } } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index c661cc92eef..bf2081355ad 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -904,6 +904,21 @@ mod test { assert!(get_program_errors(src).is_empty()); } + #[test] + fn resolve_literal_slice() { + let src = r#" + fn const_0(_x : [Field]) -> Field { + 0 + } + fn main(x : Field) { + let y: [Field] = &[1, 2, 3]; + assert(const_0(y) == x); + } + "#; + // assert!(get_program_errors(src).is_empty()); + assert!(get_program_errors(src) == vec![], "{:?}", get_program_errors(src)); + } + #[test] fn multiple_resolution_errors() { let src = r#" diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr index 98237a54779..23fb627e453 100644 --- a/noir_stdlib/src/bigint.nr +++ b/noir_stdlib/src/bigint.nr @@ -9,10 +9,10 @@ global secpk1_fr = [0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; global secpk1_fq = [0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fq = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fr = [0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fq: [u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fr: [u8] = &[0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; struct BigInt { pointer: u32, From 23d3a725017efb37c1f919ddfdd772715a0e36fc Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 8 Mar 2024 15:09:58 -0500 Subject: [PATCH 04/26] wip debugging: test slice index, got slice index working, slice-specific black box functions, stdlib building --- .../noirc_frontend/src/hir/type_check/expr.rs | 1 + compiler/noirc_frontend/src/tests.rs | 14 ++++- noir_stdlib/src/array.nr | 2 +- noir_stdlib/src/bigint.nr | 22 ++++---- noir_stdlib/src/collections/vec.nr | 2 +- noir_stdlib/src/hash.nr | 51 +++++++++++++++++-- noir_stdlib/src/hash/pedersen.nr | 6 +-- noir_stdlib/src/slice.nr | 3 ++ 8 files changed, 80 insertions(+), 21 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 7c143ff433c..cc7bfa09a13 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -572,6 +572,7 @@ impl<'interner> TypeChecker<'interner> { // XXX: We can check the array bounds here also, but it may be better to constant fold first // and have ConstId instead of ExprId for constants Type::Array(_, base_type) => *base_type, + Type::Slice(base_type) => *base_type, Type::Error => Type::Error, typ => { let span = self.interner.expr_span(&new_lhs); diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index bf2081355ad..5ae566509f9 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -915,8 +915,18 @@ mod test { assert(const_0(y) == x); } "#; - // assert!(get_program_errors(src).is_empty()); - assert!(get_program_errors(src) == vec![], "{:?}", get_program_errors(src)); + assert!(get_program_errors(src).is_empty()); + } + + #[test] + fn index_literal_slice() { + let src = r#" + fn main(x : Field) { + let y: [Field] = &[1, 2, 3]; + assert(y[0] == x); + } + "#; + assert!(get_program_errors(src).is_empty()); } #[test] diff --git a/noir_stdlib/src/array.nr b/noir_stdlib/src/array.nr index 3da4b649174..b5d1572537e 100644 --- a/noir_stdlib/src/array.nr +++ b/noir_stdlib/src/array.nr @@ -54,7 +54,7 @@ impl [T; N] { // Converts an array into a slice. pub fn as_slice(self) -> [T] { - let mut slice = []; + let mut slice = &[]; for elem in self { slice = slice.push_back(elem); } diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr index 23fb627e453..3afa50e5b6e 100644 --- a/noir_stdlib/src/bigint.nr +++ b/noir_stdlib/src/bigint.nr @@ -1,17 +1,17 @@ use crate::ops::{Add, Sub, Mul, Div}; use crate::cmp::Eq; -global bn254_fq = [0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, - 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30]; -global bn254_fr = [0x01, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x1F, 0x43, 0x09, 0x97, 0xB9, 0x79, 0x48, 0xE8, 0x33, 0x28, - 0x5D, 0x58, 0x81, 0x81, 0xB6, 0x45, 0x50, 0xB8, 0x29, 0xA0, 0x31, 0xE1, 0x72, 0x4E, 0x64, 0x30]; -global secpk1_fr = [0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpk1_fq = [0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fq: [u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fr: [u8] = &[0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, +global bn254_fq = &[0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30]; +global bn254_fr = &[0x01, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x1F, 0x43, 0x09, 0x97, 0xB9, 0x79, 0x48, 0xE8, 0x33, 0x28, + 0x5D, 0x58, 0x81, 0x81, 0xB6, 0x45, 0x50, 0xB8, 0x29, 0xA0, 0x31, 0xE1, 0x72, 0x4E, 0x64, 0x30]; +global secpk1_fr = &[0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpk1_fq = &[0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fq = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fr = &[0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; struct BigInt { diff --git a/noir_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr index deec98185ff..56354438c89 100644 --- a/noir_stdlib/src/collections/vec.nr +++ b/noir_stdlib/src/collections/vec.nr @@ -5,7 +5,7 @@ struct Vec { // A separate type is technically not needed but helps differentiate which operations are mutable. impl Vec { pub fn new() -> Self { - Self { slice: [] } + Self { slice: &[] } } // Create a Vec containing each element from the given slice. diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index fcf21436197..701525e00c1 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -11,18 +11,36 @@ pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 {} +#[foreign(sha256)] +// docs:start:sha256_slice +pub fn sha256_slice(input: [u8]) -> [u8; 32] +// docs:end:sha256_slice +{} + #[foreign(blake2s)] // docs:start:blake2s pub fn blake2s(input: [u8; N]) -> [u8; 32] // docs:end:blake2s {} +#[foreign(blake2s)] +// docs:start:blake2s_slice +pub fn blake2s_slice(input: [u8]) -> [u8; 32] +// docs:end:blake2s_slice +{} + #[foreign(blake3)] // docs:start:blake3 pub fn blake3(input: [u8; N]) -> [u8; 32] // docs:end:blake3 {} +#[foreign(blake3)] +// docs:start:blake3_slice +pub fn blake3_slice(input: [u8]) -> [u8; 32] +// docs:end:blake3_slice +{} + // docs:start:pedersen_commitment struct PedersenPoint { x : Field, @@ -43,6 +61,14 @@ pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) PedersenPoint { x: values[0], y: values[1] } } +#[foreign(pedersen_commitment)] +pub fn __pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> [Field; 2] {} + +pub fn pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> PedersenPoint { + let values = __pedersen_commitment_with_separator_slice(input, separator); + PedersenPoint { x: values[0], y: values[1] } +} + // docs:start:pedersen_hash pub fn pedersen_hash(input: [Field; N]) -> Field // docs:end:pedersen_hash @@ -50,11 +76,21 @@ pub fn pedersen_hash(input: [Field; N]) -> Field pedersen_hash_with_separator(input, 0) } +// docs:start:pedersen_hash_slice +pub fn pedersen_hash_slice(input: [Field]) -> Field +// docs:end:pedersen_hash_slice +{ + pedersen_hash_with_separator_slice(input, 0) +} + #[foreign(pedersen_hash)] pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} +#[foreign(pedersen_hash)] +pub fn pedersen_hash_with_separator_slice(input: [Field], separator: u32) -> Field {} + pub fn hash_to_field(input: [Field; N]) -> Field { - let mut inputs_as_bytes = []; + let mut inputs_as_bytes = &[]; for i in 0..N { let input_bytes = input[i].to_le_bytes(32); @@ -63,7 +99,7 @@ pub fn hash_to_field(input: [Field; N]) -> Field { } } - let hashed_input = blake2s(inputs_as_bytes); + let hashed_input = blake2s_slice(inputs_as_bytes); crate::field::bytes32_to_field(hashed_input) } @@ -73,9 +109,18 @@ pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} +#[foreign(keccak256)] +// docs:start:keccak256_slice +pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] +// docs:end:keccak256_slice +{} + #[foreign(poseidon2_permutation)] pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} +#[foreign(poseidon2_permutation)] +pub fn poseidon2_permutation_slice(_input: [Field], _state_length: u32) -> [Field] {} + #[foreign(sha256_compression)] pub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {} @@ -123,7 +168,7 @@ where // TODO: add implementations for the remainder of primitive types. impl Hash for Field{ fn hash(self, state: &mut H) where H: Hasher{ - let input: [Field] = [self]; + let input: [Field] = &[self]; H::write(state, input); } } diff --git a/noir_stdlib/src/hash/pedersen.nr b/noir_stdlib/src/hash/pedersen.nr index ace6851099d..ad21e728945 100644 --- a/noir_stdlib/src/hash/pedersen.nr +++ b/noir_stdlib/src/hash/pedersen.nr @@ -1,4 +1,4 @@ -use crate::hash::{Hasher, pedersen_hash}; +use crate::hash::{Hasher, pedersen_hash_slice}; use crate::default::Default; struct PedersenHasher{ @@ -7,7 +7,7 @@ struct PedersenHasher{ impl Hasher for PedersenHasher { fn finish(self) -> Field { - pedersen_hash(self._state) + pedersen_hash_slice(self._state) } fn write(&mut self, input: [Field]){ @@ -18,7 +18,7 @@ impl Hasher for PedersenHasher { impl Default for PedersenHasher{ fn default() -> Self{ PedersenHasher{ - _state: [] + _state: &[] } } } diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr index ea8d09d14ce..164b4f96cf6 100644 --- a/noir_stdlib/src/slice.nr +++ b/noir_stdlib/src/slice.nr @@ -1,4 +1,7 @@ impl [T] { + #[builtin(array_len)] + pub fn len(self) -> u64 {} + /// Push a new element to the end of the slice, returning a /// new slice with a length one greater than the /// original unmodified slice. From c683028c2218a0dba14a9c5ec598a595c7a8de3c Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Sun, 10 Mar 2024 22:15:36 -0400 Subject: [PATCH 05/26] got tests passing, update stdlib methods to take slices, fix missing type check case, updating test_programs, defaulting unknown array length to zero, cleanup debugging println, add utf8 decoding and serde error to execution json decoding error message, cargo clippy/fmt --- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 10 +-- .../src/hir/resolution/resolver.rs | 19 +++-- .../noirc_frontend/src/hir/type_check/expr.rs | 79 ++++++++++--------- .../noirc_frontend/src/hir/type_check/stmt.rs | 1 + compiler/noirc_frontend/src/hir_def/types.rs | 30 +++---- .../src/monomorphization/mod.rs | 11 +-- compiler/noirc_frontend/src/parser/parser.rs | 3 +- compiler/noirc_printable_type/src/lib.rs | 12 ++- noir_stdlib/src/ecdsa_secp256k1.nr | 4 +- noir_stdlib/src/ecdsa_secp256r1.nr | 4 +- noir_stdlib/src/hash.nr | 71 +++-------------- noir_stdlib/src/hash/pedersen.nr | 4 +- noir_stdlib/src/merkle.nr | 2 +- noir_stdlib/src/schnorr.nr | 4 +- noir_stdlib/src/sha512.nr | 2 +- .../intrinsic_die/src/main.nr | 2 +- .../compile_success_empty/vectors/src/main.nr | 2 +- test_programs/execution_success/6/src/main.nr | 4 +- test_programs/execution_success/7/src/main.nr | 2 +- .../array_dynamic_blackbox_input/src/main.nr | 2 +- .../src/main.nr | 2 +- .../execution_success/bigint/src/main.nr | 4 +- .../execution_success/blake3/src/main.nr | 2 +- .../brillig_blake2s/src/main.nr | 2 +- .../brillig_blake3/src/main.nr | 2 +- .../brillig_cow_regression/src/main.nr | 4 +- .../brillig_ecdsa_secp256k1/src/main.nr | 2 +- .../brillig_ecdsa_secp256r1/src/main.nr | 2 +- .../brillig_hash_to_field/src/main.nr | 2 +- .../brillig_keccak/src/main.nr | 4 +- .../brillig_pedersen/src/main.nr | 8 +- .../brillig_schnorr/src/main.nr | 2 +- .../brillig_sha256/src/main.nr | 2 +- .../brillig_slices/src/main.nr | 8 +- .../conditional_1/src/main.nr | 2 +- .../src/main.nr | 4 +- .../ecdsa_secp256k1/src/main.nr | 4 +- .../ecdsa_secp256r1/src/main.nr | 2 +- .../hash_to_field/src/main.nr | 2 +- .../execution_success/import/src/main.nr | 2 +- .../execution_success/keccak256/src/main.nr | 8 +- .../nested_array_in_slice/src/main.nr | 2 +- .../pedersen_check/src/main.nr | 8 +- .../pedersen_commitment/src/main.nr | 2 +- .../pedersen_hash/src/main.nr | 2 +- .../regression_4202/src/main.nr | 2 +- .../execution_success/schnorr/src/main.nr | 2 +- .../execution_success/sha256/src/main.nr | 2 +- .../execution_success/sha2_byte/src/main.nr | 2 +- .../simple_shield/src/main.nr | 6 +- .../slice_dynamic_index/src/main.nr | 2 +- .../execution_success/slices/src/main.nr | 33 ++++---- .../execution_success/strings/src/main.nr | 4 +- .../should_fail_with_matches/src/main.nr | 4 +- tooling/nargo/src/artifacts/debug_vars.rs | 15 +++- tooling/nargo_cli/build.rs | 4 +- tooling/nargo_fmt/src/rewrite/array.rs | 13 +-- 57 files changed, 195 insertions(+), 246 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 39013fa6e12..6d4c01ab0b2 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -194,10 +194,7 @@ impl<'a> FunctionContext<'a> { ast::Type::Array(_, _) => { self.codegen_array_checked(elements, typ[0].clone())? } - _ => unreachable!( - "ICE: unexpected array literal type, got {}", - array.typ - ), + _ => unreachable!("ICE: unexpected array literal type, got {}", array.typ), }) } ast::Literal::Slice(array) => { @@ -213,10 +210,7 @@ impl<'a> FunctionContext<'a> { self.codegen_array_checked(elements, typ[1].clone())?; Tree::Branch(vec![slice_length.into(), slice_contents]) } - _ => unreachable!( - "ICE: unexpected slice literal type, got {}", - array.typ - ), + _ => unreachable!("ICE: unexpected slice literal type, got {}", array.typ), }) } ast::Literal::Integer(value, typ, location) => { diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 96fcc1a43d4..3928235dfcd 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1400,21 +1400,20 @@ impl<'a> Resolver<'a> { ArrayLiteral::Standard(elements) => { let elements = vecmap(elements, |elem| self.resolve_expression(elem)); HirArrayLiteral::Standard(elements) - }, + } ArrayLiteral::Repeated { repeated_element, length } => { let span = length.span; - let length = UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else( - |error| { + let length = + UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else(|error| { self.errors.push(ResolverError::ParserError(Box::new(error))); UnresolvedTypeExpression::Constant(0, span) - }, - ); + }); let length = self.convert_expression_type(length); let repeated_element = self.resolve_expression(*repeated_element); HirArrayLiteral::Repeated { repeated_element, length } - }, + } } } @@ -1422,8 +1421,12 @@ impl<'a> Resolver<'a> { let hir_expr = match expr.kind { ExpressionKind::Literal(literal) => HirExpression::Literal(match literal { Literal::Bool(b) => HirLiteral::Bool(b), - Literal::Array(array_literal) => HirLiteral::Array(self.resolve_array_literal(array_literal)), - Literal::Slice(array_literal) => HirLiteral::Slice(self.resolve_array_literal(array_literal)), + Literal::Array(array_literal) => { + HirLiteral::Array(self.resolve_array_literal(array_literal)) + } + Literal::Slice(array_literal) => { + HirLiteral::Slice(self.resolve_array_literal(array_literal)) + } Literal::Integer(integer, sign) => HirLiteral::Integer(integer, sign), Literal::Str(str) => HirLiteral::Str(str), Literal::RawStr(str, _) => HirLiteral::Str(str), diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index cc7bfa09a13..a3c31366886 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -48,7 +48,10 @@ impl<'interner> TypeChecker<'interner> { false } - fn check_hir_array_literal(&mut self, hir_array_literal: HirArrayLiteral) -> (Result, u64>, Box) { + fn check_hir_array_literal( + &mut self, + hir_array_literal: HirArrayLiteral, + ) -> (Result, u64>, Box) { match hir_array_literal { HirArrayLiteral::Standard(arr) => { let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); @@ -75,21 +78,16 @@ impl<'interner> TypeChecker<'interner> { }); } - ( - Err(arr.len() as u64), - Box::new(first_elem_type.clone()) - ) - }, + (Err(arr.len() as u64), Box::new(first_elem_type.clone())) + } HirArrayLiteral::Repeated { repeated_element, length } => { let elem_type = self.check_expression(&repeated_element); let length = match length { - Type::Constant(length) => { - Err(length) - } + Type::Constant(length) => Err(length), other => Ok(Box::new(other)), }; (length, Box::new(elem_type)) - }, + } } } @@ -104,38 +102,41 @@ impl<'interner> TypeChecker<'interner> { pub(crate) fn check_expression(&mut self, expr_id: &ExprId) -> Type { let typ = match self.interner.expression(expr_id) { HirExpression::Ident(ident) => self.check_ident(ident, expr_id), - HirExpression::Literal(literal) => { - match literal { - HirLiteral::Array(hir_array_literal) => { - let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); - Type::Array(length.unwrap_or_else(|constant| Box::new(Type::constant_variable(constant, self.interner))), elem_type) - }, - HirLiteral::Slice(hir_array_literal) => { - let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); - match length_type { - Ok(_non_constant) => { - self.errors.push(TypeCheckError::NonConstantSliceLength { - span: self.interner.expr_span(expr_id), - }); - Type::Error - }, - Err(_length) => Type::Slice(elem_type), + HirExpression::Literal(literal) => match literal { + HirLiteral::Array(hir_array_literal) => { + let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); + Type::Array( + length.unwrap_or_else(|constant| { + Box::new(Type::constant_variable(constant, self.interner)) + }), + elem_type, + ) + } + HirLiteral::Slice(hir_array_literal) => { + let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); + match length_type { + Ok(_non_constant) => { + self.errors.push(TypeCheckError::NonConstantSliceLength { + span: self.interner.expr_span(expr_id), + }); + Type::Error } - }, - HirLiteral::Bool(_) => Type::Bool, - HirLiteral::Integer(_, _) => Type::polymorphic_integer_or_field(self.interner), - HirLiteral::Str(string) => { - let len = Type::Constant(string.len() as u64); - Type::String(Box::new(len)) + Err(_length) => Type::Slice(elem_type), } - HirLiteral::FmtStr(string, idents) => { - let len = Type::Constant(string.len() as u64); - let types = vecmap(&idents, |elem| self.check_expression(elem)); - Type::FmtString(Box::new(len), Box::new(Type::Tuple(types))) - } - HirLiteral::Unit => Type::Unit, } - } + HirLiteral::Bool(_) => Type::Bool, + HirLiteral::Integer(_, _) => Type::polymorphic_integer_or_field(self.interner), + HirLiteral::Str(string) => { + let len = Type::Constant(string.len() as u64); + Type::String(Box::new(len)) + } + HirLiteral::FmtStr(string, idents) => { + let len = Type::Constant(string.len() as u64); + let types = vecmap(&idents, |elem| self.check_expression(elem)); + Type::FmtString(Box::new(len), Box::new(Type::Tuple(types))) + } + HirLiteral::Unit => Type::Unit, + }, HirExpression::Infix(infix_expr) => { // The type of the infix expression must be looked up from a type table let lhs_type = self.check_expression(&infix_expr.lhs); diff --git a/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/compiler/noirc_frontend/src/hir/type_check/stmt.rs index 358bea86922..2fb0522623c 100644 --- a/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -256,6 +256,7 @@ impl<'interner> TypeChecker<'interner> { let typ = match lvalue_type.follow_bindings() { Type::Array(_, elem_type) => *elem_type, + Type::Slice(elem_type) => *elem_type, Type::Error => Type::Error, other => { // TODO: Need a better span here diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 3f7eba598db..05fe706192a 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -156,9 +156,7 @@ impl Type { pub(crate) fn is_nested_slice(&self) -> bool { match self { Type::Slice(elem) => elem.as_ref().contains_slice(), - Type::Array(_, elem) => { - elem.as_ref().contains_slice() - } + Type::Array(_, elem) => elem.as_ref().contains_slice(), _ => false, } } @@ -636,9 +634,7 @@ impl Type { Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) } - Type::Slice(elem) => { - elem.contains_numeric_typevar(target_id) - } + Type::Slice(elem) => elem.contains_numeric_typevar(target_id), Type::Tuple(fields) => { fields.iter().any(|field| field.contains_numeric_typevar(target_id)) } @@ -1152,9 +1148,7 @@ impl Type { elem_a.try_unify(elem_b, bindings) } - (Slice(elem_a), Slice(elem_b)) => { - elem_a.try_unify(elem_b, bindings) - } + (Slice(elem_a), Slice(elem_b)) => elem_a.try_unify(elem_b, bindings), (String(len_a), String(len_b)) => len_a.try_unify(len_b, bindings), @@ -1304,7 +1298,7 @@ impl Type { let length = size.follow_bindings(); // If we have an array and our target is a slice - if matches!(length, Type::Constant(_)) { + if matches!(length, Type::Constant(_)) { // Still have to ensure the element types match. // Don't need to issue an error here if not, it will be done in unify_with_coercions let mut bindings = TypeBindings::new(); @@ -1600,9 +1594,7 @@ impl Type { Array(size, elem) => { Array(Box::new(size.follow_bindings()), Box::new(elem.follow_bindings())) } - Slice(elem) => { - Slice(Box::new(elem.follow_bindings())) - } + Slice(elem) => Slice(Box::new(elem.follow_bindings())), String(size) => String(Box::new(size.follow_bindings())), FmtString(size, args) => { let size = Box::new(size.follow_bindings()); @@ -1637,13 +1629,9 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - TraitAsType(..) - | FieldElement - | Integer(_, _) - | Bool - | Constant(_) - | Unit - | Error => self.clone(), + TraitAsType(..) | FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Error => { + self.clone() + } } } @@ -1725,7 +1713,7 @@ impl From<&Type> for PrintableType { } Type::Slice(typ) => { let typ = typ.as_ref(); - PrintableType::Slice{ typ: Box::new(typ.into()) } + PrintableType::Slice { typ: Box::new(typ.into()) } } Type::Integer(sign, bit_width) => match sign { Signedness::Unsigned => { diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 5a8af4c699f..d28f9056f1f 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -868,9 +868,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Array(length, element) => { let element = Box::new(self.convert_type(element.as_ref())); // TODO: convert to MonomorphizationError - let length = length.evaluate_to_u64().unwrap_or_else(|| { - panic!("Length of generic array could not be determined.") - }); + let length = length.evaluate_to_u64().unwrap_or(0); ast::Type::Array(length, element) } HirType::Slice(element) => { @@ -950,9 +948,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::MutableReference(Box::new(element)) } - HirType::Forall(_, _) - | HirType::Constant(_) - | HirType::Error => { + HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { unreachable!("Unexpected type {} found", typ) } } @@ -1236,9 +1232,6 @@ impl<'interner> Monomorphizer<'interner> { ) -> ast::Expression { use ast::*; - // TODO: remove - println!("modulus_array_literal: {:?}, {:?}, {:?}", bytes, arr_elem_bits, location); - let int_type = Type::Integer(crate::Signedness::Unsigned, arr_elem_bits); let bytes_as_expr = vecmap(bytes, |byte| { diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 30948267384..86df57f9f7b 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -1081,7 +1081,8 @@ fn slice_expr

(expr_parser: P) -> impl NoirParser where P: ExprParser, { - just(Token::Ampersand).ignore_then(standard_slice(expr_parser.clone()).or(slice_sugar(expr_parser))) + just(Token::Ampersand) + .ignore_then(standard_slice(expr_parser.clone()).or(slice_sugar(expr_parser))) } /// &[a, b, c, ...] diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 9abc993606b..44877b5d990 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -52,10 +52,7 @@ pub enum PrintableType { pub enum PrintableValue { Field(FieldElement), String(String), - Vec { - array_elements: Vec, - is_slice: bool, - }, + Vec { array_elements: Vec, is_slice: bool }, Struct(BTreeMap), Other, } @@ -353,9 +350,10 @@ pub fn decode_value( PrintableValue::Vec { array_elements, is_slice: true } } - PrintableType::Tuple { types } => { - PrintableValue::Vec { array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), is_slice: false } - } + PrintableType::Tuple { types } => PrintableValue::Vec { + array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), + is_slice: false, + }, PrintableType::String { length } => { let field_elements: Vec = field_iterator.take(*length as usize).collect(); diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index b72a1acd041..79510dc0e5e 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,10 +1,10 @@ #[foreign(ecdsa_secp256k1)] // docs:start:ecdsa_secp256k1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8; N] + message_hash: [u8] ) -> bool // docs:end:ecdsa_secp256k1 {} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index ef92bf24ae4..8085693bde2 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,10 +1,10 @@ #[foreign(ecdsa_secp256r1)] // docs:start:ecdsa_secp256r1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8; N] + message_hash: [u8] ) -> bool // docs:end:ecdsa_secp256r1 {} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 701525e00c1..da5cc3f63cf 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -7,120 +7,75 @@ use crate::default::Default; #[foreign(sha256)] // docs:start:sha256 -pub fn sha256(input: [u8; N]) -> [u8; 32] +pub fn sha256(input: [u8]) -> [u8; 32] // docs:end:sha256 {} -#[foreign(sha256)] -// docs:start:sha256_slice -pub fn sha256_slice(input: [u8]) -> [u8; 32] -// docs:end:sha256_slice -{} - #[foreign(blake2s)] // docs:start:blake2s -pub fn blake2s(input: [u8; N]) -> [u8; 32] +pub fn blake2s(input: [u8]) -> [u8; 32] // docs:end:blake2s {} -#[foreign(blake2s)] -// docs:start:blake2s_slice -pub fn blake2s_slice(input: [u8]) -> [u8; 32] -// docs:end:blake2s_slice -{} - #[foreign(blake3)] // docs:start:blake3 -pub fn blake3(input: [u8; N]) -> [u8; 32] +pub fn blake3(input: [u8]) -> [u8; 32] // docs:end:blake3 {} -#[foreign(blake3)] -// docs:start:blake3_slice -pub fn blake3_slice(input: [u8]) -> [u8; 32] -// docs:end:blake3_slice -{} - // docs:start:pedersen_commitment struct PedersenPoint { x : Field, y : Field, } -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint +pub fn pedersen_commitment(input: [Field]) -> PedersenPoint // docs:end:pedersen_commitment { pedersen_commitment_with_separator(input, 0) } #[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} +pub fn __pedersen_commitment_with_separator(input: [Field], separator: u32) -> [Field; 2] {} -pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { +pub fn pedersen_commitment_with_separator(input: [Field], separator: u32) -> PedersenPoint { let values = __pedersen_commitment_with_separator(input, separator); PedersenPoint { x: values[0], y: values[1] } } -#[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> [Field; 2] {} - -pub fn pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> PedersenPoint { - let values = __pedersen_commitment_with_separator_slice(input, separator); - PedersenPoint { x: values[0], y: values[1] } -} - // docs:start:pedersen_hash -pub fn pedersen_hash(input: [Field; N]) -> Field +pub fn pedersen_hash(input: [Field]) -> Field // docs:end:pedersen_hash { pedersen_hash_with_separator(input, 0) } -// docs:start:pedersen_hash_slice -pub fn pedersen_hash_slice(input: [Field]) -> Field -// docs:end:pedersen_hash_slice -{ - pedersen_hash_with_separator_slice(input, 0) -} - -#[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} - #[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator_slice(input: [Field], separator: u32) -> Field {} +pub fn pedersen_hash_with_separator(input: [Field], separator: u32) -> Field {} -pub fn hash_to_field(input: [Field; N]) -> Field { +pub fn hash_to_field(inputs: [Field]) -> Field { let mut inputs_as_bytes = &[]; - for i in 0..N { - let input_bytes = input[i].to_le_bytes(32); + for input in inputs { + let input_bytes = input.to_le_bytes(32); for i in 0..32 { inputs_as_bytes = inputs_as_bytes.push_back(input_bytes[i]); } } - let hashed_input = blake2s_slice(inputs_as_bytes); + let hashed_input = blake2s(inputs_as_bytes); crate::field::bytes32_to_field(hashed_input) } #[foreign(keccak256)] // docs:start:keccak256 -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} -#[foreign(keccak256)] -// docs:start:keccak256_slice -pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] -// docs:end:keccak256_slice -{} - #[foreign(poseidon2_permutation)] pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} -#[foreign(poseidon2_permutation)] -pub fn poseidon2_permutation_slice(_input: [Field], _state_length: u32) -> [Field] {} - #[foreign(sha256_compression)] pub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {} diff --git a/noir_stdlib/src/hash/pedersen.nr b/noir_stdlib/src/hash/pedersen.nr index ad21e728945..09e436a32ae 100644 --- a/noir_stdlib/src/hash/pedersen.nr +++ b/noir_stdlib/src/hash/pedersen.nr @@ -1,4 +1,4 @@ -use crate::hash::{Hasher, pedersen_hash_slice}; +use crate::hash::{Hasher, pedersen_hash}; use crate::default::Default; struct PedersenHasher{ @@ -7,7 +7,7 @@ struct PedersenHasher{ impl Hasher for PedersenHasher { fn finish(self) -> Field { - pedersen_hash_slice(self._state) + pedersen_hash(self._state) } fn write(&mut self, input: [Field]){ diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr index 9b15fe7313d..ba65b1adae5 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -13,7 +13,7 @@ pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) } else { (current, hash_path[i]) }; - current = crate::hash::pedersen_hash([hash_left, hash_right]); + current = crate::hash::pedersen_hash([hash_left, hash_right].as_slice()); } current } diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 757963d40d7..024f47e63e8 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -1,10 +1,10 @@ #[foreign(schnorr_verify)] // docs:start:schnorr_verify -pub fn verify_signature( +pub fn verify_signature( public_key_x: Field, public_key_y: Field, signature: [u8; 64], - message: [u8; N] + message: [u8] ) -> bool // docs:end:schnorr_verify {} diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 4dfe78308e2..39009bd0651 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -85,7 +85,7 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { msg64 } // SHA-512 hash function -pub fn digest(msg: [u8; N]) -> [u8; 64] { +pub fn digest(msg: [u8]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; // noir-fmt:ignore let mut h: [u64; 8] = [7640891576956012808, 13503953896175478587, 4354685564936845355, 11912009170470909681, 5840696475078001361, 11170449401992604703, 2270897969802886507, 6620516959819538809]; // Intermediate hash, starting with the canonical initial value diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr index 8cac707dfea..8963073859a 100644 --- a/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -1,6 +1,6 @@ use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { - let hash = std::hash::pedersen_commitment([x]); + let hash = std::hash::pedersen_commitment([x].as_slice()); let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); } diff --git a/test_programs/compile_success_empty/vectors/src/main.nr b/test_programs/compile_success_empty/vectors/src/main.nr index 28187a4f619..d105ceed180 100644 --- a/test_programs/compile_success_empty/vectors/src/main.nr +++ b/test_programs/compile_success_empty/vectors/src/main.nr @@ -26,7 +26,7 @@ fn main(x: Field, y: pub Field) { assert(vector.get(3) == 3); assert(vector.len() == 4); - let mut inputs_vector = Vec::from_slice([x, y]); + let mut inputs_vector = Vec::from_slice(&[x, y]); assert(inputs_vector.get(0) == x); assert(inputs_vector.get(1) == y); } diff --git a/test_programs/execution_success/6/src/main.nr b/test_programs/execution_success/6/src/main.nr index 5ecb809e68b..294d406637a 100644 --- a/test_programs/execution_success/6/src/main.nr +++ b/test_programs/execution_success/6/src/main.nr @@ -8,9 +8,9 @@ use dep::std; fn main(x: [u8; 5], result: pub [u8; 32]) { - let mut digest = std::hash::sha256(x); + let mut digest = std::hash::sha256(x.as_slice()); digest[0] = 5 as u8; - digest = std::hash::sha256(x); + digest = std::hash::sha256(x.as_slice()); assert(digest == result); let y = [12, 45, 78, 41]; diff --git a/test_programs/execution_success/7/src/main.nr b/test_programs/execution_success/7/src/main.nr index a6bba978644..996a3b24f24 100644 --- a/test_programs/execution_success/7/src/main.nr +++ b/test_programs/execution_success/7/src/main.nr @@ -5,6 +5,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake2s(x); + let digest = std::hash::blake2s(x.as_slice()); assert(digest == result); } diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr index 4cbf1bd8e6d..a936f1d5c4a 100644 --- a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr @@ -18,7 +18,7 @@ fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { hash_input[j + b] = path[offset + j]; } - current = dep::std::hash::sha256(hash_input); + current = dep::std::hash::sha256(hash_input.as_slice()); index = index >> 1; } diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr index 8faaf69dfc8..7c92890e950 100644 --- a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr @@ -15,6 +15,6 @@ fn main(mut x: [Foo; 3], y: pub Field, hash_result: pub [u8; 32]) { // Make sure that we are passing a dynamic array to the black box function call // by setting the array using a dynamic index here hash_input[y - 1] = 0; - let hash = dep::std::hash::sha256(hash_input); + let hash = dep::std::hash::sha256(hash_input.as_slice()); assert_eq(hash, hash_result); } diff --git a/test_programs/execution_success/bigint/src/main.nr b/test_programs/execution_success/bigint/src/main.nr index b93fec370e5..9ca612baf63 100644 --- a/test_programs/execution_success/bigint/src/main.nr +++ b/test_programs/execution_success/bigint/src/main.nr @@ -1,8 +1,8 @@ use dep::std::bigint; fn main(mut x: [u8; 5], y: [u8; 5]) { - let a = bigint::Secpk1Fq::from_le_bytes([x[0], x[1], x[2], x[3], x[4]]); - let b = bigint::Secpk1Fq::from_le_bytes([y[0], y[1], y[2], y[3], y[4]]); + let a = bigint::Secpk1Fq::from_le_bytes(&[x[0], x[1], x[2], x[3], x[4]]); + let b = bigint::Secpk1Fq::from_le_bytes(&[y[0], y[1], y[2], y[3], y[4]]); let a_bytes = a.to_le_bytes(); let b_bytes = b.to_le_bytes(); for i in 0..5 { diff --git a/test_programs/execution_success/blake3/src/main.nr b/test_programs/execution_success/blake3/src/main.nr index 3bfea6c5f95..7a9810b6abc 100644 --- a/test_programs/execution_success/blake3/src/main.nr +++ b/test_programs/execution_success/blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3(x); + let digest = std::hash::blake3(x.as_slice()); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_blake2s/src/main.nr b/test_programs/execution_success/brillig_blake2s/src/main.nr index 5bd52666ae9..b358fa8236b 100644 --- a/test_programs/execution_success/brillig_blake2s/src/main.nr +++ b/test_programs/execution_success/brillig_blake2s/src/main.nr @@ -7,5 +7,5 @@ fn main(x: [u8; 5], result: [u8; 32]) { } unconstrained fn blake2s(x: [u8; 5]) -> [u8; 32] { - std::hash::blake2s(x) + std::hash::blake2s(x.as_slice()) } diff --git a/test_programs/execution_success/brillig_blake3/src/main.nr b/test_programs/execution_success/brillig_blake3/src/main.nr index 05a5b31f936..30dc2fb46a2 100644 --- a/test_programs/execution_success/brillig_blake3/src/main.nr +++ b/test_programs/execution_success/brillig_blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; unconstrained fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3(x); + let digest = std::hash::blake3(x.as_slice()); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_cow_regression/src/main.nr b/test_programs/execution_success/brillig_cow_regression/src/main.nr index ba51548d9dd..e2a8ff2fb35 100644 --- a/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -25,7 +25,7 @@ struct NewContractData { impl NewContractData { fn hash(self) -> Field { - dep::std::hash::pedersen_hash([self.contract_address, self.portal_contract_address]) + dep::std::hash::pedersen_hash(&[self.contract_address, self.portal_contract_address]) } } @@ -173,6 +173,6 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA } } - let sha_digest = dep::std::hash::sha256(hash_input_flattened); + let sha_digest = dep::std::hash::sha256(hash_input_flattened.as_slice()); U256::from_bytes32(sha_digest).to_u128_limbs() } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr index 5d84d885567..64af1132aff 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) + std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()) } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr index 9da07f531aa..c96261858fb 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) + std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()) } diff --git a/test_programs/execution_success/brillig_hash_to_field/src/main.nr b/test_programs/execution_success/brillig_hash_to_field/src/main.nr index 4b4177a521e..53ed85b3ddd 100644 --- a/test_programs/execution_success/brillig_hash_to_field/src/main.nr +++ b/test_programs/execution_success/brillig_hash_to_field/src/main.nr @@ -7,5 +7,5 @@ fn main(input: Field) -> pub Field { } unconstrained fn hash_to_field(input: Field) -> Field { - std::hash::hash_to_field([input]) + std::hash::hash_to_field(&[input]) } diff --git a/test_programs/execution_success/brillig_keccak/src/main.nr b/test_programs/execution_success/brillig_keccak/src/main.nr index 1e9b65a6eb4..641ba485094 100644 --- a/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/test_programs/execution_success/brillig_keccak/src/main.nr @@ -7,7 +7,7 @@ fn main(x: Field, result: [u8; 32]) { // The padding is taken care of by the program let digest = keccak256([x as u8], 1); assert(digest == result); - //#1399: variable meesage size + //#1399: variable message size let message_size = 4; let hash_a = keccak256([1, 2, 3, 4], message_size); let hash_b = keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); @@ -21,5 +21,5 @@ fn main(x: Field, result: [u8; 32]) { } unconstrained fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { - std::hash::keccak256(data, msg_len) + std::hash::keccak256(data.as_slice(), msg_len) } diff --git a/test_programs/execution_success/brillig_pedersen/src/main.nr b/test_programs/execution_success/brillig_pedersen/src/main.nr index 2379818c454..3a23a7b3de6 100644 --- a/test_programs/execution_success/brillig_pedersen/src/main.nr +++ b/test_programs/execution_success/brillig_pedersen/src/main.nr @@ -1,11 +1,11 @@ use dep::std; unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment_with_separator([x, y], 0); + let res = std::hash::pedersen_commitment_with_separator(&[x, y], 0); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator(&[x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Fiel state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment_with_separator([state], 0); - assert(std::hash::pedersen_commitment_with_separator([43], 0).x == hash.x); + let hash = std::hash::pedersen_commitment_with_separator(&[state], 0); + assert(std::hash::pedersen_commitment_with_separator(&[43], 0).x == hash.x); } diff --git a/test_programs/execution_success/brillig_schnorr/src/main.nr b/test_programs/execution_success/brillig_schnorr/src/main.nr index 4cc79ae7e07..4c7ec16887e 100644 --- a/test_programs/execution_success/brillig_schnorr/src/main.nr +++ b/test_programs/execution_success/brillig_schnorr/src/main.nr @@ -20,6 +20,6 @@ unconstrained fn main( let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message.as_slice()); assert(valid_signature); } diff --git a/test_programs/execution_success/brillig_sha256/src/main.nr b/test_programs/execution_success/brillig_sha256/src/main.nr index e76109df9c3..953bfe05644 100644 --- a/test_programs/execution_success/brillig_sha256/src/main.nr +++ b/test_programs/execution_success/brillig_sha256/src/main.nr @@ -9,6 +9,6 @@ fn main(x: Field, result: [u8; 32]) { unconstrained fn sha256(x: Field) -> [u8; 32] { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - std::hash::sha256([x as u8]) + std::hash::sha256(&[x as u8]) } diff --git a/test_programs/execution_success/brillig_slices/src/main.nr b/test_programs/execution_success/brillig_slices/src/main.nr index 847c41de25c..2cf1850f151 100644 --- a/test_programs/execution_success/brillig_slices/src/main.nr +++ b/test_programs/execution_success/brillig_slices/src/main.nr @@ -1,6 +1,6 @@ use dep::std::slice; unconstrained fn main(x: Field, y: Field) { - let mut slice: [Field] = [y, x]; + let mut slice: [Field] = &[y, x]; assert(slice.len() == 2); slice = slice.push_back(7); @@ -108,7 +108,7 @@ unconstrained fn merge_slices_else(x: Field) { } // Test returning a merged slice without a mutation unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] { - let slice = [0; 2]; + let slice = &[0; 2]; if x != y { if x != 20 { slice.push_back(y) } else { slice } } else { @@ -117,7 +117,7 @@ unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] { } // Test mutating a slice inside of an if statement unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -128,7 +128,7 @@ unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { } // Test mutating a slice inside of a loop in an if statement unconstrained fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { for i in 0..5 { slice = slice.push_back(i as Field); diff --git a/test_programs/execution_success/conditional_1/src/main.nr b/test_programs/execution_success/conditional_1/src/main.nr index 5064c82bce9..f49c24579ba 100644 --- a/test_programs/execution_success/conditional_1/src/main.nr +++ b/test_programs/execution_success/conditional_1/src/main.nr @@ -55,7 +55,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { let mut y = 0; if a == 0 { - let digest = std::hash::sha256(x); + let digest = std::hash::sha256(x.as_slice()); y = digest[0]; } else { y = 5; diff --git a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr index d260fa49dc3..7eeefae16e9 100644 --- a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr +++ b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr @@ -26,9 +26,9 @@ fn bar(x: Field) { } fn call_intrinsic(x: [u8; 5], result: [u8; 32]) { - let mut digest = std::hash::sha256(x); + let mut digest = std::hash::sha256(x.as_slice()); digest[0] = 5 as u8; - digest = std::hash::sha256(x); + digest = std::hash::sha256(x.as_slice()); assert(digest == result); } diff --git a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr index ac0359e4bb8..d9ffef69644 100644 --- a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -8,9 +8,9 @@ fn main( signature: [u8; 64] ) { // Hash the message, since secp256k1 expects a hashed_message - let expected = std::hash::sha256(message); + let expected = std::hash::sha256(message.as_slice()); assert(hashed_message == expected); - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); assert(valid_signature); } diff --git a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr index c64e390d652..dda6d688a60 100644 --- a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); assert(valid_signature); } diff --git a/test_programs/execution_success/hash_to_field/src/main.nr b/test_programs/execution_success/hash_to_field/src/main.nr index 5af1c5af55e..242b5ecbc18 100644 --- a/test_programs/execution_success/hash_to_field/src/main.nr +++ b/test_programs/execution_success/hash_to_field/src/main.nr @@ -1,5 +1,5 @@ use dep::std; fn main(input: Field) -> pub Field { - std::hash::hash_to_field([input]) + std::hash::hash_to_field(&[input]) } diff --git a/test_programs/execution_success/import/src/main.nr b/test_programs/execution_success/import/src/main.nr index 7dcc16fed16..85e7b0c2dfa 100644 --- a/test_programs/execution_success/import/src/main.nr +++ b/test_programs/execution_success/import/src/main.nr @@ -2,7 +2,7 @@ mod import; use crate::import::hello; fn main(x: Field, y: Field) { - let _k = dep::std::hash::pedersen_commitment([x]); + let _k = dep::std::hash::pedersen_commitment(&[x]); let _l = hello(x); assert(x != import::hello(y)); diff --git a/test_programs/execution_success/keccak256/src/main.nr b/test_programs/execution_success/keccak256/src/main.nr index eb401fe614c..24f1695c67d 100644 --- a/test_programs/execution_success/keccak256/src/main.nr +++ b/test_programs/execution_success/keccak256/src/main.nr @@ -4,18 +4,18 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::keccak256([x as u8], 1); + let digest = std::hash::keccak256(&[x as u8], 1); assert(digest == result); //#1399: variable message size let message_size = 4; - let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); + let hash_a = std::hash::keccak256(&[1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256(&[1, 2, 3, 4, 0, 0, 0, 0], message_size); assert(hash_a == hash_b); let message_size_big = 8; - let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + let hash_c = std::hash::keccak256(&[1, 2, 3, 4, 0, 0, 0, 0], message_size_big); assert(hash_a != hash_c); } diff --git a/test_programs/execution_success/nested_array_in_slice/src/main.nr b/test_programs/execution_success/nested_array_in_slice/src/main.nr index a3007d5d0dc..0890115e95a 100644 --- a/test_programs/execution_success/nested_array_in_slice/src/main.nr +++ b/test_programs/execution_success/nested_array_in_slice/src/main.nr @@ -13,7 +13,7 @@ fn main(y: Field) { let foo_two = Foo { a: 4, b: [5, 6, 21], bar: Bar { inner: [103, 104, 105] } }; let foo_three = Foo { a: 7, b: [8, 9, 22], bar: Bar { inner: [106, 107, 108] } }; let foo_four = Foo { a: 10, b: [11, 12, 23], bar: Bar { inner: [109, 110, 111] } }; - let mut x = [foo_one]; + let mut x = &[foo_one]; x = x.push_back(foo_two); x = x.push_back(foo_three); x = x.push_back(foo_four); diff --git a/test_programs/execution_success/pedersen_check/src/main.nr b/test_programs/execution_success/pedersen_check/src/main.nr index 90ef218249b..16e3841ea25 100644 --- a/test_programs/execution_success/pedersen_check/src/main.nr +++ b/test_programs/execution_success/pedersen_check/src/main.nr @@ -1,11 +1,11 @@ use dep::std; fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment([x, y]); + let res = std::hash::pedersen_commitment(&[x, y]); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator(&[x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: F state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment([state]); - assert(std::hash::pedersen_commitment([43]).x == hash.x); + let hash = std::hash::pedersen_commitment(&[state]); + assert(std::hash::pedersen_commitment(&[43]).x == hash.x); } diff --git a/test_programs/execution_success/pedersen_commitment/src/main.nr b/test_programs/execution_success/pedersen_commitment/src/main.nr index 83cbe20851d..4d07cbffbe6 100644 --- a/test_programs/execution_success/pedersen_commitment/src/main.nr +++ b/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment([x, y]); + let commitment = std::hash::pedersen_commitment(&[x, y]); assert_eq(commitment.x, expected_commitment.x); assert_eq(commitment.y, expected_commitment.y); } diff --git a/test_programs/execution_success/pedersen_hash/src/main.nr b/test_programs/execution_success/pedersen_hash/src/main.nr index 20c7de12d6c..d97495ce3b7 100644 --- a/test_programs/execution_success/pedersen_hash/src/main.nr +++ b/test_programs/execution_success/pedersen_hash/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash([x, y]); + let hash = std::hash::pedersen_hash(&[x, y]); assert_eq(hash, expected_hash); } // docs:end:pedersen-hash diff --git a/test_programs/execution_success/regression_4202/src/main.nr b/test_programs/execution_success/regression_4202/src/main.nr index 37d2ee4578d..faa14f03912 100644 --- a/test_programs/execution_success/regression_4202/src/main.nr +++ b/test_programs/execution_success/regression_4202/src/main.nr @@ -1,5 +1,5 @@ fn main(input: [u32; 4]) { - let mut slice1: [u32] = [1, 2, 3, 4]; + let mut slice1: [u32] = &[1, 2, 3, 4]; if slice1[0] == 3 { slice1[1] = 4; } diff --git a/test_programs/execution_success/schnorr/src/main.nr b/test_programs/execution_success/schnorr/src/main.nr index 107af152625..4e4e602595c 100644 --- a/test_programs/execution_success/schnorr/src/main.nr +++ b/test_programs/execution_success/schnorr/src/main.nr @@ -20,6 +20,6 @@ fn main( let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message.as_slice()); assert(valid_signature); } diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index fd5340e2384..5bdd04ff9f4 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -14,6 +14,6 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::sha256([x as u8]); + let digest = std::hash::sha256(&[x as u8]); assert(digest == result); } diff --git a/test_programs/execution_success/sha2_byte/src/main.nr b/test_programs/execution_success/sha2_byte/src/main.nr index fa8ddfbdf69..0a24a9dc98e 100644 --- a/test_programs/execution_success/sha2_byte/src/main.nr +++ b/test_programs/execution_success/sha2_byte/src/main.nr @@ -5,6 +5,6 @@ fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { let digest256 = std::sha256::digest([x as u8]); assert(digest256 == result256); - let digest512 = std::sha512::digest([x as u8]); + let digest512 = std::sha512::digest(&[x as u8]); assert(digest512 == result512); } diff --git a/test_programs/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr index c46d3b4594c..e33326ab749 100644 --- a/test_programs/execution_success/simple_shield/src/main.nr +++ b/test_programs/execution_success/simple_shield/src/main.nr @@ -17,11 +17,11 @@ fn main( let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; // Compute input note commitment - let note_commitment = std::hash::pedersen_commitment([pubkey_x, pubkey_y]); + let note_commitment = std::hash::pedersen_commitment(&[pubkey_x, pubkey_y]); // Compute input note nullifier - let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); + let nullifier = std::hash::pedersen_commitment(&[note_commitment.x, index, priv_key]); // Compute output note nullifier - let receiver_note_commitment = std::hash::pedersen_commitment([to_pubkey_x, to_pubkey_y]); + let receiver_note_commitment = std::hash::pedersen_commitment(&[to_pubkey_x, to_pubkey_y]); // Check that the input note nullifier is in the root assert(note_root == std::merkle::compute_merkle_root(note_commitment.x, index, note_hash_path)); diff --git a/test_programs/execution_success/slice_dynamic_index/src/main.nr b/test_programs/execution_success/slice_dynamic_index/src/main.nr index 41fc9a645c1..9b97c0721bb 100644 --- a/test_programs/execution_success/slice_dynamic_index/src/main.nr +++ b/test_programs/execution_success/slice_dynamic_index/src/main.nr @@ -4,7 +4,7 @@ fn main(x: Field) { } fn regression_dynamic_slice_index(x: Field, y: Field) { - let mut slice = []; + let mut slice = &[]; for i in 0..5 { slice = slice.push_back(i as Field); } diff --git a/test_programs/execution_success/slices/src/main.nr b/test_programs/execution_success/slices/src/main.nr index eca42a660c4..0d253c8b2b2 100644 --- a/test_programs/execution_success/slices/src/main.nr +++ b/test_programs/execution_success/slices/src/main.nr @@ -2,7 +2,7 @@ use dep::std::slice; use dep::std; fn main(x: Field, y: pub Field) { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; assert(slice[0] == 0); assert(slice[0] != 1); slice[0] = x; @@ -13,7 +13,7 @@ fn main(x: Field, y: pub Field) { assert(slice_plus_10[2] != 8); assert(slice_plus_10.len() == 3); - let mut new_slice = []; + let mut new_slice = &[]; for i in 0..5 { new_slice = new_slice.push_back(i); } @@ -41,7 +41,7 @@ fn main(x: Field, y: pub Field) { assert(remove_slice[3] == 3); assert(remove_slice.len() == 4); - let append = [1, 2].append([3, 4, 5]); + let append = &[1, 2].append(&[3, 4, 5]); assert(append.len() == 5); assert(append[0] == 1); assert(append[4] == 5); @@ -51,9 +51,10 @@ fn main(x: Field, y: pub Field) { regression_merge_slices(x, y); regression_2370(); } + // Ensure that slices of struct/tuple values work. fn regression_2083() { - let y = [(1, 2)]; + let y = &[(1, 2)]; let y = y.push_back((3, 4)); // [(1, 2), (3, 4)] let y = y.push_back((5, 6)); // [(1, 2), (3, 4), (5, 6)] assert(y[2].1 == 6); @@ -82,6 +83,7 @@ fn regression_2083() { assert(x.0 == 5); assert(x.1 == 6); } + // The parameters to this function must come from witness values (inputs to main) fn regression_merge_slices(x: Field, y: Field) { merge_slices_if(x, y); @@ -142,18 +144,20 @@ fn merge_slices_else(x: Field) { assert(slice[2] == 5); assert(slice.len() == 3); } + // Test returning a merged slice without a mutation fn merge_slices_return(x: Field, y: Field) -> [Field] { - let slice = [0; 2]; + let slice = &[0; 2]; if x != y { if x != 20 { slice.push_back(y) } else { slice } } else { slice } } + // Test mutating a slice inside of an if statement fn merge_slices_mutate(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -162,9 +166,10 @@ fn merge_slices_mutate(x: Field, y: Field) -> [Field] { } slice } + // Test mutating a slice inside of a loop in an if statement fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { for i in 0..5 { slice = slice.push_back(i as Field); @@ -176,7 +181,7 @@ fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { } fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -195,7 +200,7 @@ fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { } fn merge_slices_mutate_between_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -221,7 +226,7 @@ fn merge_slices_mutate_between_ifs(x: Field, y: Field) -> [Field] { } fn merge_slices_push_then_pop(x: Field, y: Field) { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -245,7 +250,7 @@ fn merge_slices_push_then_pop(x: Field, y: Field) { } fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -268,7 +273,7 @@ fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { } fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -294,6 +299,6 @@ fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { // Previously, we'd get a type error when trying to assign an array of a different size to // an existing array variable. Now, we infer the variable must be a slice. fn regression_2370() { - let mut slice = []; - slice = [1, 2, 3]; + let mut slice = &[]; + slice = &[1, 2, 3]; } diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr index cff229d368a..6f039fef285 100644 --- a/test_programs/execution_success/strings/src/main.nr +++ b/test_programs/execution_success/strings/src/main.nr @@ -27,7 +27,7 @@ fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Fie std::print(bad_message); assert(message != bad_message); - let hash = std::hash::pedersen_commitment([x]); + let hash = std::hash::pedersen_commitment(&[x]); std::println(hash); std::print(hash); @@ -61,7 +61,7 @@ fn test_prints_array() { std::println(array); - let hash = std::hash::pedersen_commitment(array); + let hash = std::hash::pedersen_commitment(array.as_slice()); std::println(hash); } diff --git a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr index d2b7d155a32..5eda9db4d1a 100644 --- a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr +++ b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -10,10 +10,10 @@ fn test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] fn test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); + assert_eq(dep::std::hash::pedersen_commitment(&[27]).x, 0, "Not equal"); } #[test(should_fail)] fn test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); + assert_eq(dep::std::hash::pedersen_commitment(&[27]).x, 0); } diff --git a/tooling/nargo/src/artifacts/debug_vars.rs b/tooling/nargo/src/artifacts/debug_vars.rs index 0921dbd3e7c..86cb4256635 100644 --- a/tooling/nargo/src/artifacts/debug_vars.rs +++ b/tooling/nargo/src/artifacts/debug_vars.rs @@ -62,7 +62,10 @@ impl DebugVars { .unwrap_or_else(|| panic!("type unavailable for type id {cursor_type_id:?}")); for index in indexes.iter() { (cursor, cursor_type) = match (cursor, cursor_type) { - (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Array { length, typ }) => { + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Array { length, typ }, + ) => { assert!(!*is_slice, "slice has array type"); if let Some(len) = length { if *index as u64 >= *len { @@ -74,7 +77,10 @@ impl DebugVars { } (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) } - (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Slice { typ }) => { + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Slice { typ }, + ) => { assert!(*is_slice, "array has slice type"); (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) } @@ -88,7 +94,10 @@ impl DebugVars { let (key, typ) = fields.get(*index as usize).unwrap(); (field_map.get_mut(key).unwrap(), typ) } - (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Tuple { types }) => { + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Tuple { types }, + ) => { assert!(!*is_slice, "slice has tuple type"); if *index >= types.len() as u32 { panic!( diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 1ca12b75dfb..0a40810bdab 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -203,8 +203,8 @@ fn compile_success_empty_{test_name}() {{ }} // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|_| {{ - panic!("JSON was not well-formatted {{:?}}",output.stdout) + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ + panic!("JSON was not well-formatted {{:?}}\n\n{{:?}}", e, std::str::from_utf8(&output.stdout)) }}); let num_opcodes = &json["programs"][0]["acir_opcodes"]; assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); diff --git a/tooling/nargo_fmt/src/rewrite/array.rs b/tooling/nargo_fmt/src/rewrite/array.rs index 4499760c1a4..db7dc4701b7 100644 --- a/tooling/nargo_fmt/src/rewrite/array.rs +++ b/tooling/nargo_fmt/src/rewrite/array.rs @@ -6,7 +6,12 @@ use crate::{ visitor::{expr::NewlineMode, FmtVisitor}, }; -pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span, is_slice: bool) -> String { +pub(crate) fn rewrite( + mut visitor: FmtVisitor, + array: Vec, + array_span: Span, + is_slice: bool, +) -> String { let pattern: &[_] = &[' ', '\t']; visitor.indent.block_indent(visitor.config); @@ -75,11 +80,7 @@ pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_spa } } - let open_bracket = if is_slice { - "&[" - } else { - "[" - }; + let open_bracket = if is_slice { "&[" } else { "[" }; crate::visitor::expr::wrap_exprs( open_bracket, "]", From 64738057a6178440f3ab7f633ee4bb803565dec1 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Sun, 10 Mar 2024 22:52:25 -0400 Subject: [PATCH 06/26] update poseidon/mimic hash slice literals, add eq/ord/default instances for slices, fix slice literal in regression test --- noir_stdlib/src/cmp.nr | 30 +++++++++++++++++++ noir_stdlib/src/default.nr | 6 ++++ noir_stdlib/src/hash/mimc.nr | 2 +- noir_stdlib/src/hash/poseidon.nr | 2 +- noir_stdlib/src/hash/poseidon2.nr | 2 +- .../execution_success/slices/src/main.nr | 2 +- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index 38316e5d6a8..ed89cf89f7f 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -28,6 +28,16 @@ impl Eq for [T; N] where T: Eq { } } +impl Eq for [T] where T: Eq { + fn eq(self, other: [T]) -> bool { + let mut result = true; + for i in 0 .. self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + impl Eq for str { fn eq(self, other: str) -> bool { let self_bytes = self.as_bytes(); @@ -213,6 +223,26 @@ impl Ord for [T; N] where T: Ord { } } +impl Ord for [T] where T: Ord { + // The first non-equal element of both arrays determines + // the ordering for the whole array. + fn cmp(self, other: [T]) -> Ordering { + let mut result = Ordering::equal(); + for i in 0 .. self.len() { + if result == Ordering::equal() { + let result_i = self[i].cmp(other[i]); + + if result_i == Ordering::less() { + result = result_i; + } else if result_i == Ordering::greater() { + result = result_i; + } + } + } + result + } +} + impl Ord for (A, B) where A: Ord, B: Ord { fn cmp(self, other: (A, B)) -> Ordering { let result = self.0.cmp(other.0); diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr index 32c4f3f3b48..bd2f1ce0cd2 100644 --- a/noir_stdlib/src/default.nr +++ b/noir_stdlib/src/default.nr @@ -23,6 +23,12 @@ impl Default for [T; N] where T: Default { } } +impl Default for [T] { + fn default() -> [T] { + &[] + } +} + impl Default for (A, B) where A: Default, B: Default { fn default() -> (A, B) { (A::default(), B::default()) diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index db8a32d7909..1fb53701013 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -152,7 +152,7 @@ impl Hasher for MimcHasher { impl Default for MimcHasher{ fn default() -> Self{ MimcHasher{ - _state: [], + _state: &[], _len: 0, } } diff --git a/noir_stdlib/src/hash/poseidon.nr b/noir_stdlib/src/hash/poseidon.nr index 7f99ad36316..85a0802f630 100644 --- a/noir_stdlib/src/hash/poseidon.nr +++ b/noir_stdlib/src/hash/poseidon.nr @@ -171,7 +171,7 @@ impl Hasher for PoseidonHasher { impl Default for PoseidonHasher{ fn default() -> Self{ PoseidonHasher{ - _state: [], + _state: &[], _len: 0, } } diff --git a/noir_stdlib/src/hash/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr index 52229f18dbd..5b97d809896 100644 --- a/noir_stdlib/src/hash/poseidon2.nr +++ b/noir_stdlib/src/hash/poseidon2.nr @@ -139,7 +139,7 @@ impl Hasher for Poseidon2Hasher { impl Default for Poseidon2Hasher{ fn default() -> Self{ Poseidon2Hasher{ - _state: [], + _state: &[], _len: 0, } } diff --git a/test_programs/execution_success/slices/src/main.nr b/test_programs/execution_success/slices/src/main.nr index 6c293ba2571..b20e3478898 100644 --- a/test_programs/execution_success/slices/src/main.nr +++ b/test_programs/execution_success/slices/src/main.nr @@ -332,6 +332,6 @@ fn regression_slice_call_result(x: Field, y: Field) { } fn regression_4506() { - let slice: [Field] = [1, 2, 3]; + let slice: [Field] = &[1, 2, 3]; assert(slice == slice); } From 4f66228ce97360767da77d30f5b19c1dae732511 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Sun, 10 Mar 2024 23:57:41 -0400 Subject: [PATCH 07/26] added missing element_type_at_index case for slices, fixed all but one debugger error (timeout in brillig_cow_regression) --- compiler/noirc_frontend/src/monomorphization/debug.rs | 3 ++- tooling/debugger/tests/debug.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_frontend/src/monomorphization/debug.rs b/compiler/noirc_frontend/src/monomorphization/debug.rs index cf4e0ab792e..9c682ac119b 100644 --- a/compiler/noirc_frontend/src/monomorphization/debug.rs +++ b/compiler/noirc_frontend/src/monomorphization/debug.rs @@ -192,11 +192,12 @@ impl<'interner> Monomorphizer<'interner> { fn element_type_at_index(ptype: &PrintableType, i: usize) -> &PrintableType { match ptype { PrintableType::Array { length: _length, typ } => typ.as_ref(), + PrintableType::Slice { typ } => typ.as_ref(), PrintableType::Tuple { types } => &types[i], PrintableType::Struct { name: _name, fields } => &fields[i].1, PrintableType::String { length: _length } => &PrintableType::UnsignedInteger { width: 8 }, _ => { - panic!["expected type with sub-fields, found terminal type"] + panic!("expected type with sub-fields, found terminal type: {:?}", ptype) } } } diff --git a/tooling/debugger/tests/debug.rs b/tooling/debugger/tests/debug.rs index 143ee7987f8..4de1b25f48a 100644 --- a/tooling/debugger/tests/debug.rs +++ b/tooling/debugger/tests/debug.rs @@ -12,7 +12,9 @@ mod tests { let nargo_bin = cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); - let mut dbg_session = spawn_bash(Some(15000)).expect("Could not start bash session"); + let timeout_seconds = 120; + let mut dbg_session = + spawn_bash(Some(timeout_seconds * 1000)).expect("Could not start bash session"); // Set backend to `/dev/null` to force an error if nargo tries to speak to a backend. dbg_session From cd2807d02c946931d969cf7699812d63642894cb Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 11 Mar 2024 00:06:26 -0400 Subject: [PATCH 08/26] update slice literal in pedersen_hash wasm example --- compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr index e0c82fb1960..877f932b038 100644 --- a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr +++ b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr @@ -1,3 +1,3 @@ pub fn bar(param: Field) -> Field { - dep::std::hash::pedersen_hash([param]) + dep::std::hash::pedersen_hash(&[param]) } From 7a50955933b0b118e9877fb5b85ebb50c9318829 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 11 Mar 2024 09:41:50 -0400 Subject: [PATCH 09/26] remove redundant match on array vs slice --- compiler/noirc_frontend/src/hir_def/types.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 63d156c408e..fc23d8beb3f 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1295,18 +1295,13 @@ impl Type { let target = target.follow_bindings(); if let (Type::Array(size, element1), Type::Slice(element2)) = (&this, &target) { - let length = size.follow_bindings(); - - // If we have an array and our target is a slice - if matches!(length, Type::Constant(_)) { - // Still have to ensure the element types match. - // Don't need to issue an error here if not, it will be done in unify_with_coercions - let mut bindings = TypeBindings::new(); - if element1.try_unify(element2, &mut bindings).is_ok() { - convert_array_expression_to_slice(expression, this, target, interner); - Self::apply_type_bindings(bindings); - return true; - } + // Still have to ensure the element types match. + // Don't need to issue an error here if not, it will be done in unify_with_coercions + let mut bindings = TypeBindings::new(); + if element1.try_unify(element2, &mut bindings).is_ok() { + convert_array_expression_to_slice(expression, this, target, interner); + Self::apply_type_bindings(bindings); + return true; } } false From 4adc6915ab8096e3fbe953cd1a30781aaac853a7 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 11 Mar 2024 09:51:30 -0400 Subject: [PATCH 10/26] remove unused variable, flip result type order --- .../noirc_frontend/src/hir/type_check/expr.rs | 19 ++++++++++--------- compiler/noirc_frontend/src/hir_def/types.rs | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 5bae9a0b3ef..856bb2fed23 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -51,7 +51,7 @@ impl<'interner> TypeChecker<'interner> { fn check_hir_array_literal( &mut self, hir_array_literal: HirArrayLiteral, - ) -> (Result, u64>, Box) { + ) -> (Result>, Box) { match hir_array_literal { HirArrayLiteral::Standard(arr) => { let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); @@ -78,13 +78,13 @@ impl<'interner> TypeChecker<'interner> { }); } - (Err(arr.len() as u64), Box::new(first_elem_type.clone())) + (Ok(arr.len() as u64), Box::new(first_elem_type.clone())) } HirArrayLiteral::Repeated { repeated_element, length } => { let elem_type = self.check_expression(&repeated_element); let length = match length { - Type::Constant(length) => Err(length), - other => Ok(Box::new(other)), + Type::Constant(length) => Ok(length), + other => Err(Box::new(other)), }; (length, Box::new(elem_type)) } @@ -106,22 +106,23 @@ impl<'interner> TypeChecker<'interner> { HirLiteral::Array(hir_array_literal) => { let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); Type::Array( - length.unwrap_or_else(|constant| { - Box::new(Type::constant_variable(constant, self.interner)) - }), + length.map_or_else( + |typ| typ, + |constant| Box::new(Type::constant_variable(constant, self.interner)), + ), elem_type, ) } HirLiteral::Slice(hir_array_literal) => { let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); match length_type { - Ok(_non_constant) => { + Ok(_length) => Type::Slice(elem_type), + Err(_non_constant) => { self.errors.push(TypeCheckError::NonConstantSliceLength { span: self.interner.expr_span(expr_id), }); Type::Error } - Err(_length) => Type::Slice(elem_type), } } HirLiteral::Bool(_) => Type::Bool, diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index fc23d8beb3f..309671aaf0f 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1294,7 +1294,7 @@ impl Type { let this = self.follow_bindings(); let target = target.follow_bindings(); - if let (Type::Array(size, element1), Type::Slice(element2)) = (&this, &target) { + if let (Type::Array(_size, element1), Type::Slice(element2)) = (&this, &target) { // Still have to ensure the element types match. // Don't need to issue an error here if not, it will be done in unify_with_coercions let mut bindings = TypeBindings::new(); From 88f53b533966b3c6bc568a5e4292c74bfe7bf985 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Fri, 15 Mar 2024 15:27:05 -0400 Subject: [PATCH 11/26] Update noir_stdlib/src/merkle.nr Co-authored-by: jfecher --- noir_stdlib/src/merkle.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr index ba65b1adae5..f58e80f9d99 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -13,7 +13,7 @@ pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) } else { (current, hash_path[i]) }; - current = crate::hash::pedersen_hash([hash_left, hash_right].as_slice()); + current = crate::hash::pedersen_hash(&[hash_left, hash_right]); } current } From 95526267d7d80d78839acbead9f807a60c39383c Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Fri, 15 Mar 2024 15:27:14 -0400 Subject: [PATCH 12/26] Update test_programs/compile_success_empty/intrinsic_die/src/main.nr Co-authored-by: jfecher --- test_programs/compile_success_empty/intrinsic_die/src/main.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr index 8963073859a..67b5c391a3e 100644 --- a/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -1,6 +1,6 @@ use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { - let hash = std::hash::pedersen_commitment([x].as_slice()); + let hash = std::hash::pedersen_commitment(&[x]); let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); } From 421469172b52ca2c41fa2aa1888af433e9e34c32 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 15 Mar 2024 15:36:34 -0400 Subject: [PATCH 13/26] remove unused slice tests from frontend, fix Eq and Cmp for slices assuming same lengths, fix bigint slice literal from master --- compiler/noirc_frontend/src/tests.rs | 25 ------------------- noir_stdlib/src/cmp.nr | 4 +-- .../execution_success/bigint/src/main.nr | 4 +-- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index e04222c39a8..b8ed6fb73d2 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -902,31 +902,6 @@ mod test { assert!(get_program_errors(src).is_empty()); } - #[test] - fn resolve_literal_slice() { - let src = r#" - fn const_0(_x : [Field]) -> Field { - 0 - } - fn main(x : Field) { - let y: [Field] = &[1, 2, 3]; - assert(const_0(y) == x); - } - "#; - assert!(get_program_errors(src).is_empty()); - } - - #[test] - fn index_literal_slice() { - let src = r#" - fn main(x : Field) { - let y: [Field] = &[1, 2, 3]; - assert(y[0] == x); - } - "#; - assert!(get_program_errors(src).is_empty()); - } - #[test] fn multiple_resolution_errors() { let src = r#" diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index ed89cf89f7f..0eed50eb42b 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -30,7 +30,7 @@ impl Eq for [T; N] where T: Eq { impl Eq for [T] where T: Eq { fn eq(self, other: [T]) -> bool { - let mut result = true; + let mut result = self.len() == other.len(); for i in 0 .. self.len() { result &= self[i].eq(other[i]); } @@ -227,7 +227,7 @@ impl Ord for [T] where T: Ord { // The first non-equal element of both arrays determines // the ordering for the whole array. fn cmp(self, other: [T]) -> Ordering { - let mut result = Ordering::equal(); + let mut result = self.len().cmp(other.len()); for i in 0 .. self.len() { if result == Ordering::equal() { let result_i = self[i].cmp(other[i]); diff --git a/test_programs/execution_success/bigint/src/main.nr b/test_programs/execution_success/bigint/src/main.nr index 64d7d8ff9f1..db269d63ac0 100644 --- a/test_programs/execution_success/bigint/src/main.nr +++ b/test_programs/execution_success/bigint/src/main.nr @@ -19,8 +19,8 @@ fn main(mut x: [u8; 5], y: [u8; 5]) { // docs:start:big_int_example fn big_int_example(x: u8, y: u8) { - let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]); - let b = Secpk1Fq::from_le_bytes([y, x, 9]); + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); let c = (a + b) * b / a; let d = c.to_le_bytes(); println(d[0]); From 370b8ae60feabdc0e2a4d74b23a9b755c24fbc04 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 15 Mar 2024 16:16:48 -0400 Subject: [PATCH 14/26] remove unused PartialEq --- compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs | 2 +- compiler/noirc_frontend/src/hir/def_collector/errors.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 42e086bcbf6..0c53bff4a54 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -136,7 +136,7 @@ pub struct DefCollector { pub(crate) type ImplMap = HashMap<(UnresolvedType, LocalModuleId), Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>>; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub enum CompilationError { ParseError(ParserError), DefinitionError(DefCollectorErrorKind), diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index f2f33df2594..29daf5d6369 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -23,7 +23,7 @@ pub enum DuplicateType { TraitAssociatedFunction, } -#[derive(Error, Debug, Clone, PartialEq)] +#[derive(Error, Debug, Clone)] pub enum DefCollectorErrorKind { #[error("duplicate {typ} found in namespace")] Duplicate { typ: DuplicateType, first_def: Ident, second_def: Ident }, @@ -70,7 +70,7 @@ pub enum DefCollectorErrorKind { } /// An error struct that macro processors can return. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub struct MacroError { pub primary_message: String, pub secondary_message: Option, From 0b59ecce08951092b7d69778f1b7aff36c152707 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 15 Mar 2024 17:07:58 -0400 Subject: [PATCH 15/26] add back [hash]_array methods, use those methods in tests/stdlib --- noir_stdlib/src/ecdsa_secp256k1.nr | 11 +++++ noir_stdlib/src/ecdsa_secp256r1.nr | 11 +++++ noir_stdlib/src/hash.nr | 48 +++++++++++++++++++ noir_stdlib/src/merkle.nr | 2 +- noir_stdlib/src/schnorr.nr | 11 +++++ noir_stdlib/src/sha512.nr | 2 +- .../intrinsic_die/src/main.nr | 2 +- test_programs/execution_success/6/src/main.nr | 4 +- test_programs/execution_success/7/src/main.nr | 2 +- .../array_dynamic_blackbox_input/src/main.nr | 2 +- .../src/main.nr | 2 +- .../execution_success/blake3/src/main.nr | 2 +- .../brillig_blake2s/src/main.nr | 2 +- .../brillig_blake3/src/main.nr | 2 +- .../brillig_cow_regression/src/main.nr | 4 +- .../brillig_ecdsa_secp256k1/src/main.nr | 2 +- .../brillig_ecdsa_secp256r1/src/main.nr | 2 +- .../brillig_keccak/src/main.nr | 2 +- .../brillig_pedersen/src/main.nr | 8 ++-- .../brillig_schnorr/src/main.nr | 2 +- .../brillig_sha256/src/main.nr | 2 +- .../conditional_1/src/main.nr | 2 +- .../src/main.nr | 4 +- .../ecdsa_secp256k1/src/main.nr | 4 +- .../ecdsa_secp256r1/src/main.nr | 2 +- .../execution_success/import/src/main.nr | 2 +- .../execution_success/keccak256/src/main.nr | 8 ++-- .../pedersen_check/src/main.nr | 8 ++-- .../pedersen_commitment/src/main.nr | 2 +- .../pedersen_hash/src/main.nr | 2 +- .../execution_success/schnorr/src/main.nr | 2 +- .../execution_success/sha256/src/main.nr | 2 +- .../execution_success/sha2_byte/src/main.nr | 2 +- .../simple_shield/src/main.nr | 6 +-- .../execution_success/strings/src/main.nr | 4 +- .../should_fail_with_matches/src/main.nr | 4 +- 36 files changed, 130 insertions(+), 49 deletions(-) diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 79510dc0e5e..244b2571587 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -8,3 +8,14 @@ pub fn verify_signature( ) -> bool // docs:end:ecdsa_secp256k1 {} + +#[foreign(ecdsa_secp256k1)] +// docs:start:ecdsa_secp256k1 +pub fn verify_signature_array( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +// docs:end:ecdsa_secp256k1 +{} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index 8085693bde2..bd201fc1687 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -8,3 +8,14 @@ pub fn verify_signature( ) -> bool // docs:end:ecdsa_secp256r1 {} + +#[foreign(ecdsa_secp256r1)] +// docs:start:ecdsa_secp256r1 +pub fn verify_signature_array( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +// docs:end:ecdsa_secp256r1 +{} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 2b7b2868d75..9e755bf6feb 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -12,18 +12,36 @@ pub fn sha256(input: [u8]) -> [u8; 32] // docs:end:sha256 {} +#[foreign(sha256)] +// docs:start:sha256 +pub fn sha256_array(input: [u8; N]) -> [u8; 32] +// docs:end:sha256 +{} + #[foreign(blake2s)] // docs:start:blake2s pub fn blake2s(input: [u8]) -> [u8; 32] // docs:end:blake2s {} +#[foreign(blake2s)] +// docs:start:blake2s +pub fn blake2s_array(input: [u8; N]) -> [u8; 32] +// docs:end:blake2s +{} + #[foreign(blake3)] // docs:start:blake3 pub fn blake3(input: [u8]) -> [u8; 32] // docs:end:blake3 {} +#[foreign(blake3)] +// docs:start:blake3 +pub fn blake3_array(input: [u8; N]) -> [u8; 32] +// docs:end:blake3 +{} + // docs:start:pedersen_commitment struct PedersenPoint { x : Field, @@ -36,14 +54,28 @@ pub fn pedersen_commitment(input: [Field]) -> PedersenPoint pedersen_commitment_with_separator(input, 0) } +pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint +// docs:end:pedersen_commitment +{ + pedersen_commitment_with_separator_array(input, 0) +} + #[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(input: [Field], separator: u32) -> [Field; 2] {} +#[foreign(pedersen_commitment)] +pub fn __pedersen_commitment_with_separator_array(input: [Field; N], separator: u32) -> [Field; 2] {} + pub fn pedersen_commitment_with_separator(input: [Field], separator: u32) -> PedersenPoint { let values = __pedersen_commitment_with_separator(input, separator); PedersenPoint { x: values[0], y: values[1] } } +pub fn pedersen_commitment_with_separator_array(input: [Field; N], separator: u32) -> PedersenPoint { + let values = __pedersen_commitment_with_separator_array(input, separator); + PedersenPoint { x: values[0], y: values[1] } +} + // docs:start:pedersen_hash pub fn pedersen_hash(input: [Field]) -> Field // docs:end:pedersen_hash @@ -51,9 +83,19 @@ pub fn pedersen_hash(input: [Field]) -> Field pedersen_hash_with_separator(input, 0) } +// docs:start:pedersen_hash +pub fn pedersen_hash_array(input: [Field; N]) -> Field +// docs:end:pedersen_hash +{ + pedersen_hash_with_separator_array(input, 0) +} + #[foreign(pedersen_hash)] pub fn pedersen_hash_with_separator(input: [Field], separator: u32) -> Field {} +#[foreign(pedersen_hash)] +pub fn pedersen_hash_with_separator_array(input: [Field; N], separator: u32) -> Field {} + pub fn hash_to_field(inputs: [Field]) -> Field { let mut inputs_as_bytes = &[]; @@ -74,6 +116,12 @@ pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} +#[foreign(keccak256)] +// docs:start:keccak256 +pub fn keccak256_array(input: [u8; N], message_size: u32) -> [u8; 32] +// docs:end:keccak256 +{} + #[foreign(poseidon2_permutation)] pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr index f58e80f9d99..be31768ed57 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -13,7 +13,7 @@ pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) } else { (current, hash_path[i]) }; - current = crate::hash::pedersen_hash(&[hash_left, hash_right]); + current = crate::hash::pedersen_hash_array([hash_left, hash_right]); } current } diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 024f47e63e8..18351fca429 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -8,3 +8,14 @@ pub fn verify_signature( ) -> bool // docs:end:schnorr_verify {} + +#[foreign(schnorr_verify)] +// docs:start:schnorr_verify +pub fn verify_signature_array( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +// docs:end:schnorr_verify +{} diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 4b7bbe39237..a766ae50d55 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -87,7 +87,7 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { msg64 } // SHA-512 hash function -pub fn digest(msg: [u8]) -> [u8; 64] { +pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; // noir-fmt:ignore let mut h: [u64; 8] = [7640891576956012808, 13503953896175478587, 4354685564936845355, 11912009170470909681, 5840696475078001361, 11170449401992604703, 2270897969802886507, 6620516959819538809]; // Intermediate hash, starting with the canonical initial value diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr index 67b5c391a3e..0551ddd246c 100644 --- a/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -1,6 +1,6 @@ use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { - let hash = std::hash::pedersen_commitment(&[x]); + let hash = std::hash::pedersen_commitment_array([x]); let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); } diff --git a/test_programs/execution_success/6/src/main.nr b/test_programs/execution_success/6/src/main.nr index 294d406637a..e1e063ede00 100644 --- a/test_programs/execution_success/6/src/main.nr +++ b/test_programs/execution_success/6/src/main.nr @@ -8,9 +8,9 @@ use dep::std; fn main(x: [u8; 5], result: pub [u8; 32]) { - let mut digest = std::hash::sha256(x.as_slice()); + let mut digest = std::hash::sha256_array(x); digest[0] = 5 as u8; - digest = std::hash::sha256(x.as_slice()); + digest = std::hash::sha256_array(x); assert(digest == result); let y = [12, 45, 78, 41]; diff --git a/test_programs/execution_success/7/src/main.nr b/test_programs/execution_success/7/src/main.nr index 996a3b24f24..ae27a4e4926 100644 --- a/test_programs/execution_success/7/src/main.nr +++ b/test_programs/execution_success/7/src/main.nr @@ -5,6 +5,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake2s(x.as_slice()); + let digest = std::hash::blake2s_array(x); assert(digest == result); } diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr index a936f1d5c4a..ed92929a70c 100644 --- a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr @@ -18,7 +18,7 @@ fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { hash_input[j + b] = path[offset + j]; } - current = dep::std::hash::sha256(hash_input.as_slice()); + current = dep::std::hash::sha256_array(hash_input); index = index >> 1; } diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr index 7c92890e950..fc9c01ccbac 100644 --- a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr @@ -15,6 +15,6 @@ fn main(mut x: [Foo; 3], y: pub Field, hash_result: pub [u8; 32]) { // Make sure that we are passing a dynamic array to the black box function call // by setting the array using a dynamic index here hash_input[y - 1] = 0; - let hash = dep::std::hash::sha256(hash_input.as_slice()); + let hash = dep::std::hash::sha256_array(hash_input); assert_eq(hash, hash_result); } diff --git a/test_programs/execution_success/blake3/src/main.nr b/test_programs/execution_success/blake3/src/main.nr index 7a9810b6abc..c0b460382e1 100644 --- a/test_programs/execution_success/blake3/src/main.nr +++ b/test_programs/execution_success/blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3(x.as_slice()); + let digest = std::hash::blake3_array(x); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_blake2s/src/main.nr b/test_programs/execution_success/brillig_blake2s/src/main.nr index b358fa8236b..ef2b19ae30c 100644 --- a/test_programs/execution_success/brillig_blake2s/src/main.nr +++ b/test_programs/execution_success/brillig_blake2s/src/main.nr @@ -7,5 +7,5 @@ fn main(x: [u8; 5], result: [u8; 32]) { } unconstrained fn blake2s(x: [u8; 5]) -> [u8; 32] { - std::hash::blake2s(x.as_slice()) + std::hash::blake2s_array(x) } diff --git a/test_programs/execution_success/brillig_blake3/src/main.nr b/test_programs/execution_success/brillig_blake3/src/main.nr index 30dc2fb46a2..dfabe441651 100644 --- a/test_programs/execution_success/brillig_blake3/src/main.nr +++ b/test_programs/execution_success/brillig_blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; unconstrained fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3(x.as_slice()); + let digest = std::hash::blake3_array(x); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_cow_regression/src/main.nr b/test_programs/execution_success/brillig_cow_regression/src/main.nr index ca316d26fc0..0032a3e8918 100644 --- a/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -25,7 +25,7 @@ struct NewContractData { impl NewContractData { fn hash(self) -> Field { - dep::std::hash::pedersen_hash(&[self.contract_address, self.portal_contract_address]) + dep::std::hash::pedersen_hash_array([self.contract_address, self.portal_contract_address]) } } @@ -173,6 +173,6 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA } } - let sha_digest = dep::std::hash::sha256(hash_input_flattened.as_slice()); + let sha_digest = dep::std::hash::sha256_array(hash_input_flattened); U256::from_bytes32(sha_digest).to_u128_limbs() } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr index 64af1132aff..a8b6ed0f88b 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()) + std::ecdsa_secp256k1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr index c96261858fb..272cc994ea6 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()) + std::ecdsa_secp256r1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/test_programs/execution_success/brillig_keccak/src/main.nr b/test_programs/execution_success/brillig_keccak/src/main.nr index 641ba485094..7657c64ce9d 100644 --- a/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/test_programs/execution_success/brillig_keccak/src/main.nr @@ -21,5 +21,5 @@ fn main(x: Field, result: [u8; 32]) { } unconstrained fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { - std::hash::keccak256(data.as_slice(), msg_len) + std::hash::keccak256_array(data, msg_len) } diff --git a/test_programs/execution_success/brillig_pedersen/src/main.nr b/test_programs/execution_success/brillig_pedersen/src/main.nr index 3a23a7b3de6..82d144bd8ab 100644 --- a/test_programs/execution_success/brillig_pedersen/src/main.nr +++ b/test_programs/execution_success/brillig_pedersen/src/main.nr @@ -1,11 +1,11 @@ use dep::std; unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment_with_separator(&[x, y], 0); + let res = std::hash::pedersen_commitment_with_separator_array([x, y], 0); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator(&[x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator_array([x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Fiel state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment_with_separator(&[state], 0); - assert(std::hash::pedersen_commitment_with_separator(&[43], 0).x == hash.x); + let hash = std::hash::pedersen_commitment_with_separator_array([state], 0); + assert(std::hash::pedersen_commitment_with_separator_array([43], 0).x == hash.x); } diff --git a/test_programs/execution_success/brillig_schnorr/src/main.nr b/test_programs/execution_success/brillig_schnorr/src/main.nr index 4c7ec16887e..da210b3c798 100644 --- a/test_programs/execution_success/brillig_schnorr/src/main.nr +++ b/test_programs/execution_success/brillig_schnorr/src/main.nr @@ -20,6 +20,6 @@ unconstrained fn main( let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message.as_slice()); + let valid_signature = std::schnorr::verify_signature_array(pub_key_x, pub_key_y, signature, message); assert(valid_signature); } diff --git a/test_programs/execution_success/brillig_sha256/src/main.nr b/test_programs/execution_success/brillig_sha256/src/main.nr index 953bfe05644..f3ce02a3739 100644 --- a/test_programs/execution_success/brillig_sha256/src/main.nr +++ b/test_programs/execution_success/brillig_sha256/src/main.nr @@ -9,6 +9,6 @@ fn main(x: Field, result: [u8; 32]) { unconstrained fn sha256(x: Field) -> [u8; 32] { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - std::hash::sha256(&[x as u8]) + std::hash::sha256_array([x as u8]) } diff --git a/test_programs/execution_success/conditional_1/src/main.nr b/test_programs/execution_success/conditional_1/src/main.nr index f49c24579ba..96ca3937319 100644 --- a/test_programs/execution_success/conditional_1/src/main.nr +++ b/test_programs/execution_success/conditional_1/src/main.nr @@ -55,7 +55,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { let mut y = 0; if a == 0 { - let digest = std::hash::sha256(x.as_slice()); + let digest = std::hash::sha256_array(x); y = digest[0]; } else { y = 5; diff --git a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr index 7eeefae16e9..600a49f0c24 100644 --- a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr +++ b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr @@ -26,9 +26,9 @@ fn bar(x: Field) { } fn call_intrinsic(x: [u8; 5], result: [u8; 32]) { - let mut digest = std::hash::sha256(x.as_slice()); + let mut digest = std::hash::sha256_array(x); digest[0] = 5 as u8; - digest = std::hash::sha256(x.as_slice()); + digest = std::hash::sha256_array(x); assert(digest == result); } diff --git a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr index d9ffef69644..510ed402e52 100644 --- a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -8,9 +8,9 @@ fn main( signature: [u8; 64] ) { // Hash the message, since secp256k1 expects a hashed_message - let expected = std::hash::sha256(message.as_slice()); + let expected = std::hash::sha256_array(message); assert(hashed_message == expected); - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + let valid_signature = std::ecdsa_secp256k1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } diff --git a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr index dda6d688a60..9bdb99d7fce 100644 --- a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + let valid_signature = std::ecdsa_secp256r1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } diff --git a/test_programs/execution_success/import/src/main.nr b/test_programs/execution_success/import/src/main.nr index 85e7b0c2dfa..991d8904901 100644 --- a/test_programs/execution_success/import/src/main.nr +++ b/test_programs/execution_success/import/src/main.nr @@ -2,7 +2,7 @@ mod import; use crate::import::hello; fn main(x: Field, y: Field) { - let _k = dep::std::hash::pedersen_commitment(&[x]); + let _k = dep::std::hash::pedersen_commitment_array([x]); let _l = hello(x); assert(x != import::hello(y)); diff --git a/test_programs/execution_success/keccak256/src/main.nr b/test_programs/execution_success/keccak256/src/main.nr index 24f1695c67d..2e4c3d7e4d7 100644 --- a/test_programs/execution_success/keccak256/src/main.nr +++ b/test_programs/execution_success/keccak256/src/main.nr @@ -4,18 +4,18 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::keccak256(&[x as u8], 1); + let digest = std::hash::keccak256_array([x as u8], 1); assert(digest == result); //#1399: variable message size let message_size = 4; - let hash_a = std::hash::keccak256(&[1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256(&[1, 2, 3, 4, 0, 0, 0, 0], message_size); + let hash_a = std::hash::keccak256_array([1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256_array([1, 2, 3, 4, 0, 0, 0, 0], message_size); assert(hash_a == hash_b); let message_size_big = 8; - let hash_c = std::hash::keccak256(&[1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + let hash_c = std::hash::keccak256_array([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); assert(hash_a != hash_c); } diff --git a/test_programs/execution_success/pedersen_check/src/main.nr b/test_programs/execution_success/pedersen_check/src/main.nr index 16e3841ea25..df0a2b91acd 100644 --- a/test_programs/execution_success/pedersen_check/src/main.nr +++ b/test_programs/execution_success/pedersen_check/src/main.nr @@ -1,11 +1,11 @@ use dep::std; fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment(&[x, y]); + let res = std::hash::pedersen_commitment_array([x, y]); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator(&[x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator_array([x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: F state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment(&[state]); - assert(std::hash::pedersen_commitment(&[43]).x == hash.x); + let hash = std::hash::pedersen_commitment_array([state]); + assert(std::hash::pedersen_commitment_array([43]).x == hash.x); } diff --git a/test_programs/execution_success/pedersen_commitment/src/main.nr b/test_programs/execution_success/pedersen_commitment/src/main.nr index 4d07cbffbe6..95f9074532f 100644 --- a/test_programs/execution_success/pedersen_commitment/src/main.nr +++ b/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment(&[x, y]); + let commitment = std::hash::pedersen_commitment_array([x, y]); assert_eq(commitment.x, expected_commitment.x); assert_eq(commitment.y, expected_commitment.y); } diff --git a/test_programs/execution_success/pedersen_hash/src/main.nr b/test_programs/execution_success/pedersen_hash/src/main.nr index d97495ce3b7..bcdfd2c249f 100644 --- a/test_programs/execution_success/pedersen_hash/src/main.nr +++ b/test_programs/execution_success/pedersen_hash/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash(&[x, y]); + let hash = std::hash::pedersen_hash_array([x, y]); assert_eq(hash, expected_hash); } // docs:end:pedersen-hash diff --git a/test_programs/execution_success/schnorr/src/main.nr b/test_programs/execution_success/schnorr/src/main.nr index 4e4e602595c..69ae0d2cbd0 100644 --- a/test_programs/execution_success/schnorr/src/main.nr +++ b/test_programs/execution_success/schnorr/src/main.nr @@ -20,6 +20,6 @@ fn main( let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message.as_slice()); + let valid_signature = std::schnorr::verify_signature_array(pub_key_x, pub_key_y, signature, message); assert(valid_signature); } diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index 5bdd04ff9f4..6787cad8366 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -14,6 +14,6 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::sha256(&[x as u8]); + let digest = std::hash::sha256_array([x as u8]); assert(digest == result); } diff --git a/test_programs/execution_success/sha2_byte/src/main.nr b/test_programs/execution_success/sha2_byte/src/main.nr index 0a24a9dc98e..fa8ddfbdf69 100644 --- a/test_programs/execution_success/sha2_byte/src/main.nr +++ b/test_programs/execution_success/sha2_byte/src/main.nr @@ -5,6 +5,6 @@ fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { let digest256 = std::sha256::digest([x as u8]); assert(digest256 == result256); - let digest512 = std::sha512::digest(&[x as u8]); + let digest512 = std::sha512::digest([x as u8]); assert(digest512 == result512); } diff --git a/test_programs/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr index e33326ab749..02a616882e5 100644 --- a/test_programs/execution_success/simple_shield/src/main.nr +++ b/test_programs/execution_success/simple_shield/src/main.nr @@ -17,11 +17,11 @@ fn main( let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; // Compute input note commitment - let note_commitment = std::hash::pedersen_commitment(&[pubkey_x, pubkey_y]); + let note_commitment = std::hash::pedersen_commitment_array([pubkey_x, pubkey_y]); // Compute input note nullifier - let nullifier = std::hash::pedersen_commitment(&[note_commitment.x, index, priv_key]); + let nullifier = std::hash::pedersen_commitment_array([note_commitment.x, index, priv_key]); // Compute output note nullifier - let receiver_note_commitment = std::hash::pedersen_commitment(&[to_pubkey_x, to_pubkey_y]); + let receiver_note_commitment = std::hash::pedersen_commitment_array([to_pubkey_x, to_pubkey_y]); // Check that the input note nullifier is in the root assert(note_root == std::merkle::compute_merkle_root(note_commitment.x, index, note_hash_path)); diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr index 6f039fef285..8e297277711 100644 --- a/test_programs/execution_success/strings/src/main.nr +++ b/test_programs/execution_success/strings/src/main.nr @@ -27,7 +27,7 @@ fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Fie std::print(bad_message); assert(message != bad_message); - let hash = std::hash::pedersen_commitment(&[x]); + let hash = std::hash::pedersen_commitment_array([x]); std::println(hash); std::print(hash); @@ -61,7 +61,7 @@ fn test_prints_array() { std::println(array); - let hash = std::hash::pedersen_commitment(array.as_slice()); + let hash = std::hash::pedersen_commitment_array(array); std::println(hash); } diff --git a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr index 5eda9db4d1a..9ba143503fe 100644 --- a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr +++ b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -10,10 +10,10 @@ fn test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] fn test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment(&[27]).x, 0, "Not equal"); + assert_eq(dep::std::hash::pedersen_commitment_array([27]).x, 0, "Not equal"); } #[test(should_fail)] fn test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment(&[27]).x, 0); + assert_eq(dep::std::hash::pedersen_commitment_array([27]).x, 0); } From e2fdfa9b9414b80b385c49dc4eb316d44ca9b539 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Fri, 15 Mar 2024 17:20:38 -0400 Subject: [PATCH 16/26] fix slice literal from merge --- test_programs/execution_success/array_to_slice/src/main.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_programs/execution_success/array_to_slice/src/main.nr b/test_programs/execution_success/array_to_slice/src/main.nr index 4f5594c6d11..b97f68fc280 100644 --- a/test_programs/execution_success/array_to_slice/src/main.nr +++ b/test_programs/execution_success/array_to_slice/src/main.nr @@ -1,6 +1,6 @@ // Converts an array into a slice. fn as_slice_push(xs: [T; N]) -> [T] { - let mut slice = []; + let mut slice = &[]; for elem in xs { slice = slice.push_back(elem); } From 2a5cb847873d78262ced1074338038e938bce4a3 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 18 Mar 2024 11:40:49 -0400 Subject: [PATCH 17/26] update docs for slices, fix/remove missing docs links, fix duplicated docs links --- docs/docs/explainers/explainer-oracle.md | 2 +- docs/docs/how_to/how-to-oracles.md | 2 +- docs/docs/noir/concepts/data_types/arrays.md | 2 +- docs/docs/noir/concepts/data_types/slices.mdx | 8 +++---- docs/docs/noir/standard_library/bigint.md | 4 ++-- .../noir/standard_library/containers/vec.mdx | 10 ++++----- .../cryptographic_primitives/hashes.mdx | 8 +++---- .../noir/standard_library/merkle_trees.md | 2 +- noir_stdlib/src/bigint.nr | 3 ++- noir_stdlib/src/ecdsa_secp256k1.nr | 4 ++-- noir_stdlib/src/ecdsa_secp256r1.nr | 4 ++-- noir_stdlib/src/hash.nr | 21 +++++++++---------- noir_stdlib/src/schnorr.nr | 4 ++-- 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/docs/explainers/explainer-oracle.md b/docs/docs/explainers/explainer-oracle.md index b84ca5dd986..631d0c32dc7 100644 --- a/docs/docs/explainers/explainer-oracle.md +++ b/docs/docs/explainers/explainer-oracle.md @@ -52,6 +52,6 @@ If you don't constrain the return of your oracle, you could be clearly opening a On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md index 0d84d992320..6947e3c8409 100644 --- a/docs/docs/how_to/how-to-oracles.md +++ b/docs/docs/how_to/how-to-oracles.md @@ -201,7 +201,7 @@ const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc await noir.generateFinalProof(inputs, foreignCallHandler) ``` -As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. +As one can see, in NoirJS, the `foreignCallHandler` function simply means "a callback function that returns a value of type `ForeignCallOutput`. It doesn't have to be an RPC call like in the case for Nargo. :::tip diff --git a/docs/docs/noir/concepts/data_types/arrays.md b/docs/docs/noir/concepts/data_types/arrays.md index a8bd338e736..efce3e95d32 100644 --- a/docs/docs/noir/concepts/data_types/arrays.md +++ b/docs/docs/noir/concepts/data_types/arrays.md @@ -72,7 +72,7 @@ let element = array[0][0]; ``` However, multidimensional slices are not supported. For example, the following code will error at compile time: ```rust -let slice : [[Field]] = []; +let slice : [[Field]] = &[]; ``` ## Types diff --git a/docs/docs/noir/concepts/data_types/slices.mdx b/docs/docs/noir/concepts/data_types/slices.mdx index 4a6ee816aa2..e09418f77e6 100644 --- a/docs/docs/noir/concepts/data_types/slices.mdx +++ b/docs/docs/noir/concepts/data_types/slices.mdx @@ -15,7 +15,7 @@ A slice is a dynamically-sized view into a sequence of elements. They can be res use dep::std::slice; fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; + let mut slice: [Field] = &[0; 2]; let mut new_slice = slice.push_back(6); new_slice.len() @@ -42,7 +42,7 @@ example: ```rust fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; + let mut slice: [Field] = &[0; 2]; let mut new_slice = slice.push_back(6); new_slice.len() @@ -62,7 +62,7 @@ fn push_front(_self: Self, _elem: T) -> Self Example: ```rust -let mut new_slice: [Field] = []; +let mut new_slice: [Field] = &[]; new_slice = new_slice.push_front(20); assert(new_slice[0] == 20); // returns true ``` @@ -112,7 +112,7 @@ fn append(mut self, other: Self) -> Self Example: ```rust -let append = [1, 2].append([3, 4, 5]); +let append = &[1, 2].append(&[3, 4, 5]); ``` ### insert diff --git a/docs/docs/noir/standard_library/bigint.md b/docs/docs/noir/standard_library/bigint.md index 7d7931840cf..9aa4fb77112 100644 --- a/docs/docs/noir/standard_library/bigint.md +++ b/docs/docs/noir/standard_library/bigint.md @@ -31,7 +31,7 @@ For instance the big integer 'Secpk1Fq' in the standard library refers to intege Feel free to explore the source code for the other primes: -#include_code curve_order_base noir_stdlib/src/bigint.nr rust +#include_code big_int_definition noir_stdlib/src/bigint.nr rust ## Example usage @@ -48,7 +48,7 @@ The available operations for each big integer are: Construct a big integer from its little-endian bytes representation. Example: ```rust - let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]); + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); ``` Sure, here's the formatted version of the remaining methods: diff --git a/docs/docs/noir/standard_library/containers/vec.mdx b/docs/docs/noir/standard_library/containers/vec.mdx index 1954f05bc76..7a4bea7e047 100644 --- a/docs/docs/noir/standard_library/containers/vec.mdx +++ b/docs/docs/noir/standard_library/containers/vec.mdx @@ -49,7 +49,7 @@ pub fn from_slice(slice: [T]) -> Self Example: ```rust -let arr: [Field] = [1, 2, 3]; +let arr: [Field] = &[1, 2, 3]; let vector_from_slice = Vec::from_slice(arr); assert(vector_from_slice.len() == 3); ``` @@ -80,7 +80,7 @@ pub fn get(self, index: Field) -> T Example: ```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); +let vector: Vec = Vec::from_slice(&[10, 20, 30]); assert(vector.get(1) == 20); ``` @@ -111,7 +111,7 @@ pub fn pop(&mut self) -> T Example: ```rust -let mut vector = Vec::from_slice([10, 20]); +let mut vector = Vec::from_slice(&[10, 20]); let popped_elem = vector.pop(); assert(popped_elem == 20); assert(vector.len() == 1); @@ -128,7 +128,7 @@ pub fn insert(&mut self, index: Field, elem: T) Example: ```rust -let mut vector = Vec::from_slice([10, 30]); +let mut vector = Vec::from_slice(&[10, 30]); vector.insert(1, 20); assert(vector.get(1) == 20); ``` @@ -144,7 +144,7 @@ pub fn remove(&mut self, index: Field) -> T Example: ```rust -let mut vector = Vec::from_slice([10, 20, 30]); +let mut vector = Vec::from_slice(&[10, 20, 30]); let removed_elem = vector.remove(1); assert(removed_elem == 20); assert(vector.len() == 2); diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index b9239f822e8..aca2f688073 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -20,7 +20,7 @@ example: ```rust fn main() { - let x = [163, 117, 178, 149]; // some random bytes + let x = &[163, 117, 178, 149]; // some random bytes let hash = std::hash::sha256(x); } ``` @@ -37,7 +37,7 @@ example: ```rust fn main() { - let x = [163, 117, 178, 149]; // some random bytes + let x = &[163, 117, 178, 149]; // some random bytes let hash = std::hash::blake2s(x); } ``` @@ -54,7 +54,7 @@ example: ```rust fn main() { - let x = [163, 117, 178, 149]; // some random bytes + let x = &[163, 117, 178, 149]; // some random bytes let hash = std::hash::blake3(x); } ``` @@ -156,7 +156,7 @@ fn main() { ## hash_to_field ```rust -fn hash_to_field(_input : [Field; N]) -> Field {} +fn hash_to_field(_input : [Field]) -> Field {} ``` Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return diff --git a/docs/docs/noir/standard_library/merkle_trees.md b/docs/docs/noir/standard_library/merkle_trees.md index fa488677884..10159d07b38 100644 --- a/docs/docs/noir/standard_library/merkle_trees.md +++ b/docs/docs/noir/standard_library/merkle_trees.md @@ -44,7 +44,7 @@ fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3] let pubkey_y = pubkey[1]; let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); println(root); } ``` diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr index 3afa50e5b6e..39ec40a1480 100644 --- a/noir_stdlib/src/bigint.nr +++ b/noir_stdlib/src/bigint.nr @@ -13,11 +13,12 @@ global secpr1_fq = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; global secpr1_fr = &[0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; - +// docs:start:big_int_definition struct BigInt { pointer: u32, modulus: u32, } +// docs:end:big_int_definition impl BigInt { #[builtin(bigint_add)] diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 244b2571587..92e11e62747 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -10,12 +10,12 @@ pub fn verify_signature( {} #[foreign(ecdsa_secp256k1)] -// docs:start:ecdsa_secp256k1 +// docs:start:ecdsa_secp256k1_array pub fn verify_signature_array( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], message_hash: [u8; N] ) -> bool -// docs:end:ecdsa_secp256k1 +// docs:end:ecdsa_secp256k1_array {} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index bd201fc1687..5205de8dcfb 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -10,12 +10,12 @@ pub fn verify_signature( {} #[foreign(ecdsa_secp256r1)] -// docs:start:ecdsa_secp256r1 +// docs:start:ecdsa_secp256r1_array pub fn verify_signature_array( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], message_hash: [u8; N] ) -> bool -// docs:end:ecdsa_secp256r1 +// docs:end:ecdsa_secp256r1_array {} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 9e755bf6feb..fdc99f8e8ea 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -13,9 +13,9 @@ pub fn sha256(input: [u8]) -> [u8; 32] {} #[foreign(sha256)] -// docs:start:sha256 +// docs:start:sha256_array pub fn sha256_array(input: [u8; N]) -> [u8; 32] -// docs:end:sha256 +// docs:end:sha256_array {} #[foreign(blake2s)] @@ -25,9 +25,9 @@ pub fn blake2s(input: [u8]) -> [u8; 32] {} #[foreign(blake2s)] -// docs:start:blake2s +// docs:start:blake2s_array pub fn blake2s_array(input: [u8; N]) -> [u8; 32] -// docs:end:blake2s +// docs:end:blake2s_array {} #[foreign(blake3)] @@ -37,9 +37,9 @@ pub fn blake3(input: [u8]) -> [u8; 32] {} #[foreign(blake3)] -// docs:start:blake3 +// docs:start:blake3_array pub fn blake3_array(input: [u8; N]) -> [u8; 32] -// docs:end:blake3 +// docs:end:blake3_array {} // docs:start:pedersen_commitment @@ -55,7 +55,6 @@ pub fn pedersen_commitment(input: [Field]) -> PedersenPoint } pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint -// docs:end:pedersen_commitment { pedersen_commitment_with_separator_array(input, 0) } @@ -83,9 +82,9 @@ pub fn pedersen_hash(input: [Field]) -> Field pedersen_hash_with_separator(input, 0) } -// docs:start:pedersen_hash +// docs:start:pedersen_hash_array pub fn pedersen_hash_array(input: [Field; N]) -> Field -// docs:end:pedersen_hash +// docs:end:pedersen_hash_array { pedersen_hash_with_separator_array(input, 0) } @@ -117,9 +116,9 @@ pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32] {} #[foreign(keccak256)] -// docs:start:keccak256 +// docs:start:keccak256_array pub fn keccak256_array(input: [u8; N], message_size: u32) -> [u8; 32] -// docs:end:keccak256 +// docs:end:keccak256_array {} #[foreign(poseidon2_permutation)] diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 18351fca429..12a51fa767e 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -10,12 +10,12 @@ pub fn verify_signature( {} #[foreign(schnorr_verify)] -// docs:start:schnorr_verify +// docs:start:schnorr_verify_array pub fn verify_signature_array( public_key_x: Field, public_key_y: Field, signature: [u8; 64], message: [u8; N] ) -> bool -// docs:end:schnorr_verify +// docs:end:schnorr_verify_array {} From b1302d86c3f62dc9e33b58ae830c9838aa141e7e Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 18 Mar 2024 13:40:53 -0400 Subject: [PATCH 18/26] update docs pass: add missing as_slice's, fix old types for stdlib functions in docs, document slice literals, doc slice len, add docs for _array hash/verify/trait methods, add missing doc ref for pedersen_commitment_array --- docs/docs/how_to/merkle-proof.mdx | 4 +- docs/docs/noir/concepts/data_types/fields.md | 4 +- docs/docs/noir/concepts/data_types/slices.mdx | 19 +++++ docs/docs/noir/concepts/functions.md | 2 +- .../noir/standard_library/containers/vec.mdx | 4 +- .../ecdsa_sig_verification.mdx | 28 ++++++-- .../cryptographic_primitives/hashes.mdx | 71 ++++++++++++++++--- .../cryptographic_primitives/schnorr.mdx | 10 +++ .../noir/standard_library/merkle_trees.md | 2 +- docs/docs/noir/standard_library/recursion.md | 4 +- docs/docs/noir/standard_library/traits.md | 11 ++- docs/docs/noir/standard_library/zeroed.md | 1 + noir_stdlib/src/hash.nr | 2 + 13 files changed, 139 insertions(+), 23 deletions(-) diff --git a/docs/docs/how_to/merkle-proof.mdx b/docs/docs/how_to/merkle-proof.mdx index 34074659ac1..003c7019a93 100644 --- a/docs/docs/how_to/merkle-proof.mdx +++ b/docs/docs/how_to/merkle-proof.mdx @@ -14,7 +14,7 @@ in a merkle tree. use dep::std; fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); + let leaf = std::hash::hash_to_field(message.as_slice()); let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); assert(merkle_root == root); } @@ -27,7 +27,7 @@ random oracle. If only collision resistance is needed, then one can call `std::h instead. ```rust -let leaf = std::hash::hash_to_field(message); +let leaf = std::hash::hash_to_field(message.as_slice()); ``` The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. diff --git a/docs/docs/noir/concepts/data_types/fields.md b/docs/docs/noir/concepts/data_types/fields.md index 99b4aa63549..a10a4810788 100644 --- a/docs/docs/noir/concepts/data_types/fields.md +++ b/docs/docs/noir/concepts/data_types/fields.md @@ -42,7 +42,7 @@ After declaring a Field, you can use these common methods on it: Transforms the field into an array of bits, Little Endian. ```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] ``` example: @@ -59,7 +59,7 @@ fn main() { Transforms the field into an array of bits, Big Endian. ```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] ``` example: diff --git a/docs/docs/noir/concepts/data_types/slices.mdx b/docs/docs/noir/concepts/data_types/slices.mdx index e09418f77e6..5f7f52c7cda 100644 --- a/docs/docs/noir/concepts/data_types/slices.mdx +++ b/docs/docs/noir/concepts/data_types/slices.mdx @@ -22,6 +22,8 @@ fn main() -> pub Field { } ``` +Note that slice literals have a preceeding ampersand, e.g. `&[0; 2]` or `&[1, 2, 3]`. + View the corresponding test file [here][test-file]. [test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr @@ -145,3 +147,20 @@ Example: ```rust let (remove_slice, removed_elem) = slice.remove(3); ``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` diff --git a/docs/docs/noir/concepts/functions.md b/docs/docs/noir/concepts/functions.md index 48aba9cd058..2c9bc33fdfc 100644 --- a/docs/docs/noir/concepts/functions.md +++ b/docs/docs/noir/concepts/functions.md @@ -71,7 +71,7 @@ fn main(x : [Field]) { #[test] fn test_one() { - main([1, 2]); + main(&[1, 2]); } ``` diff --git a/docs/docs/noir/standard_library/containers/vec.mdx b/docs/docs/noir/standard_library/containers/vec.mdx index 7a4bea7e047..fcfd7e07aa0 100644 --- a/docs/docs/noir/standard_library/containers/vec.mdx +++ b/docs/docs/noir/standard_library/containers/vec.mdx @@ -49,8 +49,8 @@ pub fn from_slice(slice: [T]) -> Self Example: ```rust -let arr: [Field] = &[1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); assert(vector_from_slice.len() == 3); ``` diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx index d67a1ac94df..dc1479a53da 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -11,7 +11,8 @@ Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 cur ## ecdsa_secp256k1::verify_signature -Verifier for ECDSA Secp256k1 signatures +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_array for a version that accepts arrays directly. #include_code ecdsa_secp256k1 noir_stdlib/src/ecdsa_secp256k1.nr rust @@ -19,14 +20,25 @@ example: ```rust fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); assert(valid_signature); } ``` + + +## ecdsa_secp256k1::verify_signature_array + +Verifier for ECDSA Secp256k1 signatures where the message is an array. + +#include_code ecdsa_secp256k1_array noir_stdlib/src/ecdsa_secp256k1.nr rust + + + ## ecdsa_secp256r1::verify_signature -Verifier for ECDSA Secp256r1 signatures +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_array for a version that accepts arrays directly. #include_code ecdsa_secp256r1 noir_stdlib/src/ecdsa_secp256r1.nr rust @@ -34,9 +46,17 @@ example: ```rust fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); assert(valid_signature); } ``` + +## ecdsa_secp256r1::verify_signature_array + +Verifier for ECDSA Secp256r1 signatures where the message is an array. + +#include_code ecdsa_secp256r1_array noir_stdlib/src/ecdsa_secp256r1.nr rust + + diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index aca2f688073..4b0b9951f3e 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -12,7 +12,8 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 -Given an array of bytes, returns the resulting sha256 hash. +Given a slice of bytes, returns the resulting sha256 hash. +See sha256_array for a version that works directly on arrays. #include_code sha256 noir_stdlib/src/hash.nr rust @@ -27,9 +28,18 @@ fn main() { +## sha256_array + +A version of sha256 specialized to arrays: + +#include_code sha256_array noir_stdlib/src/hash.nr rust + + + ## blake2s -Given an array of bytes, returns an array with the Blake2 hash +Given a slice of bytes, returns an array with the Blake2 hash +See blake2s_array for a version that works directly on arrays. #include_code blake2s noir_stdlib/src/hash.nr rust @@ -44,9 +54,18 @@ fn main() { +## blake2s_array + +A version of blake2s specialized to arrays: + +#include_code blake2s_array noir_stdlib/src/hash.nr rust + + + ## blake3 -Given an array of bytes, returns an array with the Blake3 hash +Given a slice of bytes, returns an array with the Blake3 hash +See blake3_array for a version that works directly on arrays. #include_code blake3 noir_stdlib/src/hash.nr rust @@ -61,9 +80,18 @@ fn main() { +## blake3_array + +A version of blake3 specialized to arrays: + +#include_code blake3_array noir_stdlib/src/hash.nr rust + + + ## pedersen_hash -Given an array of Fields, returns the Pedersen hash. +Given a slice of Fields, returns the Pedersen hash. +See pedersen_hash_array for a version that works directly on arrays. #include_code pedersen_hash noir_stdlib/src/hash.nr rust @@ -73,10 +101,18 @@ example: +## pedersen_hash_array + +Given an array of Fields, returns the Pedersen hash. + +#include_code pedersen_hash_array noir_stdlib/src/hash.nr rust + + ## pedersen_commitment -Given an array of Fields, returns the Pedersen commitment. +Given a slice of Fields, returns the Pedersen commitment. +See pedersen_commitment_array for a version that works directly on arrays. #include_code pedersen_commitment noir_stdlib/src/hash.nr rust @@ -86,11 +122,20 @@ example: +## pedersen_commitment_array + +Given an array of Fields, returns the Pedersen commitment. + +#include_code pedersen_commitment_array noir_stdlib/src/hash.nr rust + + + ## keccak256 -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. +Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). +See keccak256_array for a version that works directly on arrays and supports +hashing only the first `message_size` bytes of the input. #include_code keccak256 noir_stdlib/src/hash.nr rust @@ -100,6 +145,16 @@ example: +## keccak256_array + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). Specify a message_size to hash only the first +`message_size` bytes of the input. + +#include_code keccak256_array noir_stdlib/src/hash.nr rust + + + ## poseidon Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx index 0e0c358c6e1..8c6dadbd395 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -10,6 +10,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## schnorr::verify_signature Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_array for a version that works directly on arrays. #include_code schnorr_verify noir_stdlib/src/schnorr.nr rust @@ -34,3 +35,12 @@ const signature = Array.from( ``` + +## schnorr::verify_signature_array + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is an array. + +#include_code schnorr_verify_array noir_stdlib/src/schnorr.nr rust + + diff --git a/docs/docs/noir/standard_library/merkle_trees.md b/docs/docs/noir/standard_library/merkle_trees.md index 10159d07b38..6a9ebf72ada 100644 --- a/docs/docs/noir/standard_library/merkle_trees.md +++ b/docs/docs/noir/standard_library/merkle_trees.md @@ -42,7 +42,7 @@ fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3] let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); println(root); diff --git a/docs/docs/noir/standard_library/recursion.md b/docs/docs/noir/standard_library/recursion.md index 9337499dac8..aab5f890ad3 100644 --- a/docs/docs/noir/standard_library/recursion.md +++ b/docs/docs/noir/standard_library/recursion.md @@ -29,8 +29,8 @@ By incorporating this attribute directly in the circuit's definition, tooling li ## Verifying Recursive Proofs ```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} ``` :::info diff --git a/docs/docs/noir/standard_library/traits.md b/docs/docs/noir/standard_library/traits.md index fb6d5ae1c48..e6e7e6d40cb 100644 --- a/docs/docs/noir/standard_library/traits.md +++ b/docs/docs/noir/standard_library/traits.md @@ -32,6 +32,8 @@ impl Default for bool { .. } impl Default for [T; N] where T: Default { .. } +impl Default for [T] { .. } + impl Default for (A, B) where A: Default, B: Default { .. } @@ -46,7 +48,8 @@ impl Default for (A, B, C, D, E) ``` For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. ## `std::convert` @@ -112,6 +115,9 @@ impl Eq for bool { .. } impl Eq for [T; N] where T: Eq { .. } +impl Eq for [T] + where T: Eq { .. } + impl Eq for (A, B) where A: Eq, B: Eq { .. } @@ -154,6 +160,9 @@ impl Ord for bool { .. } impl Ord for [T; N] where T: Ord { .. } +impl Ord for [T] + where T: Ord { .. } + impl Ord for (A, B) where A: Ord, B: Ord { .. } diff --git a/docs/docs/noir/standard_library/zeroed.md b/docs/docs/noir/standard_library/zeroed.md index 97dab02dac2..f450fecdd36 100644 --- a/docs/docs/noir/standard_library/zeroed.md +++ b/docs/docs/noir/standard_library/zeroed.md @@ -18,6 +18,7 @@ This function currently supports the following types: - Bool - Uint - Array +- Slice - String - Tuple - Function diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index fdc99f8e8ea..82ed85026c9 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -54,10 +54,12 @@ pub fn pedersen_commitment(input: [Field]) -> PedersenPoint pedersen_commitment_with_separator(input, 0) } +// docs:start:pedersen_commitment_array pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint { pedersen_commitment_with_separator_array(input, 0) } +// docs:end:pedersen_commitment_array #[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(input: [Field], separator: u32) -> [Field; 2] {} From 3378b8e8bba482cd2ce6b15b69ab24521c6bda57 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 18 Mar 2024 13:46:35 -0400 Subject: [PATCH 19/26] nargo fmt --- noir_stdlib/src/hash.nr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 82ed85026c9..48c65beeaab 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -55,8 +55,7 @@ pub fn pedersen_commitment(input: [Field]) -> PedersenPoint } // docs:start:pedersen_commitment_array -pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint -{ +pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint { pedersen_commitment_with_separator_array(input, 0) } // docs:end:pedersen_commitment_array From f56a4dbbaea88432a8de28b4a609d713e60cd221 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Mon, 18 Mar 2024 20:33:03 -0400 Subject: [PATCH 20/26] Update compiler/noirc_frontend/src/ast/mod.rs Co-authored-by: jfecher --- compiler/noirc_frontend/src/ast/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index a0b131d9add..4547dc2a176 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -83,7 +83,7 @@ impl core::fmt::Display for IntegerBitSize { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum UnresolvedTypeData { FieldElement, - Array(UnresolvedTypeExpression, Box), // [4]Witness = Array(4, Witness) + Array(UnresolvedTypeExpression, Box), // [Field; 4] = Array(4, Field) Slice(Box), Integer(Signedness, IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, From be2d631f1e12e7ad468ba43744857c93c2c2bea8 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Mon, 18 Mar 2024 20:33:21 -0400 Subject: [PATCH 21/26] Update compiler/noirc_frontend/src/hir_def/types.rs Co-authored-by: jfecher --- compiler/noirc_frontend/src/hir_def/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index a4d152c5df7..7fb26aa3879 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -153,6 +153,7 @@ impl Type { match self { Type::Slice(elem) => elem.as_ref().contains_slice(), Type::Array(_, elem) => elem.as_ref().contains_slice(), + Type::Alias(alias, generics) => alias.borrow().get_type(generics).is_nested_slice(), _ => false, } } From 57375cd63e2e26d0951f3d5d0c9c05914cbffdc0 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Mon, 18 Mar 2024 20:36:05 -0400 Subject: [PATCH 22/26] Update docs/docs/noir/standard_library/recursion.md Co-authored-by: jfecher --- docs/docs/noir/standard_library/recursion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/noir/standard_library/recursion.md b/docs/docs/noir/standard_library/recursion.md index aab5f890ad3..a93894043dc 100644 --- a/docs/docs/noir/standard_library/recursion.md +++ b/docs/docs/noir/standard_library/recursion.md @@ -30,7 +30,7 @@ By incorporating this attribute directly in the circuit's definition, tooling li ```rust #[foreign(recursive_aggregation)] -pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} ``` :::info From 1f9257be41e2e4d05670384aa6a2b2e818cc48e3 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Tue, 19 Mar 2024 12:52:22 -0400 Subject: [PATCH 23/26] fix duplicated error match from merging master, add docs differentiating slices from references to arrays, switch _array and _slice type defaults and updates docs/tests --- .../src/hir/type_check/errors.rs | 3 +- docs/docs/noir/concepts/data_types/slices.mdx | 6 +- .../ecdsa_sig_verification.mdx | 20 ++--- .../cryptographic_primitives/hashes.mdx | 73 +++++++++---------- .../cryptographic_primitives/schnorr.mdx | 8 +- noir_stdlib/src/ecdsa_secp256k1.nr | 13 ++-- noir_stdlib/src/ecdsa_secp256r1.nr | 12 +-- noir_stdlib/src/hash.nr | 71 +++++++++--------- noir_stdlib/src/hash/pedersen.nr | 4 +- noir_stdlib/src/merkle.nr | 2 +- noir_stdlib/src/schnorr.nr | 13 ++-- .../intrinsic_die/src/main.nr | 2 +- test_programs/execution_success/6/src/main.nr | 4 +- test_programs/execution_success/7/src/main.nr | 2 +- .../array_dynamic_blackbox_input/src/main.nr | 2 +- .../src/main.nr | 2 +- .../execution_success/blake3/src/main.nr | 2 +- .../brillig_blake2s/src/main.nr | 2 +- .../brillig_blake3/src/main.nr | 2 +- .../brillig_cow_regression/src/main.nr | 4 +- .../brillig_ecdsa_secp256k1/src/main.nr | 2 +- .../brillig_ecdsa_secp256r1/src/main.nr | 2 +- .../brillig_keccak/src/main.nr | 2 +- .../brillig_pedersen/src/main.nr | 8 +- .../brillig_schnorr/src/main.nr | 4 +- .../brillig_sha256/src/main.nr | 2 +- .../conditional_1/src/main.nr | 2 +- .../src/main.nr | 4 +- .../ecdsa_secp256k1/src/main.nr | 4 +- .../ecdsa_secp256r1/src/main.nr | 2 +- .../execution_success/import/src/main.nr | 2 +- .../execution_success/keccak256/src/main.nr | 8 +- .../pedersen_check/src/main.nr | 8 +- .../pedersen_commitment/src/main.nr | 2 +- .../pedersen_hash/src/main.nr | 2 +- .../execution_success/schnorr/src/main.nr | 4 +- .../execution_success/sha256/src/main.nr | 2 +- .../simple_shield/src/main.nr | 6 +- .../execution_success/strings/src/main.nr | 4 +- .../should_fail_with_matches/src/main.nr | 4 +- 40 files changed, 163 insertions(+), 158 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index ab58db44183..4e2a3a8b4a2 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -235,8 +235,7 @@ impl From for Diagnostic { | TypeCheckError::OverflowingAssignment { span, .. } | TypeCheckError::FieldModulo { span } | TypeCheckError::ConstrainedReferenceToUnconstrained { span } - | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } - | TypeCheckError::NonConstantSliceLength { span } => { + | TypeCheckError::NonConstantSliceLength { span } | TypeCheckError::UnconstrainedReferenceToConstrained { span } | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } => { Diagnostic::simple_error(error.to_string(), String::new(), span) diff --git a/docs/docs/noir/concepts/data_types/slices.mdx b/docs/docs/noir/concepts/data_types/slices.mdx index 5f7f52c7cda..828faf4a8f8 100644 --- a/docs/docs/noir/concepts/data_types/slices.mdx +++ b/docs/docs/noir/concepts/data_types/slices.mdx @@ -22,7 +22,11 @@ fn main() -> pub Field { } ``` -Note that slice literals have a preceeding ampersand, e.g. `&[0; 2]` or `&[1, 2, 3]`. +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. View the corresponding test file [here][test-file]. diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx index dc1479a53da..6787c9f46a1 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -12,7 +12,7 @@ Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 cur ## ecdsa_secp256k1::verify_signature Verifier for ECDSA Secp256k1 signatures. -See ecdsa_secp256k1::verify_signature_array for a version that accepts arrays directly. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. #include_code ecdsa_secp256k1 noir_stdlib/src/ecdsa_secp256k1.nr rust @@ -20,25 +20,25 @@ example: ```rust fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } ``` -## ecdsa_secp256k1::verify_signature_array +## ecdsa_secp256k1::verify_signature_slice -Verifier for ECDSA Secp256k1 signatures where the message is an array. +Verifier for ECDSA Secp256k1 signatures where the message is a slice. -#include_code ecdsa_secp256k1_array noir_stdlib/src/ecdsa_secp256k1.nr rust +#include_code ecdsa_secp256k1_slice noir_stdlib/src/ecdsa_secp256k1.nr rust ## ecdsa_secp256r1::verify_signature Verifier for ECDSA Secp256r1 signatures. -See ecdsa_secp256r1::verify_signature_array for a version that accepts arrays directly. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. #include_code ecdsa_secp256r1 noir_stdlib/src/ecdsa_secp256r1.nr rust @@ -46,17 +46,17 @@ example: ```rust fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } ``` -## ecdsa_secp256r1::verify_signature_array +## ecdsa_secp256r1::verify_signature -Verifier for ECDSA Secp256r1 signatures where the message is an array. +Verifier for ECDSA Secp256r1 signatures where the message is a slice. -#include_code ecdsa_secp256r1_array noir_stdlib/src/ecdsa_secp256r1.nr rust +#include_code ecdsa_secp256r1_slice noir_stdlib/src/ecdsa_secp256r1.nr rust diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index 4b0b9951f3e..f98c90a97c8 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -12,8 +12,8 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 -Given a slice of bytes, returns the resulting sha256 hash. -See sha256_array for a version that works directly on arrays. +Given an array of bytes, returns the resulting sha256 hash. +See sha256_slice for a version that works directly on slices. #include_code sha256 noir_stdlib/src/hash.nr rust @@ -21,25 +21,25 @@ example: ```rust fn main() { - let x = &[163, 117, 178, 149]; // some random bytes + let x = [163, 117, 178, 149]; // some random bytes let hash = std::hash::sha256(x); } ``` -## sha256_array +## sha256_slice -A version of sha256 specialized to arrays: +A version of sha256 specialized to slices: -#include_code sha256_array noir_stdlib/src/hash.nr rust +#include_code sha256_slice noir_stdlib/src/hash.nr rust ## blake2s -Given a slice of bytes, returns an array with the Blake2 hash -See blake2s_array for a version that works directly on arrays. +Given an array of bytes, returns an array with the Blake2 hash +See blake2s_slice for a version that works directly on slices. #include_code blake2s noir_stdlib/src/hash.nr rust @@ -47,25 +47,25 @@ example: ```rust fn main() { - let x = &[163, 117, 178, 149]; // some random bytes + let x = [163, 117, 178, 149]; // some random bytes let hash = std::hash::blake2s(x); } ``` -## blake2s_array +## blake2s_slice -A version of blake2s specialized to arrays: +A version of blake2s specialized to slices: -#include_code blake2s_array noir_stdlib/src/hash.nr rust +#include_code blake2s_slice noir_stdlib/src/hash.nr rust ## blake3 -Given a slice of bytes, returns an array with the Blake3 hash -See blake3_array for a version that works directly on arrays. +Given an array of bytes, returns an array with the Blake3 hash +See blake3_slice for a version that works directly on slices. #include_code blake3 noir_stdlib/src/hash.nr rust @@ -73,25 +73,25 @@ example: ```rust fn main() { - let x = &[163, 117, 178, 149]; // some random bytes + let x = [163, 117, 178, 149]; // some random bytes let hash = std::hash::blake3(x); } ``` -## blake3_array +## blake3_slice -A version of blake3 specialized to arrays: +A version of blake3 specialized to slices: -#include_code blake3_array noir_stdlib/src/hash.nr rust +#include_code blake3_slice noir_stdlib/src/hash.nr rust ## pedersen_hash -Given a slice of Fields, returns the Pedersen hash. -See pedersen_hash_array for a version that works directly on arrays. +Given an array of Fields, returns the Pedersen hash. +See pedersen_hash_slice for a version that works directly on slices. #include_code pedersen_hash noir_stdlib/src/hash.nr rust @@ -101,18 +101,18 @@ example: -## pedersen_hash_array +## pedersen_hash_slice -Given an array of Fields, returns the Pedersen hash. +Given a slice of Fields, returns the Pedersen hash. -#include_code pedersen_hash_array noir_stdlib/src/hash.nr rust +#include_code pedersen_hash_slice noir_stdlib/src/hash.nr rust ## pedersen_commitment -Given a slice of Fields, returns the Pedersen commitment. -See pedersen_commitment_array for a version that works directly on arrays. +Given an array of Fields, returns the Pedersen commitment. +See pedersen_commitment_slice for a version that works directly on slices. #include_code pedersen_commitment noir_stdlib/src/hash.nr rust @@ -122,20 +122,20 @@ example: -## pedersen_commitment_array +## pedersen_commitment_slice -Given an array of Fields, returns the Pedersen commitment. +Given a slice of Fields, returns the Pedersen commitment. -#include_code pedersen_commitment_array noir_stdlib/src/hash.nr rust +#include_code pedersen_commitment_slice noir_stdlib/src/hash.nr rust ## keccak256 -Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). -See keccak256_array for a version that works directly on arrays and supports -hashing only the first `message_size` bytes of the input. +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). Specify a message_size to hash only the first +`message_size` bytes of the input. See keccak256_slice for a version that works +directly on slices. #include_code keccak256 noir_stdlib/src/hash.nr rust @@ -145,13 +145,12 @@ example: -## keccak256_array +## keccak256_slice -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. +Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). -#include_code keccak256_array noir_stdlib/src/hash.nr rust +#include_code keccak256_slice noir_stdlib/src/hash.nr rust diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx index 8c6dadbd395..2c9eb18cd34 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -10,7 +10,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## schnorr::verify_signature Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). -See schnorr::verify_signature_array for a version that works directly on arrays. +See schnorr::verify_signature_slice for a version that works directly on slices. #include_code schnorr_verify noir_stdlib/src/schnorr.nr rust @@ -36,11 +36,11 @@ const signature = Array.from( -## schnorr::verify_signature_array +## schnorr::verify_signature_slice Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) -where the message is an array. +where the message is a slice. -#include_code schnorr_verify_array noir_stdlib/src/schnorr.nr rust +#include_code schnorr_verify_slice noir_stdlib/src/schnorr.nr rust diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 92e11e62747..f84e2221f57 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,21 +1,22 @@ #[foreign(ecdsa_secp256k1)] // docs:start:ecdsa_secp256k1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8] + message_hash: [u8; N] ) -> bool // docs:end:ecdsa_secp256k1 {} #[foreign(ecdsa_secp256k1)] -// docs:start:ecdsa_secp256k1_array -pub fn verify_signature_array( +// docs:start:ecdsa_secp256k1_slice +pub fn verify_signature_slice( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8; N] + message_hash: [u8] ) -> bool -// docs:end:ecdsa_secp256k1_array +// docs:end:ecdsa_secp256k1_slice {} + diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index 5205de8dcfb..76e68aeeafa 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,21 +1,21 @@ #[foreign(ecdsa_secp256r1)] // docs:start:ecdsa_secp256r1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8] + message_hash: [u8; N] ) -> bool // docs:end:ecdsa_secp256r1 {} #[foreign(ecdsa_secp256r1)] -// docs:start:ecdsa_secp256r1_array -pub fn verify_signature_array( +// docs:start:ecdsa_secp256r1_slice +pub fn verify_signature_slice( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], - message_hash: [u8; N] + message_hash: [u8] ) -> bool -// docs:end:ecdsa_secp256r1_array +// docs:end:ecdsa_secp256r1_slice {} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 48c65beeaab..bc317a36884 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -8,38 +8,38 @@ use crate::uint128::U128; #[foreign(sha256)] // docs:start:sha256 -pub fn sha256(input: [u8]) -> [u8; 32] +pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 {} #[foreign(sha256)] -// docs:start:sha256_array -pub fn sha256_array(input: [u8; N]) -> [u8; 32] -// docs:end:sha256_array +// docs:start:sha256_slice +pub fn sha256_slice(input: [u8]) -> [u8; 32] +// docs:end:sha256_slice {} #[foreign(blake2s)] // docs:start:blake2s -pub fn blake2s(input: [u8]) -> [u8; 32] +pub fn blake2s(input: [u8; N]) -> [u8; 32] // docs:end:blake2s {} #[foreign(blake2s)] -// docs:start:blake2s_array -pub fn blake2s_array(input: [u8; N]) -> [u8; 32] -// docs:end:blake2s_array +// docs:start:blake2s_slice +pub fn blake2s_slice(input: [u8]) -> [u8; 32] +// docs:end:blake2s_slice {} #[foreign(blake3)] // docs:start:blake3 -pub fn blake3(input: [u8]) -> [u8; 32] +pub fn blake3(input: [u8; N]) -> [u8; 32] // docs:end:blake3 {} #[foreign(blake3)] -// docs:start:blake3_array -pub fn blake3_array(input: [u8; N]) -> [u8; 32] -// docs:end:blake3_array +// docs:start:blake3_slice +pub fn blake3_slice(input: [u8]) -> [u8; 32] +// docs:end:blake3_slice {} // docs:start:pedersen_commitment @@ -48,53 +48,54 @@ struct PedersenPoint { y : Field, } -pub fn pedersen_commitment(input: [Field]) -> PedersenPoint +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { // docs:end:pedersen_commitment -{ pedersen_commitment_with_separator(input, 0) } -// docs:start:pedersen_commitment_array -pub fn pedersen_commitment_array(input: [Field; N]) -> PedersenPoint { - pedersen_commitment_with_separator_array(input, 0) +// docs:start:pedersen_commitment_slice +pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint +{ + pedersen_commitment_with_separator_slice(input, 0) } -// docs:end:pedersen_commitment_array +// docs:end:pedersen_commitment_slice + #[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator(input: [Field], separator: u32) -> [Field; 2] {} +pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} #[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator_array(input: [Field; N], separator: u32) -> [Field; 2] {} +pub fn __pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> [Field; 2] {} -pub fn pedersen_commitment_with_separator(input: [Field], separator: u32) -> PedersenPoint { +pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { let values = __pedersen_commitment_with_separator(input, separator); PedersenPoint { x: values[0], y: values[1] } } -pub fn pedersen_commitment_with_separator_array(input: [Field; N], separator: u32) -> PedersenPoint { - let values = __pedersen_commitment_with_separator_array(input, separator); +pub fn pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> PedersenPoint { + let values = __pedersen_commitment_with_separator_slice(input, separator); PedersenPoint { x: values[0], y: values[1] } } // docs:start:pedersen_hash -pub fn pedersen_hash(input: [Field]) -> Field +pub fn pedersen_hash(input: [Field; N]) -> Field // docs:end:pedersen_hash { pedersen_hash_with_separator(input, 0) } -// docs:start:pedersen_hash_array -pub fn pedersen_hash_array(input: [Field; N]) -> Field -// docs:end:pedersen_hash_array +// docs:start:pedersen_hash_slice +pub fn pedersen_hash_slice(input: [Field]) -> Field +// docs:end:pedersen_hash_slice { - pedersen_hash_with_separator_array(input, 0) + pedersen_hash_with_separator_slice(input, 0) } #[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator(input: [Field], separator: u32) -> Field {} +pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} #[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator_array(input: [Field; N], separator: u32) -> Field {} +pub fn pedersen_hash_with_separator_slice(input: [Field], separator: u32) -> Field {} pub fn hash_to_field(inputs: [Field]) -> Field { let mut inputs_as_bytes = &[]; @@ -106,20 +107,20 @@ pub fn hash_to_field(inputs: [Field]) -> Field { } } - let hashed_input = blake2s(inputs_as_bytes); + let hashed_input = blake2s_slice(inputs_as_bytes); crate::field::bytes32_to_field(hashed_input) } #[foreign(keccak256)] // docs:start:keccak256 -pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32] +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} #[foreign(keccak256)] -// docs:start:keccak256_array -pub fn keccak256_array(input: [u8; N], message_size: u32) -> [u8; 32] -// docs:end:keccak256_array +// docs:start:keccak256_slice +pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] +// docs:end:keccak256_slice {} #[foreign(poseidon2_permutation)] diff --git a/noir_stdlib/src/hash/pedersen.nr b/noir_stdlib/src/hash/pedersen.nr index 09e436a32ae..ad21e728945 100644 --- a/noir_stdlib/src/hash/pedersen.nr +++ b/noir_stdlib/src/hash/pedersen.nr @@ -1,4 +1,4 @@ -use crate::hash::{Hasher, pedersen_hash}; +use crate::hash::{Hasher, pedersen_hash_slice}; use crate::default::Default; struct PedersenHasher{ @@ -7,7 +7,7 @@ struct PedersenHasher{ impl Hasher for PedersenHasher { fn finish(self) -> Field { - pedersen_hash(self._state) + pedersen_hash_slice(self._state) } fn write(&mut self, input: [Field]){ diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr index be31768ed57..9b15fe7313d 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -13,7 +13,7 @@ pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) } else { (current, hash_path[i]) }; - current = crate::hash::pedersen_hash_array([hash_left, hash_right]); + current = crate::hash::pedersen_hash([hash_left, hash_right]); } current } diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 12a51fa767e..c63915061cb 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -1,21 +1,22 @@ #[foreign(schnorr_verify)] // docs:start:schnorr_verify -pub fn verify_signature( +pub fn verify_signature( public_key_x: Field, public_key_y: Field, signature: [u8; 64], - message: [u8] + message: [u8; N] ) -> bool // docs:end:schnorr_verify {} #[foreign(schnorr_verify)] -// docs:start:schnorr_verify_array -pub fn verify_signature_array( +// docs:start:schnorr_verify_slice +pub fn verify_signature_slice( public_key_x: Field, public_key_y: Field, signature: [u8; 64], - message: [u8; N] + message: [u8] ) -> bool -// docs:end:schnorr_verify_array +// docs:end:schnorr_verify_slice {} + diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr index 0551ddd246c..8cac707dfea 100644 --- a/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -1,6 +1,6 @@ use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { - let hash = std::hash::pedersen_commitment_array([x]); + let hash = std::hash::pedersen_commitment([x]); let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); } diff --git a/test_programs/execution_success/6/src/main.nr b/test_programs/execution_success/6/src/main.nr index e1e063ede00..5ecb809e68b 100644 --- a/test_programs/execution_success/6/src/main.nr +++ b/test_programs/execution_success/6/src/main.nr @@ -8,9 +8,9 @@ use dep::std; fn main(x: [u8; 5], result: pub [u8; 32]) { - let mut digest = std::hash::sha256_array(x); + let mut digest = std::hash::sha256(x); digest[0] = 5 as u8; - digest = std::hash::sha256_array(x); + digest = std::hash::sha256(x); assert(digest == result); let y = [12, 45, 78, 41]; diff --git a/test_programs/execution_success/7/src/main.nr b/test_programs/execution_success/7/src/main.nr index ae27a4e4926..a6bba978644 100644 --- a/test_programs/execution_success/7/src/main.nr +++ b/test_programs/execution_success/7/src/main.nr @@ -5,6 +5,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake2s_array(x); + let digest = std::hash::blake2s(x); assert(digest == result); } diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr index ed92929a70c..4cbf1bd8e6d 100644 --- a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr @@ -18,7 +18,7 @@ fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { hash_input[j + b] = path[offset + j]; } - current = dep::std::hash::sha256_array(hash_input); + current = dep::std::hash::sha256(hash_input); index = index >> 1; } diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr index fc9c01ccbac..8faaf69dfc8 100644 --- a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr @@ -15,6 +15,6 @@ fn main(mut x: [Foo; 3], y: pub Field, hash_result: pub [u8; 32]) { // Make sure that we are passing a dynamic array to the black box function call // by setting the array using a dynamic index here hash_input[y - 1] = 0; - let hash = dep::std::hash::sha256_array(hash_input); + let hash = dep::std::hash::sha256(hash_input); assert_eq(hash, hash_result); } diff --git a/test_programs/execution_success/blake3/src/main.nr b/test_programs/execution_success/blake3/src/main.nr index c0b460382e1..3bfea6c5f95 100644 --- a/test_programs/execution_success/blake3/src/main.nr +++ b/test_programs/execution_success/blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3_array(x); + let digest = std::hash::blake3(x); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_blake2s/src/main.nr b/test_programs/execution_success/brillig_blake2s/src/main.nr index ef2b19ae30c..5bd52666ae9 100644 --- a/test_programs/execution_success/brillig_blake2s/src/main.nr +++ b/test_programs/execution_success/brillig_blake2s/src/main.nr @@ -7,5 +7,5 @@ fn main(x: [u8; 5], result: [u8; 32]) { } unconstrained fn blake2s(x: [u8; 5]) -> [u8; 32] { - std::hash::blake2s_array(x) + std::hash::blake2s(x) } diff --git a/test_programs/execution_success/brillig_blake3/src/main.nr b/test_programs/execution_success/brillig_blake3/src/main.nr index dfabe441651..05a5b31f936 100644 --- a/test_programs/execution_success/brillig_blake3/src/main.nr +++ b/test_programs/execution_success/brillig_blake3/src/main.nr @@ -1,6 +1,6 @@ use dep::std; unconstrained fn main(x: [u8; 5], result: [u8; 32]) { - let digest = std::hash::blake3_array(x); + let digest = std::hash::blake3(x); assert(digest == result); } diff --git a/test_programs/execution_success/brillig_cow_regression/src/main.nr b/test_programs/execution_success/brillig_cow_regression/src/main.nr index 0032a3e8918..1cae9b1ba41 100644 --- a/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -25,7 +25,7 @@ struct NewContractData { impl NewContractData { fn hash(self) -> Field { - dep::std::hash::pedersen_hash_array([self.contract_address, self.portal_contract_address]) + dep::std::hash::pedersen_hash([self.contract_address, self.portal_contract_address]) } } @@ -173,6 +173,6 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA } } - let sha_digest = dep::std::hash::sha256_array(hash_input_flattened); + let sha_digest = dep::std::hash::sha256(hash_input_flattened); U256::from_bytes32(sha_digest).to_u128_limbs() } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr index a8b6ed0f88b..5d84d885567 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256k1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message) + std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr index 272cc994ea6..9da07f531aa 100644 --- a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr @@ -12,5 +12,5 @@ unconstrained fn ecdsa( pub_key_y: [u8; 32], signature: [u8; 64] ) -> bool { - std::ecdsa_secp256r1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message) + std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/test_programs/execution_success/brillig_keccak/src/main.nr b/test_programs/execution_success/brillig_keccak/src/main.nr index 7657c64ce9d..a300bc18279 100644 --- a/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/test_programs/execution_success/brillig_keccak/src/main.nr @@ -21,5 +21,5 @@ fn main(x: Field, result: [u8; 32]) { } unconstrained fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { - std::hash::keccak256_array(data, msg_len) + std::hash::keccak256(data, msg_len) } diff --git a/test_programs/execution_success/brillig_pedersen/src/main.nr b/test_programs/execution_success/brillig_pedersen/src/main.nr index 82d144bd8ab..2379818c454 100644 --- a/test_programs/execution_success/brillig_pedersen/src/main.nr +++ b/test_programs/execution_success/brillig_pedersen/src/main.nr @@ -1,11 +1,11 @@ use dep::std; unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment_with_separator_array([x, y], 0); + let res = std::hash::pedersen_commitment_with_separator([x, y], 0); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator_array([x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Fiel state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment_with_separator_array([state], 0); - assert(std::hash::pedersen_commitment_with_separator_array([43], 0).x == hash.x); + let hash = std::hash::pedersen_commitment_with_separator([state], 0); + assert(std::hash::pedersen_commitment_with_separator([43], 0).x == hash.x); } diff --git a/test_programs/execution_success/brillig_schnorr/src/main.nr b/test_programs/execution_success/brillig_schnorr/src/main.nr index da210b3c798..03c635b4f6f 100644 --- a/test_programs/execution_success/brillig_schnorr/src/main.nr +++ b/test_programs/execution_success/brillig_schnorr/src/main.nr @@ -17,9 +17,9 @@ unconstrained fn main( // Is there ever a situation where someone would want // to ensure that a signature was invalid? // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); + let valid_signature = std::schnorr::verify_signature_slice(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature_array(pub_key_x, pub_key_y, signature, message); + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); assert(valid_signature); } diff --git a/test_programs/execution_success/brillig_sha256/src/main.nr b/test_programs/execution_success/brillig_sha256/src/main.nr index f3ce02a3739..e76109df9c3 100644 --- a/test_programs/execution_success/brillig_sha256/src/main.nr +++ b/test_programs/execution_success/brillig_sha256/src/main.nr @@ -9,6 +9,6 @@ fn main(x: Field, result: [u8; 32]) { unconstrained fn sha256(x: Field) -> [u8; 32] { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - std::hash::sha256_array([x as u8]) + std::hash::sha256([x as u8]) } diff --git a/test_programs/execution_success/conditional_1/src/main.nr b/test_programs/execution_success/conditional_1/src/main.nr index 96ca3937319..5064c82bce9 100644 --- a/test_programs/execution_success/conditional_1/src/main.nr +++ b/test_programs/execution_success/conditional_1/src/main.nr @@ -55,7 +55,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { let mut y = 0; if a == 0 { - let digest = std::hash::sha256_array(x); + let digest = std::hash::sha256(x); y = digest[0]; } else { y = 5; diff --git a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr index 600a49f0c24..d260fa49dc3 100644 --- a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr +++ b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr @@ -26,9 +26,9 @@ fn bar(x: Field) { } fn call_intrinsic(x: [u8; 5], result: [u8; 32]) { - let mut digest = std::hash::sha256_array(x); + let mut digest = std::hash::sha256(x); digest[0] = 5 as u8; - digest = std::hash::sha256_array(x); + digest = std::hash::sha256(x); assert(digest == result); } diff --git a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr index 510ed402e52..ac0359e4bb8 100644 --- a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -8,9 +8,9 @@ fn main( signature: [u8; 64] ) { // Hash the message, since secp256k1 expects a hashed_message - let expected = std::hash::sha256_array(message); + let expected = std::hash::sha256(message); assert(hashed_message == expected); - let valid_signature = std::ecdsa_secp256k1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } diff --git a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr index 9bdb99d7fce..c64e390d652 100644 --- a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr +++ b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr @@ -1,6 +1,6 @@ use dep::std; fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature_array(pub_key_x, pub_key_y, signature, hashed_message); + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); } diff --git a/test_programs/execution_success/import/src/main.nr b/test_programs/execution_success/import/src/main.nr index 991d8904901..7dcc16fed16 100644 --- a/test_programs/execution_success/import/src/main.nr +++ b/test_programs/execution_success/import/src/main.nr @@ -2,7 +2,7 @@ mod import; use crate::import::hello; fn main(x: Field, y: Field) { - let _k = dep::std::hash::pedersen_commitment_array([x]); + let _k = dep::std::hash::pedersen_commitment([x]); let _l = hello(x); assert(x != import::hello(y)); diff --git a/test_programs/execution_success/keccak256/src/main.nr b/test_programs/execution_success/keccak256/src/main.nr index 2e4c3d7e4d7..eb401fe614c 100644 --- a/test_programs/execution_success/keccak256/src/main.nr +++ b/test_programs/execution_success/keccak256/src/main.nr @@ -4,18 +4,18 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::keccak256_array([x as u8], 1); + let digest = std::hash::keccak256([x as u8], 1); assert(digest == result); //#1399: variable message size let message_size = 4; - let hash_a = std::hash::keccak256_array([1, 2, 3, 4], message_size); - let hash_b = std::hash::keccak256_array([1, 2, 3, 4, 0, 0, 0, 0], message_size); + let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); assert(hash_a == hash_b); let message_size_big = 8; - let hash_c = std::hash::keccak256_array([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); assert(hash_a != hash_c); } diff --git a/test_programs/execution_success/pedersen_check/src/main.nr b/test_programs/execution_success/pedersen_check/src/main.nr index df0a2b91acd..90ef218249b 100644 --- a/test_programs/execution_success/pedersen_check/src/main.nr +++ b/test_programs/execution_success/pedersen_check/src/main.nr @@ -1,11 +1,11 @@ use dep::std; fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_commitment_array([x, y]); + let res = std::hash::pedersen_commitment([x, y]); assert(res.x == out_x); assert(res.y == out_y); - let res_hash = std::hash::pedersen_hash_with_separator_array([x, y], 0); + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); assert_eq(res_hash, out_hash); assert(res_hash != res.x); @@ -16,7 +16,7 @@ fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: F state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_commitment_array([state]); - assert(std::hash::pedersen_commitment_array([43]).x == hash.x); + let hash = std::hash::pedersen_commitment([state]); + assert(std::hash::pedersen_commitment([43]).x == hash.x); } diff --git a/test_programs/execution_success/pedersen_commitment/src/main.nr b/test_programs/execution_success/pedersen_commitment/src/main.nr index 95f9074532f..83cbe20851d 100644 --- a/test_programs/execution_success/pedersen_commitment/src/main.nr +++ b/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { - let commitment = std::hash::pedersen_commitment_array([x, y]); + let commitment = std::hash::pedersen_commitment([x, y]); assert_eq(commitment.x, expected_commitment.x); assert_eq(commitment.y, expected_commitment.y); } diff --git a/test_programs/execution_success/pedersen_hash/src/main.nr b/test_programs/execution_success/pedersen_hash/src/main.nr index bcdfd2c249f..20c7de12d6c 100644 --- a/test_programs/execution_success/pedersen_hash/src/main.nr +++ b/test_programs/execution_success/pedersen_hash/src/main.nr @@ -2,7 +2,7 @@ use dep::std; fn main(x: Field, y: Field, expected_hash: Field) { - let hash = std::hash::pedersen_hash_array([x, y]); + let hash = std::hash::pedersen_hash([x, y]); assert_eq(hash, expected_hash); } // docs:end:pedersen-hash diff --git a/test_programs/execution_success/schnorr/src/main.nr b/test_programs/execution_success/schnorr/src/main.nr index 69ae0d2cbd0..9e2838c34d9 100644 --- a/test_programs/execution_success/schnorr/src/main.nr +++ b/test_programs/execution_success/schnorr/src/main.nr @@ -17,9 +17,9 @@ fn main( // Is there ever a situation where someone would want // to ensure that a signature was invalid? // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); + let valid_signature = std::schnorr::verify_signature_slice(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature_array(pub_key_x, pub_key_y, signature, message); + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); assert(valid_signature); } diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index 6787cad8366..fd5340e2384 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -14,6 +14,6 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::sha256_array([x as u8]); + let digest = std::hash::sha256([x as u8]); assert(digest == result); } diff --git a/test_programs/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr index 02a616882e5..c46d3b4594c 100644 --- a/test_programs/execution_success/simple_shield/src/main.nr +++ b/test_programs/execution_success/simple_shield/src/main.nr @@ -17,11 +17,11 @@ fn main( let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; // Compute input note commitment - let note_commitment = std::hash::pedersen_commitment_array([pubkey_x, pubkey_y]); + let note_commitment = std::hash::pedersen_commitment([pubkey_x, pubkey_y]); // Compute input note nullifier - let nullifier = std::hash::pedersen_commitment_array([note_commitment.x, index, priv_key]); + let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); // Compute output note nullifier - let receiver_note_commitment = std::hash::pedersen_commitment_array([to_pubkey_x, to_pubkey_y]); + let receiver_note_commitment = std::hash::pedersen_commitment([to_pubkey_x, to_pubkey_y]); // Check that the input note nullifier is in the root assert(note_root == std::merkle::compute_merkle_root(note_commitment.x, index, note_hash_path)); diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr index 8e297277711..cff229d368a 100644 --- a/test_programs/execution_success/strings/src/main.nr +++ b/test_programs/execution_success/strings/src/main.nr @@ -27,7 +27,7 @@ fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Fie std::print(bad_message); assert(message != bad_message); - let hash = std::hash::pedersen_commitment_array([x]); + let hash = std::hash::pedersen_commitment([x]); std::println(hash); std::print(hash); @@ -61,7 +61,7 @@ fn test_prints_array() { std::println(array); - let hash = std::hash::pedersen_commitment_array(array); + let hash = std::hash::pedersen_commitment(array); std::println(hash); } diff --git a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr index 9ba143503fe..d2b7d155a32 100644 --- a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr +++ b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -10,10 +10,10 @@ fn test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] fn test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment_array([27]).x, 0, "Not equal"); + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); } #[test(should_fail)] fn test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment_array([27]).x, 0); + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); } From bc28b78b8b6cf70890ae8f684191cf97152917c8 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Tue, 19 Mar 2024 13:01:05 -0400 Subject: [PATCH 24/26] nargo fmt --- noir_stdlib/src/hash.nr | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index bc317a36884..2de4cb3745e 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -49,18 +49,16 @@ struct PedersenPoint { } pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { -// docs:end:pedersen_commitment + // docs:end:pedersen_commitment pedersen_commitment_with_separator(input, 0) } // docs:start:pedersen_commitment_slice -pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint -{ +pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { pedersen_commitment_with_separator_slice(input, 0) } // docs:end:pedersen_commitment_slice - #[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} From 93a1e0251bf8d53e27a91fb0fb379121c489044b Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Tue, 19 Mar 2024 13:17:46 -0400 Subject: [PATCH 25/26] fix array/slice for hash in wasm test --- compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr index 4bbd136e409..0376cd4cb87 100644 --- a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr +++ b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr @@ -1,3 +1,3 @@ pub fn bar(param: Field) -> Field { - dep::std::hash::pedersen_hash(&[param]) + dep::std::hash::pedersen_hash([param]) } From e2b2ba964c6929444bcaaf75071d89a9adb92b92 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Tue, 19 Mar 2024 15:33:55 -0400 Subject: [PATCH 26/26] include len in slice's hash, revert broken link fixes (reference folder in docs) --- docs/docs/explainers/explainer-oracle.md | 2 +- docs/docs/how_to/how-to-oracles.md | 2 +- noir_stdlib/src/hash.nr | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/docs/explainers/explainer-oracle.md b/docs/docs/explainers/explainer-oracle.md index 631d0c32dc7..b84ca5dd986 100644 --- a/docs/docs/explainers/explainer-oracle.md +++ b/docs/docs/explainers/explainer-oracle.md @@ -52,6 +52,6 @@ If you don't constrain the return of your oracle, you could be clearly opening a On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. -In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md index 6947e3c8409..0d84d992320 100644 --- a/docs/docs/how_to/how-to-oracles.md +++ b/docs/docs/how_to/how-to-oracles.md @@ -201,7 +201,7 @@ const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc await noir.generateFinalProof(inputs, foreignCallHandler) ``` -As one can see, in NoirJS, the `foreignCallHandler` function simply means "a callback function that returns a value of type `ForeignCallOutput`. It doesn't have to be an RPC call like in the case for Nargo. +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. :::tip diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 2de4cb3745e..1a61b5e084e 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -236,6 +236,7 @@ impl Hash for [T; N] where T: Hash { impl Hash for [T] where T: Hash { fn hash(self, state: &mut H) where H: Hasher{ + self.len().hash(state); for elem in self { elem.hash(state); }