diff --git a/.aztec-sync-commit b/.aztec-sync-commit index c97738f7226..78e53d61647 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -9e246c1289fa40c35c4b28d2f0081dfdc2aa9d19 +73d640a4a033f0c865d45da470ef40c1fb03a844 diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 559b271bf38..00000000000 --- a/.dockerignore +++ /dev/null @@ -1,27 +0,0 @@ -Dockerfile* -.dockerignore - -# Yarn -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions - -packages -**/package.tgz -**/target -**/node_modules -**/outputs - -# Noir.js -tooling/noir_js/lib - -# Wasm build artifacts -compiler/wasm/nodejs -compiler/wasm/web -tooling/noirc_abi_wasm/nodejs -tooling/noirc_abi_wasm/web -tooling/noir_js/lib diff --git a/.gitignore b/.gitignore index 8d02d34d463..5f41566c94b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,5 @@ tooling/noirc_abi_wasm/nodejs tooling/noirc_abi_wasm/web tooling/noir_js/lib -**/package.tgz -packages - # docs autogen build /docs/docs/noir_js/reference/ diff --git a/Cargo.lock b/Cargo.lock index 028ff2b1434..30445f295a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2703,9 +2703,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 3a478c3f95a..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM rust:bullseye -WORKDIR /usr/src/noir -COPY . . -RUN ./scripts/bootstrap_native.sh - -# When running the container, mount the users home directory to same location. -FROM ubuntu:focal -# Install Tini as nargo doesn't handle signals properly. -# Install git as nargo needs it to clone. -RUN apt-get update && apt-get install -y git tini && rm -rf /var/lib/apt/lists/* && apt-get clean -COPY --from=0 /usr/src/noir/target/release/nargo /usr/src/noir/target/release/nargo -ENTRYPOINT ["/usr/bin/tini", "--", "/usr/src/noir/target/release/nargo"] diff --git a/Dockerfile.packages b/Dockerfile.packages deleted file mode 100644 index f40670c19e4..00000000000 --- a/Dockerfile.packages +++ /dev/null @@ -1,22 +0,0 @@ -FROM rust:alpine3.17 -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - pkgconfig \ - openssl-dev \ - npm \ - yarn \ - bash \ - jq \ - git \ - curl - -WORKDIR /usr/src/noir -COPY . . -RUN ./scripts/bootstrap_packages.sh - -FROM scratch -COPY --from=0 /usr/src/noir/packages /usr/src/noir/packages -# For some unknown reason, on alpine only, we need this to exist. -COPY --from=0 /usr/src/noir/node_modules/@noir-lang /usr/src/noir/node_modules/@noir-lang diff --git a/acvm-repo/acvm_js/test/node/build_info.test.ts b/acvm-repo/acvm_js/test/node/build_info.test.ts index 23100505011..014bb6f422d 100644 --- a/acvm-repo/acvm_js/test/node/build_info.test.ts +++ b/acvm-repo/acvm_js/test/node/build_info.test.ts @@ -3,12 +3,20 @@ import { BuildInfo, buildInfo } from '@noir-lang/acvm_js'; import child_process from 'child_process'; import pkg from '../../package.json'; -it('returns the correct build into', () => { +it('returns the correct build info', () => { + let revision: string; + + try { + revision = child_process.execSync('git rev-parse HEAD').toString().trim(); + } catch (error) { + console.log('Failed to get revision, skipping test.'); + return; + } + const info: BuildInfo = buildInfo(); // TODO: enforce that `package.json` and `Cargo.toml` are consistent. expect(info.version).to.be.eq(pkg.version); - const revision = child_process.execSync('git rev-parse HEAD').toString().trim(); expect(info.gitHash).to.be.eq(revision); }); diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index 09deb2c9712..f860f2c465a 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -3,7 +3,7 @@ use std::vec; use convert_case::{Case, Casing}; use iter_extended::vecmap; -use noirc_errors::Location; +use noirc_errors::{Location, Spanned}; use noirc_frontend::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; use noirc_frontend::hir::def_map::{LocalModuleId, ModuleId}; use noirc_frontend::macros_api::parse_program; @@ -11,17 +11,17 @@ use noirc_frontend::macros_api::FieldElement; use noirc_frontend::macros_api::{ BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, - HirContext, HirExpression, HirLiteral, HirStatement, Ident, ImportStatement, IndexExpression, - LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, - Param, Path, PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span, - Statement, StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType, - UnresolvedTypeData, Visibility, + HirContext, HirExpression, HirLiteral, HirStatement, Ident, IndexExpression, LetStatement, + Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, Param, Path, + PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span, Statement, + StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType, UnresolvedTypeData, + Visibility, }; use noirc_frontend::macros_api::{CrateId, FileId}; use noirc_frontend::macros_api::{MacroError, MacroProcessor}; use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; use noirc_frontend::node_interner::{FuncId, TraitId, TraitImplId, TraitImplKind}; -use noirc_frontend::Lambda; +use noirc_frontend::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Lambda}; pub struct AztecMacro; impl MacroProcessor for AztecMacro { @@ -74,6 +74,7 @@ pub enum AztecMacroError { UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, CouldNotAssignStorageSlots { secondary_message: Option }, EventError { span: Span, message: String }, + UnsupportedAttributes { span: Span, secondary_message: Option }, } impl From for MacroError { @@ -114,6 +115,11 @@ impl From for MacroError { secondary_message: None, span: Some(span), }, + AztecMacroError::UnsupportedAttributes { span, secondary_message } => MacroError { + primary_message: "Unsupported attributes in contract function".to_string(), + secondary_message, + span: Some(span), + }, } } } @@ -215,6 +221,14 @@ fn lambda(parameters: Vec<(Pattern, UnresolvedType)>, body: Expression) -> Expre }))) } +fn make_eq(lhs: Expression, rhs: Expression) -> Expression { + expression(ExpressionKind::Infix(Box::new(InfixExpression { + lhs, + rhs, + operator: Spanned::from(Span::default(), BinaryOpKind::Equal), + }))) +} + macro_rules! chained_path { ( $base:expr ) => { { @@ -267,10 +281,6 @@ fn index_array_variable(array: Expression, index: &str) -> Expression { }))) } -fn import(path: Path) -> ImportStatement { - ImportStatement { path, alias: None } -} - // // Create AST Nodes for Aztec // @@ -290,7 +300,6 @@ fn transform( .map_err(|(err, file_id)| (err.into(), file_id))? { check_for_aztec_dependency(crate_id, context)?; - include_relevant_imports(&mut submodule.contents); } } Ok(ast) @@ -309,21 +318,6 @@ fn transform_hir( assign_storage_slots(crate_id, context) } -/// Includes an import to the aztec library if it has not been included yet -fn include_relevant_imports(ast: &mut SortedModule) { - // Create the aztec import path using the assumed chained_dep! macro - let aztec_import_path = import(chained_dep!("aztec")); - - // Check if the aztec import already exists - let is_aztec_imported = - ast.imports.iter().any(|existing_import| existing_import.path == aztec_import_path.path); - - // If aztec is not imported, add the import at the beginning - if !is_aztec_imported { - ast.imports.insert(0, aztec_import_path); - } -} - /// Creates an error alerting the user that they have not downloaded the Aztec-noir library fn check_for_aztec_dependency( crate_id: &CrateId, @@ -429,23 +423,58 @@ fn transform_module( } } + let has_initializer = module.functions.iter().any(|func| { + func.def + .attributes + .secondary + .iter() + .any(|attr| is_custom_attribute(attr, "aztec(initializer)")) + }); + for func in module.functions.iter_mut() { + let mut is_private = false; + let mut is_public = false; + let mut is_public_vm = false; + let mut is_initializer = false; + let mut is_internal = false; + let mut insert_init_check = has_initializer; + for secondary_attribute in func.def.attributes.secondary.clone() { - let crate_graph = &context.crate_graph[crate_id]; if is_custom_attribute(&secondary_attribute, "aztec(private)") { - transform_function("Private", func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; + is_private = true; + } else if is_custom_attribute(&secondary_attribute, "aztec(initializer)") { + is_initializer = true; + insert_init_check = false; + } else if is_custom_attribute(&secondary_attribute, "aztec(noinitcheck)") { + insert_init_check = false; + } else if is_custom_attribute(&secondary_attribute, "aztec(internal)") { + is_internal = true; } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { - transform_function("Public", func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; + is_public = true; + insert_init_check = false; } else if is_custom_attribute(&secondary_attribute, "aztec(public-vm)") { - transform_vm_function(func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; + is_public_vm = true; } } + + // Apply transformations to the function based on collected attributes + if is_private || is_public { + transform_function( + if is_private { "Private" } else { "Public" }, + func, + storage_defined, + is_initializer, + insert_init_check, + is_internal, + ) + .map_err(|err| (err, crate_graph.root_file_id))?; + has_transformed_module = true; + } else if is_public_vm { + transform_vm_function(func, storage_defined) + .map_err(|err| (err, crate_graph.root_file_id))?; + has_transformed_module = true; + } + // Add the storage struct to the beginning of the function if it is unconstrained in an aztec contract if storage_defined && func.def.is_unconstrained { transform_unconstrained(func); @@ -511,7 +540,7 @@ fn generate_storage_field_constructor( ( pattern("context"), make_type(UnresolvedTypeData::Named( - chained_path!("aztec", "context", "Context"), + chained_dep!("aztec", "context", "Context"), vec![], true, )), @@ -595,7 +624,7 @@ fn generate_storage_implementation(module: &mut SortedModule) -> Result<(), Azte &[( ident("context"), make_type(UnresolvedTypeData::Named( - chained_path!("aztec", "context", "Context"), + chained_dep!("aztec", "context", "Context"), vec![], true, )), @@ -627,11 +656,36 @@ fn transform_function( ty: &str, func: &mut NoirFunction, storage_defined: bool, + is_initializer: bool, + insert_init_check: bool, + is_internal: bool, ) -> Result<(), AztecMacroError> { let context_name = format!("{}Context", ty); let inputs_name = format!("{}ContextInputs", ty); let return_type_name = format!("{}CircuitPublicInputs", ty); + // Add check that msg sender equals this address and flag function as internal + if is_internal { + let is_internal_check = create_internal_check(func.name()); + func.def.body.0.insert(0, is_internal_check); + func.def.is_internal = true; + } + + // Add initialization check + if insert_init_check { + if ty == "Public" { + let error = AztecMacroError::UnsupportedAttributes { + span: func.def.name.span(), + secondary_message: Some( + "public functions do not yet support initialization check".to_owned(), + ), + }; + return Err(error); + } + let init_check = create_init_check(); + func.def.body.0.insert(0, init_check); + } + // Add access to the storage struct if storage_defined { let storage_def = abstract_storage(&ty.to_lowercase(), false); @@ -655,6 +709,21 @@ fn transform_function( func.def.body.0.push(return_values); } + // Before returning mark the contract as initialized + if is_initializer { + if ty == "Public" { + let error = AztecMacroError::UnsupportedAttributes { + span: func.def.name.span(), + secondary_message: Some( + "public functions cannot yet be used as initializers".to_owned(), + ), + }; + return Err(error); + } + let mark_initialized = create_mark_as_initialized(); + func.def.body.0.push(mark_initialized); + } + // Push the finish method call to the end of the function let finish_def = create_context_finish(); func.def.body.0.push(finish_def); @@ -1028,7 +1097,7 @@ fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); let selector_path = - chained_path!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); + chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); let mut from_signature_path = selector_path.clone(); from_signature_path.segments.push(ident("from_signature")); @@ -1083,7 +1152,7 @@ fn create_inputs(ty: &str) -> Param { let context_pattern = Pattern::Identifier(context_ident); let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs - let type_path = chained_path!("aztec", "context", "inputs", &path_snippet, ty); + let type_path = chained_dep!("aztec", "context", "inputs", &path_snippet, ty); let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![], true)); let visibility = Visibility::Private; @@ -1091,6 +1160,51 @@ fn create_inputs(ty: &str) -> Param { Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } } +/// Creates an initialization check to ensure that the contract has been initialized, meant to +/// be injected as the first statement of any function after the context has been created. +/// +/// ```noir +/// assert_is_initialized(&mut context); +/// ``` +fn create_init_check() -> Statement { + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", "assert_is_initialized")), + vec![mutable_reference("context")], + ))) +} + +/// Creates a call to mark_as_initialized which emits the initialization nullifier, meant to +/// be injected as the last statement before returning in a constructor. +/// +/// ```noir +/// mark_as_initialized(&mut context); +/// ``` +fn create_mark_as_initialized() -> Statement { + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", "mark_as_initialized")), + vec![mutable_reference("context")], + ))) +} + +/// Creates a check for internal functions ensuring that the caller is self. +/// +/// ```noir +/// assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); +/// ``` +fn create_internal_check(fname: &str) -> Statement { + make_statement(StatementKind::Constrain(ConstrainStatement( + make_eq( + method_call(variable("context"), "msg_sender", vec![]), + method_call(variable("context"), "this_address", vec![]), + ), + Some(expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called internally", + fname + ))))), + ConstrainKind::Assert, + ))) +} + /// Creates the private context object to be accessed within the function, the parameters need to be extracted to be /// appended into the args hash object. /// @@ -1123,8 +1237,8 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac let let_hasher = mutable_assignment( "hasher", // Assigned to call( - variable_path(chained_path!("aztec", "hasher", "Hasher", "new")), // Path - vec![], // args + variable_path(chained_dep!("aztec", "hasher", "Hasher", "new")), // Path + vec![], // args ), ); @@ -1192,8 +1306,8 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac let let_context = mutable_assignment( "context", // Assigned to call( - variable_path(chained_path!("aztec", "context", &path_snippet, ty, "new")), // Path - vec![inputs_expression, hash_call], // args + variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path + vec![inputs_expression, hash_call], // args ), ); injected_expressions.push(let_context); @@ -1223,8 +1337,8 @@ fn create_avm_context() -> Result { let let_context = mutable_assignment( "context", // Assigned to call( - variable_path(chained_path!("aztec", "context", "AVMContext", "new")), // Path - vec![], // args + variable_path(chained_dep!("aztec", "context", "AVMContext", "new")), // Path + vec![], // args ), ); @@ -1259,13 +1373,13 @@ fn create_avm_context() -> Result { /// Any primitive type that can be cast will be casted to a field and pushed to the context. fn abstract_return_values(func: &NoirFunction) -> Option { let current_return_type = func.return_type().typ; - let last_statement = func.def.body.0.last()?; + let last_statement = func.def.body.0.last(); // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size // Doesn't need done until we have settled on a kernel size // TODO: support tuples here and in inputs -> convert into an issue // Check if the return type is an expression, if it is, we can handle it - match last_statement { + match last_statement? { Statement { kind: StatementKind::Expression(expression), .. } => { match current_return_type { // Call serialize on structs, push the whole array, calling push_array @@ -1309,13 +1423,13 @@ fn abstract_return_values(func: &NoirFunction) -> Option { fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { let init_context_call = if unconstrained { call( - variable_path(chained_path!("aztec", "context", "Context", "none")), // Path - vec![], // args + variable_path(chained_dep!("aztec", "context", "Context", "none")), // Path + vec![], // args ) } else { call( - variable_path(chained_path!("aztec", "context", "Context", typ)), // Path - vec![mutable_reference("context")], // args + variable_path(chained_dep!("aztec", "context", "Context", typ)), // Path + vec![mutable_reference("context")], // args ) }; @@ -1436,7 +1550,7 @@ fn make_castable_return_type(expression: Expression) -> Statement { /// } fn create_return_type(ty: &str) -> FunctionReturnType { let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs - let return_path = chained_path!("aztec", "protocol_types", "abis", &path_snippet, ty); + let return_path = chained_dep!("aztec", "protocol_types", "abis", &path_snippet, ty); return_type(return_path) } @@ -1792,7 +1906,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> let if_statements: Vec = note_types.iter().map(|note_type| format!( "if (note_type_id == {0}::get_note_type_id()) {{ - note_utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) + dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) }}" , note_type)).collect(); @@ -1812,7 +1926,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> note_type_id: Field, serialized_note: [Field; 20] ) -> pub [Field; 4] {{ - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); {} }}", diff --git a/bootstrap.sh b/bootstrap.sh deleted file mode 100755 index 54129c3d61a..00000000000 --- a/bootstrap.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0") - -CMD=${1:-} - -if [ -n "$CMD" ]; then - if [ "$CMD" = "clean" ]; then - git clean -fdx - exit 0 - else - echo "Unknown command: $CMD" - exit 1 - fi -fi - -# Attempt to just pull artefacts from CI and exit on success. -[ -n "${USE_CACHE:-}" ] && ./bootstrap_cache.sh && exit - -./scripts/bootstrap_native.sh -./scripts/bootstrap_packages.sh diff --git a/bootstrap_cache.sh b/bootstrap_cache.sh deleted file mode 100755 index 1cec6c81d8e..00000000000 --- a/bootstrap_cache.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd "$(dirname "$0")" -source ../build-system/scripts/setup_env '' '' mainframe_$USER > /dev/null - -echo -e "\033[1mRetrieving noir packages from remote cache...\033[0m" -extract_repo noir-packages /usr/src/noir/packages ./ -echo -e "\033[1mRetrieving nargo from remote cache...\033[0m" -extract_repo noir /usr/src/noir/target/release ./target/ - -remove_old_images noir-packages -remove_old_images noir diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 5674ae5a39a..f096c220200 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -661,7 +661,6 @@ pub enum Keyword { If, Impl, In, - Internal, Let, Mod, Mut, @@ -704,7 +703,6 @@ impl fmt::Display for Keyword { Keyword::If => write!(f, "if"), Keyword::Impl => write!(f, "impl"), Keyword::In => write!(f, "in"), - Keyword::Internal => write!(f, "internal"), Keyword::Let => write!(f, "let"), Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), @@ -750,7 +748,6 @@ impl Keyword { "if" => Keyword::If, "impl" => Keyword::Impl, "in" => Keyword::In, - "internal" => Keyword::Internal, "let" => Keyword::Let, "mod" => Keyword::Mod, "mut" => Keyword::Mut, diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 42ee484bfc9..7448d84cfe1 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -37,7 +37,8 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser { choice((is_pub_crate, is_pub, is_private)) } -/// function_modifiers: 'unconstrained'? (visibility)? 'open'? 'internal'? +/// function_modifiers: 'unconstrained'? (visibility)? 'open'? /// -/// returns (is_unconstrained, visibility, is_open, is_internal) for whether each keyword was present -fn function_modifiers() -> impl NoirParser<(bool, FunctionVisibility, bool, bool)> { +/// returns (is_unconstrained, visibility, is_open) for whether each keyword was present +fn function_modifiers() -> impl NoirParser<(bool, FunctionVisibility, bool)> { keyword(Keyword::Unconstrained) .or_not() .then(visibility_modifier()) .then(keyword(Keyword::Open).or_not()) - .then(keyword(Keyword::Internal).or_not()) - .map(|(((unconstrained, visibility), open), internal)| { - (unconstrained.is_some(), visibility, open.is_some(), internal.is_some()) + .map(|((unconstrained, visibility), open)| { + (unconstrained.is_some(), visibility, open.is_some()) }) } diff --git a/compiler/wasm/scripts/build-fixtures.sh b/compiler/wasm/scripts/build-fixtures.sh index 3a2330d4726..4c0505ef519 100755 --- a/compiler/wasm/scripts/build-fixtures.sh +++ b/compiler/wasm/scripts/build-fixtures.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash nargo compile --program-dir ./test/fixtures/simple -nargo compile --program-dir ./test/fixtures/with-deps +nargo compile --program-dir ./test/fixtures/with-deps nargo compile --program-dir ./test/fixtures/noir-contract \ No newline at end of file diff --git a/docs/docs/noir/standard_library/containers/index.md b/docs/docs/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/docs/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx index a9c10da6c06..99b7f830a20 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -16,3 +16,14 @@ fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s ``` + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/noir_stdlib/src/eddsa.nr b/noir_stdlib/src/eddsa.nr index 657e791e9c7..966bc1da2a1 100644 --- a/noir_stdlib/src/eddsa.nr +++ b/noir_stdlib/src/eddsa.nr @@ -38,3 +38,10 @@ pub fn eddsa_poseidon_verify( left.eq(right) } + +// Returns the public key of the given secret key as (pub_key_x, pub_key_y) +pub fn eddsa_to_pub(secret: Field) -> (Field, Field) { + let bjj = baby_jubjub(); + let pub_key = bjj.curve.mul(secret, bjj.curve.gen); + (pub_key.x, pub_key.y) +} diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 4dfe78308e2..f3155dd7528 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -136,7 +136,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { msg_block[i as Field] = 0; i += 1; } else if i < 128 { - let mut len = 8 * msg.len(); + let mut len = 8 * msg.len(); // u128 unsupported for j in 0..16 { msg_block[127 - j] = len as u8; len >>= 8; diff --git a/package.json b/package.json index 4987602c709..fcf36c9b969 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ ], "scripts": { "build": "yarn workspaces foreach --parallel --topological-dev --verbose run build", - "test": "yarn workspaces foreach run test", + "test": "yarn workspaces foreach --parallel --verbose run test", "test:integration": "yarn workspace integration-tests test", "clean:workspaces": "yarn workspaces foreach --exclude @noir-lang/root run clean", "clean:root": "rm -rf ./result ./target ./packages", diff --git a/scripts/bootstrap_native.sh b/scripts/bootstrap_native.sh deleted file mode 100755 index 974f0edcfec..00000000000 --- a/scripts/bootstrap_native.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0")/.. - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -# Check if the 'cargo' command is available in the system -if ! command -v cargo > /dev/null; then - echo "Cargo is not installed. Please install Cargo and the Rust toolchain." - exit 1 -fi - -# Build native. -if [ -n "${DEBUG:-}" ]; then - cargo build -else - cargo build --release -fi diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh deleted file mode 100755 index 47ffe12beec..00000000000 --- a/scripts/bootstrap_packages.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0")/.. - -./.github/scripts/wasm-bindgen-install.sh - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -yarn --immutable -yarn build - -# We create a folder called packages, that contains each package as it would be published to npm, named correctly. -# These can be useful for testing, or portaling into other projects. -yarn workspaces foreach pack - -rm -rf packages && mkdir -p packages -tar zxfv acvm-repo/acvm_js/package.tgz -C packages && mv packages/package packages/acvm_js -tar zxfv compiler/wasm/package.tgz -C packages && mv packages/package packages/noir_wasm -tar zxfv tooling/noir_codegen/package.tgz -C packages && mv packages/package packages/noir_codegen -tar zxfv tooling/noir_js/package.tgz -C packages && mv packages/package packages/noir_js -tar zxfv tooling/noir_js_backend_barretenberg/package.tgz -C packages && mv packages/package packages/backend_barretenberg -tar zxfv tooling/noir_js_types/package.tgz -C packages && mv packages/package packages/types -tar zxfv tooling/noirc_abi_wasm/package.tgz -C packages && mv packages/package packages/noirc_abi diff --git a/scripts/test_js_packages.sh b/scripts/test_js_packages.sh deleted file mode 100755 index e1e10c543e0..00000000000 --- a/scripts/test_js_packages.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -eu - -cd $(dirname "$0")/.. - -./.github/scripts/wasm-bindgen-install.sh - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -cargo build --release -export PATH="${PATH}:/usr/src/noir/target/release/" - -yarn --immutable -yarn build -./.github/scripts/playwright-install.sh - -./scripts/test.sh -yarn test diff --git a/scripts/test_native.sh b/scripts/test_native.sh deleted file mode 100755 index 9b9aa0ce4d7..00000000000 --- a/scripts/test_native.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -eu - -cd $(dirname "$0")/.. - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -cargo fmt --all --check -cargo clippy --workspace --locked --release -cargo test --workspace --locked --release diff --git a/test_programs/compile_success_contract/simple_contract/src/main.nr b/test_programs/compile_success_contract/simple_contract/src/main.nr index fea0ae08c22..ed90ac8bd1d 100644 --- a/test_programs/compile_success_contract/simple_contract/src/main.nr +++ b/test_programs/compile_success_contract/simple_contract/src/main.nr @@ -5,10 +5,10 @@ contract Foo { fn triple(x: Field) -> pub Field { x * 3 } - internal fn quadruple(x: Field) -> pub Field { + fn quadruple(x: Field) -> pub Field { x * 4 } - open internal fn skibbidy(x: Field) -> pub Field { + open fn skibbidy(x: Field) -> pub Field { x * 5 } // Regression for issue #3344 diff --git a/test_programs/execution_success/eddsa/src/main.nr b/test_programs/execution_success/eddsa/src/main.nr index 12e8ea92785..4404ffe75f7 100644 --- a/test_programs/execution_success/eddsa/src/main.nr +++ b/test_programs/execution_success/eddsa/src/main.nr @@ -1,14 +1,20 @@ use dep::std::compat; use dep::std::ec::consts::te::baby_jubjub; +use dep::std::ec::tecurve::affine::Point as TEPoint; use dep::std::hash; -use dep::std::eddsa::eddsa_poseidon_verify; +use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify}; + fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Skip this test for non-bn254 backends if compat::is_bn254() { let bjj = baby_jubjub(); let pub_key_a = bjj.curve.mul(_priv_key_a, bjj.curve.gen); - // let pub_key_b = bjj.curve.mul(_priv_key_b, bjj.curve.gen); + let pub_key_b = bjj.curve.mul(_priv_key_b, bjj.curve.gen); + let (pub_key_a_x, pub_key_a_y) = eddsa_to_pub(_priv_key_a); + let (pub_key_b_x, pub_key_b_y) = eddsa_to_pub(_priv_key_b); + assert(TEPoint::new(pub_key_a_x, pub_key_a_y) == pub_key_a); + assert(TEPoint::new(pub_key_b_x, pub_key_b_y) == pub_key_b); // Manually computed as fields can't use modulo. Importantantly the commitment is within // the subgroup order. Note that choice of hash is flexible for this step. // let r_a = hash::pedersen_commitment([_priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually diff --git a/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Prover.toml b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr new file mode 100644 index 00000000000..8ed9003164a --- /dev/null +++ b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr @@ -0,0 +1,11 @@ +/// Test to make sure the entire test suite fails, even if some of the tests pass! + +#[test] +fn this_will_pass() { + assert(true); +} + +#[test] +fn this_will_fail() { + assert(false); +} diff --git a/tooling/nargo_cli/src/cli/noir_template_files/contract.nr b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr index e126726393d..3cd3b5b3766 100644 --- a/tooling/nargo_cli/src/cli/noir_template_files/contract.nr +++ b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr @@ -1,5 +1,5 @@ contract Main { - internal fn double(x: Field) -> pub Field { x * 2 } + fn double(x: Field) -> pub Field { x * 2 } fn triple(x: Field) -> pub Field { x * 3 } fn quadruple(x: Field) -> pub Field { double(double(x)) } } diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 503fd5afdd4..68660d62d23 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -116,10 +116,10 @@ pub(crate) fn run( }; } - if test_report.iter().any(|(_, status)| !matches!(status, TestStatus::Fail { .. })) { - Ok(()) - } else { + if test_report.iter().any(|(_, status)| matches!(status, TestStatus::Fail { .. })) { Err(CliError::Generic(String::new())) + } else { + Ok(()) } } diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr index a03b8774700..c5b19a686d2 100644 --- a/tooling/nargo_fmt/tests/expected/contract.nr +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -8,8 +8,7 @@ contract Benchmarking { use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; use dep::aztec::{ - context::{Context}, - note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, types::address::{AztecAddress} diff --git a/tooling/nargo_fmt/tests/input/contract.nr b/tooling/nargo_fmt/tests/input/contract.nr index a03b8774700..c5b19a686d2 100644 --- a/tooling/nargo_fmt/tests/input/contract.nr +++ b/tooling/nargo_fmt/tests/input/contract.nr @@ -8,8 +8,7 @@ contract Benchmarking { use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; use dep::aztec::{ - context::{Context}, - note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, types::address::{AztecAddress}