diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 662b024d6b7..3680a1661d8 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: pull_request: paths: - - ./compiler/integration-tests + - ./compiler/integration-tests/** schedule: - cron: "0 2 * * *" # Run nightly at 2 AM UTC diff --git a/Cargo.lock b/Cargo.lock index 6050e15ad28..3464172b513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2358,6 +2358,7 @@ dependencies = [ "base64", "clap", "fm", + "fxhash", "noirc_abi", "noirc_errors", "noirc_evaluator", diff --git a/Cargo.toml b/Cargo.toml index 343bad4918f..d7df1363921 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ # Crates related to tooling built ontop of the Noir compiler "tooling/backend_interface", "tooling/bb_abstraction_leaks", + "tooling/lsp", "tooling/nargo", "tooling/nargo_cli", "tooling/nargo_toml", @@ -71,3 +72,4 @@ url = "2.2.0" wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] } wasm-bindgen-test = "0.3.33" base64 = "0.21.2" +fxhash = "0.2.1" diff --git a/compiler/fm/Cargo.toml b/compiler/fm/Cargo.toml index 1f6d6dabcb1..54e302c61e0 100644 --- a/compiler/fm/Cargo.toml +++ b/compiler/fm/Cargo.toml @@ -13,7 +13,7 @@ cfg-if.workspace = true rust-embed = "6.6.0" serde.workspace = true -[target.'cfg(target_arch = "wasm32")'.dependencies] +[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] wasm-bindgen.workspace = true [dev-dependencies] diff --git a/compiler/fm/src/file_reader.rs b/compiler/fm/src/file_reader.rs index 887d0b12f88..08df5abc349 100644 --- a/compiler/fm/src/file_reader.rs +++ b/compiler/fm/src/file_reader.rs @@ -22,7 +22,7 @@ pub(super) fn is_stdlib_asset(path: &Path) -> bool { } cfg_if::cfg_if! { - if #[cfg(target_arch = "wasm32")] { + if #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))] { use wasm_bindgen::{prelude::*, JsValue}; #[wasm_bindgen(module = "@noir-lang/source-resolver")] diff --git a/compiler/integration-tests/test/integration/browser/compile_prove_verify.test.ts b/compiler/integration-tests/test/integration/browser/compile_prove_verify.test.ts index 5b390d566a8..19f6fc4a804 100644 --- a/compiler/integration-tests/test/integration/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/integration/browser/compile_prove_verify.test.ts @@ -56,11 +56,11 @@ test_cases.forEach((testInfo) => { const noir_source_url = new URL( `${base_relative_path}/${test_case}/src/main.nr`, - import.meta.url + import.meta.url, ); const prover_toml_url = new URL( `${base_relative_path}/${test_case}/Prover.toml`, - import.meta.url + import.meta.url, ); const noir_source = await getFile(noir_source_url); @@ -101,7 +101,7 @@ test_cases.forEach((testInfo) => { try { compressedByteCode = Uint8Array.from( atob(compile_output.circuit), - (c) => c.charCodeAt(0) + (c) => c.charCodeAt(0), ); solvedWitness = await executeCircuit( @@ -109,7 +109,7 @@ test_cases.forEach((testInfo) => { witnessMap, () => { throw Error("unexpected oracle"); - } + }, ); } catch (e) { expect(e, "Abi Encoding Step").to.not.be.an("error"); @@ -130,7 +130,7 @@ test_cases.forEach((testInfo) => { await api.srsInitSrs( new RawBuffer(crs.getG1Data()), crs.numPoints, - new RawBuffer(crs.getG2Data()) + new RawBuffer(crs.getG2Data()), ); const acirComposer = await api.acirNewAcirComposer(CIRCUIT_SIZE); @@ -140,14 +140,14 @@ test_cases.forEach((testInfo) => { acirComposer, acirUint8Array, witnessUint8Array, - isRecursive + isRecursive, ); // And this took ~5 minutes! const verified = await api.acirVerifyProof( acirComposer, proof, - isRecursive + isRecursive, ); expect(verified).to.be.true; @@ -155,7 +155,7 @@ test_cases.forEach((testInfo) => { expect(e, "Proving and Verifying").to.not.be.an("error"); throw e; } - } + }, ); suite.addTest(mochaTest); diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index 4b67afb73ff..f1c21f74aab 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -17,3 +17,4 @@ acvm.workspace = true fm.workspace = true serde.workspace = true base64.workspace = true +fxhash.workspace = true diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index f58c9708577..8d74825a9b6 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -58,7 +58,7 @@ pub type CompilationResult = Result<(T, Warnings), ErrorsAndWarnings>; // with the restricted version which only uses one file pub fn compile_file(context: &mut Context, root_file: &Path) -> CompilationResult { let crate_id = prepare_crate(context, root_file); - compile_main(context, crate_id, &CompileOptions::default()) + compile_main(context, crate_id, &CompileOptions::default(), None) } /// Adds the file from the file system at `Path` to the crate graph as a root file @@ -143,6 +143,7 @@ pub fn compile_main( context: &mut Context, crate_id: CrateId, options: &CompileOptions, + cached_program: Option, ) -> CompilationResult { let (_, warnings) = check_crate(context, crate_id, options.deny_warnings)?; @@ -158,7 +159,7 @@ pub fn compile_main( } }; - let compiled_program = compile_no_check(context, options, main)?; + let compiled_program = compile_no_check(context, options, main, cached_program)?; if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); @@ -252,7 +253,7 @@ fn compile_contract_inner( continue; } - let function = match compile_no_check(context, options, function_id) { + let function = match compile_no_check(context, options, function_id, None) { Ok(function) => function, Err(new_error) => { errors.push(new_error); @@ -295,13 +296,21 @@ pub fn compile_no_check( context: &Context, options: &CompileOptions, main_function: FuncId, + cached_program: Option, ) -> Result { let program = monomorphize(main_function, &context.def_interner); + let hash = fxhash::hash64(&program); + if let Some(cached_program) = cached_program { + if hash == cached_program.hash { + return Ok(cached_program); + } + } + let (circuit, debug, abi) = create_circuit(context, program, options.show_ssa, options.show_brillig)?; let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); - Ok(CompiledProgram { circuit, debug, abi, file_map }) + Ok(CompiledProgram { hash, circuit, debug, abi, file_map }) } diff --git a/compiler/noirc_driver/src/program.rs b/compiler/noirc_driver/src/program.rs index 1ed2b0ddddc..3ebd4129312 100644 --- a/compiler/noirc_driver/src/program.rs +++ b/compiler/noirc_driver/src/program.rs @@ -11,6 +11,12 @@ use super::debug::DebugFile; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct CompiledProgram { + /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`CompiledProgram`] + /// was compiled. + /// + /// Used to short-circuit compilation in the case of the source code not changing since the last compilation. + pub hash: u64, + #[serde(serialize_with = "serialize_circuit", deserialize_with = "deserialize_circuit")] pub circuit: Circuit, pub abi: noirc_abi::Abi, diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index 2b207e3d43c..d70c9d3179e 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -12,7 +12,7 @@ noirc_frontend.workspace = true noirc_errors.workspace = true noirc_abi.workspace = true acvm.workspace = true -fxhash = "0.2.1" +fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index 72ed1db6e3b..e16c0fcba15 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use noirc_errors::Span; use crate::{ - token::{Attributes, PrimaryAttribute, SecondaryAttribute}, + token::{Attributes, FunctionAttribute, SecondaryAttribute}, FunctionReturnType, Ident, Pattern, Visibility, }; @@ -65,8 +65,8 @@ impl NoirFunction { pub fn attributes(&self) -> &Attributes { &self.def.attributes } - pub fn primary_attribute(&self) -> Option<&PrimaryAttribute> { - self.def.attributes.primary.as_ref() + pub fn function_attribute(&self) -> Option<&FunctionAttribute> { + self.def.attributes.function.as_ref() } pub fn secondary_attributes(&self) -> &Vec { self.def.attributes.secondary.as_ref() @@ -89,19 +89,19 @@ impl NoirFunction { FunctionKind::LowLevel => {} _ => return None, } - assert!(self.primary_attribute().unwrap().is_foreign()); + assert!(self.function_attribute().unwrap().is_foreign()); Some(&self.def) } } impl From for NoirFunction { fn from(fd: FunctionDefinition) -> Self { - // The function type is determined by the existence of a primary attribute - let kind = match fd.attributes.primary { - Some(PrimaryAttribute::Builtin(_)) => FunctionKind::Builtin, - Some(PrimaryAttribute::Foreign(_)) => FunctionKind::LowLevel, - Some(PrimaryAttribute::Test { .. }) => FunctionKind::Normal, - Some(PrimaryAttribute::Oracle(_)) => FunctionKind::Oracle, + // The function type is determined by the existence of a function attribute + let kind = match fd.attributes.function { + Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin, + Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel, + Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, + Some(FunctionAttribute::Oracle(_)) => FunctionKind::Oracle, None => FunctionKind::Normal, }; diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index aa79929fdd7..662c3b28bef 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -259,7 +259,7 @@ impl UnresolvedTypeExpression { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] /// Represents whether the parameter is public or known only to the prover. pub enum Visibility { Public, @@ -277,7 +277,7 @@ impl std::fmt::Display for Visibility { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] /// Represents whether the return value should compromise of unique witness indices such that no /// index occurs within the program's abi more than once. /// diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 9b4c0153f52..6a32fa717f3 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::{Ident, UnresolvedGenerics, UnresolvedType}; +use crate::{token::SecondaryAttribute, Ident, UnresolvedGenerics, UnresolvedType}; use iter_extended::vecmap; use noirc_errors::Span; @@ -8,6 +8,7 @@ use noirc_errors::Span; #[derive(Clone, Debug, PartialEq, Eq)] pub struct NoirStruct { pub name: Ident, + pub attributes: Vec, pub generics: UnresolvedGenerics, pub fields: Vec<(Ident, UnresolvedType)>, pub span: Span, @@ -16,11 +17,12 @@ pub struct NoirStruct { impl NoirStruct { pub fn new( name: Ident, + attributes: Vec, generics: Vec, fields: Vec<(Ident, UnresolvedType)>, span: Span, ) -> NoirStruct { - NoirStruct { name, generics, fields, span } + NoirStruct { name, attributes, generics, fields, span } } } diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index f17cee65585..017027a1da2 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -3,7 +3,7 @@ use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir::Context; use crate::node_interner::{FuncId, NodeInterner}; use crate::parser::{parse_program, ParsedModule}; -use crate::token::{PrimaryAttribute, TestScope}; +use crate::token::{FunctionAttribute, TestScope}; use arena::{Arena, Index}; use fm::{FileId, FileManager}; use noirc_errors::{FileDiagnostic, Location}; @@ -140,8 +140,8 @@ impl CrateDefMap { module.value_definitions().filter_map(|id| { if let Some(func_id) = id.as_function() { let attributes = interner.function_attributes(&func_id); - match &attributes.primary { - Some(PrimaryAttribute::Test(scope)) => { + match &attributes.function { + Some(FunctionAttribute::Test(scope)) => { let location = interner.function_meta(&func_id).name.location; Some(TestFunction::new(func_id, scope.clone(), location)) } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 2c6d39a2601..78388eacb94 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -17,8 +17,9 @@ use crate::hir_def::expr::{ HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, HirMemberAccess, HirMethodCallExpression, HirPrefixExpression, }; + use crate::hir_def::traits::{Trait, TraitConstraint}; -use crate::token::PrimaryAttribute; +use crate::token::FunctionAttribute; use regex::Regex; use std::collections::{BTreeMap, HashSet}; use std::rc::Rc; @@ -737,7 +738,7 @@ impl<'a> Resolver<'a> { self.push_err(ResolverError::DistinctNotAllowed { ident: func.name_ident().clone() }); } - if matches!(attributes.primary, Some(PrimaryAttribute::Test { .. })) + if matches!(attributes.function, Some(FunctionAttribute::Test { .. })) && !parameters.is_empty() { self.push_err(ResolverError::TestFunctionHasParameters { diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index fd980328f5f..3c49d3e4afc 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -41,7 +41,7 @@ impl HirExpression { } /// Corresponds to a variable in the source code -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct HirIdent { pub location: Location, pub id: DefinitionId, diff --git a/compiler/noirc_frontend/src/hir_def/stmt.rs b/compiler/noirc_frontend/src/hir_def/stmt.rs index d7f0d2e466f..76601d893ed 100644 --- a/compiler/noirc_frontend/src/hir_def/stmt.rs +++ b/compiler/noirc_frontend/src/hir_def/stmt.rs @@ -48,7 +48,7 @@ pub struct HirAssignStatement { #[derive(Debug, Clone)] pub struct HirConstrainStatement(pub ExprId, pub FileId, pub Option); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub enum HirPattern { Identifier(HirIdent), Mutable(Box, Span), diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 5b6e010cc77..c32b956b716 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -1,6 +1,8 @@ +use crate::token::Attribute; + use super::{ errors::LexerErrorKind, - token::{Attribute, IntType, Keyword, SpannedToken, Token, Tokens}, + token::{IntType, Keyword, SpannedToken, Token, Tokens}, }; use acvm::FieldElement; use noirc_errors::{Position, Span}; @@ -411,7 +413,7 @@ impl<'a> Iterator for Lexer<'a> { #[cfg(test)] mod tests { use super::*; - use crate::token::{Attribute, PrimaryAttribute, SecondaryAttribute, TestScope}; + use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; #[test] fn test_single_double_char() { let input = "! != + ( ) { } [ ] | , ; : :: < <= > >= & - -> . .. % / * = == << >>"; @@ -499,9 +501,11 @@ mod tests { let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; let expected = vec![ - Token::Attribute(Attribute::Primary(PrimaryAttribute::Foreign("sha256".to_string()))), - Token::Attribute(Attribute::Primary(PrimaryAttribute::Foreign("blake2s".to_string()))), - Token::Attribute(Attribute::Primary(PrimaryAttribute::Builtin("sum".to_string()))), + Token::Attribute(Attribute::Function(FunctionAttribute::Foreign("sha256".to_string()))), + Token::Attribute(Attribute::Function(FunctionAttribute::Foreign( + "blake2s".to_string(), + ))), + Token::Attribute(Attribute::Function(FunctionAttribute::Builtin("sum".to_string()))), ]; let mut lexer = Lexer::new(input); @@ -533,7 +537,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test(TestScope::None))) + &Token::Attribute(Attribute::Function(FunctionAttribute::Test(TestScope::None))) ); } @@ -557,7 +561,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test( + &Token::Attribute(Attribute::Function(FunctionAttribute::Test( TestScope::ShouldFailWith { reason: None } ))) ); @@ -571,7 +575,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test( + &Token::Attribute(Attribute::Function(FunctionAttribute::Test( TestScope::ShouldFailWith { reason: Some("hello".to_owned()) } ))) ); diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index e99dcb72fb6..fb5ab220b2c 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -364,14 +364,14 @@ impl fmt::Display for TestScope { // Calls to functions which have the foreign attribute are executed in the host language pub struct Attributes { // Each function can have a single Primary Attribute - pub primary: Option, + pub function: Option, // Each function can have many Secondary Attributes pub secondary: Vec, } impl Attributes { pub fn empty() -> Self { - Self { primary: None, secondary: Vec::new() } + Self { function: None, secondary: Vec::new() } } /// Returns true if one of the secondary attributes is `contract_library_method` @@ -398,14 +398,14 @@ impl Attributes { /// A secondary attribute has no effect and is either consumed by a library or used as a notice for the developer #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub enum Attribute { - Primary(PrimaryAttribute), + Function(FunctionAttribute), Secondary(SecondaryAttribute), } impl fmt::Display for Attribute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Attribute::Primary(attribute) => write!(f, "{}", attribute), + Attribute::Function(attribute) => write!(f, "{}", attribute), Attribute::Secondary(attribute) => write!(f, "{}", attribute), } } @@ -442,23 +442,23 @@ impl Attribute { // Primary Attributes ["foreign", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Foreign(name.to_string())) + Attribute::Function(FunctionAttribute::Foreign(name.to_string())) } ["builtin", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Builtin(name.to_string())) + Attribute::Function(FunctionAttribute::Builtin(name.to_string())) } ["oracle", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Oracle(name.to_string())) + Attribute::Function(FunctionAttribute::Oracle(name.to_string())) } - ["test"] => Attribute::Primary(PrimaryAttribute::Test(TestScope::None)), + ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), ["test", name] => { validate(name)?; let malformed_scope = LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }; match TestScope::lookup_str(name) { - Some(scope) => Attribute::Primary(PrimaryAttribute::Test(scope)), + Some(scope) => Attribute::Function(FunctionAttribute::Test(scope)), None => return Err(malformed_scope), } } @@ -492,44 +492,44 @@ impl Attribute { /// Primary Attributes are those which a function can only have one of. /// They change the FunctionKind and thus have direct impact on the IR output #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] -pub enum PrimaryAttribute { +pub enum FunctionAttribute { Foreign(String), Builtin(String), Oracle(String), Test(TestScope), } -impl PrimaryAttribute { +impl FunctionAttribute { pub fn builtin(self) -> Option { match self { - PrimaryAttribute::Builtin(name) => Some(name), + FunctionAttribute::Builtin(name) => Some(name), _ => None, } } pub fn foreign(self) -> Option { match self { - PrimaryAttribute::Foreign(name) => Some(name), + FunctionAttribute::Foreign(name) => Some(name), _ => None, } } pub fn is_foreign(&self) -> bool { - matches!(self, PrimaryAttribute::Foreign(_)) + matches!(self, FunctionAttribute::Foreign(_)) } pub fn is_low_level(&self) -> bool { - matches!(self, PrimaryAttribute::Foreign(_) | PrimaryAttribute::Builtin(_)) + matches!(self, FunctionAttribute::Foreign(_) | FunctionAttribute::Builtin(_)) } } -impl fmt::Display for PrimaryAttribute { +impl fmt::Display for FunctionAttribute { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - PrimaryAttribute::Test(scope) => write!(f, "#[test{}]", scope), - PrimaryAttribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), - PrimaryAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), - PrimaryAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), + FunctionAttribute::Test(scope) => write!(f, "#[test{}]", scope), + FunctionAttribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), + FunctionAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), + FunctionAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), } } } @@ -560,13 +560,13 @@ impl fmt::Display for SecondaryAttribute { } } -impl AsRef for PrimaryAttribute { +impl AsRef for FunctionAttribute { fn as_ref(&self) -> &str { match self { - PrimaryAttribute::Foreign(string) => string, - PrimaryAttribute::Builtin(string) => string, - PrimaryAttribute::Oracle(string) => string, - PrimaryAttribute::Test { .. } => "", + FunctionAttribute::Foreign(string) => string, + FunctionAttribute::Builtin(string) => string, + FunctionAttribute::Oracle(string) => string, + FunctionAttribute::Test { .. } => "", } } } diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index bc59249b489..5124e6767f3 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -14,7 +14,7 @@ use crate::{hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Si /// e.g. `let (a, b) = (1, 2)` have been split up: `let tmp = (1, 2); let a = tmp.0; let b = tmp.1;`. /// This also affects function parameters: `fn foo((a, b): (i32, i32)` => `fn foo(a: i32, b: i32)`. /// - All structs are replaced with tuples -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub enum Expression { Ident(Ident), Literal(Literal), @@ -55,7 +55,7 @@ pub struct LocalId(pub u32); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct FuncId(pub u32); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Ident { pub location: Option, pub definition: Definition, @@ -64,7 +64,7 @@ pub struct Ident { pub typ: Type, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct For { pub index_variable: LocalId, pub index_name: String, @@ -78,7 +78,7 @@ pub struct For { pub end_range_location: Location, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub enum Literal { Array(ArrayLiteral), Integer(FieldElement, Type), @@ -87,7 +87,7 @@ pub enum Literal { FmtStr(String, u64, Box), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Unary { pub operator: crate::UnaryOp, pub rhs: Box, @@ -97,7 +97,7 @@ pub struct Unary { pub type BinaryOp = BinaryOpKind; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Binary { pub lhs: Box, pub operator: BinaryOp, @@ -111,7 +111,7 @@ pub struct Lambda { pub env: Ident, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct If { pub condition: Box, pub consequence: Box, @@ -119,20 +119,20 @@ pub struct If { pub typ: Type, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Cast { pub lhs: Box, pub r#type: Type, pub location: Location, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct ArrayLiteral { pub contents: Vec, pub typ: Type, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Call { pub func: Box, pub arguments: Vec, @@ -140,7 +140,7 @@ pub struct Call { pub location: Location, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Index { pub collection: Box, pub index: Box, @@ -160,7 +160,7 @@ pub struct Index { /// let field1 = tmp.0; // the struct has been translated to a tuple as well /// let field2 = tmp.1; /// ``` -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Let { pub id: LocalId, pub mutable: bool, @@ -168,7 +168,7 @@ pub struct Let { pub expression: Box, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Assign { pub lvalue: LValue, pub expression: Box, @@ -182,7 +182,7 @@ pub struct BinaryStatement { } /// Represents an Ast form that can be assigned to -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub enum LValue { Ident(Ident), Index { array: Box, index: Box, element_type: Type, location: Location }, @@ -192,7 +192,7 @@ pub enum LValue { pub type Parameters = Vec<(LocalId, /*mutable:*/ bool, /*name:*/ String, Type)>; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Function { pub id: FuncId, pub name: String, @@ -209,7 +209,7 @@ pub struct Function { /// - Concrete lengths for each array and string /// - Several other variants removed (such as Type::Constant) /// - All structs replaced with tuples -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum Type { Field, Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] @@ -233,7 +233,7 @@ impl Type { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Program { pub functions: Vec, pub main_function_signature: FunctionSignature, diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 61bb6be091a..c912464695e 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -21,7 +21,7 @@ use crate::{ types, }, node_interner::{self, DefinitionKind, NodeInterner, StmtId}, - token::PrimaryAttribute, + token::FunctionAttribute, ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, Visibility, }; @@ -145,14 +145,14 @@ impl<'interner> Monomorphizer<'interner> { let attributes = self.interner.function_attributes(&id); match self.interner.function_meta(&id).kind { FunctionKind::LowLevel => { - let attribute = attributes.primary.clone().expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); + let attribute = attributes.function.clone().expect("all low level functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.foreign().expect( "ice: function marked as foreign, but attribute kind does not match this", ); Definition::LowLevel(opcode) } FunctionKind::Builtin => { - let attribute = attributes.primary.clone().expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); + let attribute = attributes.function.clone().expect("all low level functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.builtin().expect( "ice: function marked as builtin, but attribute kind does not match this", ); @@ -164,12 +164,12 @@ impl<'interner> Monomorphizer<'interner> { } FunctionKind::Oracle => { let attr = attributes - .primary + .function .clone() .expect("Oracle function must have an oracle attribute"); match attr { - PrimaryAttribute::Oracle(name) => Definition::Oracle(name), + FunctionAttribute::Oracle(name) => Definition::Oracle(name), _ => unreachable!("Oracle function must have an oracle attribute"), } } diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 830e0258766..3c5bc777186 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -34,9 +34,11 @@ pub enum ParserErrorReason { #[error("Where clauses are allowed only on functions with generic parameters")] WhereClauseOnNonGenericFunction, #[error( - "Multiple primary attributes found. Only one primary attribute is allowed per function." + "Multiple primary attributes found. Only one function attribute is allowed per function" )] - MultiplePrimaryAttributesFound, + MultipleFunctionAttributesFound, + #[error("A function attribute cannot be placed on a struct")] + NoFunctionAttributesAllowedOnStruct, #[error("Assert statements can only accept string literals")] AssertMessageNotString, } @@ -124,9 +126,9 @@ impl From for Diagnostic { match &error.reason { Some(reason) => { match reason { - ParserErrorReason::ConstrainDeprecated => Diagnostic::simple_warning( + ParserErrorReason::ConstrainDeprecated => Diagnostic::simple_error( "Use of deprecated keyword 'constrain'".into(), - "The 'constrain' keyword has been deprecated. Please use the 'assert' function instead.".into(), + "The 'constrain' keyword is deprecated. Please use the 'assert' function instead.".into(), error.span, ), ParserErrorReason::ComptimeDeprecated => Diagnostic::simple_warning( diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index ef9015b7964..13385108603 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -35,7 +35,7 @@ use crate::ast::{ }; use crate::lexer::Lexer; use crate::parser::{force, ignore_then_commit, statement_recovery}; -use crate::token::{Attribute, Attributes, Keyword, Token, TokenKind}; +use crate::token::{Attribute, Attributes, Keyword, SecondaryAttribute, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, ConstrainStatement, Distinctness, FunctionDefinition, FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Lambda, Literal, @@ -174,7 +174,7 @@ fn function_definition(allow_self: bool) -> impl NoirParser { .validate(|(((args, ret), where_clause), (body, body_span)), span, emit| { let ((((attributes, modifiers), name), generics), parameters) = args; - // Validate collected attributes, filtering them into primary and secondary variants + // Validate collected attributes, filtering them into function and secondary variants let attrs = validate_attributes(attributes, span, emit); validate_where_clause(&generics, &where_clause, span, emit); FunctionDefinition { @@ -239,11 +239,16 @@ fn struct_definition() -> impl NoirParser { ), ); - keyword(Struct).ignore_then(ident()).then(generics()).then(fields).map_with_span( - |((name, generics), fields), span| { - TopLevelStatement::Struct(NoirStruct { name, generics, fields, span }) - }, - ) + attributes() + .or_not() + .then_ignore(keyword(Struct)) + .then(ident()) + .then(generics()) + .then(fields) + .validate(|(((raw_attributes, name), generics), fields), span, emit| { + let attributes = validate_struct_attributes(raw_attributes, span, emit); + TopLevelStatement::Struct(NoirStruct { name, attributes, generics, fields, span }) + }) } fn type_alias_definition() -> impl NoirParser { @@ -443,10 +448,10 @@ fn validate_attributes( for attribute in attrs { match attribute { - Attribute::Primary(attr) => { + Attribute::Function(attr) => { if primary.is_some() { emit(ParserError::with_reason( - ParserErrorReason::MultiplePrimaryAttributesFound, + ParserErrorReason::MultipleFunctionAttributesFound, span, )); } @@ -456,7 +461,30 @@ fn validate_attributes( } } - Attributes { primary, secondary } + Attributes { function: primary, secondary } +} + +fn validate_struct_attributes( + attributes: Option>, + span: Span, + emit: &mut dyn FnMut(ParserError), +) -> Vec { + let attrs = attributes.unwrap_or_default(); + let mut struct_attributes = vec![]; + + for attribute in attrs { + match attribute { + Attribute::Function(..) => { + emit(ParserError::with_reason( + ParserErrorReason::NoFunctionAttributesAllowedOnStruct, + span, + )); + } + Attribute::Secondary(attr) => struct_attributes.push(attr), + } + } + + struct_attributes } fn validate_where_clause( @@ -1624,23 +1652,6 @@ mod test { }) } - fn parse_all_warnings(parser: P, programs: Vec<&str>) -> Vec - where - P: NoirParser, - T: std::fmt::Display, - { - programs - .into_iter() - .flat_map(|program| { - let (_expr, diagnostics) = parse_recover(&parser, program); - diagnostics.iter().for_each(|diagnostic| if diagnostic.is_error() { - unreachable!("Expected this input to pass with warning:\n{program}\nYet it failed with error:\n{diagnostic}") - }); - diagnostics - }) - .collect() - } - fn parse_all_failing(parser: P, programs: Vec<&str>) -> Vec where P: NoirParser, @@ -1857,7 +1868,7 @@ mod test { // The first (inner) `==` is a predicate which returns 0/1 // The outer layer is an infix `==` which is // associated with the Constrain statement - let errors = parse_all_warnings( + let errors = parse_all_failing( constrain(expression()), vec![ "constrain ((x + y) == k) + z == y", @@ -1870,7 +1881,7 @@ mod test { assert_eq!(errors.len(), 5); assert!(errors .iter() - .all(|err| { err.is_warning() && err.to_string().contains("deprecated") })); + .all(|err| { err.is_error() && err.to_string().contains("deprecated") })); } /// This is the standard way to declare an assert statement @@ -2228,10 +2239,16 @@ mod test { "struct Foo { }", "struct Bar { ident: Field, }", "struct Baz { ident: Field, other: Field }", + "#[attribute] struct Baz { ident: Field, other: Field }", ]; parse_all(struct_definition(), cases); - let failing = vec!["struct { }", "struct Foo { bar: pub Field }"]; + let failing = vec![ + "struct { }", + "struct Foo { bar: pub Field }", + "struct Foo { bar: pub Field }", + "#[oracle(some)] struct Foo { bar: Field }", + ]; parse_all_failing(struct_definition(), failing); } diff --git a/compiler/source-resolver/src/index.ts b/compiler/source-resolver/src/index.ts index e7e1db64b75..66ff1e947aa 100644 --- a/compiler/source-resolver/src/index.ts +++ b/compiler/source-resolver/src/index.ts @@ -8,30 +8,30 @@ export const read_file = function (source_id: string): string { return result; } else { throw new Error( - "Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?" + "Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?", ); } } else { throw new Error( - "Not yet initialized. Use initializeResolver(() => string)" + "Not yet initialized. Use initializeResolver(() => string)", ); } }; function initialize( - noir_resolver: (source_id: string) => string + noir_resolver: (source_id: string) => string, ): (source_id: string) => string { if (typeof noir_resolver === "function") { return noir_resolver; } else { throw new Error( - "Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter" + "Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter", ); } } export function initializeResolver( - resolver: (source_id: string) => string + resolver: (source_id: string) => string, ): void { resolveFunction = initialize(resolver); } diff --git a/compiler/source-resolver/types/index.d.ts b/compiler/source-resolver/types/index.d.ts index ef4e98c87e1..bf144c3928f 100644 --- a/compiler/source-resolver/types/index.d.ts +++ b/compiler/source-resolver/types/index.d.ts @@ -1,4 +1,4 @@ export declare const read_file: (source_id: string) => string; export declare function initializeResolver( - resolver: (source_id: string) => string + resolver: (source_id: string) => string, ): void; diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index c98e586ab45..99051a98407 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -125,7 +125,7 @@ pub fn compile(args: JsValue) -> JsValue { ::from_serde(&optimized_contract).unwrap() } else { - let compiled_program = compile_main(&mut context, crate_id, &options.compile_options) + let compiled_program = compile_main(&mut context, crate_id, &options.compile_options, None) .expect("Compilation failed") .0; diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index c180fd6db39..f823db35944 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -34,7 +34,7 @@ describe("noir wasm compilation", () => { console.log( "Compilation is a match? ", - wasmCircuitBase64 === cliCircuitBase64 + wasmCircuitBase64 === cliCircuitBase64, ); expect(wasmCircuitBase64).to.equal(cliCircuitBase64); diff --git a/package.json b/package.json index abfa7f270ba..718bd757042 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "@typescript-eslint/parser": "^5.59.5", "chai": "^4.3.7", "eslint": "^8.40.0", - "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-prettier": "^5.0.0", "mocha": "^10.2.0", - "prettier": "^2.8.8", + "prettier": "3.0.3", "ts-node": "^10.9.1", "typescript": "^5.0.4" }, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 870d0089548..63f41db96a1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] channel = "1.66.1" components = [ "rust-src" ] -targets = [ "wasm32-unknown-unknown", "aarch64-apple-darwin" ] +targets = [ "wasm32-unknown-unknown", "wasm32-wasi", "aarch64-apple-darwin" ] profile = "default" diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index d7de6aac4ae..ae174da1b33 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -6,6 +6,7 @@ use std::{ task::{self, Poll}, }; +use acvm::BlackBoxFunctionSolver; use async_lsp::{ router::Router, AnyEvent, AnyNotification, AnyRequest, ClientSocket, Error, ErrorCode, LanguageClient, LspService, ResponseError, @@ -46,15 +47,49 @@ const COMPILE_CODELENS_TITLE: &str = "Compile"; const EXECUTE_COMMAND: &str = "nargo.execute"; const EXECUTE_CODELENS_TITLE: &str = "Execute"; +// This is a struct that wraps a dynamically dispatched `BlackBoxFunctionSolver` +// where we proxy the unimplemented stuff to the wrapped backend, but it +// allows us to avoid changing function signatures to include the `Box` +struct WrapperSolver(Box); + +impl BlackBoxFunctionSolver for WrapperSolver { + fn schnorr_verify( + &self, + public_key_x: &acvm::FieldElement, + public_key_y: &acvm::FieldElement, + signature: &[u8], + message: &[u8], + ) -> Result { + self.0.schnorr_verify(public_key_x, public_key_y, signature, message) + } + + fn pedersen( + &self, + inputs: &[acvm::FieldElement], + domain_separator: u32, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { + self.0.pedersen(inputs, domain_separator) + } + + fn fixed_base_scalar_mul( + &self, + low: &acvm::FieldElement, + high: &acvm::FieldElement, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { + self.0.fixed_base_scalar_mul(low, high) + } +} + // State for the LSP gets implemented on this struct and is internal to the implementation pub struct LspState { root_path: Option, client: ClientSocket, + solver: WrapperSolver, } impl LspState { - fn new(client: &ClientSocket) -> Self { - Self { client: client.clone(), root_path: None } + fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self { + Self { client: client.clone(), root_path: None, solver: WrapperSolver(Box::new(solver)) } } } @@ -63,8 +98,8 @@ pub struct NargoLspService { } impl NargoLspService { - pub fn new(client: &ClientSocket) -> Self { - let state = LspState::new(client); + pub fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self { + let state = LspState::new(client, solver); let mut router = Router::new(state); router .request::(on_initialize) @@ -214,10 +249,8 @@ fn on_test_run_request( match test_functions.into_iter().next() { Some((_, test_function)) => { - #[allow(deprecated)] - let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); let test_result = run_test( - &blackbox_solver, + &state.solver, &context, test_function, false, @@ -722,9 +755,40 @@ mod lsp_tests { #[test] async fn test_on_initialize() { - // Not available in published release yet + struct MockBackend; + impl BlackBoxFunctionSolver for MockBackend { + fn schnorr_verify( + &self, + _public_key_x: &acvm::FieldElement, + _public_key_y: &acvm::FieldElement, + _signature: &[u8], + _message: &[u8], + ) -> Result { + unimplemented!() + } + + fn pedersen( + &self, + _inputs: &[acvm::FieldElement], + _domain_separator: u32, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> + { + unimplemented!() + } + + fn fixed_base_scalar_mul( + &self, + _low: &acvm::FieldElement, + _high: &acvm::FieldElement, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> + { + unimplemented!() + } + } + let client = ClientSocket::new_closed(); - let mut state = LspState::new(&client); + let solver = MockBackend; + let mut state = LspState::new(&client, solver); let params = InitializeParams::default(); let response = on_initialize(&mut state, params).await.unwrap(); assert!(matches!( diff --git a/tooling/nargo/src/artifacts/program.rs b/tooling/nargo/src/artifacts/program.rs index be01b7bdec1..190b4c76897 100644 --- a/tooling/nargo/src/artifacts/program.rs +++ b/tooling/nargo/src/artifacts/program.rs @@ -9,6 +9,12 @@ use serde::{Deserialize, Serialize}; /// - Proving and verification keys have been pregenerated based on this ACIR. #[derive(Serialize, Deserialize, Debug)] pub struct PreprocessedProgram { + /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`PreprocessedProgram`] + /// was compiled. + /// + /// Used to short-circuit compilation in the case of the source code not changing since the last compilation. + pub hash: u64, + pub backend: String, pub abi: Abi, diff --git a/tooling/nargo/src/ops/test.rs b/tooling/nargo/src/ops/test.rs index 512780cc271..993ceb0f21e 100644 --- a/tooling/nargo/src/ops/test.rs +++ b/tooling/nargo/src/ops/test.rs @@ -20,7 +20,7 @@ pub fn run_test( show_output: bool, config: &CompileOptions, ) -> TestStatus { - let program = compile_no_check(context, config, test_function.get_id()); + let program = compile_no_check(context, config, test_function.get_id(), None); match program { Ok(program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, diff --git a/tooling/nargo/src/workspace.rs b/tooling/nargo/src/workspace.rs index 5df13350683..65f9ab7e0d9 100644 --- a/tooling/nargo/src/workspace.rs +++ b/tooling/nargo/src/workspace.rs @@ -25,7 +25,7 @@ pub struct Workspace { impl Workspace { pub fn package_build_path(&self, package: &Package) -> PathBuf { let name: String = package.name.clone().into(); - self.target_directory_path().join(name) + self.target_directory_path().join(name).with_extension("json") } pub fn contracts_directory_path(&self, package: &Package) -> PathBuf { diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 30b865063d3..856970544b8 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -1,9 +1,7 @@ -use std::path::PathBuf; - use super::NargoConfig; use super::{ compile_cmd::compile_bin_package, - fs::{create_named_dir, program::read_program_from_file, write_to_file}, + fs::{create_named_dir, write_to_file}, }; use crate::backends::Backend; use crate::errors::CliError; @@ -12,15 +10,12 @@ use acvm::acir::circuit::Opcode; use acvm::Language; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use clap::Args; -use nargo::artifacts::program::PreprocessedProgram; use nargo::package::Package; +use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::CompileOptions; use noirc_frontend::graph::CrateName; -// TODO(#1388): pull this from backend. -const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; - /// Generates a Solidity verifier smart contract for the program #[derive(Debug, Clone, Args)] pub(crate) struct CodegenVerifierCommand { @@ -49,12 +44,10 @@ pub(crate) fn run( let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { - let circuit_build_path = workspace.package_build_path(package); - let smart_contract_string = smart_contract_for_package( + &workspace, backend, package, - circuit_build_path, &args.compile_options, np_language, &|opcode| opcode_support.is_opcode_supported(opcode), @@ -72,27 +65,22 @@ pub(crate) fn run( } fn smart_contract_for_package( + workspace: &Workspace, backend: &Backend, package: &Package, - circuit_build_path: PathBuf, compile_options: &CompileOptions, np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> Result { - let preprocessed_program = if circuit_build_path.exists() { - read_program_from_file(circuit_build_path)? - } else { - let program = - compile_bin_package(package, compile_options, np_language, &is_opcode_supported)?; - - PreprocessedProgram { - backend: String::from(BACKEND_IDENTIFIER), - abi: program.abi, - bytecode: program.circuit, - } - }; - - let mut smart_contract_string = backend.eth_contract(&preprocessed_program.bytecode)?; + let program = compile_bin_package( + workspace, + package, + compile_options, + np_language, + &is_opcode_supported, + )?; + + let mut smart_contract_string = backend.eth_contract(&program.circuit)?; if backend.name() == ACVM_BACKEND_BARRETENBERG { smart_contract_string = diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 3ccd99558a7..d7bcf475a40 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::path::Path; use acvm::acir::circuit::Opcode; @@ -11,8 +12,10 @@ use nargo::artifacts::debug::DebugArtifact; use nargo::artifacts::program::PreprocessedProgram; use nargo::package::Package; use nargo::prepare_package; +use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; +use noirc_errors::debug_info::DebugInfo; use noirc_frontend::graph::CrateName; use clap::Args; @@ -20,6 +23,7 @@ use clap::Args; use crate::backends::Backend; use crate::errors::{CliError, CompileError}; +use super::fs::program::read_program_from_file; use super::fs::program::{ save_contract_to_file, save_debug_artifact_to_file, save_program_to_file, }; @@ -71,7 +75,8 @@ pub(crate) fn run( .partition(|package| package.is_binary()); let (np_language, opcode_support) = backend.get_backend_info()?; - let (compiled_programs, compiled_contracts) = compile_workspace( + let (_, compiled_contracts) = compile_workspace( + &workspace, &binary_packages, &contract_packages, np_language, @@ -80,9 +85,6 @@ pub(crate) fn run( )?; // Save build artifacts to disk. - for (package, program) in binary_packages.into_iter().zip(compiled_programs) { - save_program(program, &package, &circuit_dir, args.output_debug); - } for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) { save_contract(contract, &package, &circuit_dir, args.output_debug); } @@ -91,6 +93,7 @@ pub(crate) fn run( } pub(super) fn compile_workspace( + workspace: &Workspace, binary_packages: &[Package], contract_packages: &[Package], np_language: Language, @@ -102,7 +105,9 @@ pub(super) fn compile_workspace( // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() - .map(|package| compile_program(package, compile_options, np_language, &is_opcode_supported)) + .map(|package| { + compile_program(workspace, package, compile_options, np_language, &is_opcode_supported) + }) .collect(); let contract_results: Vec<(FileManager, CompilationResult)> = contract_packages @@ -130,6 +135,7 @@ pub(super) fn compile_workspace( } pub(crate) fn compile_bin_package( + workspace: &Workspace, package: &Package, compile_options: &CompileOptions, np_language: Language, @@ -140,7 +146,7 @@ pub(crate) fn compile_bin_package( } let (file_manager, compilation_result) = - compile_program(package, compile_options, np_language, &is_opcode_supported); + compile_program(workspace, package, compile_options, np_language, &is_opcode_supported); let program = report_errors(compilation_result, &file_manager, compile_options.deny_warnings)?; @@ -148,6 +154,7 @@ pub(crate) fn compile_bin_package( } fn compile_program( + workspace: &Workspace, package: &Package, compile_options: &CompileOptions, np_language: Language, @@ -155,8 +162,23 @@ fn compile_program( ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); + let cached_program = if let Ok(preprocessed_program) = + read_program_from_file(workspace.package_build_path(package)) + { + // TODO: Load debug information. + Some(CompiledProgram { + hash: preprocessed_program.hash, + circuit: preprocessed_program.bytecode, + abi: preprocessed_program.abi, + debug: DebugInfo::default(), + file_map: BTreeMap::new(), + }) + } else { + None + }; + let (program, warnings) = - match noirc_driver::compile_main(&mut context, crate_id, compile_options) { + match noirc_driver::compile_main(&mut context, crate_id, compile_options, cached_program) { Ok(program_and_warnings) => program_and_warnings, Err(errors) => { return (context.file_manager, Err(errors)); @@ -168,6 +190,8 @@ fn compile_program( nargo::ops::optimize_program(program, np_language, &is_opcode_supported) .expect("Backend does not support an opcode that is in the IR"); + save_program(optimized_program.clone(), package, &workspace.target_directory_path(), false); + (context.file_manager, Ok((optimized_program, warnings))) } @@ -200,6 +224,7 @@ fn save_program( output_debug: bool, ) { let preprocessed_program = PreprocessedProgram { + hash: program.hash, backend: String::from(BACKEND_IDENTIFIER), abi: program.abi, bytecode: program.circuit, diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index c3a30743849..7d8cf6de394 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -1,5 +1,5 @@ use acvm::acir::circuit::OpcodeLocation; -use acvm::acir::{circuit::Circuit, native_types::WitnessMap}; +use acvm::acir::native_types::WitnessMap; use acvm::pwg::{ErrorLocation, OpcodeResolutionError}; use clap::Args; @@ -9,7 +9,7 @@ use nargo::errors::{ExecutionError, NargoError}; use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; -use noirc_abi::{Abi, InputMap}; +use noirc_abi::InputMap; use noirc_driver::{CompileOptions, CompiledProgram}; use noirc_errors::CustomDiagnostic; use noirc_frontend::graph::CrateName; @@ -56,10 +56,13 @@ pub(crate) fn run( let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { - let compiled_program = - compile_bin_package(package, &args.compile_options, np_language, &|opcode| { - opcode_support.is_opcode_supported(opcode) - })?; + let compiled_program = compile_bin_package( + &workspace, + package, + &args.compile_options, + np_language, + &|opcode| opcode_support.is_opcode_supported(opcode), + )?; let (return_value, solved_witness) = execute_program_and_decode(compiled_program, package, &args.prover_name)?; @@ -82,14 +85,11 @@ fn execute_program_and_decode( package: &Package, prover_name: &str, ) -> Result<(Option, WitnessMap), CliError> { - let CompiledProgram { abi, circuit, debug, file_map } = program; - let debug_artifact = DebugArtifact { debug_symbols: vec![debug], file_map }; - // Parse the initial witness values from Prover.toml let (inputs_map, _) = - read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &abi)?; - let solved_witness = execute_program(circuit, &abi, &inputs_map, Some(debug_artifact))?; - let public_abi = abi.public_abi(); + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; + let solved_witness = execute_program(&program, &inputs_map)?; + let public_abi = program.abi.public_abi(); let (_, return_value) = public_abi.decode(&solved_witness)?; Ok((return_value, solved_witness)) @@ -186,25 +186,30 @@ fn report_error_with_opcode_locations( } pub(crate) fn execute_program( - circuit: Circuit, - abi: &Abi, + compiled_program: &CompiledProgram, inputs_map: &InputMap, - debug_data: Option, ) -> Result { #[allow(deprecated)] let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); - let initial_witness = abi.encode(inputs_map, None)?; + let initial_witness = compiled_program.abi.encode(inputs_map, None)?; - let solved_witness_err = - nargo::ops::execute_circuit(&blackbox_solver, circuit, initial_witness, true); + let solved_witness_err = nargo::ops::execute_circuit( + &blackbox_solver, + compiled_program.circuit.clone(), + initial_witness, + true, + ); match solved_witness_err { Ok(solved_witness) => Ok(solved_witness), Err(err) => { - if let Some(debug_data) = debug_data { - let opcode_err_info = extract_opcode_error_from_nargo_error(&err); - report_error_with_opcode_locations(opcode_err_info, &debug_data); - } + let debug_artifact = DebugArtifact { + debug_symbols: vec![compiled_program.debug.clone()], + file_map: compiled_program.file_map.clone(), + }; + + let opcode_err_info = extract_opcode_error_from_nargo_error(&err); + report_error_with_opcode_locations(opcode_err_info, &debug_artifact); Err(crate::errors::CliError::NargoError(err)) } diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index 8018308ee54..50021e842c4 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -57,6 +57,7 @@ pub(crate) fn run( let (np_language, opcode_support) = backend.get_backend_info()?; let (compiled_programs, compiled_contracts) = compile_workspace( + &workspace, &binary_packages, &contract_packages, np_language, diff --git a/tooling/nargo_cli/src/cli/lsp_cmd.rs b/tooling/nargo_cli/src/cli/lsp_cmd.rs index 7350c5c3099..a41bb877991 100644 --- a/tooling/nargo_cli/src/cli/lsp_cmd.rs +++ b/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -30,7 +30,9 @@ pub(crate) fn run( runtime.block_on(async { let (server, _) = async_lsp::MainLoop::new_server(|client| { - let router = NargoLspService::new(&client); + #[allow(deprecated)] + let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + let router = NargoLspService::new(&client, blackbox_solver); ServiceBuilder::new() .layer(TracingLayer::default()) diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index cbe6deca1c2..af300b7ebe0 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -1,29 +1,20 @@ -use std::path::{Path, PathBuf}; - -use acvm::acir::circuit::Opcode; -use acvm::Language; use clap::Args; -use nargo::artifacts::debug::DebugArtifact; -use nargo::artifacts::program::PreprocessedProgram; use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; use nargo::package::Package; +use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; -use noirc_driver::CompileOptions; +use noirc_driver::{CompileOptions, CompiledProgram}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; use super::fs::{ inputs::{read_inputs_from_file, write_inputs_to_file}, - program::read_program_from_file, proof::save_proof_to_dir, }; use super::NargoConfig; use crate::{backends::Backend, cli::execute_cmd::execute_program, errors::CliError}; -// TODO(#1388): pull this from backend. -const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; - /// Create proof for this program. The proof is returned as a hex encoded string. #[derive(Debug, Clone, Args)] pub(crate) struct ProveCommand { @@ -61,70 +52,48 @@ pub(crate) fn run( if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); let workspace = resolve_workspace_from_toml(&toml_path, selection)?; - let proof_dir = workspace.proofs_directory_path(); let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { - let circuit_build_path = workspace.package_build_path(package); + let program = compile_bin_package( + &workspace, + package, + &args.compile_options, + np_language, + &|opcode| opcode_support.is_opcode_supported(opcode), + )?; prove_package( backend, + &workspace, package, + program, &args.prover_name, &args.verifier_name, - &proof_dir, - circuit_build_path, args.verify, - &args.compile_options, - np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), )?; } Ok(()) } -#[allow(clippy::too_many_arguments)] pub(crate) fn prove_package( backend: &Backend, + workspace: &Workspace, package: &Package, + compiled_program: CompiledProgram, prover_name: &str, verifier_name: &str, - proof_dir: &Path, - circuit_build_path: PathBuf, check_proof: bool, - compile_options: &CompileOptions, - np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> Result<(), CliError> { - let (preprocessed_program, debug_data) = if circuit_build_path.exists() { - let program = read_program_from_file(circuit_build_path)?; - - (program, None) - } else { - let program = - compile_bin_package(package, compile_options, np_language, &is_opcode_supported)?; - let preprocessed_program = PreprocessedProgram { - backend: String::from(BACKEND_IDENTIFIER), - abi: program.abi, - bytecode: program.circuit, - }; - let debug_artifact = - DebugArtifact { debug_symbols: vec![program.debug], file_map: program.file_map }; - - (preprocessed_program, Some(debug_artifact)) - }; - - let PreprocessedProgram { abi, bytecode, .. } = preprocessed_program; - // Parse the initial witness values from Prover.toml let (inputs_map, _) = - read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &abi)?; + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)?; - let solved_witness = execute_program(bytecode.clone(), &abi, &inputs_map, debug_data)?; + let solved_witness = execute_program(&compiled_program, &inputs_map)?; // Write public inputs into Verifier.toml - let public_abi = abi.public_abi(); + let public_abi = compiled_program.abi.public_abi(); let (public_inputs, return_value) = public_abi.decode(&solved_witness)?; write_inputs_to_file( @@ -136,18 +105,19 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = backend.prove(&bytecode, solved_witness, false)?; + let proof = backend.prove(&compiled_program.circuit, solved_witness, false)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &bytecode, false)?; + let valid_proof = + backend.verify(&proof, public_inputs, &compiled_program.circuit, false)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); } } - save_proof_to_dir(&proof, &String::from(&package.name), proof_dir)?; + save_proof_to_dir(&proof, &String::from(&package.name), workspace.proofs_directory_path())?; Ok(()) } diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 8d10d70ddd0..6ae2b78fd0c 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -1,23 +1,18 @@ use super::NargoConfig; use super::{ compile_cmd::compile_bin_package, - fs::{inputs::read_inputs_from_file, load_hex_data, program::read_program_from_file}, + fs::{inputs::read_inputs_from_file, load_hex_data}, }; use crate::{backends::Backend, errors::CliError}; -use acvm::acir::circuit::Opcode; -use acvm::Language; use clap::Args; use nargo::constants::{PROOF_EXT, VERIFIER_INPUT_FILE}; -use nargo::{artifacts::program::PreprocessedProgram, package::Package}; +use nargo::package::Package; +use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; -use noirc_driver::CompileOptions; +use noirc_driver::{CompileOptions, CompiledProgram}; use noirc_frontend::graph::CrateName; -use std::path::{Path, PathBuf}; - -// TODO(#1388): pull this from backend. -const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; /// Given a proof and a program, verify whether the proof is valid #[derive(Debug, Clone, Args)] @@ -48,68 +43,47 @@ pub(crate) fn run( if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); let workspace = resolve_workspace_from_toml(&toml_path, selection)?; - let proofs_dir = workspace.proofs_directory_path(); let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { - let circuit_build_path = workspace.package_build_path(package); - - let proof_path = proofs_dir.join(String::from(&package.name)).with_extension(PROOF_EXT); - - verify_package( - backend, + let program = compile_bin_package( + &workspace, package, - &proof_path, - circuit_build_path, - &args.verifier_name, &args.compile_options, np_language, &|opcode| opcode_support.is_opcode_supported(opcode), )?; + + verify_package(backend, &workspace, package, program, &args.verifier_name)?; } Ok(()) } -#[allow(clippy::too_many_arguments)] fn verify_package( backend: &Backend, + workspace: &Workspace, package: &Package, - proof_path: &Path, - circuit_build_path: PathBuf, + compiled_program: CompiledProgram, verifier_name: &str, - compile_options: &CompileOptions, - np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> Result<(), CliError> { - let preprocessed_program = if circuit_build_path.exists() { - read_program_from_file(circuit_build_path)? - } else { - let program = - compile_bin_package(package, compile_options, np_language, &is_opcode_supported)?; - - PreprocessedProgram { - backend: String::from(BACKEND_IDENTIFIER), - abi: program.abi, - bytecode: program.circuit, - } - }; - - let PreprocessedProgram { abi, bytecode, .. } = preprocessed_program; - // Load public inputs (if any) from `verifier_name`. - let public_abi = abi.public_abi(); + let public_abi = compiled_program.abi.public_abi(); let (public_inputs_map, return_value) = read_inputs_from_file(&package.root_dir, verifier_name, Format::Toml, &public_abi)?; let public_inputs = public_abi.encode(&public_inputs_map, return_value)?; - let proof = load_hex_data(proof_path)?; - let valid_proof = backend.verify(&proof, public_inputs, &bytecode, false)?; + let proof_path = + workspace.proofs_directory_path().join(package.name.to_string()).with_extension(PROOF_EXT); + + let proof = load_hex_data(&proof_path)?; + + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit, false)?; if valid_proof { Ok(()) } else { - Err(CliError::InvalidProof(proof_path.to_path_buf())) + Err(CliError::InvalidProof(proof_path)) } } diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml new file mode 100644 index 00000000000..872c8f2030d --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml @@ -0,0 +1,8 @@ + +[package] +name = "primary_attribute_struct" +type = "bin" +authors = [""] +compiler_version = "0.11.1" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr new file mode 100644 index 00000000000..8922ef60091 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr @@ -0,0 +1,8 @@ +// An primary attribute should not be able to be added to a struct defintion +#[oracle(some_oracle)] +struct SomeStruct{ + x: Field, + y: Field +} + +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml new file mode 100644 index 00000000000..0f00e7d9c73 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "attributes_struct" +type = "bin" +authors = [""] +compiler_version = "0.11.1" + +[dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr new file mode 100644 index 00000000000..0bad42aee57 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr @@ -0,0 +1,8 @@ +#[some_attribute] +#[another_attribute] +struct SomeStruct { + a: Field, + b: Field +} + +fn main() {} diff --git a/tooling/noir_js/.eslintignore b/tooling/noir_js/.eslintignore index 3c3629e647f..fcbc654a839 100644 --- a/tooling/noir_js/.eslintignore +++ b/tooling/noir_js/.eslintignore @@ -1 +1,2 @@ node_modules +test/backend/barretenberg.ts \ No newline at end of file diff --git a/tooling/noir_js/.eslintrc.js b/tooling/noir_js/.eslintrc.cjs similarity index 100% rename from tooling/noir_js/.eslintrc.js rename to tooling/noir_js/.eslintrc.cjs diff --git a/tooling/noir_js/.gitignore b/tooling/noir_js/.gitignore new file mode 100644 index 00000000000..9d26861cc3c --- /dev/null +++ b/tooling/noir_js/.gitignore @@ -0,0 +1 @@ +!test/noir_compiled_examples/*/target \ No newline at end of file diff --git a/tooling/noir_js/.mocharc.json b/tooling/noir_js/.mocharc.json new file mode 100644 index 00000000000..9e1a6acc542 --- /dev/null +++ b/tooling/noir_js/.mocharc.json @@ -0,0 +1,8 @@ +{ + "require": "ts-node/register", + "loader": "ts-node/esm", + "extensions": ["ts"], + "spec": [ + "test/node/**/*.test.ts*" + ] +} \ No newline at end of file diff --git a/tooling/noir_js/.prettierrc b/tooling/noir_js/.prettierrc new file mode 100644 index 00000000000..ef937f9697a --- /dev/null +++ b/tooling/noir_js/.prettierrc @@ -0,0 +1,6 @@ +{ + "parser": "typescript", + "printWidth": 120, + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index 432afa653dc..5fd66672f0f 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -6,9 +6,11 @@ "version": "0.12.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", + "type": "module", "dependencies": { "@noir-lang/acvm_js": "0.27.0", - "@noir-lang/noirc_abi": "workspace:*" + "@noir-lang/noirc_abi": "workspace:*", + "fflate": "^0.8.0" }, "files": [ "lib", @@ -17,10 +19,26 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { + "dev": "tsc --watch", "build": "tsc", + "test": "yarn test:node", + "test:node": "mocha --timeout 25000", + "prettier": "prettier 'src/**/*.ts'", + "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "devDependencies": { + "@aztec/bb.js": "0.7.2", + "@types/chai": "^4", + "@types/mocha": "^10.0.1", + "@types/node": "^20.6.2", + "@types/prettier": "^3", + "chai": "^4.3.8", + "eslint": "^8.40.0", + "eslint-plugin-prettier": "^5.0.0", + "mocha": "^10.2.0", + "prettier": "3.0.3", + "ts-node": "^10.9.1", "typescript": "^5.2.2" } } diff --git a/tooling/noir_js/src/base64_decode.ts b/tooling/noir_js/src/base64_decode.ts new file mode 100644 index 00000000000..d53aed187c7 --- /dev/null +++ b/tooling/noir_js/src/base64_decode.ts @@ -0,0 +1,13 @@ +// Since this is a simple function, we can use feature detection to +// see if we are in the nodeJs environment or the browser environment. +export function base64Decode(input: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + // Node.js environment + return Buffer.from(input, 'base64'); + } else if (typeof atob === 'function') { + // Browser environment + return Uint8Array.from(atob(input), (c) => c.charCodeAt(0)); + } else { + throw new Error('No implementation found for base64 decoding.'); + } +} diff --git a/tooling/noir_js/src/index.ts b/tooling/noir_js/src/index.ts index 3455663f046..4125affae6d 100644 --- a/tooling/noir_js/src/index.ts +++ b/tooling/noir_js/src/index.ts @@ -1,3 +1,8 @@ -import * as acvm from "@noir-lang/acvm_js"; -import * as noirc from "@noir-lang/noirc_abi"; -export { acvm, noirc }; +import * as acvm from '@noir-lang/acvm_js'; +import * as abi from '@noir-lang/noirc_abi'; + +export { acvm, abi }; + +import { generateWitness } from './witness_generation.js'; +import { acirToUint8Array, witnessMapToUint8Array } from './serialize.js'; +export { acirToUint8Array, witnessMapToUint8Array, generateWitness }; diff --git a/tooling/noir_js/src/input_validation.ts b/tooling/noir_js/src/input_validation.ts new file mode 100644 index 00000000000..9a19528a0cf --- /dev/null +++ b/tooling/noir_js/src/input_validation.ts @@ -0,0 +1,55 @@ +// Check if all of the input values are correct according to the ABI +export function validateInputs(inputs, abi) { + for (const param of abi.parameters) { + const inputValue = inputs[param.name]; + if (inputValue === undefined) { + // This is checked by noirc_abi, so we could likely remove this check + return { isValid: false, error: `Input for ${param.name} is missing` }; + } + if (!checkType(inputValue, param.type)) { + return { + isValid: false, + error: `Input for ${param.name} is the wrong type, expected ${type_to_string(param.type)}, got "${inputValue}"`, + }; + } + } + return { isValid: true, error: null }; +} + +// Checks that value is of type "type" +// Where type is taken from the abi +function checkType(value, type) { + switch (type.kind) { + case 'integer': + if (type.sign === 'unsigned') { + return isUnsignedInteger(value, type.width); + } + // Other integer sign checks can be added here + break; + // Other type.kind checks can be added here + } + return false; +} + +function type_to_string(type): string { + switch (type.kind) { + case 'integer': + if (type.sign === 'unsigned') { + return `uint${type.width}`; + } + break; + case 'array': + return `${type_to_string(type.element)}[${type.length}]`; + } + return 'unknown type'; +} + +// Returns true if `value` is an unsigned integer that is less than 2^{width} +function isUnsignedInteger(value: bigint, width: bigint) { + try { + const bigIntValue = BigInt(value); + return bigIntValue >= 0 && bigIntValue <= BigInt(2) ** BigInt(width) - 1n; + } catch (e) { + return false; // Not a valid integer + } +} diff --git a/tooling/noir_js/src/serialize.ts b/tooling/noir_js/src/serialize.ts new file mode 100644 index 00000000000..df01769c06e --- /dev/null +++ b/tooling/noir_js/src/serialize.ts @@ -0,0 +1,17 @@ +import { WitnessMap, compressWitness } from '@noir-lang/acvm_js'; +import { decompressSync as gunzip } from 'fflate'; +import { base64Decode } from './base64_decode.js'; + +// After solving the witness, to pass it a backend, we need to serialize it to a Uint8Array +export function witnessMapToUint8Array(solvedWitness: WitnessMap): Uint8Array { + // TODO: We just want to serialize, but this will zip up the witness + // TODO so its not ideal + const compressedWitness = compressWitness(solvedWitness); + return gunzip(compressedWitness); +} + +// Converts an bytecode to a Uint8Array +export function acirToUint8Array(base64EncodedBytecode): Uint8Array { + const compressedByteCode = base64Decode(base64EncodedBytecode); + return gunzip(compressedByteCode); +} diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts new file mode 100644 index 00000000000..d72033b275a --- /dev/null +++ b/tooling/noir_js/src/witness_generation.ts @@ -0,0 +1,24 @@ +import { abiEncode } from '@noir-lang/noirc_abi'; +import { validateInputs } from './input_validation.js'; +import { base64Decode } from './base64_decode.js'; +import { WitnessMap, executeCircuit } from '@noir-lang/acvm_js'; + +// Generates the witnesses needed to feed into the chosen proving system +export async function generateWitness(compiledProgram, inputs): Promise { + // Validate inputs + const { isValid, error } = validateInputs(inputs, compiledProgram.abi); + if (!isValid) { + throw new Error(error?.toString()); + } + const witnessMap = abiEncode(compiledProgram.abi, inputs, null); + + // Execute the circuit to generate the rest of the witnesses + try { + const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, () => { + throw Error('unexpected oracle during execution'); + }); + return solvedWitness; + } catch (err) { + throw new Error(`Circuit execution failed: ${err}`); + } +} diff --git a/tooling/noir_js/test/backend/barretenberg.ts b/tooling/noir_js/test/backend/barretenberg.ts new file mode 100644 index 00000000000..6a770cde2f2 --- /dev/null +++ b/tooling/noir_js/test/backend/barretenberg.ts @@ -0,0 +1,122 @@ +// @ts-ignore +import { Barretenberg, Crs, RawBuffer } from '@aztec/bb.js'; +// TODO: This should be re-exported from @aztec/bb-js +import { Ptr } from '@aztec/bb.js/dest/browser/types'; +import { acirToUint8Array } from '../../src/index.js'; + +export class Backend { + // These type assertions are used so that we don't + // have to initialize `api` and `acirComposer` in the constructor. + // These are initialized asynchronously in the `init` function, + // constructors cannot be asynchronous which is why we do this. + api = {} as Barretenberg; + acirComposer = {} as Ptr; + acirUncompressedBytecode: Uint8Array; + + constructor(acirBytecodeBase64: string) { + this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64); + } + async init() { + const numThreads = 4; + + const { api, composer } = await this.initBarretenberg(numThreads, this.acirUncompressedBytecode); + + this.api = api; + this.acirComposer = composer; + } + + async initBarretenberg(numThreads: number, acirUncompressedBytecode: Uint8Array) { + const api = await Barretenberg.new(numThreads); + + const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(acirUncompressedBytecode); + const crs = await Crs.new(subgroupSize + 1); + await api.commonInitSlabAllocator(subgroupSize); + await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); + + const acirComposer = await api.acirNewAcirComposer(subgroupSize); + return { api: api, composer: acirComposer }; + } + + // Generate an outer proof. This is the proof for the circuit which will verify + // inner proofs and or can be seen as the proof created for regular circuits. + // + // The settings for this proof are the same as the settings for a "normal" proof + // ie one that is not in the recursive setting. + async generateOuterProof(decompressedWitness: Uint8Array) { + const makeEasyToVerifyInCircuit = false; + return this.generateProof(decompressedWitness, makeEasyToVerifyInCircuit); + } + + // Generates an inner proof. This is the proof that will be verified + // in another circuit. + // + // This is sometimes referred to as a recursive proof. + // We avoid this terminology as the only property of this proof + // that matters, is the fact that it is easy to verify in another + // circuit. We _could_ choose to verify this proof in the CLI. + // + // We set `makeEasyToVerifyInCircuit` to true, which will tell the backend to + // generate the proof using components that will make the proof + // easier to verify in a circuit. + async generateInnerProof(witness: Uint8Array) { + const makeEasyToVerifyInCircuit = true; + return this.generateProof(witness, makeEasyToVerifyInCircuit); + } + + async generateProof(decompressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean) { + const proof = await this.api.acirCreateProof( + this.acirComposer, + this.acirUncompressedBytecode, + decompressedWitness, + makeEasyToVerifyInCircuit, + ); + + return proof; + } + + // Generates artifacts that will be passed to a circuit that will verify this proof. + // + // Instead of passing the proof and verification key as a byte array, we pass them + // as fields which makes it cheaper to verify in a circuit. + // + // The proof that is passed here will have been created using the `generateInnerProof` + // method. + // + // The number of public inputs denotes how many public inputs are in the inner proof. + async generateInnerProofArtifacts(proof: Uint8Array, numOfPublicInputs = 0) { + const proofAsFields = await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs); + + // TODO: perhaps we should put this in the init function. Need to benchmark + // TODO how long it takes. + await this.api.acirInitVerificationKey(this.acirComposer); + + // Note: If you don't init verification key, `acirSerializeVerificationKeyIntoFields`` will just hang on serialization + const vk = await this.api.acirSerializeVerificationKeyIntoFields(this.acirComposer); + + return { + proofAsFields: proofAsFields.map((p) => p.toString()), + vkAsFields: vk[0].map((vk) => vk.toString()), + vkHash: vk[1].toString(), + }; + } + + async verifyOuterProof(proof: Uint8Array) { + const makeEasyToVerifyInCircuit = false; + const verified = await this.verifyProof(proof, makeEasyToVerifyInCircuit); + return verified; + } + + async verifyInnerProof(proof: Uint8Array) { + const makeEasyToVerifyInCircuit = true; + return this.verifyProof(proof, makeEasyToVerifyInCircuit); + } + + async verifyProof(proof: Uint8Array, makeEasyToVerifyInCircuit: boolean) { + await this.api.acirInitVerificationKey(this.acirComposer); + return await this.api.acirVerifyProof(this.acirComposer, proof, makeEasyToVerifyInCircuit); + } + + async destroy() { + await this.api.destroy(); + } +} diff --git a/tooling/noir_js/test/node/e2e.test.ts b/tooling/noir_js/test/node/e2e.test.ts new file mode 100644 index 00000000000..ddd91cca834 --- /dev/null +++ b/tooling/noir_js/test/node/e2e.test.ts @@ -0,0 +1,128 @@ +import { expect } from 'chai'; +import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' }; +import { generateWitness, witnessMapToUint8Array } from '../../src/index.js'; +import { Backend } from '../backend/barretenberg.js'; + +it('end-to-end proof creation and verification (outer)', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + const solvedWitness = await generateWitness(assert_lt_json, inputs); + + // bb.js part + // + // Proof creation + const prover = new Backend(assert_lt_json.bytecode); + await prover.init(); + const serializedWitness = witnessMapToUint8Array(solvedWitness); + const proof = await prover.generateOuterProof(serializedWitness); + + // Proof verification + const isValid = await prover.verifyOuterProof(proof); + expect(isValid).to.be.true; +}); + +it('end-to-end proof creation and verification (inner)', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + const solvedWitness = await generateWitness(assert_lt_json, inputs); + + // bb.js part + // + // Proof creation + const prover = new Backend(assert_lt_json.bytecode); + await prover.init(); + const serializedWitness = witnessMapToUint8Array(solvedWitness); + const proof = await prover.generateInnerProof(serializedWitness); + + // Proof verification + const isValid = await prover.verifyInnerProof(proof); + expect(isValid).to.be.true; +}); + +// The "real" workflow will involve a prover and a verifier on different systems. +// +// We cannot do this in our tests because they will panic with: +// `RuntimeError: null function or function signature mismatch` +// +// This happens when we we create a proof with one barretenberg instance and +// try to verify it with another. +// +// If this bug is fixed, we can remove this test and split barretenberg into +// a prover and verifier class to more accurately reflect what happens in production. +// +// If its not fixable, we can leave it in as documentation of this behavior. +it('[BUG] -- bb.js null function or function signature mismatch (different instance) ', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + const solvedWitness = await generateWitness(assert_lt_json, inputs); + + // bb.js part + const prover = new Backend(assert_lt_json.bytecode); + await prover.init(); + + const serializedWitness = witnessMapToUint8Array(solvedWitness); + const proof = await prover.generateOuterProof(serializedWitness); + + try { + const verifier = new Backend(assert_lt_json.bytecode); + await verifier.init(); + await verifier.verifyOuterProof(proof); + expect.fail( + 'bb.js currently returns a bug when we try to verify a proof with a different Barretenberg instance that created it.', + ); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.contain('null function or function signature mismatch'); + } +}); + +// This bug occurs when we use the same backend to create an inner proof and then an outer proof +// and then try to verify either one of them. +// +// The panic occurs when we try to verify the outer/inner proof that was created. +// If we only create one type of proof, then this works as expected. +// +// If we do not create an inner proof, then this will work as expected. +it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + const solvedWitness = await generateWitness(assert_lt_json, inputs); + + // bb.js part + // + // Proof creation + // + const prover = new Backend(assert_lt_json.bytecode); + await prover.init(); + const serializedWitness = witnessMapToUint8Array(solvedWitness); + // Create a proof using both proving systems, the majority of the time + // one would only use outer proofs. + const proofOuter = await prover.generateOuterProof(serializedWitness); + const _proofInner = await prover.generateInnerProof(serializedWitness); + + // Proof verification + // + try { + const isValidOuter = await prover.verifyOuterProof(proofOuter); + expect(isValidOuter).to.be.true; + // We can also try verifying an inner proof and it will fail. + // const isValidInner = await prover.verifyInnerProof(_proofInner); + // expect(isValidInner).to.be.true; + expect.fail('bb.js currently returns a bug when we try to verify an inner and outer proof with the same backend'); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.contain('null function or function signature mismatch'); + } +}); diff --git a/tooling/noir_js/test/node/smoke.test.ts b/tooling/noir_js/test/node/smoke.test.ts new file mode 100644 index 00000000000..179246745fe --- /dev/null +++ b/tooling/noir_js/test/node/smoke.test.ts @@ -0,0 +1,72 @@ +import { expect } from 'chai'; +import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' }; +import { generateWitness } from '../../src/index.js'; + +it('generates witnesses successfully', async () => { + const inputs = { + x: '2', + y: '3', + }; + const _solvedWitness = await generateWitness(assert_lt_json, inputs); +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + const solvedWitnessString = await generateWitness(assert_lt_json, inputsString); + const solvedWitnessNumber = await generateWitness(assert_lt_json, inputsNumber); + expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + + const solvedWitnessString = await generateWitness(assert_lt_json, inputsString); + const solvedWitnessNumber = await generateWitness(assert_lt_json, inputsNumber); + expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('0x prefixed string input for inputs will throw', async () => { + const inputsHexPrefix = { + x: '0x2', + y: '0x3', + }; + + try { + await generateWitness(assert_lt_json, inputsHexPrefix); + expect.fail('Expected generatedWitness to throw, due to inputs being prefixed with 0x. Currently not supported'); + } catch (error) { + // Successfully errored due to 0x not being supported. Update this test once/if we choose + // to support 0x prefixed inputs. + } +}); + +describe('input validation', () => { + it('x should be a uint64 not a string', async () => { + const inputs = { + x: 'foo', + y: '3', + }; + + try { + await generateWitness(assert_lt_json, inputs); + expect.fail('Expected generatedWitness to throw, due to x not being convertible to a uint64'); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Input for x is the wrong type, expected uint64, got "foo"'); + } + }); +}); diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml new file mode 100644 index 00000000000..742f100681f --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_lt" +type = "bin" +authors = [""] +compiler_version = "0.1" + +[dependencies] diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr new file mode 100644 index 00000000000..7f3767f4a48 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr @@ -0,0 +1,3 @@ +fn main(x : u64, y : pub u64) { + assert(x < y); +} \ No newline at end of file diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json b/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json new file mode 100644 index 00000000000..fdf25a4743d --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json @@ -0,0 +1 @@ +{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":null,"return_witnesses":[]},"bytecode":"H4sIAAAAAAAA/81WXW7DIAw20BJl0noWE6CBt6k3WbT0/kfYooJm0bQPxZZqKXKw4PPPB5Y/AOATbqL+Pl30F1nrsqaiiq52j+cQ1nlanXffOOUlRQxxOSeXXEzxZ0rerymkOS95xuyCX901Zn/Fm5jXsbDBcobE9yxm7BNn+LCQxnvY+dfEZoq2AjlB46et42nHxupcgqSDAO4R+C6/VN5Hfo6QQIrWFDvFwP9DoaKZY1aM90C/HpdrDTupvyP2nS/a6GzRA7GNhEfd7Nu4qJxvb/5CzimiFcG4kDN7e9QDnJHY6vkTiQX4aoICjR5FG3mdHCwp5rYe4H6SMAK+Kxbng+zFGkGmCbf1652eLGPOAyOvHfV72sC4J1nLyPOjptXKL8ADXjPGCwAA"} \ No newline at end of file diff --git a/tooling/noir_js/test/noir_compiled_examples/readme.md b/tooling/noir_js/test/noir_compiled_examples/readme.md new file mode 100644 index 00000000000..26c571850ae --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/readme.md @@ -0,0 +1,3 @@ +## Why + +While we do not automatically pull the .json files from .artifacts, we have these hard-coded versions of examples. diff --git a/tooling/noir_js/tsconfig.json b/tooling/noir_js/tsconfig.json index 45c1f060a57..0fd439990a6 100644 --- a/tooling/noir_js/tsconfig.json +++ b/tooling/noir_js/tsconfig.json @@ -7,7 +7,9 @@ "moduleResolution": "node", "outDir": "./lib", "esModuleInterop": true, - "strict": true + "resolveJsonModule": true, + "strict": true, + "noImplicitAny": false, }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] diff --git a/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts b/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts index 2ca45d78f5c..8cdf19c43a7 100644 --- a/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts +++ b/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts @@ -18,10 +18,10 @@ it("recovers original inputs when abi encoding and decoding", async () => { expect(BigInt(decoded_inputs.inputs.foo)).to.be.equal(BigInt(inputs.foo)); expect(BigInt(decoded_inputs.inputs.bar[0])).to.be.equal( - BigInt(inputs.bar[0]) + BigInt(inputs.bar[0]), ); expect(BigInt(decoded_inputs.inputs.bar[1])).to.be.equal( - BigInt(inputs.bar[1]) + BigInt(inputs.bar[1]), ); expect(decoded_inputs.return_value).to.be.null; }); diff --git a/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts b/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts index 8a3b6fe9ffc..b84d84fdd77 100644 --- a/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts +++ b/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts @@ -10,10 +10,10 @@ it("recovers original inputs when abi encoding and decoding", async () => { expect(BigInt(decoded_inputs.inputs.foo)).to.be.equal(BigInt(inputs.foo)); expect(BigInt(decoded_inputs.inputs.bar[0])).to.be.equal( - BigInt(inputs.bar[0]) + BigInt(inputs.bar[0]), ); expect(BigInt(decoded_inputs.inputs.bar[1])).to.be.equal( - BigInt(inputs.bar[1]) + BigInt(inputs.bar[1]), ); expect(decoded_inputs.return_value).to.be.null; }); diff --git a/yarn.lock b/yarn.lock index d9daf5f0b2a..6ce7d6ae1bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,20 @@ __metadata: languageName: node linkType: hard +"@aztec/bb.js@npm:0.7.2": + version: 0.7.2 + resolution: "@aztec/bb.js@npm:0.7.2" + dependencies: + comlink: ^4.4.1 + commander: ^10.0.1 + debug: ^4.3.4 + tslib: ^2.4.0 + bin: + bb.js: dest/node/main.js + checksum: 68299e5b0ef9583d78d1aaeb4e6a80cf5e049d45e48fb02798a41a2dfda0e68d729e8fbc1d23ab692914ce3857c729b48da9200fca49b838416b7988e5516d0b + languageName: node + linkType: hard + "@aztec/bb.js@npm:^0.6.7": version: 0.6.7 resolution: "@aztec/bb.js@npm:0.6.7" @@ -46,21 +60,21 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.19 - resolution: "@babel/helper-validator-identifier@npm:7.22.19" - checksum: cf1f94d35cdb2d0f519b31954d1c54929fb31cf8af70fed12b3a1e777c296fabe747e56d9ae3d181c1c96f33ac66aff9501189542554b6fe0508748a38c1c17f +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc languageName: node linkType: hard "@babel/highlight@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/highlight@npm:7.22.13" + version: 7.22.20 + resolution: "@babel/highlight@npm:7.22.20" dependencies: - "@babel/helper-validator-identifier": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 7266d2bff8aa8fc78eb65b6e92a8211e12897a731126a282d2f9bb50d8fcaa4c1b02af2284f990ac7e3ab8d892d448a2cab8f5ed0ea8a90bce2c025b11ebe802 + checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134 languageName: node linkType: hard @@ -396,8 +410,20 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noir_js@workspace:tooling/noir_js" dependencies: + "@aztec/bb.js": 0.7.2 "@noir-lang/acvm_js": 0.27.0 "@noir-lang/noirc_abi": "workspace:*" + "@types/chai": ^4 + "@types/mocha": ^10.0.1 + "@types/node": ^20.6.2 + "@types/prettier": ^3 + chai: ^4.3.8 + eslint: ^8.40.0 + eslint-plugin-prettier: ^5.0.0 + fflate: ^0.8.0 + mocha: ^10.2.0 + prettier: 3.0.3 + ts-node: ^10.9.1 typescript: ^5.2.2 languageName: unknown linkType: soft @@ -439,9 +465,9 @@ __metadata: "@typescript-eslint/parser": ^5.59.5 chai: ^4.3.7 eslint: ^8.40.0 - eslint-plugin-prettier: ^4.2.1 + eslint-plugin-prettier: ^5.0.0 mocha: ^10.2.0 - prettier: ^2.8.8 + prettier: 3.0.3 ts-node: ^10.9.1 typescript: ^5.0.4 languageName: unknown @@ -473,6 +499,20 @@ __metadata: languageName: node linkType: hard +"@pkgr/utils@npm:^2.3.1": + version: 2.4.2 + resolution: "@pkgr/utils@npm:2.4.2" + dependencies: + cross-spawn: ^7.0.3 + fast-glob: ^3.3.0 + is-glob: ^4.0.3 + open: ^9.1.0 + picocolors: ^1.0.0 + tslib: ^2.6.0 + checksum: 24e04c121269317d259614cd32beea3af38277151c4002df5883c4be920b8e3490bb897748e844f9d46bf68230f86dabd4e8f093773130e7e60529a769a132fc + languageName: node + linkType: hard + "@puppeteer/browsers@npm:0.5.0": version: 0.5.0 resolution: "@puppeteer/browsers@npm:0.5.0" @@ -632,23 +672,23 @@ __metadata: linkType: hard "@types/babel__code-frame@npm:^7.0.2": - version: 7.0.3 - resolution: "@types/babel__code-frame@npm:7.0.3" - checksum: 543bd933e5ffdfbf75dfee0a36461c8a9d9283d5a95ceae0e021b2aef7fe774f1f251ea56f507faedf9d3574894b4774636f2b125f5cc5f6759503e1e56feb93 + version: 7.0.4 + resolution: "@types/babel__code-frame@npm:7.0.4" + checksum: eb4adb0a79c5cbf2d88ad087b2694a1e38749dc0056693e6125c17a3967fc8d4cc1eb33eab26d3dcaaa8995236cba4a088965cc3a115967545f2a01ee430c87f languageName: node linkType: hard "@types/body-parser@npm:*": - version: 1.19.2 - resolution: "@types/body-parser@npm:1.19.2" + version: 1.19.3 + resolution: "@types/body-parser@npm:1.19.3" dependencies: "@types/connect": "*" "@types/node": "*" - checksum: e17840c7d747a549f00aebe72c89313d09fbc4b632b949b2470c5cb3b1cb73863901ae84d9335b567a79ec5efcfb8a28ff8e3f36bc8748a9686756b6d5681f40 + checksum: 932fa71437c275023799123680ef26ffd90efd37f51a1abe405e6ae6e5b4ad9511b7a3a8f5a12877ed1444a02b6286c0a137a98e914b3c61932390c83643cc2c languageName: node linkType: hard -"@types/chai@npm:^4.2.12": +"@types/chai@npm:^4, @types/chai@npm:^4.2.12": version: 4.3.6 resolution: "@types/chai@npm:4.3.6" checksum: 32a6c18bf53fb3dbd89d1bfcadb1c6fd45cc0007c34e436393cc37a0a5a556f9e6a21d1e8dd71674c40cc36589d2f30bf4d9369d7787021e54d6e997b0d7300a @@ -762,16 +802,16 @@ __metadata: linkType: hard "@types/http-cache-semantics@npm:^4.0.1": - version: 4.0.1 - resolution: "@types/http-cache-semantics@npm:4.0.1" - checksum: 1048aacf627829f0d5f00184e16548205cd9f964bf0841c29b36bc504509230c40bc57c39778703a1c965a6f5b416ae2cbf4c1d4589c889d2838dd9dbfccf6e9 + version: 4.0.2 + resolution: "@types/http-cache-semantics@npm:4.0.2" + checksum: 513429786a45d8124f93cc7ea1454b692008190ef743e9fec75a6a3c998309782d216f1e67d7d497ffece9c9212310ae05a8c56e8955492ee400eacdd7620e61 languageName: node linkType: hard "@types/http-errors@npm:*": - version: 2.0.1 - resolution: "@types/http-errors@npm:2.0.1" - checksum: 3bb0c50b0a652e679a84c30cd0340d696c32ef6558518268c238840346c077f899315daaf1c26c09c57ddd5dc80510f2a7f46acd52bf949e339e35ed3ee9654f + version: 2.0.2 + resolution: "@types/http-errors@npm:2.0.2" + checksum: d7f14045240ac4b563725130942b8e5c8080bfabc724c8ff3f166ea928ff7ae02c5194763bc8f6aaf21897e8a44049b0492493b9de3e058247e58fdfe0f86692 languageName: node linkType: hard @@ -801,9 +841,9 @@ __metadata: linkType: hard "@types/json-schema@npm:^7.0.9": - version: 7.0.12 - resolution: "@types/json-schema@npm:7.0.12" - checksum: 00239e97234eeb5ceefb0c1875d98ade6e922bfec39dd365ec6bd360b5c2f825e612ac4f6e5f1d13601b8b30f378f15e6faa805a3a732f4a1bbe61915163d293 + version: 7.0.13 + resolution: "@types/json-schema@npm:7.0.13" + checksum: 345df21a678fa72fb389f35f33de77833d09d4a142bb2bcb27c18690efa4cf70fc2876e43843cefb3fbdb9fcb12cd3e970a90936df30f53bbee899865ff605ab languageName: node linkType: hard @@ -860,6 +900,13 @@ __metadata: languageName: node linkType: hard +"@types/mocha@npm:^10.0.1": + version: 10.0.1 + resolution: "@types/mocha@npm:10.0.1" + checksum: 224ea9fce7b1734ccdb9aa99a622d902a538ce1847bca7fd22c5fb38adcf3ed536f50f48f587085db988a4bb3c2eb68f4b98e1cd6a38bc5547bd3bbbedc54495 + languageName: node + linkType: hard + "@types/mocha@npm:^8.2.0": version: 8.2.3 resolution: "@types/mocha@npm:8.2.3" @@ -867,17 +914,17 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.1.0, @types/node@npm:^20.5.7": - version: 20.6.1 - resolution: "@types/node@npm:20.6.1" - checksum: f9848617221b513d558071c804b006750d1ee1734c5ffea3ada9a0edd1642334ad0812222d6b99b7b8c0e1a5f1e557946ae99444c2705e9afc125abdf9fa36c2 +"@types/node@npm:*, @types/node@npm:^20.1.0, @types/node@npm:^20.5.7, @types/node@npm:^20.6.2": + version: 20.6.3 + resolution: "@types/node@npm:20.6.3" + checksum: 444a6f1f41cfa8d3e20ce0108e6e43960fb2ae0e481f233bb1c14d6252aa63a92e021de561cd317d9fdb411688f871065f40175a1f18763282dee2613a08f8a3 languageName: node linkType: hard "@types/node@npm:^18.7.20": - version: 18.17.16 - resolution: "@types/node@npm:18.17.16" - checksum: 8f9dbaf4a67a14110e2a0d805f9b57f3a5cda774dbcb7b1e7973efe31d5eeea358482dbe36a5bfadb0dde99f065f1ae0531f25a032f015871aa0b2896eb3c4ae + version: 18.17.18 + resolution: "@types/node@npm:18.17.18" + checksum: 59cbd906363d37017fe9ba0c08c1446e440d4d977459609c5f90b8fb7eb41f273ce8af30c5a5b5d599d7de934c1b3702bc9fc27caf8d2270e5cdb659c5232991 languageName: node linkType: hard @@ -895,6 +942,15 @@ __metadata: languageName: node linkType: hard +"@types/prettier@npm:^3": + version: 3.0.0 + resolution: "@types/prettier@npm:3.0.0" + dependencies: + prettier: "*" + checksum: a2a512d304e5bcf78f38089dc88ad19215e6ab871d435a17aef3ce538a63b07c0e359c18db23989dc1ed9fff96d99eee1f680416080184df5c7e0e3bf767e165 + languageName: node + linkType: hard + "@types/ps-tree@npm:^1.1.2": version: 1.1.2 resolution: "@types/ps-tree@npm:1.1.2" @@ -1108,19 +1164,19 @@ __metadata: languageName: node linkType: hard -"@wdio/config@npm:8.16.7": - version: 8.16.7 - resolution: "@wdio/config@npm:8.16.7" +"@wdio/config@npm:8.16.11": + version: 8.16.11 + resolution: "@wdio/config@npm:8.16.11" dependencies: "@wdio/logger": 8.11.0 "@wdio/types": 8.16.7 - "@wdio/utils": 8.16.7 + "@wdio/utils": 8.16.11 decamelize: ^6.0.0 deepmerge-ts: ^5.0.0 glob: ^10.2.2 import-meta-resolve: ^3.0.0 read-pkg-up: ^10.0.0 - checksum: 3eeaccfb8876c54101ad6d3c122e07d4e60dd3c69a9596b3b24333804835af60103bfa660c0d784dd1444263771a003879787eba3030f1179433b5330697a0a3 + checksum: 3e7aa863307f847fe9cd559878a61f9927fe7c389514b2281c120b81a7753a16fb329be224099daf8385d5a3e01c84cc012c4e37d943ba275fa46b7380546a64 languageName: node linkType: hard @@ -1161,9 +1217,9 @@ __metadata: languageName: node linkType: hard -"@wdio/utils@npm:8.16.7": - version: 8.16.7 - resolution: "@wdio/utils@npm:8.16.7" +"@wdio/utils@npm:8.16.11": + version: 8.16.11 + resolution: "@wdio/utils@npm:8.16.11" dependencies: "@puppeteer/browsers": ^1.6.0 "@wdio/logger": 8.11.0 @@ -1177,8 +1233,9 @@ __metadata: import-meta-resolve: ^3.0.0 locate-app: ^2.1.0 safaridriver: ^0.1.0 + split2: ^4.2.0 wait-port: ^1.0.4 - checksum: 0d064f85f4b436728751574f1993cc541f0c395c583cd6d90dd24f3410c66ed120a69b073b344de96bfaf4203109e1c6abbc9fe1f57a19f6fc7e297cc3cc6fb7 + checksum: d044cd135c02fc3d2d605a3607a60c2c318658649fbb8679e400fe33c7d5d2ef07e5e8730599bec3b42c04abbc880dfd3a22cf0e074ed5a78308ba8eaac37f9f languageName: node linkType: hard @@ -1917,7 +1974,7 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.17": +"big-integer@npm:^1.6.17, big-integer@npm:^1.6.44": version: 1.6.51 resolution: "big-integer@npm:1.6.51" checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 @@ -1966,6 +2023,15 @@ __metadata: languageName: node linkType: hard +"bplist-parser@npm:^0.2.0": + version: 0.2.0 + resolution: "bplist-parser@npm:0.2.0" + dependencies: + big-integer: ^1.6.44 + checksum: d5339dd16afc51de6c88f88f58a45b72ed6a06aa31f5557d09877575f220b7c1d3fbe375da0b62e6a10d4b8ed80523567e351f24014f5bc886ad523758142cdd + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -2039,6 +2105,15 @@ __metadata: languageName: node linkType: hard +"bundle-name@npm:^3.0.0": + version: 3.0.0 + resolution: "bundle-name@npm:3.0.0" + dependencies: + run-applescript: ^5.0.0 + checksum: edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 + languageName: node + linkType: hard + "bytes@npm:3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -2138,7 +2213,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.7": +"chai@npm:^4.3.7, chai@npm:^4.3.8": version: 4.3.8 resolution: "chai@npm:4.3.8" dependencies: @@ -2628,7 +2703,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -2782,6 +2857,28 @@ __metadata: languageName: node linkType: hard +"default-browser-id@npm:^3.0.0": + version: 3.0.0 + resolution: "default-browser-id@npm:3.0.0" + dependencies: + bplist-parser: ^0.2.0 + untildify: ^4.0.0 + checksum: 279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 + languageName: node + linkType: hard + +"default-browser@npm:^4.0.0": + version: 4.0.0 + resolution: "default-browser@npm:4.0.0" + dependencies: + bundle-name: ^3.0.0 + default-browser-id: ^3.0.0 + execa: ^7.1.1 + titleize: ^3.0.0 + checksum: 40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 + languageName: node + linkType: hard + "defer-to-connect@npm:^2.0.1": version: 2.0.1 resolution: "defer-to-connect@npm:2.0.1" @@ -2796,6 +2893,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^3.0.0": + version: 3.0.0 + resolution: "define-lazy-prop@npm:3.0.0" + checksum: 54884f94caac0791bf6395a3ec530ce901cf71c47b0196b8754f3fd17edb6c0e80149c1214429d851873bb0d689dbe08dcedbb2306dc45c8534a5934723851b6 + languageName: node + linkType: hard + "degenerator@npm:^5.0.0": version: 5.0.1 resolution: "degenerator@npm:5.0.1" @@ -3185,18 +3289,22 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:^4.2.1": - version: 4.2.1 - resolution: "eslint-plugin-prettier@npm:4.2.1" +"eslint-plugin-prettier@npm:^5.0.0": + version: 5.0.0 + resolution: "eslint-plugin-prettier@npm:5.0.0" dependencies: prettier-linter-helpers: ^1.0.0 + synckit: ^0.8.5 peerDependencies: - eslint: ">=7.28.0" - prettier: ">=2.0.0" + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + prettier: ">=3.0.0" peerDependenciesMeta: + "@types/eslint": + optional: true eslint-config-prettier: optional: true - checksum: b9e839d2334ad8ec7a5589c5cb0f219bded260839a857d7a486997f9870e95106aa59b8756ff3f37202085ebab658de382b0267cae44c3a7f0eb0bcc03a4f6d6 + checksum: 84e88744b9050f2d5ef31b94e85294dda16f3a53c2449f9d33eac8ae6264889b459bf35a68e438fb6b329c2a1d6491aac4bfa00d86317e7009de3dad0311bec6 languageName: node linkType: hard @@ -3363,6 +3471,40 @@ __metadata: languageName: node linkType: hard +"execa@npm:^5.0.0": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.0 + human-signals: ^2.1.0 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.1 + onetime: ^5.1.2 + signal-exit: ^3.0.3 + strip-final-newline: ^2.0.0 + checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 + languageName: node + linkType: hard + +"execa@npm:^7.1.1": + version: 7.2.0 + resolution: "execa@npm:7.2.0" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.1 + human-signals: ^4.3.0 + is-stream: ^3.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^5.1.0 + onetime: ^6.0.0 + signal-exit: ^3.0.7 + strip-final-newline: ^3.0.0 + checksum: 14fd17ba0ca8c87b277584d93b1d9fc24f2a65e5152b31d5eb159a3b814854283eaae5f51efa9525e304447e2f757c691877f7adff8fde5746aae67eb1edd1cc + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -3471,9 +3613,9 @@ __metadata: linkType: hard "fflate@npm:^0.8.0": - version: 0.8.0 - resolution: "fflate@npm:0.8.0" - checksum: 6215f95ee01d620a41e459247a7de7e7117dd23e78ef017c26b64c26f2a880a90eedc77675918bbf816d18cc990f6505cd71be933c67cc48cc1e7ebbff1589ea + version: 0.8.1 + resolution: "fflate@npm:0.8.1" + checksum: 7207e2d333243724485d2488095256b776184bd4545aa9967b655feaee5dc18e9525ed9b6d75f94cfd71d98fb285336f4902641683472f1d0c19a99137084cec languageName: node linkType: hard @@ -3555,9 +3697,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.7": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 + version: 3.2.9 + resolution: "flatted@npm:3.2.9" + checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 languageName: node linkType: hard @@ -3840,8 +3982,8 @@ __metadata: linkType: hard "glob@npm:^10.2.2": - version: 10.3.4 - resolution: "glob@npm:10.3.4" + version: 10.3.5 + resolution: "glob@npm:10.3.5" dependencies: foreground-child: ^3.1.0 jackspeak: ^2.0.3 @@ -3850,7 +3992,7 @@ __metadata: path-scurry: ^1.10.1 bin: glob: dist/cjs/src/bin.js - checksum: 176b97c124414401cb51329a93d2ba112cef8814adbed10348481916b9521b677773eee2691cb6b24d66632d8c8bb8913533f5ac4bfb2d0ef5454a1856082361 + checksum: 564f4799cae48c0bcc841c88a20b539b5701c27ed5596f8623f588b3c523262d3fc20eb1ea89cab9c75b0912faf40ca5501fc835f982225d0d0599282b09e97a languageName: node linkType: hard @@ -3882,11 +4024,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.21.0 - resolution: "globals@npm:13.21.0" + version: 13.22.0 + resolution: "globals@npm:13.22.0" dependencies: type-fest: ^0.20.2 - checksum: 86c92ca8a04efd864c10852cd9abb1ebe6d447dcc72936783e66eaba1087d7dba5c9c3421a48d6ca722c319378754dbcc3f3f732dbe47592d7de908edf58a773 + checksum: 64af5a09565341432770444085f7aa98b54331c3b69732e0de411003921fa2dd060222ae7b50bec0b98f29c4d00b4f49bf434049ba9f7c36ca4ee1773f60458c languageName: node linkType: hard @@ -4160,6 +4302,20 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 + languageName: node + linkType: hard + +"human-signals@npm:^4.3.0": + version: 4.3.1 + resolution: "human-signals@npm:4.3.1" + checksum: 6f12958df3f21b6fdaf02d90896c271df00636a31e2bbea05bddf817a35c66b38a6fdac5863e2df85bd52f34958997f1f50350ff97249e1dff8452865d5235d1 + languageName: node + linkType: hard + "humanize-ms@npm:^1.2.1": version: 1.2.1 resolution: "humanize-ms@npm:1.2.1" @@ -4357,6 +4513,15 @@ __metadata: languageName: node linkType: hard +"is-docker@npm:^3.0.0": + version: 3.0.0 + resolution: "is-docker@npm:3.0.0" + bin: + is-docker: cli.js + checksum: b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 + languageName: node + linkType: hard + "is-error@npm:^2.2.2": version: 2.2.2 resolution: "is-error@npm:2.2.2" @@ -4403,6 +4568,17 @@ __metadata: languageName: node linkType: hard +"is-inside-container@npm:^1.0.0": + version: 1.0.0 + resolution: "is-inside-container@npm:1.0.0" + dependencies: + is-docker: ^3.0.0 + bin: + is-inside-container: cli.js + checksum: c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 + languageName: node + linkType: hard + "is-lambda@npm:^1.0.1": version: 1.0.1 resolution: "is-lambda@npm:1.0.1" @@ -4466,6 +4642,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -5058,6 +5241,13 @@ __metadata: languageName: node linkType: hard +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -5522,6 +5712,24 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: ^3.0.0 + checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 + languageName: node + linkType: hard + +"npm-run-path@npm:^5.1.0": + version: 5.1.0 + resolution: "npm-run-path@npm:5.1.0" + dependencies: + path-key: ^4.0.0 + checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 + languageName: node + linkType: hard + "npmlog@npm:^6.0.0": version: 6.0.2 resolution: "npmlog@npm:6.0.2" @@ -5559,7 +5767,7 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.0": +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -5568,6 +5776,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: ^4.0.0 + checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 + languageName: node + linkType: hard + "only@npm:~0.0.2": version: 0.0.2 resolution: "only@npm:0.0.2" @@ -5586,6 +5803,18 @@ __metadata: languageName: node linkType: hard +"open@npm:^9.1.0": + version: 9.1.0 + resolution: "open@npm:9.1.0" + dependencies: + default-browser: ^4.0.0 + define-lazy-prop: ^3.0.0 + is-inside-container: ^1.0.0 + is-wsl: ^2.2.0 + checksum: 3993c0f61d51fed8ac290e99c9c3cf45d3b6cfb3e2aa2b74cafd312c3486c22fd81df16ac8f3ab91dd8a4e3e729a16fc2480cfc406c4833416cf908acf1ae7c9 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -5775,13 +6004,20 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^3.1.0": +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 + languageName: node + linkType: hard + "path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -5829,6 +6065,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -5906,12 +6149,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.8.8": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" +"prettier@npm:*, prettier@npm:3.0.3": + version: 3.0.3 + resolution: "prettier@npm:3.0.3" bin: - prettier: bin-prettier.js - checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 + prettier: bin/prettier.cjs + checksum: e10b9af02b281f6c617362ebd2571b1d7fc9fb8a3bd17e371754428cda992e5e8d8b7a046e8f7d3e2da1dcd21aa001e2e3c797402ebb6111b5cd19609dd228e0 languageName: node linkType: hard @@ -6240,28 +6483,28 @@ __metadata: linkType: hard "resolve@npm:^1.19.0": - version: 1.22.5 - resolution: "resolve@npm:1.22.5" + version: 1.22.6 + resolution: "resolve@npm:1.22.6" dependencies: is-core-module: ^2.13.0 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 6d8c8e414c0727341bc5b78d3806aa6730975d6c633ff266e90f3502ae1c10353d3535c9810aa94187a32ea192b9b3722afecac67487e27f44e60d89cca45cda + checksum: d13bf66d4e2ee30d291491f16f2fa44edd4e0cefb85d53249dd6f93e70b2b8c20ec62f01b18662e3cd40e50a7528f18c4087a99490048992a3bb954cf3201a5b languageName: node linkType: hard "resolve@patch:resolve@^1.19.0#~builtin": - version: 1.22.5 - resolution: "resolve@patch:resolve@npm%3A1.22.5#~builtin::version=1.22.5&hash=c3c19d" + version: 1.22.6 + resolution: "resolve@patch:resolve@npm%3A1.22.6#~builtin::version=1.22.6&hash=c3c19d" dependencies: is-core-module: ^2.13.0 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 8478df3911a3420450038b87aab4a6c66b91461035d901cd794076b46adfbf157fcfc8e83e3d0ef41a5956ce72ae166c33bd78432d6b41d43ee473b05c51cb32 + checksum: 9d3b3c67aefd12cecbe5f10ca4d1f51ea190891096497c43f301b086883b426466918c3a64f1bbf1788fabb52b579d58809614006c5d0b49186702b3b8fb746a languageName: node linkType: hard @@ -6350,6 +6593,15 @@ __metadata: languageName: node linkType: hard +"run-applescript@npm:^5.0.0": + version: 5.0.0 + resolution: "run-applescript@npm:5.0.0" + dependencies: + execa: ^5.0.0 + checksum: d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -6489,7 +6741,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -6626,9 +6878,16 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.13 - resolution: "spdx-license-ids@npm:3.0.13" - checksum: 3469d85c65f3245a279fa11afc250c3dca96e9e847f2f79d57f466940c5bb8495da08a542646086d499b7f24a74b8d0b42f3fc0f95d50ff99af1f599f6360ad7 + version: 3.0.15 + resolution: "spdx-license-ids@npm:3.0.15" + checksum: 99d567875b50504e1a7359f6da7d03e28db2b855b412ced18310679d091565a44f61ffd2585f19ea53a1192c35f2156c143507b12339dda26ef928547df32002 + languageName: node + linkType: hard + +"split2@npm:^4.2.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 05d54102546549fe4d2455900699056580cca006c0275c334611420f854da30ac999230857a85fdd9914dc2109ae50f80fda43d2a445f2aa86eccdc1dfce779d languageName: node linkType: hard @@ -6764,6 +7023,20 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 + languageName: node + linkType: hard + +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 + languageName: node + linkType: hard + "strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -6817,6 +7090,16 @@ __metadata: languageName: node linkType: hard +"synckit@npm:^0.8.5": + version: 0.8.5 + resolution: "synckit@npm:0.8.5" + dependencies: + "@pkgr/utils": ^2.3.1 + tslib: ^2.5.0 + checksum: 8a9560e5d8f3d94dc3cf5f7b9c83490ffa30d320093560a37b88f59483040771fd1750e76b9939abfbb1b5a23fd6dfbae77f6b338abffe7cae7329cd9b9bb86b + languageName: node + linkType: hard + "table-layout@npm:^3.0.0": version: 3.0.2 resolution: "table-layout@npm:3.0.2" @@ -6923,6 +7206,13 @@ __metadata: languageName: node linkType: hard +"titleize@npm:^3.0.0": + version: 3.0.0 + resolution: "titleize@npm:3.0.0" + checksum: 71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -7007,7 +7297,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.4.0": +"tslib@npm:^2.0.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad @@ -7217,6 +7507,13 @@ __metadata: languageName: node linkType: hard +"untildify@npm:^4.0.0": + version: 4.0.0 + resolution: "untildify@npm:4.0.0" + checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 + languageName: node + linkType: hard + "unzipper@npm:^0.10.14": version: 0.10.14 resolution: "unzipper@npm:0.10.14" @@ -7308,15 +7605,15 @@ __metadata: linkType: hard "wait-port@npm:^1.0.4": - version: 1.0.4 - resolution: "wait-port@npm:1.0.4" + version: 1.1.0 + resolution: "wait-port@npm:1.1.0" dependencies: chalk: ^4.1.2 commander: ^9.3.0 debug: ^4.3.4 bin: wait-port: bin/wait-port.js - checksum: 062aa830be38d16e0d004cb6b770cc1ce0b529e4e5cc2bca4c2e670c123bac1a1e692db938e9ce3db5199766a55fd02b1af5f4fee574b1b07ec65f373bbae324 + checksum: bf7c2cd566449530e2599a00cdf4b5a8a6e8c55d370bcd4045db6eacdc7040fdf3d83ff8773bbb036ac614e0d677ade28724a4d259cd3cc555cf9b4995647bab languageName: node linkType: hard @@ -7327,36 +7624,36 @@ __metadata: languageName: node linkType: hard -"webdriver@npm:8.16.7": - version: 8.16.7 - resolution: "webdriver@npm:8.16.7" +"webdriver@npm:8.16.11": + version: 8.16.11 + resolution: "webdriver@npm:8.16.11" dependencies: "@types/node": ^20.1.0 "@types/ws": ^8.5.3 - "@wdio/config": 8.16.7 + "@wdio/config": 8.16.11 "@wdio/logger": 8.11.0 "@wdio/protocols": 8.16.5 "@wdio/types": 8.16.7 - "@wdio/utils": 8.16.7 + "@wdio/utils": 8.16.11 deepmerge-ts: ^5.1.0 got: ^ 12.6.1 ky: ^0.33.0 ws: ^8.8.0 - checksum: e53546c5d330e93b21dfa1f970aed858d9c05408a2abab94196b6d51e9bbe2c3bcccd4f8e7e758cbec13148e31aabe4dd28050881d7aa09a336332d00610ab82 + checksum: 809331016bb04c303252f84a0b4d965dc716f18a798829dc35601cf7ed1fbfbf3f49d35a01ffe5573bdb3175121cbec36d18492f107fe47ecde8a4bffae0af88 languageName: node linkType: hard "webdriverio@npm:^8.8.6": - version: 8.16.7 - resolution: "webdriverio@npm:8.16.7" + version: 8.16.11 + resolution: "webdriverio@npm:8.16.11" dependencies: "@types/node": ^20.1.0 - "@wdio/config": 8.16.7 + "@wdio/config": 8.16.11 "@wdio/logger": 8.11.0 "@wdio/protocols": 8.16.5 "@wdio/repl": 8.10.1 "@wdio/types": 8.16.7 - "@wdio/utils": 8.16.7 + "@wdio/utils": 8.16.11 archiver: ^6.0.0 aria-query: ^5.0.0 css-shorthand-properties: ^1.1.1 @@ -7373,13 +7670,13 @@ __metadata: resq: ^1.9.1 rgb2hex: 0.2.5 serialize-error: ^11.0.1 - webdriver: 8.16.7 + webdriver: 8.16.11 peerDependencies: devtools: ^8.14.0 peerDependenciesMeta: devtools: optional: true - checksum: 6be1952f7ce4a87bf95ef2624f674a9f3d0f1483f91bf6bcec47f2766d496ba670aa564fad547695913439ffccc36b9a702e2922538cb0d128fa9ee4a39d5929 + checksum: 74199a7900ee81f1ccdf0e9096ab5a7ee6c9c1ec53a82293e64d5f06123f041155b3d9b594ac7e78e9fea4abb7f3c961f03d2f18fd2ca1ce50748c19b00a1a82 languageName: node linkType: hard @@ -7550,8 +7847,8 @@ __metadata: linkType: hard "ws@npm:^8.8.0": - version: 8.14.1 - resolution: "ws@npm:8.14.1" + version: 8.14.2 + resolution: "ws@npm:8.14.2" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -7560,7 +7857,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 9e310be2b0ff69e1f87d8c6d093ecd17a1ed4c37f281d17c35e8c30e2bd116401775b3d503249651374e6e0e1e9905db62fff096b694371c77561aee06bc3466 + checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b languageName: node linkType: hard