diff --git a/Cargo.lock b/Cargo.lock index 17d714fe9bb..f6011b705e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2906,6 +2906,7 @@ version = "0.32.0" dependencies = [ "acvm", "base64 0.21.2", + "bn254_blackbox_solver", "cfg-if 1.0.0", "chumsky", "fm", diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index 052d2c5f484..f7439a09204 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -10,6 +10,7 @@ license.workspace = true [dependencies] acvm.workspace = true +bn254_blackbox_solver.workspace = true noirc_arena.workspace = true noirc_errors.workspace = true noirc_printable_type.workspace = true diff --git a/compiler/noirc_frontend/src/hir/comptime/errors.rs b/compiler/noirc_frontend/src/hir/comptime/errors.rs index 0472b0040e5..b52201146dd 100644 --- a/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -7,7 +7,7 @@ use crate::{ token::Tokens, Type, }; -use acvm::{acir::AcirField, FieldElement}; +use acvm::{acir::AcirField, BlackBoxResolutionError, FieldElement}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Location}; @@ -53,13 +53,11 @@ pub enum InterpreterError { NoImpl { location: Location }, NoMatchingImplFound { error: NoMatchingImplFoundError, file: FileId }, ImplMethodTypeMismatch { expected: Type, actual: Type, location: Location }, - - Unimplemented { item: String, location: Location }, - - // Perhaps this should be unreachable! due to type checking also preventing this error? - // Currently it and the Continue variant are the only interpreter errors without a Location field BreakNotInLoop { location: Location }, ContinueNotInLoop { location: Location }, + BlackBoxError(BlackBoxResolutionError, Location), + + Unimplemented { item: String, location: Location }, // These cases are not errors, they are just used to prevent us from running more code // until the loop can be resumed properly. These cases will never be displayed to users. @@ -118,9 +116,11 @@ impl InterpreterError { | InterpreterError::Unimplemented { location, .. } | InterpreterError::NoImpl { location, .. } | InterpreterError::ImplMethodTypeMismatch { location, .. } + | InterpreterError::DebugEvaluateComptime { location, .. } + | InterpreterError::BlackBoxError(_, location) | InterpreterError::BreakNotInLoop { location, .. } - | InterpreterError::DebugEvaluateComptime { location, .. } => *location, - InterpreterError::ContinueNotInLoop { location, .. } => *location, + | InterpreterError::ContinueNotInLoop { location, .. } => *location, + InterpreterError::FailedToParseMacro { error, file, .. } => { Location::new(error.span(), *file) } @@ -370,6 +370,9 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { ); CustomDiagnostic::simple_error(msg, String::new(), location.span) } + InterpreterError::BlackBoxError(error, location) => { + CustomDiagnostic::simple_error(error.to_string(), String::new(), location.span) + } InterpreterError::NoMatchingImplFound { error, .. } => error.into(), InterpreterError::Break => unreachable!("Uncaught InterpreterError::Break"), InterpreterError::Continue => unreachable!("Uncaught InterpreterError::Continue"), diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 7c144ce2782..3f0ea38a617 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -103,6 +103,15 @@ fn get_slice( } } +pub(super) fn get_field(value: Value, location: Location) -> IResult { + match value { + Value::Field(value) => Ok(value), + value => { + Err(InterpreterError::TypeMismatch { expected: Type::FieldElement, value, location }) + } + } +} + pub(super) fn get_u32(value: Value, location: Location) -> IResult { match value { Value::U32(value) => Ok(value), diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs index 4a8a7edb427..fc8c57ab634 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs @@ -1,13 +1,14 @@ - -use acvm::{AcirField, FieldElement, BlackBoxFunctionSolver}; +use acvm::BlackBoxFunctionSolver; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use iter_extended::try_vecmap; use noirc_errors::Location; use crate::{ - hir::comptime::{errors::IResult, InterpreterError, Value}, + hir::comptime::{errors::IResult, interpreter::builtin::get_field, InterpreterError, Value}, macros_api::NodeInterner, }; -use super::builtin::{check_argument_count, get_u32, get_array}; +use super::builtin::{check_argument_count, get_array, get_u32}; pub(super) fn call_foreign( interner: &mut NodeInterner, @@ -25,15 +26,23 @@ pub(super) fn call_foreign( } // poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] -fn posdon2_permutation( +fn poseidon2_permutation( interner: &mut NodeInterner, mut arguments: Vec<(Value, Location)>, location: Location, ) -> IResult { check_argument_count(2, &arguments, location)?; - let state_length = get_u32(arguments.pop().unwrap().0, location); - let input = get_array(interner, arguments.pop().unwrap().0, location); + let state_length = get_u32(arguments.pop().unwrap().0, location)?; + let (input, typ) = get_array(interner, arguments.pop().unwrap().0, location)?; + + let input = try_vecmap(input, |integer| get_field(integer, location))?; + + // Currently locked to only bn254! + let fields = Bn254BlackBoxSolver + .poseidon2_permutation(&input, state_length) + .map_err(|error| InterpreterError::BlackBoxError(error, location))?; - let result = Bn254BlackBoxSolver.poseidon2_permutation(inputs, state_length); + let array = fields.into_iter().map(Value::Field).collect(); + Ok(Value::Array(array, typ)) }