From ee31cba81ecc7abc52a2128cc6cc810e5d7fab50 Mon Sep 17 00:00:00 2001 From: sam <1211977+sambarnes@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:19:27 -0700 Subject: [PATCH 001/137] chore: fix broken onboarding link in README (#3732) # Description was onboarding this morning to tackle [a quick issue over here](https://github.com/noir-lang/noir/issues/3372) and noticed this link broke in the top level README https://github.com/noir-lang/noir?tab=readme-ov-file#working-on-this-project ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. Co-authored-by: kevaundray --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c48c9110187..2fc47f16fef 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ This crate's minimum supported rustc version is 1.71.1. ## Working on this project -This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/getting_started/nargo_installation/#option-4-compile-from-source) to setup your environment for working on the project. +This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/getting_started/nargo_installation/#option-3-compile-from-source) to setup your environment for working on the project. ### Building against a different local/remote version of Barretenberg From 506b0c199d1e797a6e64faf47baf45c7ee52ac72 Mon Sep 17 00:00:00 2001 From: sam <1211977+sambarnes@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:40:25 -0700 Subject: [PATCH 002/137] chore: allow common ascii punctuation in attributes (#3733) # Description spotted an issue with punctuation inside a `#[test(should_fail_with = "")]` block ([comment on original issue](https://github.com/noir-lang/noir/issues/3372#issuecomment-1845660516)) ## Problem\* Resolves #3372 (an extension of this original issue) ## Summary\* I built off of the original work done over here #3374 but simplified things down to just cover all common punctuation ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- compiler/noirc_frontend/src/lexer/lexer.rs | 9 ++++++--- compiler/noirc_frontend/src/lexer/token.rs | 7 +------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 7a2197ebb93..9d2c1a6bca2 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -633,15 +633,18 @@ mod tests { } #[test] - fn test_attribute_with_apostrophe() { - let input = r#"#[test(should_fail_with = "the eagle's feathers")]"#; + fn test_attribute_with_common_punctuation() { + let input = + r#"#[test(should_fail_with = "stmt. q? exclaim! & symbols, 1% shouldn't fail")]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap().token().clone(); assert_eq!( token, Token::Attribute(Attribute::Function(FunctionAttribute::Test( - TestScope::ShouldFailWith { reason: "the eagle's feathers".to_owned().into() } + TestScope::ShouldFailWith { + reason: "stmt. q? exclaim! & symbols, 1% shouldn't fail".to_owned().into() + } ))) ); } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index ba93e52e1a8..e6542c643ad 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -468,13 +468,8 @@ impl Attribute { .all(|ch| { ch.is_ascii_alphabetic() || ch.is_numeric() - || ch == '_' - || ch == '(' - || ch == ')' - || ch == '=' - || ch == '"' + || ch.is_ascii_punctuation() || ch == ' ' - || ch == '\'' }) .then_some(()); From 3cf1f92efb035e99d32c84ea60f5b5dcfa771df0 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Sat, 9 Dec 2023 01:34:10 +0000 Subject: [PATCH 003/137] chore(ci): fail `tests-end` job if any dependants failed (#3737) # Description ## Problem\* Resolves ## Summary\* It seems like despite the `tests-end` job not running and being skipped if any of the dependants fail, this is enough to satisfy the required check status. This PR changes it so that this job explicitly fails if any of the dependants failed or were skipped. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. Co-authored-by: kevaundray --- .github/workflows/test-js-packages.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index 9ac61f34203..71d6c9a537f 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -418,11 +418,13 @@ jobs: run: | yarn test:integration - # This is a noop job which depends on all test jobs + # This is a job which depends on all test jobs and reports the overall status. # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: End runs-on: ubuntu-latest + # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. + if: ${{ always() }} needs: - test-acvm_js-node - test-acvm_js-browser @@ -435,5 +437,13 @@ jobs: - test-integration steps: - - name: Noop - run: echo "noop" + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + fi + env: + # We treat any skipped or failing jobs as a failure for the workflow as a whole. + FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') }} From 61fe99d480fee9ddcc66058e040d0239d37326fa Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 9 Dec 2023 19:04:11 +0000 Subject: [PATCH 004/137] chore: use `tsx` instead of `ts-node` for `noir_js` (#3750) # Description This gets rid of the experimental loader warning, as tsx does not require it. This experimental loader feature is unstable and just to rule it out, could be one of the reasons why tests have become a bit flaky. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/noir_js/.mocharc.json | 3 +-- tooling/noir_js/package.json | 1 + yarn.lock | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tooling/noir_js/.mocharc.json b/tooling/noir_js/.mocharc.json index c2e70b73d0f..be7e952e7ca 100644 --- a/tooling/noir_js/.mocharc.json +++ b/tooling/noir_js/.mocharc.json @@ -1,6 +1,5 @@ { - "require": "ts-node/register", - "loader": "ts-node/esm", + "require": "tsx", "extensions": ["ts", "cjs"], "spec": [ "test/node/**/*.test.ts*" diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index d3811759c0c..e42cbb1d162 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -50,6 +50,7 @@ "prettier": "3.0.3", "ts-node": "^10.9.1", "tsc-multi": "^1.1.0", + "tsx": "^4.6.2", "typescript": "^5.2.2" } } diff --git a/yarn.lock b/yarn.lock index dc30304ba68..22ad5ac50ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3715,6 +3715,7 @@ __metadata: prettier: 3.0.3 ts-node: ^10.9.1 tsc-multi: ^1.1.0 + tsx: ^4.6.2 typescript: ^5.2.2 languageName: unknown linkType: soft From c9c72ae7b80aa9504a082dd083b19d4b80d954c5 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:39:57 +0000 Subject: [PATCH 005/137] feat: optimize out unnecessary truncation instructions (#3717) # Description ## Problem\* Resolves ## Summary\* We're currently adding a double truncation when performing overflow checks on left shifts. We could/should address this directly but as a more general rule we can optimize out any truncation which is truncating a value to fit into a type which is equal or larger to the source type. I've also replaced a few instances of `insert_instruction` with the more instruction-specific version to reduce verbosity. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../src/ssa/function_builder/mod.rs | 11 ++--- .../noirc_evaluator/src/ssa/ir/instruction.rs | 14 +++++- .../src/ssa/ssa_gen/context.rs | 49 +++++-------------- 3 files changed, 28 insertions(+), 46 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index f143ca7ee86..56a22fd4107 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -314,16 +314,11 @@ impl FunctionBuilder { (FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow)) }; - let instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul }); if max_bit <= bit_size { - self.insert_instruction(instruction, None).first() + self.insert_binary(lhs, BinaryOp::Mul, pow) } else { - let result = self.insert_instruction(instruction, None).first(); - self.insert_instruction( - Instruction::Truncate { value: result, bit_size, max_bit_size: max_bit }, - None, - ) - .first() + let result = self.insert_binary(lhs, BinaryOp::Mul, pow); + self.insert_truncate(result, bit_size, max_bit) } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index e940b719cb6..af6bf2c4687 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -467,11 +467,23 @@ impl Instruction { } None } - Instruction::Truncate { value, bit_size, .. } => { + Instruction::Truncate { value, bit_size, max_bit_size } => { if let Some((numeric_constant, typ)) = dfg.get_numeric_constant_with_type(*value) { let integer_modulus = 2_u128.pow(*bit_size); let truncated = numeric_constant.to_u128() % integer_modulus; SimplifiedTo(dfg.make_constant(truncated.into(), typ)) + } else if let Value::Instruction { instruction, .. } = &dfg[dfg.resolve(*value)] { + if let Instruction::Truncate { bit_size: src_bit_size, .. } = &dfg[*instruction] + { + // If we're truncating the value to fit into the same or larger bit size then this is a noop. + if src_bit_size <= bit_size && src_bit_size <= max_bit_size { + SimplifiedTo(*value) + } else { + None + } + } else { + None + } } else { None } diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 9d27ffc60d8..260ee129e86 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -275,16 +275,11 @@ impl<'a> FunctionContext<'a> { let bit_width = self.builder.numeric_constant(FieldElement::from(2_i128.pow(bit_size)), Type::field()); let sign_not = self.builder.insert_binary(one, BinaryOp::Sub, sign); - let as_field = - self.builder.insert_instruction(Instruction::Cast(input, Type::field()), None).first(); - let sign_field = - self.builder.insert_instruction(Instruction::Cast(sign, Type::field()), None).first(); + let as_field = self.builder.insert_cast(input, Type::field()); + let sign_field = self.builder.insert_cast(sign, Type::field()); let positive_predicate = self.builder.insert_binary(sign_field, BinaryOp::Mul, as_field); let two_complement = self.builder.insert_binary(bit_width, BinaryOp::Sub, as_field); - let sign_not_field = self - .builder - .insert_instruction(Instruction::Cast(sign_not, Type::field()), None) - .first(); + let sign_not_field = self.builder.insert_cast(sign_not, Type::field()); let negative_predicate = self.builder.insert_binary(sign_not_field, BinaryOp::Mul, two_complement); self.builder.insert_binary(positive_predicate, BinaryOp::Add, negative_predicate) @@ -315,17 +310,8 @@ impl<'a> FunctionContext<'a> { match operator { BinaryOpKind::Add | BinaryOpKind::Subtract => { // Result is computed modulo the bit size - let mut result = self - .builder - .insert_instruction( - Instruction::Truncate { - value: result, - bit_size, - max_bit_size: bit_size + 1, - }, - None, - ) - .first(); + let mut result = + self.builder.insert_truncate(result, bit_size, bit_size + 1); result = self.builder.insert_cast(result, Type::unsigned(bit_size)); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); @@ -335,17 +321,7 @@ impl<'a> FunctionContext<'a> { // Result is computed modulo the bit size let mut result = self.builder.insert_cast(result, Type::unsigned(2 * bit_size)); - result = self - .builder - .insert_instruction( - Instruction::Truncate { - value: result, - bit_size, - max_bit_size: 2 * bit_size, - }, - None, - ) - .first(); + result = self.builder.insert_truncate(result, bit_size, 2 * bit_size); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); self.builder.insert_cast(result, result_type) @@ -476,17 +452,16 @@ impl<'a> FunctionContext<'a> { // Then we check the signed product fits in a signed integer of bit_size-bits let not_same = self.builder.insert_binary(one, BinaryOp::Sub, same_sign); - let not_same_sign_field = self - .builder - .insert_instruction(Instruction::Cast(not_same, Type::unsigned(bit_size)), None) - .first(); + let not_same_sign_field = + self.builder.insert_cast(not_same, Type::unsigned(bit_size)); let positive_maximum_with_offset = self.builder.insert_binary(half_width, BinaryOp::Add, not_same_sign_field); let product_overflow_check = self.builder.insert_binary(product, BinaryOp::Lt, positive_maximum_with_offset); - self.builder.set_location(location).insert_instruction( - Instruction::Constrain(product_overflow_check, one, Some(message)), - None, + self.builder.set_location(location).insert_constrain( + product_overflow_check, + one, + Some(message), ); } BinaryOpKind::ShiftLeft => unreachable!("shift is not supported for signed integer"), From 4000fb279221eb07187d657bfaa7f1c7b311abf2 Mon Sep 17 00:00:00 2001 From: sam <1211977+sambarnes@users.noreply.github.com> Date: Sat, 9 Dec 2023 11:54:01 -0700 Subject: [PATCH 006/137] fix: deserialize odd length hex literals (#3747) # Description single digit (or generally, odd length) hex literals such as `0x4` result in an `InvalidIntegerLiteral` error ## Problem\* Resolves #3235 ## Summary\* i just prefixed all odd-length hex literals with another `0`, happy to change course if there's a better/more efficient way here (i'm kinda rust noob) ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acir_field/src/generic_ark.rs | 24 ++++++++++++++++++- .../execution_success/strings/src/main.nr | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/acvm-repo/acir_field/src/generic_ark.rs b/acvm-repo/acir_field/src/generic_ark.rs index e3e66fe7a92..5c70d3cda37 100644 --- a/acvm-repo/acir_field/src/generic_ark.rs +++ b/acvm-repo/acir_field/src/generic_ark.rs @@ -272,7 +272,10 @@ impl FieldElement { } pub fn from_hex(hex_str: &str) -> Option> { let value = hex_str.strip_prefix("0x").unwrap_or(hex_str); - let hex_as_bytes = hex::decode(value).ok()?; + // Values of odd length require an additional "0" prefix + let sanitized_value = + if value.len() % 2 == 0 { value.to_string() } else { format!("0{}", value) }; + let hex_as_bytes = hex::decode(sanitized_value).ok()?; Some(FieldElement::from_be_bytes_reduce(&hex_as_bytes)) } @@ -446,6 +449,25 @@ mod tests { assert_eq!(minus_i_field_element.to_hex(), string); } } + + #[test] + fn deserialize_even_and_odd_length_hex() { + // Test cases of (odd, even) length hex strings + let hex_strings = + vec![("0x0", "0x00"), ("0x1", "0x01"), ("0x002", "0x0002"), ("0x00003", "0x000003")]; + for (i, case) in hex_strings.into_iter().enumerate() { + let i_field_element = + crate::generic_ark::FieldElement::::from(i as i128); + let odd_field_element = + crate::generic_ark::FieldElement::::from_hex(case.0).unwrap(); + let even_field_element = + crate::generic_ark::FieldElement::::from_hex(case.1).unwrap(); + + assert_eq!(i_field_element, odd_field_element); + assert_eq!(odd_field_element, even_field_element); + } + } + #[test] fn max_num_bits_smoke() { let max_num_bits_bn254 = crate::generic_ark::FieldElement::::max_num_bits(); diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr index c35f59dd8c5..cff229d368a 100644 --- a/test_programs/execution_success/strings/src/main.nr +++ b/test_programs/execution_success/strings/src/main.nr @@ -34,6 +34,10 @@ fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Fie assert(hex_as_string == "0x41"); // assert(hex_as_string != 0x41); This will fail with a type mismatch between str[4] and Field assert(hex_as_field == 0x41); + + // Single digit & odd length hex literals are valid + assert(hex_as_field == 0x041); + assert(hex_as_field != 0x1); } #[test] From 2c06a64e502bac6839375c5636d39a172a609a5f Mon Sep 17 00:00:00 2001 From: Hayley Kwan Date: Sat, 9 Dec 2023 20:01:58 +0000 Subject: [PATCH 007/137] feat: allow underscores in integer literals (#3746) # Description ## Problem\* Resolves #3283 ## Summary\* This PR adds support for underscores in numeric literals. This is restricted to not allow multiple underscores in a row and a literal cannot start or end with an underscore. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: kevaundray --- compiler/noirc_frontend/src/lexer/lexer.rs | 52 ++++++++++++++++++---- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 9d2c1a6bca2..fd8168e36c6 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -323,11 +323,29 @@ impl<'a> Lexer<'a> { let start = self.position; let integer_str = self.eat_while(Some(initial_char), |ch| { - ch.is_ascii_digit() | ch.is_ascii_hexdigit() | (ch == 'x') + ch.is_ascii_digit() | ch.is_ascii_hexdigit() | (ch == 'x') | (ch == '_') }); let end = self.position; + // We want to enforce some simple rules about usage of underscores: + // 1. Underscores cannot appear at the end of a integer literal. e.g. 0x123_. + // 2. There cannot be more than one underscore consecutively, e.g. 0x5__5, 5__5. + // + // We're not concerned with an underscore at the beginning of a decimal literal + // such as `_5` as this would be lexed into an ident rather than an integer literal. + let invalid_underscore_location = integer_str.ends_with('_'); + let consecutive_underscores = integer_str.contains("__"); + if invalid_underscore_location || consecutive_underscores { + return Err(LexerErrorKind::InvalidIntegerLiteral { + span: Span::inclusive(start, end), + found: integer_str, + }); + } + + // Underscores needs to be stripped out before the literal can be converted to a `FieldElement. + let integer_str = integer_str.replace('_', ""); + let integer = match FieldElement::try_from_str(&integer_str) { None => { return Err(LexerErrorKind::InvalidIntegerLiteral { @@ -930,15 +948,33 @@ mod tests { } #[test] - fn test_eat_hex_int() { - let input = "0x05"; - - let expected = vec![Token::Int(5_i128.into())]; - let mut lexer = Lexer::new(input); + fn test_eat_integer_literals() { + let test_cases: Vec<(&str, Token)> = vec![ + ("0x05", Token::Int(5_i128.into())), + ("5", Token::Int(5_i128.into())), + ("0x1234_5678", Token::Int(0x1234_5678_u128.into())), + ("0x_01", Token::Int(0x1_u128.into())), + ("1_000_000", Token::Int(1_000_000_u128.into())), + ]; - for token in expected.into_iter() { + for (input, expected_token) in test_cases { + let mut lexer = Lexer::new(input); let got = lexer.next_token().unwrap(); - assert_eq!(got, token); + assert_eq!(got.token(), &expected_token); + } + } + + #[test] + fn test_reject_invalid_underscores_in_integer_literal() { + let test_cases: Vec<&str> = vec!["0x05_", "5_", "5__5", "0x5__5"]; + + for input in test_cases { + let mut lexer = Lexer::new(input); + let token = lexer.next_token(); + assert!( + matches!(token, Err(LexerErrorKind::InvalidIntegerLiteral { .. })), + "expected {input} to throw error" + ); } } From c043265e550b59bd4296504826fe15d3ce3e9ad2 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Sun, 10 Dec 2023 12:11:22 -0500 Subject: [PATCH 008/137] feat: aztec-packages (#3754) Development from Aztec. --------- Co-authored-by: ludamad Co-authored-by: ludamad Co-authored-by: kevaundray Co-authored-by: sirasistant From b0289f2d8c0ab391c0c7e36f2632f61970b2d783 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sun, 10 Dec 2023 22:33:20 +0000 Subject: [PATCH 009/137] chore: fix un-needed fully qualified path (#3755) # Description Since we already import FileMap with the usepath, using fm::FileMap is redundant ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/fm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index ea964055759..5e95e431071 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -19,7 +19,7 @@ pub const FILE_EXTENSION: &str = "nr"; pub struct FileManager { root: PathBuf, - file_map: file_map::FileMap, + file_map: FileMap, id_to_path: HashMap, path_to_id: HashMap, file_reader: Box, From 29f2cd95f5f771a06d2b4695465092992c5b3493 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sun, 10 Dec 2023 22:33:39 +0000 Subject: [PATCH 010/137] chore: remove extraneous dbg statement (#3761) # Description This removes an extraneous debug statement that was likely missed when the corresponding PR got merged. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/hir/resolution/resolver.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 68c33c93c4c..59ba30b9c34 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1662,10 +1662,7 @@ impl<'a> Resolver<'a> { fn eval_global_as_array_length(&mut self, global: StmtId) -> u64 { let stmt = match self.interner.statement(&global) { HirStatement::Let(let_expr) => let_expr, - other => { - dbg!(other); - return 0; - } + _ => return 0, }; let length = stmt.expression; From 1c66b2480a8740bfb4e88a500a817c1c8978f883 Mon Sep 17 00:00:00 2001 From: Hayley Kwan Date: Sun, 10 Dec 2023 23:08:53 +0000 Subject: [PATCH 011/137] chore: remove special casing for `pedersen_hash` black box function (#3744) # Description ## Problem\* Resolves #3370 ## Summary\* This PR removes the special case which says all backends support the pedersen hash black box function. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/nargo/src/ops/compile.rs | 17 ++--------------- tooling/nargo_cli/src/cli/compile_cmd.rs | 15 ++------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index d4164eaa865..02159345086 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -85,22 +85,9 @@ pub fn compile_program( } }; - // TODO: we say that pedersen hashing is supported by all backends for now - let is_opcode_supported_pedersen_hash = |opcode: &Opcode| -> bool { - if let Opcode::BlackBoxFuncCall( - acvm::acir::circuit::opcodes::BlackBoxFuncCall::PedersenHash { .. }, - ) = opcode - { - true - } else { - is_opcode_supported(opcode) - } - }; - // Apply backend specific optimizations. - let optimized_program = - crate::ops::optimize_program(program, np_language, &is_opcode_supported_pedersen_hash) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_program = crate::ops::optimize_program(program, np_language, is_opcode_supported) + .expect("Backend does not support an opcode that is in the IR"); (context.file_manager, Ok((optimized_program, warnings))) } diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 02ba0d13e87..7b97cc8afdc 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,6 +1,5 @@ use std::path::Path; -use acvm::acir::circuit::opcodes::BlackBoxFuncCall; use acvm::acir::circuit::Opcode; use acvm::Language; use backend_interface::BackendOpcodeSupport; @@ -213,19 +212,9 @@ fn compile_program( } }; - // TODO: we say that pedersen hashing is supported by all backends for now - let is_opcode_supported_pedersen_hash = |opcode: &Opcode| -> bool { - if let Opcode::BlackBoxFuncCall(BlackBoxFuncCall::PedersenHash { .. }) = opcode { - true - } else { - is_opcode_supported(opcode) - } - }; - // Apply backend specific optimizations. - let optimized_program = - nargo::ops::optimize_program(program, np_language, &is_opcode_supported_pedersen_hash) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_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()); From 010fdb69616f47fc0a9f252a65a903316d3cbe80 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 11 Dec 2023 10:35:52 +0000 Subject: [PATCH 012/137] chore: re-export the items needed for the lsp from the fm crate instead of importing codespan_reporting (#3757) # Description This is a small change to control the scope of what the lsp touches and to see what the fm crate is offering to other crates in this workspace. codespan_reporting is needed because the fm crate is using codespan ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 1 - compiler/fm/src/lib.rs | 4 ++++ tooling/lsp/Cargo.toml | 1 - tooling/lsp/src/lib.rs | 2 +- tooling/lsp/src/requests/goto_definition.rs | 6 +++--- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58b86705381..2fd2b444391 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2538,7 +2538,6 @@ dependencies = [ "async-lsp", "cfg-if", "codespan-lsp", - "codespan-reporting", "fm", "lsp-types 0.94.1", "nargo", diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 5e95e431071..a251ecc70c5 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -7,6 +7,10 @@ mod file_map; mod file_reader; pub use file_map::{File, FileId, FileMap, PathString}; + +// Re-export for the lsp +pub use codespan_reporting::files as codespan_files; + use file_reader::is_stdlib_asset; pub use file_reader::FileReader; diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 67778c744db..02d6d10ffa8 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true [dependencies] acvm.workspace = true codespan-lsp.workspace = true -codespan-reporting.workspace = true lsp-types.workspace = true nargo.workspace = true nargo_fmt.workspace = true diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 1474085a330..aa981a735b5 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -17,7 +17,7 @@ use async_lsp::{ router::Router, AnyEvent, AnyNotification, AnyRequest, ClientSocket, Error, LspService, ResponseError, }; -use codespan_reporting::files; +use fm::codespan_files as files; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::{Context, FunctionNameMatch}, diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 706c95d44a3..4e615cd4fe5 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -2,7 +2,7 @@ use std::future::{self, Future}; use crate::{types::GotoDefinitionResult, LspState}; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; -use codespan_reporting::files::Error; +use fm::codespan_files::Error; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Location}; use lsp_types::{Position, Url}; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -98,7 +98,7 @@ fn to_lsp_location<'a, F>( definition_span: noirc_errors::Span, ) -> Option where - F: codespan_reporting::files::Files<'a> + ?Sized, + F: fm::codespan_files::Files<'a> + ?Sized, { let range = crate::byte_span_to_range(files, file_id, definition_span.into())?; let file_name = files.name(file_id).ok()?; @@ -115,7 +115,7 @@ pub(crate) fn position_to_byte_index<'a, F>( position: &Position, ) -> Result where - F: codespan_reporting::files::Files<'a> + ?Sized, + F: fm::codespan_files::Files<'a> + ?Sized, { let source = files.source(file_id)?; let source = source.as_ref(); From bcbe11613b7205476a49ad0d588b868b4fc43ba1 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 11 Dec 2023 16:59:52 +0000 Subject: [PATCH 013/137] fix: add missing assertion to test (#3765) # Description The test should be asserting that the parse method returns an error ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/noirc_abi/src/input_parser/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tooling/noirc_abi/src/input_parser/mod.rs b/tooling/noirc_abi/src/input_parser/mod.rs index e1265da1c85..26c5a89c83a 100644 --- a/tooling/noirc_abi/src/input_parser/mod.rs +++ b/tooling/noirc_abi/src/input_parser/mod.rs @@ -297,7 +297,6 @@ mod test { #[test] fn rejects_noncanonical_fields() { let noncanonical_field = FieldElement::modulus().to_string(); - let parsed_field = parse_str_to_field(&noncanonical_field); - println!("{parsed_field:?}"); + assert!(parse_str_to_field(&noncanonical_field).is_err()); } } From 6076e08a0814bb6f3836af3c65a7b40c066b9494 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:00:08 +0000 Subject: [PATCH 014/137] feat: allow passing custom foreign call handlers when creating proofs in NoirJS (#3764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … # Description ## Problem\* Resolves ## Summary\* This PR modifies the default foreign call handler for JS to ignore `print` foreign calls so that they don't halt execution. If users want to get these values out and display them then they should provide a custom handler for the time being. The other change made is allowing passing this custom handler when generating a proof. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/noir_js/src/program.ts | 6 +++--- tooling/noir_js/src/witness_generation.ts | 9 ++++++++- .../test/noir_compiled_examples/assert_lt/src/main.nr | 5 +++++ .../assert_lt/target/assert_lt.json | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts index 711413bbc84..809943727eb 100644 --- a/tooling/noir_js/src/program.ts +++ b/tooling/noir_js/src/program.ts @@ -67,12 +67,12 @@ export class Noir { * * @example * ```typescript - * async generateFinalproof(input) + * async generateFinalProof(input) * ``` * */ - async generateFinalProof(inputs: InputMap): Promise { - const { witness } = await this.execute(inputs); + async generateFinalProof(inputs: InputMap, foreignCallHandler?: ForeignCallHandler): Promise { + const { witness } = await this.execute(inputs, foreignCallHandler); return this.getBackend().generateFinalProof(witness); } diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts index e3ddb1a2a21..a329c79c919 100644 --- a/tooling/noir_js/src/witness_generation.ts +++ b/tooling/noir_js/src/witness_generation.ts @@ -3,7 +3,14 @@ import { base64Decode } from './base64_decode.js'; import { executeCircuit, WitnessMap, ForeignCallHandler, ForeignCallInput } from '@noir-lang/acvm_js'; import { CompiledCircuit } from '@noir-lang/types'; -const defaultForeignCallHandler: ForeignCallHandler = (name: string, args: ForeignCallInput[]) => { +const defaultForeignCallHandler: ForeignCallHandler = async (name: string, args: ForeignCallInput[]) => { + if (name == 'print') { + // By default we do not print anything for `print` foreign calls due to a need for formatting, + // however we provide an empty response in order to not halt execution. + // + // If a user needs to print values then they should provide a custom foreign call handler. + return []; + } throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`); }; 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 index 0698cbce4a8..693e7285736 100644 --- 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 @@ -1,4 +1,9 @@ +use dep::std; + fn main(x: u64, y: pub u64) -> pub u64 { + // We include a println statement to show that noirJS will ignore this and continue execution + std::println("foo"); + assert(x < y); x + y } 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 index 7c9b30daa9e..5b511cdc140 100644 --- 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 @@ -1 +1 @@ -{"noir_version":"0.19.4+55670ff82c270534a4bdb999ab0de5cea7017093","hash":4729344722355302200,"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":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},"return_witnesses":[5]},"bytecode":"H4sIAAAAAAAA/81V4WrDIBDWmGxsP/YE+5FH8KI2+q/0TRJi2GAjY8j6+itM4eraQOsVeiCnF/1y9513PjLGntmf8MOoot6idRXXIs5zSbZt1LJMgCMsJTda+77zoGCQnRutkdqMGwsWjDVTZ5XyVtveja6XDrTyMBun5ghWXe8X5IYToZNhY15F1PVhNFlukn2H9nOkOcrJDp05tYefwXlCtnT+BX0vDf4fGfjnVJgiEpnjll4oQeejTEmtEWYSQczHrYqqFOuBkM81/i70U2Z+giCMuSbMawF/qw3unutmLc+yTI7qRJYJUNZJw+j7TsI894CkecOOm396IF6jHkLwn1+hDUs7TFO7fw9v7fLjv+ePZf8LJenp6WEIAAA="} \ No newline at end of file +{"noir_version":"0.20.0+010fdb69616f47fc0a9f252a65a903316d3cbe80","hash":17538653710107541030,"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":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},"return_witnesses":[5]},"bytecode":"H4sIAAAAAAAA/9Wa627aMBiGHcKhBBLOR+0Hl+Ak5PQP9U6gBK3SNqoqWm9kFzzMYu2DujhbPjvFEkrsJu/7vJ+TFDAtQkiH/GnG6VXLtxvQr+V9Mx/jx5pE3Db5lpZqYahI96Ba91e+bee1g60J6objS90mehbqN8nfuUbSpLAeNVAjXg++bZxeD/m+k9esjlyz6+t3A/p1MFfYvkyzharpPrXzmsFmXPU3YL8F8jUV5HvA1aRMs42qGe2YhgVqwuvH2Tvg721QLwu5Xgbw5Lq8bynz9Tye8Vb+joCjozF/R5lveJ7/riR/V8DR1Zi/q8w3TJiGLclvCzhsjfltZb5hyjQcSX5HwOFozO8o8w3XTKMnyd8TcPQ05od8RVmtilnxff0t0+hL8vcFHH2N+SFfUVarYlZ838hnGgNJ/oGAY6Ax/0CZb3R+rgwl+YcCjqHG/ENlvtH5fdVIkn8k4BhpzA/5irJ274jVrpgV3zeMmMZYkn8s4BhrzA/5irJaFbPi+3pPTGMiyT8RcEw05od8RVmtilnxfcPzXE0l+acCjqnG/FNlvmHANGaS/DMBx0xjfshXlNW+I9bRHbEOKmbF9w1jpjGX5J8LOOYa80O+oqzWHbH2KmbF9/XPnwUXkvwLAcdCY/6FMt9ozzSWkvxLAcdSY/4l8MVet3gAmV9en39kHKAOYPg+X2xlzQRjXOALOIeDtsj7hR60qpnk/eolAWNYPgbQ8k/fTK7TyEtd391SL9nFAV0HuzB2YzeIg70X+34ar+Mo2SURTdy1n7qHIPEPuVjt/7nc6wFBdDRtWFe46tgAE18D44/geLgCb4A5eQTniI4xPtBpgzF+vkMUXljQHEvTJJc/T+C6ZS8oE4+R8kmtk8vlWELwfxKg6qYqq9VErOet+v0jJ73idE3EzHXEeS1Rv5sPuM9839yaZ1quXdwntFxzMe+TBsF/7nDNj/6B8P0GuXz4848R/B3INsvS7y/ZKjuutvv96u05+7o6/kxfD9+Ob78Bhjydn08mAAA="} \ No newline at end of file From fcff412bb39a04a5c88506ae5a5ee2fbdefd93ef Mon Sep 17 00:00:00 2001 From: jfecher Date: Mon, 11 Dec 2023 11:41:26 -0600 Subject: [PATCH 015/137] fix: Stop cloning Traits! (#3736) # Description ## Problem\* The `Trait` struct is quite large and was being cloned every time `get_trait` was called in the NodeResolver, which was somewhat often. ## Summary\* Stops the cloning of traits! The `Clone` derive is removed entirely and when needed for ownership reasons we either re-retrieve the trait by calling `get_trait` again (which now returns a reference), or we temporarily take ownership of the trait's methods. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../src/hir/def_collector/dc_crate.rs | 19 +++++++----- .../src/hir/def_collector/dc_mod.rs | 14 ++++----- .../src/hir/resolution/resolver.rs | 18 +++++------ .../src/hir/resolution/traits.rs | 31 ++++++++++++------- .../noirc_frontend/src/hir/type_check/expr.rs | 4 ++- .../noirc_frontend/src/hir/type_check/mod.rs | 4 +-- compiler/noirc_frontend/src/hir_def/traits.rs | 7 +++-- compiler/noirc_frontend/src/hir_def/types.rs | 30 +++++++++--------- .../src/monomorphization/mod.rs | 4 +-- compiler/noirc_frontend/src/node_interner.rs | 16 ++++++---- tooling/noirc_abi/src/lib.rs | 2 +- 11 files changed, 85 insertions(+), 64 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 0806a8eb757..b9fd51dbb0f 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -410,12 +410,15 @@ pub(crate) fn check_methods_signatures( trait_impl_generic_count: usize, errors: &mut Vec<(CompilationError, FileId)>, ) { - let the_trait = resolver.interner.get_trait(trait_id); - - let self_type = resolver.get_self_type().expect("trait impl must have a Self type"); + let self_type = resolver.get_self_type().expect("trait impl must have a Self type").clone(); // Temporarily bind the trait's Self type to self_type so we can type check - the_trait.self_type_typevar.bind(self_type.clone()); + let the_trait = resolver.interner.get_trait_mut(trait_id); + the_trait.self_type_typevar.bind(self_type); + + // Temporarily take the trait's methods so we can use both them and a mutable reference + // to the interner within the loop. + let trait_methods = std::mem::take(&mut the_trait.methods); for (file_id, func_id) in impl_methods { let impl_method = resolver.interner.function_meta(func_id); @@ -427,7 +430,7 @@ pub(crate) fn check_methods_signatures( // If that's the case, a `MethodNotInTrait` error has already been thrown, and we can ignore // the impl method, since there's nothing in the trait to match its signature against. if let Some(trait_method) = - the_trait.methods.iter().find(|method| method.name.0.contents == func_name) + trait_methods.iter().find(|method| method.name.0.contents == func_name) { let impl_function_type = impl_method.typ.instantiate(resolver.interner); @@ -442,7 +445,7 @@ pub(crate) fn check_methods_signatures( let error = DefCollectorErrorKind::MismatchTraitImplementationNumGenerics { impl_method_generic_count, trait_method_generic_count, - trait_name: the_trait.name.to_string(), + trait_name: resolver.interner.get_trait(trait_id).name.to_string(), method_name: func_name.to_string(), span: impl_method.location.span, }; @@ -472,7 +475,7 @@ pub(crate) fn check_methods_signatures( let error = DefCollectorErrorKind::MismatchTraitImplementationNumParameters { actual_num_parameters: impl_method.parameters.0.len(), expected_num_parameters: trait_method.arguments().len(), - trait_name: the_trait.name.to_string(), + trait_name: resolver.interner.get_trait(trait_id).name.to_string(), method_name: func_name.to_string(), span: impl_method.location.span, }; @@ -498,5 +501,7 @@ pub(crate) fn check_methods_signatures( } } + let the_trait = resolver.interner.get_trait_mut(trait_id); + the_trait.set_methods(trait_methods); the_trait.self_type_typevar.unbind(the_trait.self_type_typevar_id); } diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 6cf2d669b9a..4cf910221ec 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -349,7 +349,7 @@ impl<'a> ModCollector<'a> { let name = trait_definition.name.clone(); // Create the corresponding module for the trait namespace - let id = match self.push_child_module(&name, self.file_id, false, false) { + let trait_id = match self.push_child_module(&name, self.file_id, false, false) { Ok(local_id) => TraitId(ModuleId { krate, local_id }), Err(error) => { errors.push((error.into(), self.file_id)); @@ -359,7 +359,7 @@ impl<'a> ModCollector<'a> { // Add the trait to scope so its path can be looked up later let result = - self.def_collector.def_map.modules[self.module_id.0].declare_trait(name, id); + self.def_collector.def_map.modules[self.module_id.0].declare_trait(name, trait_id); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -400,9 +400,9 @@ impl<'a> ModCollector<'a> { let location = Location::new(name.span(), self.file_id); context .def_interner - .push_function_definition(func_id, modifiers, id.0, location); + .push_function_definition(func_id, modifiers, trait_id.0, location); - match self.def_collector.def_map.modules[id.0.local_id.0] + match self.def_collector.def_map.modules[trait_id.0.local_id.0] .declare_function(name.clone(), func_id) { Ok(()) => { @@ -437,7 +437,7 @@ impl<'a> ModCollector<'a> { let stmt_id = context.def_interner.push_empty_global(); if let Err((first_def, second_def)) = self.def_collector.def_map.modules - [id.0.local_id.0] + [trait_id.0.local_id.0] .declare_global(name.clone(), stmt_id) { let error = DefCollectorErrorKind::Duplicate { @@ -451,7 +451,7 @@ impl<'a> ModCollector<'a> { TraitItem::Type { name } => { // TODO(nickysn or alexvitkov): implement context.def_interner.push_empty_type_alias and get an id, instead of using TypeAliasId::dummy_id() if let Err((first_def, second_def)) = self.def_collector.def_map.modules - [id.0.local_id.0] + [trait_id.0.local_id.0] .declare_type_alias(name.clone(), TypeAliasId::dummy_id()) { let error = DefCollectorErrorKind::Duplicate { @@ -473,7 +473,7 @@ impl<'a> ModCollector<'a> { trait_def: trait_definition, fns_with_default_impl: unresolved_functions, }; - self.def_collector.collected_traits.insert(id, unresolved); + self.def_collector.collected_traits.insert(trait_id, unresolved); } errors } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 59ba30b9c34..fcd747b65b5 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -523,7 +523,7 @@ impl<'a> Resolver<'a> { _new_variables: &mut Generics, ) -> Type { if let Some(t) = self.lookup_trait_or_error(path) { - Type::TraitAsType(t) + Type::TraitAsType(t.id, Rc::new(t.name.to_string())) } else { Type::Error } @@ -938,7 +938,7 @@ impl<'a> Resolver<'a> { | Type::Constant(_) | Type::NamedGeneric(_, _) | Type::NotConstant - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::Forall(_, _) => (), Type::Array(length, element_type) => { @@ -1498,8 +1498,8 @@ impl<'a> Resolver<'a> { self.interner.get_struct(type_id) } - pub fn get_trait(&self, trait_id: TraitId) -> Trait { - self.interner.get_trait(trait_id) + pub fn get_trait_mut(&mut self, trait_id: TraitId) -> &mut Trait { + self.interner.get_trait_mut(trait_id) } fn lookup(&mut self, path: Path) -> Result { @@ -1542,9 +1542,9 @@ impl<'a> Resolver<'a> { } /// Lookup a given trait by name/path. - fn lookup_trait_or_error(&mut self, path: Path) -> Option { + fn lookup_trait_or_error(&mut self, path: Path) -> Option<&mut Trait> { match self.lookup(path) { - Ok(trait_id) => Some(self.get_trait(trait_id)), + Ok(trait_id) => Some(self.get_trait_mut(trait_id)), Err(error) => { self.push_err(error); None @@ -1592,9 +1592,9 @@ impl<'a> Resolver<'a> { if name == SELF_TYPE_NAME { let the_trait = self.interner.get_trait(trait_id); - if let Some(method) = the_trait.find_method(method.clone()) { + if let Some(method) = the_trait.find_method(method.0.contents.as_str()) { let self_type = Type::TypeVariable( - the_trait.self_type_typevar, + the_trait.self_type_typevar.clone(), crate::TypeVariableKind::Normal, ); return Some((HirExpression::TraitMethodReference(method), self_type)); @@ -1628,7 +1628,7 @@ impl<'a> Resolver<'a> { { let the_trait = self.interner.get_trait(trait_id); if let Some(method) = - the_trait.find_method(path.segments.last().unwrap().clone()) + the_trait.find_method(path.segments.last().unwrap().0.contents.as_str()) { let self_type = self.resolve_type(typ.clone()); return Some((HirExpression::TraitMethodReference(method), self_type)); diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index 84f51f7ff6f..d4969c52c76 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -16,7 +16,7 @@ use crate::{ def_map::{CrateDefMap, ModuleDefId, ModuleId}, Context, }, - hir_def::traits::{Trait, TraitConstant, TraitFunction, TraitImpl, TraitType}, + hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, node_interner::{FuncId, NodeInterner, TraitId}, Path, Shared, TraitItem, Type, TypeBinding, TypeVariableKind, }; @@ -90,7 +90,7 @@ fn resolve_trait_methods( }); let file = def_maps[&crate_id].file_id(unresolved_trait.module_id); - let mut res = vec![]; + let mut functions = vec![]; let mut resolver_errors = vec![]; for item in &unresolved_trait.trait_def.items { if let TraitItem::Function { @@ -121,7 +121,8 @@ fn resolve_trait_methods( }); // Ensure the trait is generic over the Self type as well - generics.push((the_trait.self_type_typevar_id, the_trait.self_type_typevar)); + let the_trait = resolver.interner.get_trait(trait_id); + generics.push((the_trait.self_type_typevar_id, the_trait.self_type_typevar.clone())); let name = name.clone(); let span: Span = name.span(); @@ -149,11 +150,11 @@ fn resolve_trait_methods( default_impl_file_id: unresolved_trait.file_id, default_impl_module_id: unresolved_trait.module_id, }; - res.push(f); + functions.push(f); resolver_errors.extend(take_errors_filter_self_not_resolved(file, resolver)); } } - (res, resolver_errors) + (functions, resolver_errors) } fn collect_trait_impl_methods( @@ -167,15 +168,18 @@ fn collect_trait_impl_methods( // for a particular method, the default implementation will be added at that slot. let mut ordered_methods = Vec::new(); - let the_trait = interner.get_trait(trait_id); - // check whether the trait implementation is in the same crate as either the trait or the type let mut errors = - check_trait_impl_crate_coherence(interner, &the_trait, trait_impl, crate_id, def_maps); + check_trait_impl_crate_coherence(interner, trait_id, trait_impl, crate_id, def_maps); // set of function ids that have a corresponding method in the trait let mut func_ids_in_trait = HashSet::new(); - for method in &the_trait.methods { + // Temporarily take ownership of the trait's methods so we can iterate over them + // while also mutating the interner + let the_trait = interner.get_trait_mut(trait_id); + let methods = std::mem::take(&mut the_trait.methods); + + for method in &methods { let overrides: Vec<_> = trait_impl .methods .functions @@ -197,7 +201,7 @@ fn collect_trait_impl_methods( )); } else { let error = DefCollectorErrorKind::TraitMissingMethod { - trait_name: the_trait.name.clone(), + trait_name: interner.get_trait(trait_id).name.clone(), method_name: method.name.clone(), trait_impl_span: trait_impl.object_type.span.expect("type must have a span"), }; @@ -221,6 +225,10 @@ fn collect_trait_impl_methods( } } + // Restore the methods that were taken before the for loop + let the_trait = interner.get_trait_mut(trait_id); + the_trait.set_methods(methods); + // Emit MethodNotInTrait error for methods in the impl block that // don't have a corresponding method signature defined in the trait for (_, func_id, func) in &trait_impl.methods.functions { @@ -299,7 +307,7 @@ pub(crate) fn collect_trait_impls( fn check_trait_impl_crate_coherence( interner: &mut NodeInterner, - the_trait: &Trait, + trait_id: TraitId, trait_impl: &UnresolvedTraitImpl, current_crate: CrateId, def_maps: &BTreeMap, @@ -316,6 +324,7 @@ fn check_trait_impl_crate_coherence( _ => CrateId::Dummy, }; + let the_trait = interner.get_trait(trait_id); if current_crate != the_trait.crate_id && current_crate != object_crate { let error = DefCollectorErrorKind::TraitImplOrphaned { span: trait_impl.object_type.span.expect("object type must have a span"), diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 5263434a358..720ed8d5b5d 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -891,7 +891,9 @@ impl<'interner> TypeChecker<'interner> { } } } - Type::TraitAsType(_trait) => { + // TODO: We should allow method calls on `impl Trait`s eventually. + // For now it is fine since they are only allowed on return types. + Type::TraitAsType(..) => { self.errors.push(TypeCheckError::UnresolvedMethodCall { method_name: method_name.to_string(), object_type: object_type.clone(), diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index 6108e749175..95991047091 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -101,8 +101,8 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec, + pub constants: Vec, pub types: Vec, @@ -124,9 +125,9 @@ impl Trait { self.methods = methods; } - pub fn find_method(&self, name: Ident) -> Option { + pub fn find_method(&self, name: &str) -> Option { for (idx, method) in self.methods.iter().enumerate() { - if method.name == name { + if &method.name == name { return Some(TraitMethodId { trait_id: self.id, method_index: idx }); } } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 2c403d8d199..977293ec678 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -6,7 +6,7 @@ use std::{ use crate::{ hir::type_check::TypeCheckError, - node_interner::{ExprId, NodeInterner, TypeAliasId}, + node_interner::{ExprId, NodeInterner, TraitId, TypeAliasId}, }; use iter_extended::vecmap; use noirc_errors::{Location, Span}; @@ -14,10 +14,7 @@ use noirc_printable_type::PrintableType; use crate::{node_interner::StructId, Ident, Signedness}; -use super::{ - expr::{HirCallExpression, HirExpression, HirIdent}, - traits::Trait, -}; +use super::expr::{HirCallExpression, HirExpression, HirIdent}; #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum Type { @@ -65,7 +62,10 @@ pub enum Type { /// different argument types each time. TypeVariable(TypeVariable, TypeVariableKind), - TraitAsType(Trait), + /// `impl Trait` when used in a type position. + /// These are only matched based on the TraitId. The trait name paramer is only + /// used for displaying error messages using the name of the trait. + TraitAsType(TraitId, /*name:*/ Rc), /// NamedGenerics are the 'T' or 'U' in a user-defined generic function /// like `fn foo(...) {}`. Unlike TypeVariables, they cannot be bound over. @@ -132,7 +132,7 @@ impl Type { Type::FmtString(_, _) | Type::Unit | Type::TypeVariable(_, _) - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::NamedGeneric(_, _) | Type::Function(_, _, _) | Type::MutableReference(_) @@ -575,7 +575,7 @@ impl Type { | Type::NamedGeneric(_, _) | Type::NotConstant | Type::Forall(_, _) - | Type::TraitAsType(_) => false, + | Type::TraitAsType(..) => false, Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) @@ -714,8 +714,8 @@ impl std::fmt::Display for Type { write!(f, "{}<{}>", s.borrow(), args.join(", ")) } } - Type::TraitAsType(tr) => { - write!(f, "impl {}", tr.name) + Type::TraitAsType(_id, name) => { + write!(f, "impl {}", name) } Type::Tuple(elements) => { let elements = vecmap(elements, ToString::to_string); @@ -1279,7 +1279,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Unit - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::Constant(_) | Type::NotConstant | Type::Error => (), @@ -1372,7 +1372,6 @@ impl Type { let fields = vecmap(fields, |field| field.substitute(type_bindings)); Type::Tuple(fields) } - Type::TraitAsType(_) => todo!(), Type::Forall(typevars, typ) => { // Trying to substitute a variable defined within a nested Forall // is usually impossible and indicative of an error in the type checker somewhere. @@ -1396,6 +1395,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Constant(_) + | Type::TraitAsType(..) | Type::Error | Type::NotConstant | Type::Unit => self.clone(), @@ -1412,7 +1412,6 @@ impl Type { let field_occurs = fields.occurs(target_id); len_occurs || field_occurs } - Type::TraitAsType(_) => todo!(), Type::Struct(_, generic_args) => generic_args.iter().any(|arg| arg.occurs(target_id)), Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), Type::NamedGeneric(binding, _) | Type::TypeVariable(binding, _) => { @@ -1435,6 +1434,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Constant(_) + | Type::TraitAsType(..) | Type::Error | Type::NotConstant | Type::Unit => false, @@ -1482,7 +1482,7 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - TraitAsType(_) + TraitAsType(..) | FieldElement | Integer(_, _) | Bool @@ -1590,7 +1590,7 @@ impl From<&Type> for PrintableType { let fields = vecmap(fields, |(name, typ)| (name, typ.into())); PrintableType::Struct { fields, name: struct_type.name.to_string() } } - Type::TraitAsType(_) => unreachable!(), + Type::TraitAsType(..) => unreachable!(), Type::Tuple(_) => todo!("printing tuple types is not yet implemented"), Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 52ed0c746e1..78cde11593b 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -231,7 +231,7 @@ impl<'interner> Monomorphizer<'interner> { let body_expr_id = *self.interner.function(&f).as_expr(); let body_return_type = self.interner.id_type(body_expr_id); let return_type = self.convert_type(match meta.return_type() { - Type::TraitAsType(_) => &body_return_type, + Type::TraitAsType(..) => &body_return_type, _ => meta.return_type(), }); @@ -720,7 +720,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::Slice(element) } } - HirType::TraitAsType(_) => { + HirType::TraitAsType(..) => { unreachable!("All TraitAsType should be replaced before calling convert_type"); } HirType::NamedGeneric(binding, _) => { diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 8df31a51fc7..d49e236c68f 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -863,12 +863,16 @@ impl NodeInterner { self.structs[&id].clone() } - pub fn get_trait(&self, id: TraitId) -> Trait { - self.traits[&id].clone() + pub fn get_trait(&self, id: TraitId) -> &Trait { + &self.traits[&id] } - pub fn try_get_trait(&self, id: TraitId) -> Option { - self.traits.get(&id).cloned() + pub fn get_trait_mut(&mut self, id: TraitId) -> &mut Trait { + self.traits.get_mut(&id).expect("get_trait_mut given invalid TraitId") + } + + pub fn try_get_trait(&self, id: TraitId) -> Option<&Trait> { + self.traits.get(&id) } pub fn get_type_alias(&self, id: TypeAliasId) -> &TypeAliasType { @@ -892,7 +896,7 @@ impl NodeInterner { let typ = self.id_type(def_id); if let Type::Function(args, ret, env) = &typ { let def = self.definition(def_id); - if let Type::TraitAsType(_trait) = ret.as_ref() { + if let Type::TraitAsType(..) = ret.as_ref() { if let DefinitionKind::Function(func_id) = def.kind { let f = self.function(&func_id); let func_body = f.as_expr(); @@ -1382,6 +1386,6 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Error | Type::NotConstant | Type::Struct(_, _) - | Type::TraitAsType(_) => None, + | Type::TraitAsType(..) => None, } } diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 41ef7cde628..884c49c0106 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -161,7 +161,7 @@ impl AbiType { Type::Error => unreachable!(), Type::Unit => unreachable!(), Type::Constant(_) => unreachable!(), - Type::TraitAsType(_) => unreachable!(), + Type::TraitAsType(..) => unreachable!(), Type::Struct(def, ref args) => { let struct_type = def.borrow(); let fields = struct_type.get_fields(args); From 5734e4c88b5d56dcaeddb16d59b424857cb64d26 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Mon, 11 Dec 2023 18:54:30 +0100 Subject: [PATCH 016/137] chore(debugger): Add Noir Debugger README (#3735) # Description Adds a first guide on how to use the REPL debugger with binary Noir programs, and a discussion of (currently) experimental features. To be soon expanded with more details on how to test more experimental/not-yet-completed features. ## Problem Part of #3015. ## Documentation Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/debugger/README.md | 348 +++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 tooling/debugger/README.md diff --git a/tooling/debugger/README.md b/tooling/debugger/README.md new file mode 100644 index 00000000000..964784cb730 --- /dev/null +++ b/tooling/debugger/README.md @@ -0,0 +1,348 @@ +# Noir Debugger + +There are currently two ways of debugging Noir programs, both in active development and in experimental phase: + +1. The REPL debugger, which currently ships with Nargo behind a feature flag. +2. The VS Code extension, which hasn't still reached minimum viability, and so must be manually set up. + +This README explains how to use each of them as well as specifying which features are currently mature and which ones are unstable. + +## Supported project types + +At the time of writing, the debugger supports debugging binary projects, but not contracts. At the end of this README, we'll elaborate on what the current state of Noir contract debugging is, and the pre-requisites to fulfil. + + +## REPL debugger + +In order to use the REPL debugger, you will need to install a new enough version of Nargo. At the time of writing, the nightly version is 0.20.0, so we'll base this guide on it. + +Let's debug a simple circuit: + +``` +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +The debugger displays the current opcode, and the corresponding Noir code location associated to it, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> help +Available commands: + + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + memory show Brillig memory (valid when executing a + Brillig block) + into step into to the next opcode + next step until a new source location is reached + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + step step to the next ACIR opcode + registers show Brillig registers (valid when executing + a Brillig block) + regset index:usize value:String update a Brillig register with the given + value + restart restart the debugging session + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + continue continue execution until the end of the + program + opcodes display ACIR opcodes + memset index:usize value:String update a Brillig memory cell with the given + value + +Other commands: + + help Show this help message + quit Quit repl +``` + +The command menu is pretty self-explanatory. Some commands operate only at Brillig level, such as `memory`, `memset`, `registers`, `regset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing Brillig code: + +``` +> registers +Not executing a Brillig block +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_1 = 1 +_2 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2: + +``` +> witness +_1 = 1 +_2 = 2 +> witness 2 3 +_2 = 3 +> witness +_1 = 1 +_2 = 3 +> witness 2 2 +_2 = 2 +> witness +_1 = 1 +_2 = 2 +> +``` + +Let's take a look at this circuit's ACIR, using the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Note: in future versions of the debugger, we could explore prettier or more compact formats to print opcodes. + +So the next opcode will take us to Brillig execution. Let's step into opcode 1 so we can explore Brillig debugger commands. + +``` +> into +At opcode 1: BRILLIG: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] +outputs: [Simple(Witness(4))] +[JumpIfNot { condition: RegisterIndex(0), location: 3 }, Const { destination: RegisterIndex(1), value: Value { inner: 1 } }, BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) }, Stop] + +At /~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +``` + +In disassembly view: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> witness +_1 = 1 +_2 = 2 +_3 = 1 +> +``` + +We can see two arrow `->` cursors: one indicates where we are from the perspective of ACIR (opcode 1), and the other one shows us where we are in the context of the current Brillig block (opcode 1.0). + +Note: REPL commands are autocompleted when not ambiguous, so `opcodes` can be run just with `op`, `into` with `i`, etc. + +The next opcode to execute is a `JumpIfNot`, which reads from register 0. Let's inspect Brillig register state: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> registers +Brillig VM registers not available +``` + +Oops. This is unexpected, even though we were already in a Brillig block, we couldn't access the Brillig registers. This is a known issue: when just entering the Brillig block, the ACVM has not yet initialized the Brillig VM, so we can't introspect it. + +Note: In order to solve this, we would have to change the way the ACVM works, or add special handling for this case (after all, the debugger does know we're at the first opcode of a Brillig block and could keep track of how registers will be initialized). At the time of writing, we haven't yet solved this case. + +For now, let's just step once more: + +``` +> i +At opcode 1.1: Const { destination: RegisterIndex(1), value: Value { inner: 1 } } +> registers +0 = 1 +> +``` + +Now we can see that register 0 was initialized with a value of 1, so the `JumpIfNot` didn't activate. After executing opcode 1, we should see register 1 gets a value of 1: + +``` +> i +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> regist +0 = 1 +1 = 1 +> +``` + +The last operation will compute `Reg0 <- Reg1 / Reg0`: + +``` +> i +At opcode 1.3: Stop +> registers +0 = 1 +1 = 1 +> +``` + +Once we step again, we'll be out of Brillig and back on ACVM territory. With a new witness `_4` corresponding to the result of the Brillig block execution: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 -> EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> wit +_1 = 1 +_2 = 2 +_3 = 1 +_4 = 1 +> +``` + +At any time, we might also decide to restart from the beginning: + +``` +> restart +Restarted debugging session. +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +Let's set a breakpoint. For that, we can use the opcode id's listed by the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> break 1.2 +Added breakpoint at opcode 1.2 +``` + +Now we can have the debugger continue all the way to opcode 1.2: + +``` +> break 1.2 +Added breakpoint at opcode 1.2 +> continue +(Continuing execution...) +Stopped at breakpoint in opcode 1.2 +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> opcodes + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 |-> BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +## VS Code extension + +We're working on extending Noir's official VS Code extension so it uses the editor's debugger facilities to debug Noir programs. + +This section will soon show how to load the extension from sources, in order to test the debugger. + + +## Variable value inspection (unstable) + +To enable the inspection of variable values at runtime from the debugger, we're in the process of instrumenting the compiler to track and collect the necessary mappings between source code level variable names and ACIR/Brillig state. + +At the time of writing, there are still some parts of the language that haven't been fully instrumented, which means certain programs will crash when compiled with this. + +It is however possible to try out this feature, both from the REPL and VS Code, by building Nargo from branch https://github.com/manastech/noir/tree/dap-with-vars. + +We'll soon expand this section with details on how to do so for the adventurous. + + +## Towards debugging contracts + +### Contracts Runtime + +The execution of Noir contracts depends on a foreign call execution runtime to resolve all the oracle calls that the contract functions depend on. + +This means for the debugger to be usable with contracts we need to be able to do at least one of the following: + +1. Let users mock out a foreign call executor, and run the debugger with it. +2. Instrument live environments, such as the Sandbox, so that calls and transactions can be driven by the debugger, which ultimately means the debugger would use the same foreign call executor a live Sandbox uses for normal execution of Noir circuits. + +Both of these scenarios imply making the debugger available to language runtimes external to Noir. The Sandbox/PXE runs on JS runtimes, and an hypothetical mockable foreign executor could be in principle written in any language. So it seems the most promising way forward is to make sure that the debugger itself is consumable in JS runtimes. + From 0d6fd213bb40cd6857ab178e1d76d47649bf6b80 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 18:02:20 +0000 Subject: [PATCH 017/137] chore: remove unnecessary clone of workspace (#3770) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/nargo_toml/src/lib.rs | 2 +- tooling/nargo_toml/src/semver.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 141cb3411b3..31426ee4ee4 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -411,7 +411,7 @@ pub fn resolve_workspace_from_toml( let nargo_toml = read_toml(toml_path)?; let workspace = toml_to_workspace(nargo_toml, package_selection)?; if let Some(current_compiler_version) = current_compiler_version { - semver::semver_check_workspace(workspace.clone(), current_compiler_version)?; + semver::semver_check_workspace(&workspace, current_compiler_version)?; } Ok(workspace) } diff --git a/tooling/nargo_toml/src/semver.rs b/tooling/nargo_toml/src/semver.rs index 6acc68afa47..7c6e2a18b31 100644 --- a/tooling/nargo_toml/src/semver.rs +++ b/tooling/nargo_toml/src/semver.rs @@ -12,7 +12,7 @@ pub(crate) fn parse_semver_compatible_version(version: &str) -> Result Result<(), ManifestError> { let version = parse_semver_compatible_version(¤t_compiler_version) From fa93aa7d35936aeedf42cf89985866816597f59b Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 11 Dec 2023 20:05:25 +0000 Subject: [PATCH 018/137] chore: Improve error message in tests (#3775) # Description @jfecher noted that occassionally the JSON conversion method would fail. This changes `expect` to `unwrap_or_else` so that we know exactly what stdout input the error is failing on. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/nargo_cli/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 27a9b83d836..6f6d65ee89c 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -201,7 +201,9 @@ fn compile_success_empty_{test_name}() {{ }} // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).expect("JSON was not well-formatted"); + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|_| {{ + panic!("JSON was not well-formatted {{:?}}",output.stdout) + }}); let num_opcodes = &json["programs"][0]["acir_opcodes"]; assert_eq!(num_opcodes.as_u64().unwrap(), 0); }} From 0a23d425c81b3678ed91aa92adb0d052c635a575 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 11 Dec 2023 22:07:58 +0000 Subject: [PATCH 019/137] chore: conservatively use log::info instead of println for some expressions (#3766) # Description If you want to see info level logs, you can do `NOIR_LOG=info nargo compile` by default if that environment variable is not set, then it will only print out error level logs ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French --- Cargo.lock | 45 ++++++++++++++++++- Cargo.toml | 1 + acvm-repo/acvm_js/Cargo.toml | 2 +- .../src/ssa/opt/flatten_cfg.rs | 1 - compiler/wasm/Cargo.toml | 2 +- tooling/backend_interface/Cargo.toml | 1 + tooling/backend_interface/src/lib.rs | 4 +- tooling/backend_interface/src/proof_system.rs | 2 +- tooling/nargo_cli/Cargo.toml | 1 + tooling/nargo_cli/src/main.rs | 4 ++ 10 files changed, 55 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fd2b444391..652271fcaff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -407,6 +407,17 @@ dependencies = [ "waitpid-any", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -431,6 +442,7 @@ dependencies = [ "const_format", "dirs", "flate2", + "log", "reqwest", "serde", "serde_json", @@ -1481,6 +1493,19 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1907,6 +1932,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.2" @@ -1962,6 +1996,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -2159,7 +2199,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "rustix", "windows-sys 0.48.0", ] @@ -2423,6 +2463,7 @@ dependencies = [ "const_format", "criterion", "dirs", + "env_logger", "fm", "hex", "iai", @@ -2743,7 +2784,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "libc", ] diff --git a/Cargo.toml b/Cargo.toml index d5d844fbf32..c97a7cc2d99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,6 +120,7 @@ const_format = "0.2.30" num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" +log = "0.4.17" [profile.dev] # This is required to be able to run `cargo test` in acvm_js due to the `locals exceeds maximum` error. diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index 64ec90c6da3..f6054b49de1 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -26,9 +26,9 @@ wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true js-sys.workspace = true +log.workspace = true serde = { version = "1.0.136", features = ["derive"] } -log = "0.4.17" wasm-logger = "0.2.0" const-str = "0.5.5" diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 29df9d3c76d..b280ffa06e0 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -935,7 +935,6 @@ mod test { // } let ssa = ssa.flatten_cfg(); let main = ssa.main(); - println!("{ssa}"); assert_eq!(main.reachable_blocks().len(), 1); let store_count = count_instruction(main, |ins| matches!(ins, Instruction::Store { .. })); diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index 9ece26c6df4..8e693182db9 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -24,8 +24,8 @@ js-sys.workspace = true cfg-if.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true +log.workspace = true -log = "0.4.17" wasm-logger = "0.2.0" # This is an unused dependency, we are adding it diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml index 14b1609dd4a..a9217af65d2 100644 --- a/tooling/backend_interface/Cargo.toml +++ b/tooling/backend_interface/Cargo.toml @@ -16,6 +16,7 @@ thiserror.workspace = true serde.workspace = true serde_json.workspace = true bb_abstraction_leaks.workspace = true +log.workspace = true tempfile = "3.6.0" diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index 36ebe5ebb91..d25319e11d5 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -116,7 +116,7 @@ impl Backend { // If version doesn't match then download the correct version. Ok(version_string) => { - println!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); + log::warn!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; @@ -124,7 +124,7 @@ impl Backend { // If `bb` fails to report its version, then attempt to fix it by re-downloading the binary. Err(_) => { - println!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); + log::warn!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index dcf1dad56b0..bb47603bbf7 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -43,7 +43,7 @@ impl Backend { if let Ok(backend_info) = self.get_backend_info() { (backend_info.0, backend_info.1) } else { - println!("No valid backend found, defaulting to Plonk with width 3 and all opcodes supported"); + log::warn!("No valid backend found, defaulting to Plonk with width 3 and all opcodes supported"); (Language::PLONKCSat { width: 3 }, BackendOpcodeSupport::all()) } } diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 07298ae25d2..7d6be099d46 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -46,6 +46,7 @@ hex.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" color-eyre = "0.6.2" +env_logger = "0.9.0" tokio = { version = "1.0", features = ["io-std"] } # Backends diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs index 92bd7b94988..aefff697707 100644 --- a/tooling/nargo_cli/src/main.rs +++ b/tooling/nargo_cli/src/main.rs @@ -12,10 +12,14 @@ mod cli; mod errors; use color_eyre::config::HookBuilder; +use env_logger::{Builder, Env}; const PANIC_MESSAGE: &str = "This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.\nIf there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml"; fn main() { + let env = Env::default().filter_or("NOIR_LOG", "error"); // Default to 'error' if NOIR_LOG is not set + Builder::from_env(env).init(); + // Register a panic hook to display more readable panic messages to end-users let (panic_hook, _) = HookBuilder::default().display_env_section(false).panic_section(PANIC_MESSAGE).into_hooks(); From 54a1ed58c991eefa7ac9304b894c7046c294487b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Mon, 11 Dec 2023 23:38:57 +0000 Subject: [PATCH 020/137] feat: reorganizing docs to fit diataxis framework (#3711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description One of DevRel goals was to slowly start designing our docs process, and specially adopting the Diátaxis framework. A quick picture should make it easy to understand what exactly is Diátaxias: ![diataxis](https://diataxis.fr/_images/diataxis.png) Relevant WIP docs for this are (internal links): - [docs philosophy](https://hackmd.io/0ffxsnAARZaaiygZD_kWEA) - [Noir docs 2.0](https://hackmd.io/IdN1KMjIR3CgKk4t0A6-ug) This PR is a first step towards that reorg, by essentially moving things around. There are little changes to the content itself for now. However, during the reorg process, an opportunity came to upgrade to Docusaurus v3.0 with very little overhead, so I took it. ## Problem\* A small retro was made as part of the above [Noir Docs 2.0](https://hackmd.io/IdN1KMjIR3CgKk4t0A6-ug) exercise. ## Summary\* The Diátaxis framework divides docs neatly into four sections. However, in this case, it was deemed important to give a quick reference, so as to tackle the initial interest and motivation of readers and tinkerers. So, five top-level sections: - Getting Started -> Has a quick reference for all of the other sections, by providing a guide, a tutorial, an explanation, and a small reference to other tools. The idea is that most user journeys will eventually start here. - "The Noir Language" -> One of the biggest tasks will be to neatly separate explanations from reference material. This is a task that will be done later on. So this section contains a hybrid. - How-To Guides -> Given the clear distinction between "How-To" and "Tutorial", which is important to keep, this section currently doesn't have any more than the potentially outdated Merkle Tree example. - Tutorials -> Again, since no content was added, only the NoirJS e2e example is in this section. - Reference -> The reference material for Nargo commands and NoirJS lives here. This will be gradually expanded to fit the reference in the Language section. --- docs/.eslintignore | 2 + docs/.gitignore | 2 +- docs/babel.config.js | 3 - .../00_noir/00_data_types}/00_fields.md | 2 +- .../00_noir/00_data_types}/01_integers.md | 0 .../00_noir/00_data_types}/02_booleans.md | 0 .../00_noir/00_data_types}/03_strings.md | 0 .../00_noir/00_data_types}/04_arrays.md | 0 .../00_noir/00_data_types}/05_slices.mdx | 0 .../00_noir/00_data_types}/06_vectors.mdx | 0 .../00_noir/00_data_types}/07_tuples.md | 0 .../00_noir/00_data_types}/08_structs.md | 0 .../00_noir/00_data_types}/09_references.md | 0 .../00_data_types}/10_function_types.md | 0 .../00_noir/00_data_types/index.md} | 2 +- .../00_noir}/01_functions.md | 8 +- .../00_noir}/02_control_flow.md | 0 .../00_noir}/03_ops.md | 6 +- .../00_noir}/04_assert.md | 0 .../00_noir}/05_unconstrained.md | 0 .../00_noir}/06_generics.md | 0 .../00_noir}/07_mutability.md | 0 .../00_noir}/08_lambdas.md | 0 .../00_noir}/09_comments.md | 0 .../00_noir}/10_distinct.md | 0 .../00_noir}/11_shadowing.md | 0 .../00_noir}/12_data_bus.md | 0 .../00_hashes.mdx | 0 .../01_scalar.mdx | 0 .../02_schnorr.mdx | 0 .../03_ecdsa_sig_verification.mdx | 0 .../04_ec_primitives.md | 0 .../00_cryptographic_primitives}/05_eddsa.mdx | 0 .../00_cryptographic_primitives/index.md} | 2 +- .../01_standard_library}/black_box_fns.md | 0 .../01_standard_library}/logging.md | 0 .../01_standard_library}/merkle_trees.md | 2 +- .../01_standard_library}/options.md | 0 .../01_standard_library}/recursion.md | 0 .../01_standard_library}/zeroed.md | 0 .../crates_and_packages.md | 0 .../dependencies.md | 0 .../02_modules_packages_crates}/modules.md | 0 .../02_modules_packages_crates}/workspaces.md | 0 .../getting_started/00_installation/index.md | 45 + .../other_install_methods.md} | 112 +- ..._hello_world.md => 01_create_a_project.md} | 15 +- ...2_breakdown.md => 02_project_breakdown.md} | 4 +- .../03_tooling/00_language_server.md} | 0 .../03_tooling/01_testing.md} | 0 docs/docs/getting_started/03_tooling/index.md | 33 + .../{nargo => how_to}/03_solidity_verifier.md | 2 +- .../{examples => how_to}/merkle-proof.mdx | 2 +- docs/docs/index.md | 32 +- docs/docs/migration_notes.md | 4 +- docs/docs/noir_js/noir_js.md | 36 - .../00_nargo_commands.md} | 4 +- .../NoirJS/backend_barretenberg/.nojekyll | 1 + .../classes/BarretenbergBackend.md | 185 + .../NoirJS/backend_barretenberg/index.md | 45 + .../interfaces/Backend.md | 132 + .../type-aliases/BackendOptions.md | 19 + .../type-aliases/CompiledCircuit.md | 20 + .../type-aliases/ProofData.md | 20 + .../backend_barretenberg/typedoc-sidebar.cjs | 4 + docs/docs/reference/NoirJS/noir_js/.nojekyll | 1 + .../reference/NoirJS/noir_js/classes/Noir.md | 131 + .../reference/NoirJS/noir_js/functions/and.md | 22 + .../NoirJS/noir_js/functions/blake2s256.md | 21 + .../functions/ecdsa_secp256k1_verify.md | 29 + .../functions/ecdsa_secp256r1_verify.md | 28 + .../NoirJS/noir_js/functions/keccak256.md | 21 + .../NoirJS/noir_js/functions/sha256.md | 21 + .../reference/NoirJS/noir_js/functions/xor.md | 22 + docs/docs/reference/NoirJS/noir_js/index.md | 37 + .../noir_js/type-aliases/CompiledCircuit.md | 20 + .../type-aliases/ForeignCallHandler.md | 24 + .../noir_js/type-aliases/ForeignCallInput.md | 9 + .../noir_js/type-aliases/ForeignCallOutput.md | 9 + .../NoirJS/noir_js/type-aliases/InputMap.md | 13 + .../NoirJS/noir_js/type-aliases/ProofData.md | 20 + .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 + .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 + .../00_noirjs_app.md} | 4 +- docs/docusaurus.config.js | 247 -- docs/docusaurus.config.ts | 202 + docs/package.json | 39 +- docs/scripts/{setStable.js => setStable.ts} | 8 +- docs/sidebars.js | 138 +- docs/tsconfig.json | 6 + .../getting_started/00_nargo_installation.md | 9 +- docs/versioned_docs/version-v0.10.5/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.17.0/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.17.0/migration_notes.md | 2 +- .../noir_js/reference/01_noirjs.md | 8 +- .../noir_js/reference/02_bb_backend.md | 10 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.19.0/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.19.0/migration_notes.md | 2 +- .../noir_js/reference/01_noirjs.md | 8 +- .../noir_js/reference/02_bb_backend.md | 10 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.19.1/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.19.1/migration_notes.md | 2 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.19.2/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.19.2/migration_notes.md | 2 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.19.3/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.19.3/migration_notes.md | 2 +- .../getting_started/00_nargo_installation.md | 2 +- docs/versioned_docs/version-v0.19.4/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../language_concepts/data_types/00_fields.md | 2 +- .../version-v0.19.4/migration_notes.md | 2 +- .../getting_started/00_nargo_installation.md | 13 +- .../language_concepts/03_ops.md | 6 +- .../standard_library/field_methods.md | 2 +- .../getting_started/00_nargo_installation.md | 9 +- docs/versioned_docs/version-v0.7.1/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../standard_library/field_methods.md | 2 +- .../getting_started/00_nargo_installation.md | 9 +- docs/versioned_docs/version-v0.9.0/index.md | 2 +- .../language_concepts/03_ops.md | 6 +- .../standard_library/field_methods.md | 2 +- docs/versions.json | 6 +- versions.json | 4 + yarn.lock | 3835 +++++++++++++---- 142 files changed, 4441 insertions(+), 1431 deletions(-) create mode 100644 docs/.eslintignore delete mode 100644 docs/babel.config.js rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/00_fields.md (98%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/01_integers.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/02_booleans.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/03_strings.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/04_arrays.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/05_slices.mdx (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/06_vectors.mdx (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/07_tuples.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/08_structs.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/09_references.md (100%) rename docs/docs/{language_concepts/data_types => explanations/00_noir/00_data_types}/10_function_types.md (100%) rename docs/docs/{language_concepts/data_types.md => explanations/00_noir/00_data_types/index.md} (97%) rename docs/docs/{language_concepts => explanations/00_noir}/01_functions.md (91%) rename docs/docs/{language_concepts => explanations/00_noir}/02_control_flow.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/03_ops.md (90%) rename docs/docs/{language_concepts => explanations/00_noir}/04_assert.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/05_unconstrained.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/06_generics.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/07_mutability.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/08_lambdas.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/09_comments.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/10_distinct.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/11_shadowing.md (100%) rename docs/docs/{language_concepts => explanations/00_noir}/12_data_bus.md (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/00_hashes.mdx (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/01_scalar.mdx (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/02_schnorr.mdx (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/03_ecdsa_sig_verification.mdx (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/04_ec_primitives.md (100%) rename docs/docs/{standard_library/cryptographic_primitives => explanations/01_standard_library/00_cryptographic_primitives}/05_eddsa.mdx (100%) rename docs/docs/{standard_library/cryptographic_primitives.md => explanations/01_standard_library/00_cryptographic_primitives/index.md} (92%) rename docs/docs/{standard_library => explanations/01_standard_library}/black_box_fns.md (100%) rename docs/docs/{standard_library => explanations/01_standard_library}/logging.md (100%) rename docs/docs/{standard_library => explanations/01_standard_library}/merkle_trees.md (93%) rename docs/docs/{standard_library => explanations/01_standard_library}/options.md (100%) rename docs/docs/{standard_library => explanations/01_standard_library}/recursion.md (100%) rename docs/docs/{standard_library => explanations/01_standard_library}/zeroed.md (100%) rename docs/docs/{modules_packages_crates => explanations/02_modules_packages_crates}/crates_and_packages.md (100%) rename docs/docs/{modules_packages_crates => explanations/02_modules_packages_crates}/dependencies.md (100%) rename docs/docs/{modules_packages_crates => explanations/02_modules_packages_crates}/modules.md (100%) rename docs/docs/{modules_packages_crates => explanations/02_modules_packages_crates}/workspaces.md (100%) create mode 100644 docs/docs/getting_started/00_installation/index.md rename docs/docs/getting_started/{00_nargo_installation.md => 00_installation/other_install_methods.md} (64%) rename docs/docs/getting_started/{01_hello_world.md => 01_create_a_project.md} (90%) rename docs/docs/getting_started/{02_breakdown.md => 02_project_breakdown.md} (96%) rename docs/docs/{nargo/04_language_server.md => getting_started/03_tooling/00_language_server.md} (100%) rename docs/docs/{nargo/02_testing.md => getting_started/03_tooling/01_testing.md} (100%) create mode 100644 docs/docs/getting_started/03_tooling/index.md rename docs/docs/{nargo => how_to}/03_solidity_verifier.md (99%) rename docs/docs/{examples => how_to}/merkle-proof.mdx (98%) delete mode 100644 docs/docs/noir_js/noir_js.md rename docs/docs/{nargo/01_commands.md => reference/00_nargo_commands.md} (99%) create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/index.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md create mode 100644 docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs create mode 100644 docs/docs/reference/NoirJS/noir_js/.nojekyll create mode 100644 docs/docs/reference/NoirJS/noir_js/classes/Noir.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/and.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/keccak256.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/sha256.md create mode 100644 docs/docs/reference/NoirJS/noir_js/functions/xor.md create mode 100644 docs/docs/reference/NoirJS/noir_js/index.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md create mode 100644 docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md create mode 100644 docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs rename docs/docs/{noir_js/getting_started/01_tiny_noir_app.md => tutorials/00_noirjs_app.md} (95%) delete mode 100644 docs/docusaurus.config.js create mode 100644 docs/docusaurus.config.ts rename docs/scripts/{setStable.js => setStable.ts} (83%) create mode 100644 docs/tsconfig.json create mode 100644 versions.json diff --git a/docs/.eslintignore b/docs/.eslintignore new file mode 100644 index 00000000000..dd87e2d73f9 --- /dev/null +++ b/docs/.eslintignore @@ -0,0 +1,2 @@ +node_modules +build diff --git a/docs/.gitignore b/docs/.gitignore index e6e00b5b355..e4abc8785c7 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -7,7 +7,7 @@ # Generated files .docusaurus .cache-loader -/docs/docs/noir_js/reference/ +/docs/docs/reference/NoirJS # Misc .DS_Store diff --git a/docs/babel.config.js b/docs/babel.config.js deleted file mode 100644 index e00595dae7d..00000000000 --- a/docs/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; diff --git a/docs/docs/language_concepts/data_types/00_fields.md b/docs/docs/explanations/00_noir/00_data_types/00_fields.md similarity index 98% rename from docs/docs/language_concepts/data_types/00_fields.md rename to docs/docs/explanations/00_noir/00_data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/docs/language_concepts/data_types/00_fields.md +++ b/docs/docs/explanations/00_noir/00_data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/docs/language_concepts/data_types/01_integers.md b/docs/docs/explanations/00_noir/00_data_types/01_integers.md similarity index 100% rename from docs/docs/language_concepts/data_types/01_integers.md rename to docs/docs/explanations/00_noir/00_data_types/01_integers.md diff --git a/docs/docs/language_concepts/data_types/02_booleans.md b/docs/docs/explanations/00_noir/00_data_types/02_booleans.md similarity index 100% rename from docs/docs/language_concepts/data_types/02_booleans.md rename to docs/docs/explanations/00_noir/00_data_types/02_booleans.md diff --git a/docs/docs/language_concepts/data_types/03_strings.md b/docs/docs/explanations/00_noir/00_data_types/03_strings.md similarity index 100% rename from docs/docs/language_concepts/data_types/03_strings.md rename to docs/docs/explanations/00_noir/00_data_types/03_strings.md diff --git a/docs/docs/language_concepts/data_types/04_arrays.md b/docs/docs/explanations/00_noir/00_data_types/04_arrays.md similarity index 100% rename from docs/docs/language_concepts/data_types/04_arrays.md rename to docs/docs/explanations/00_noir/00_data_types/04_arrays.md diff --git a/docs/docs/language_concepts/data_types/05_slices.mdx b/docs/docs/explanations/00_noir/00_data_types/05_slices.mdx similarity index 100% rename from docs/docs/language_concepts/data_types/05_slices.mdx rename to docs/docs/explanations/00_noir/00_data_types/05_slices.mdx diff --git a/docs/docs/language_concepts/data_types/06_vectors.mdx b/docs/docs/explanations/00_noir/00_data_types/06_vectors.mdx similarity index 100% rename from docs/docs/language_concepts/data_types/06_vectors.mdx rename to docs/docs/explanations/00_noir/00_data_types/06_vectors.mdx diff --git a/docs/docs/language_concepts/data_types/07_tuples.md b/docs/docs/explanations/00_noir/00_data_types/07_tuples.md similarity index 100% rename from docs/docs/language_concepts/data_types/07_tuples.md rename to docs/docs/explanations/00_noir/00_data_types/07_tuples.md diff --git a/docs/docs/language_concepts/data_types/08_structs.md b/docs/docs/explanations/00_noir/00_data_types/08_structs.md similarity index 100% rename from docs/docs/language_concepts/data_types/08_structs.md rename to docs/docs/explanations/00_noir/00_data_types/08_structs.md diff --git a/docs/docs/language_concepts/data_types/09_references.md b/docs/docs/explanations/00_noir/00_data_types/09_references.md similarity index 100% rename from docs/docs/language_concepts/data_types/09_references.md rename to docs/docs/explanations/00_noir/00_data_types/09_references.md diff --git a/docs/docs/language_concepts/data_types/10_function_types.md b/docs/docs/explanations/00_noir/00_data_types/10_function_types.md similarity index 100% rename from docs/docs/language_concepts/data_types/10_function_types.md rename to docs/docs/explanations/00_noir/00_data_types/10_function_types.md diff --git a/docs/docs/language_concepts/data_types.md b/docs/docs/explanations/00_noir/00_data_types/index.md similarity index 97% rename from docs/docs/language_concepts/data_types.md rename to docs/docs/explanations/00_noir/00_data_types/index.md index d546cc463a8..2eda54575f6 100644 --- a/docs/docs/language_concepts/data_types.md +++ b/docs/docs/explanations/00_noir/00_data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](./06_generics.md): +Type aliases can also be used with [generics](@site/docs/explanations/00_noir/06_generics.md): ```rust type Id = Size; diff --git a/docs/docs/language_concepts/01_functions.md b/docs/docs/explanations/00_noir/01_functions.md similarity index 91% rename from docs/docs/language_concepts/01_functions.md rename to docs/docs/explanations/00_noir/01_functions.md index 5eb22170e54..9eeff5147d3 100644 --- a/docs/docs/language_concepts/01_functions.md +++ b/docs/docs/explanations/00_noir/01_functions.md @@ -14,7 +14,7 @@ To declare a function the `fn` keyword is used. fn foo() {} ``` -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](@site/docs/explanations/02_modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: ```rust pub fn foo() {} @@ -61,7 +61,7 @@ fn main(x : [Field]) // can't compile, has variable size fn main(....// i think you got it by now ``` -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: +Keep in mind [tests](@site/docs/getting_started/03_tooling/01_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: ```rust fn main(x : [Field]) { @@ -188,8 +188,8 @@ Supported attributes include: - **builtin**: the function is implemented by the compiler, for efficiency purposes. - **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` - **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](@site/docs/reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](@site/docs/getting_started/03_tooling/01_testing.md) for more details ### Field Attribute diff --git a/docs/docs/language_concepts/02_control_flow.md b/docs/docs/explanations/00_noir/02_control_flow.md similarity index 100% rename from docs/docs/language_concepts/02_control_flow.md rename to docs/docs/explanations/00_noir/02_control_flow.md diff --git a/docs/docs/language_concepts/03_ops.md b/docs/docs/explanations/00_noir/03_ops.md similarity index 90% rename from docs/docs/language_concepts/03_ops.md rename to docs/docs/explanations/00_noir/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/docs/language_concepts/03_ops.md +++ b/docs/docs/explanations/00_noir/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/docs/language_concepts/04_assert.md b/docs/docs/explanations/00_noir/04_assert.md similarity index 100% rename from docs/docs/language_concepts/04_assert.md rename to docs/docs/explanations/00_noir/04_assert.md diff --git a/docs/docs/language_concepts/05_unconstrained.md b/docs/docs/explanations/00_noir/05_unconstrained.md similarity index 100% rename from docs/docs/language_concepts/05_unconstrained.md rename to docs/docs/explanations/00_noir/05_unconstrained.md diff --git a/docs/docs/language_concepts/06_generics.md b/docs/docs/explanations/00_noir/06_generics.md similarity index 100% rename from docs/docs/language_concepts/06_generics.md rename to docs/docs/explanations/00_noir/06_generics.md diff --git a/docs/docs/language_concepts/07_mutability.md b/docs/docs/explanations/00_noir/07_mutability.md similarity index 100% rename from docs/docs/language_concepts/07_mutability.md rename to docs/docs/explanations/00_noir/07_mutability.md diff --git a/docs/docs/language_concepts/08_lambdas.md b/docs/docs/explanations/00_noir/08_lambdas.md similarity index 100% rename from docs/docs/language_concepts/08_lambdas.md rename to docs/docs/explanations/00_noir/08_lambdas.md diff --git a/docs/docs/language_concepts/09_comments.md b/docs/docs/explanations/00_noir/09_comments.md similarity index 100% rename from docs/docs/language_concepts/09_comments.md rename to docs/docs/explanations/00_noir/09_comments.md diff --git a/docs/docs/language_concepts/10_distinct.md b/docs/docs/explanations/00_noir/10_distinct.md similarity index 100% rename from docs/docs/language_concepts/10_distinct.md rename to docs/docs/explanations/00_noir/10_distinct.md diff --git a/docs/docs/language_concepts/11_shadowing.md b/docs/docs/explanations/00_noir/11_shadowing.md similarity index 100% rename from docs/docs/language_concepts/11_shadowing.md rename to docs/docs/explanations/00_noir/11_shadowing.md diff --git a/docs/docs/language_concepts/12_data_bus.md b/docs/docs/explanations/00_noir/12_data_bus.md similarity index 100% rename from docs/docs/language_concepts/12_data_bus.md rename to docs/docs/explanations/00_noir/12_data_bus.md diff --git a/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/01_scalar.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/02_schnorr.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/04_ec_primitives.md diff --git a/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/05_eddsa.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/05_eddsa.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives.md b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/index.md similarity index 92% rename from docs/docs/standard_library/cryptographic_primitives.md rename to docs/docs/explanations/01_standard_library/00_cryptographic_primitives/index.md index 2df4f929474..650f30165d5 100644 --- a/docs/docs/standard_library/cryptographic_primitives.md +++ b/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/index.md @@ -1,5 +1,5 @@ --- -title: Cryptographic primitives in Noir +title: Cryptographic Primitives description: Learn about the cryptographic primitives ready to use for any Noir project keywords: diff --git a/docs/docs/standard_library/black_box_fns.md b/docs/docs/explanations/01_standard_library/black_box_fns.md similarity index 100% rename from docs/docs/standard_library/black_box_fns.md rename to docs/docs/explanations/01_standard_library/black_box_fns.md diff --git a/docs/docs/standard_library/logging.md b/docs/docs/explanations/01_standard_library/logging.md similarity index 100% rename from docs/docs/standard_library/logging.md rename to docs/docs/explanations/01_standard_library/logging.md diff --git a/docs/docs/standard_library/merkle_trees.md b/docs/docs/explanations/01_standard_library/merkle_trees.md similarity index 93% rename from docs/docs/standard_library/merkle_trees.md rename to docs/docs/explanations/01_standard_library/merkle_trees.md index dc383a1426b..86452a2ccb3 100644 --- a/docs/docs/standard_library/merkle_trees.md +++ b/docs/docs/explanations/01_standard_library/merkle_trees.md @@ -17,7 +17,7 @@ keywords: ## compute_merkle_root -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](@site/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx#pedersen_hash). ```rust fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field diff --git a/docs/docs/standard_library/options.md b/docs/docs/explanations/01_standard_library/options.md similarity index 100% rename from docs/docs/standard_library/options.md rename to docs/docs/explanations/01_standard_library/options.md diff --git a/docs/docs/standard_library/recursion.md b/docs/docs/explanations/01_standard_library/recursion.md similarity index 100% rename from docs/docs/standard_library/recursion.md rename to docs/docs/explanations/01_standard_library/recursion.md diff --git a/docs/docs/standard_library/zeroed.md b/docs/docs/explanations/01_standard_library/zeroed.md similarity index 100% rename from docs/docs/standard_library/zeroed.md rename to docs/docs/explanations/01_standard_library/zeroed.md diff --git a/docs/docs/modules_packages_crates/crates_and_packages.md b/docs/docs/explanations/02_modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/docs/modules_packages_crates/crates_and_packages.md rename to docs/docs/explanations/02_modules_packages_crates/crates_and_packages.md diff --git a/docs/docs/modules_packages_crates/dependencies.md b/docs/docs/explanations/02_modules_packages_crates/dependencies.md similarity index 100% rename from docs/docs/modules_packages_crates/dependencies.md rename to docs/docs/explanations/02_modules_packages_crates/dependencies.md diff --git a/docs/docs/modules_packages_crates/modules.md b/docs/docs/explanations/02_modules_packages_crates/modules.md similarity index 100% rename from docs/docs/modules_packages_crates/modules.md rename to docs/docs/explanations/02_modules_packages_crates/modules.md diff --git a/docs/docs/modules_packages_crates/workspaces.md b/docs/docs/explanations/02_modules_packages_crates/workspaces.md similarity index 100% rename from docs/docs/modules_packages_crates/workspaces.md rename to docs/docs/explanations/02_modules_packages_crates/workspaces.md diff --git a/docs/docs/getting_started/00_installation/index.md b/docs/docs/getting_started/00_installation/index.md new file mode 100644 index 00000000000..ddb8a250eb4 --- /dev/null +++ b/docs/docs/getting_started/00_installation/index.md @@ -0,0 +1,45 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo though the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. diff --git a/docs/docs/getting_started/00_nargo_installation.md b/docs/docs/getting_started/00_installation/other_install_methods.md similarity index 64% rename from docs/docs/getting_started/00_nargo_installation.md rename to docs/docs/getting_started/00_installation/other_install_methods.md index 725c5f4d373..cd27185a293 100644 --- a/docs/docs/getting_started/00_nargo_installation.md +++ b/docs/docs/getting_started/00_installation/other_install_methods.md @@ -1,72 +1,37 @@ --- -title: Nargo Installation +title: Alternative Install Methods description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] + There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Shell & editor experience + Building and testing + Uninstalling Nargo + Noir vs code extension +] --- -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` +The most common method of installing Nargo is through [Noirup](@site/docs/getting_started/00_installation/index.md) -Done, you should have the latest version working. You can check with `nargo --version`. +However, there are other methods for installing Nargo: -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. +- [Binaries](#binaries) +- [Compiling from Source](#compile-from-source) +- [WSL for Windows](#wsl-for-windows) -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries +### Binaries See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous platform specific binaries. @@ -110,34 +75,11 @@ source ~/.bashrc #### Step 2 -Check if the installation was successful by running `nargo --help`. +Check if the installation was successful by running `nargo --version`. You should get a version number. > **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from > Finder. Close the new terminal popped up and `nargo` should now be accessible. -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - ### Option 3: Compile from Source Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). @@ -224,7 +166,7 @@ The default backend for Noir (Barretenberg) doesn't provide Windows binaries at Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. -step 2: Follow the [Noirup instructions](#option-1-noirup). +step 2: Follow the [Noirup instructions](@site/docs/getting_started/00_installation/index.md). ## Uninstalling Nargo @@ -245,5 +187,3 @@ If you installed Noir with Nix or from source, you can remove the binary located ```bash rm ~/.nix-profile/bin/nargo ``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/docs/getting_started/01_hello_world.md b/docs/docs/getting_started/01_create_a_project.md similarity index 90% rename from docs/docs/getting_started/01_hello_world.md rename to docs/docs/getting_started/01_create_a_project.md index 8b4416beba1..d32f397370c 100644 --- a/docs/docs/getting_started/01_hello_world.md +++ b/docs/docs/getting_started/01_create_a_project.md @@ -1,5 +1,5 @@ --- -title: Create A Project +title: Creating A Project description: Learn how to create and verify your first Noir program using Nargo, a programming language for zero-knowledge proofs. @@ -30,13 +30,6 @@ mkdir ~/projects cd ~/projects ``` -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - ## Create Our First Nargo Project Now that we are in the projects directory, create a new Nargo project by running: @@ -74,7 +67,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](@site/docs/explanations/00_noir/00_data_types/index.md) section. The next line of the program specifies its body: @@ -84,7 +77,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](@site/docs/explanations/00_noir/09_comments.md) chapter. ## Build In/Output Files @@ -144,4 +137,4 @@ corresponding error instead. Congratulations, you have now created and verified a proof for your very first Noir program! -In the [next section](breakdown), we will go into more detail on each step performed. +In the [next section](@site/docs/getting_started/02_project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/docs/getting_started/02_breakdown.md b/docs/docs/getting_started/02_project_breakdown.md similarity index 96% rename from docs/docs/getting_started/02_breakdown.md rename to docs/docs/getting_started/02_project_breakdown.md index 9a17f5d6360..8e4bf39522e 100644 --- a/docs/docs/getting_started/02_breakdown.md +++ b/docs/docs/getting_started/02_project_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](@site/docs/explanations/02_modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](@site/docs/explanations/02_modules_packages_crates/dependencies.md) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/docs/nargo/04_language_server.md b/docs/docs/getting_started/03_tooling/00_language_server.md similarity index 100% rename from docs/docs/nargo/04_language_server.md rename to docs/docs/getting_started/03_tooling/00_language_server.md diff --git a/docs/docs/nargo/02_testing.md b/docs/docs/getting_started/03_tooling/01_testing.md similarity index 100% rename from docs/docs/nargo/02_testing.md rename to docs/docs/getting_started/03_tooling/01_testing.md diff --git a/docs/docs/getting_started/03_tooling/index.md b/docs/docs/getting_started/03_tooling/index.md new file mode 100644 index 00000000000..55df833005a --- /dev/null +++ b/docs/docs/getting_started/03_tooling/index.md @@ -0,0 +1,33 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## Playground + +The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/docs/docs/nargo/03_solidity_verifier.md b/docs/docs/how_to/03_solidity_verifier.md similarity index 99% rename from docs/docs/nargo/03_solidity_verifier.md rename to docs/docs/how_to/03_solidity_verifier.md index 9ac60cb0ba7..1a89fe492f4 100644 --- a/docs/docs/nargo/03_solidity_verifier.md +++ b/docs/docs/how_to/03_solidity_verifier.md @@ -1,5 +1,5 @@ --- -title: Solidity Verifier +title: Generate a Solidity Verifier description: Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart diff --git a/docs/docs/examples/merkle-proof.mdx b/docs/docs/how_to/merkle-proof.mdx similarity index 98% rename from docs/docs/examples/merkle-proof.mdx rename to docs/docs/how_to/merkle-proof.mdx index 832fb4bb55e..34074659ac1 100644 --- a/docs/docs/examples/merkle-proof.mdx +++ b/docs/docs/how_to/merkle-proof.mdx @@ -1,5 +1,5 @@ --- -title: Merkle Proof Membership +title: Prove Merkle Tree Membership description: Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a merkle tree with a specified root, at a given index. diff --git a/docs/docs/index.md b/docs/docs/index.md index 977ce52723d..de04d263e41 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -1,5 +1,5 @@ --- -title: Introducing Noir +title: Noir description: Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. @@ -22,13 +22,13 @@ keywords: ## What's new about Noir? Noir, a domain-specific language crafted for SNARK proving systems, stands out with its simplicity, flexibility, -and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, -Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, -depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's -barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin +and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, +Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, +depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's +barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin backend, among others. -This innovative design introduces unique challenges, yet it strategically separates the programming language from the +This innovative design introduces unique challenges, yet it strategically separates the programming language from the backend. Noir's approach echoes the modular philosophy of LLVM, offering developers a versatile toolkit for cryptographic programming. @@ -36,9 +36,9 @@ programming. ### Solidity Developers -Noir streamlines the creation of Solidity contracts that interface with SNARK systems. -[`Utilize the nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to construct verifier -contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim +Noir streamlines the creation of Solidity contracts that interface with SNARK systems. +[`Utilize the nargo codegen-verifier`](@site/docs/reference/00_nargo_commands.md#nargo-codegen-verifier) command to construct verifier +contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim to modularize this process for even greater ease of use. Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be @@ -47,16 +47,16 @@ modularised in the future; however, as of the alpha, you can use the ### Protocol Developers -Should the Aztec backend not align with your existing tech stack, or if you're inclined to integrate alternative -proving systems, Noir's agnostic compilation to a proof-agnostic intermediate language offers unmatched flexibility. -This allows protocol engineers the freedom to substitute the default PLONK-based system with an alternative of their +Should the Aztec backend not align with your existing tech stack, or if you're inclined to integrate alternative +proving systems, Noir's agnostic compilation to a proof-agnostic intermediate language offers unmatched flexibility. +This allows protocol engineers the freedom to substitute the default PLONK-based system with an alternative of their choice, tailoring the proving system to their specific needs. ### Blockchain developers -Blockchain developers often face environmental constraints, such as predetermined proving systems and smart contract -languages. Noir addresses this by enabling the implementation of custom proving system backends and smart contract -interfaces, ensuring seamless integration with your blockchain's architecture, and expanding the horizons for innovation +Blockchain developers often face environmental constraints, such as predetermined proving systems and smart contract +languages. Noir addresses this by enabling the implementation of custom proving system backends and smart contract +interfaces, ensuring seamless integration with your blockchain's architecture, and expanding the horizons for innovation within your projects. ## Libraries @@ -81,4 +81,4 @@ Some libraries that are available today include: - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](@site/docs/explanations/02_modules_packages_crates/dependencies.md) for more information. diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index e87eb1feaba..4964a85c833 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -16,7 +16,7 @@ To update, please make sure this field in `Nargo.toml` matches the output of `na ## ≥0.14 -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: +The index of the [for loops](@site/docs/explanations/00_noir/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: ```rust for i in 0..10 { @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/docs/noir_js/noir_js.md b/docs/docs/noir_js/noir_js.md deleted file mode 100644 index f895b22eaf8..00000000000 --- a/docs/docs/noir_js/noir_js.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: NoirJS -description: Interact with Noir in Typescript or Javascript -keywords: [Noir project, javascript, typescript, node.js, browser, react] ---- - -NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. - -A typical workflow would be composed of two major elements: - -- NoirJS -- Proving backend of choice's JavaScript package - - - -To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: - -```bash -npm i @noir-lang/noir_js -``` - -## Proving backend - -Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. - -### Barretenberg - -Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. - -To install its JavaScript library, run this in your project: - -```bash -npm i @noir-lang/backend_barretenberg -``` - -For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/docs/docs/nargo/01_commands.md b/docs/docs/reference/00_nargo_commands.md similarity index 99% rename from docs/docs/nargo/01_commands.md rename to docs/docs/reference/00_nargo_commands.md index 7256dbc5346..8c564ca494e 100644 --- a/docs/docs/nargo/01_commands.md +++ b/docs/docs/reference/00_nargo_commands.md @@ -1,5 +1,5 @@ --- -title: Commands +title: nargo description: Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, generate Solidity verifier smart contract and compile into JSON file containing ACIR @@ -212,7 +212,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](@site/docs/getting_started/03_tooling/01_testing.md). ### Options diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..5cbe9421b92 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/index.md b/docs/docs/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..bfbecb52864 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,45 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +## Functions + +### flattenPublicInputs() + +```ts +flattenPublicInputs(publicInputs): string[] +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `WitnessMap` | + +#### Returns + +`string`[] + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 00000000000..3eb9645c8d2 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..266ade75d17 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 00000000000..3eb360a78f1 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..2aaa55bccf6 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/noir_js/.nojekyll b/docs/docs/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/noir_js/classes/Noir.md b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..e54116fb1d8 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,131 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalproof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/and.md b/docs/docs/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..0ba5783f0d5 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md b/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/sha256.md b/docs/docs/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/xor.md b/docs/docs/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/index.md b/docs/docs/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..8b9e35bc9a1 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/index.md @@ -0,0 +1,37 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [InputMap](type-aliases/InputMap.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md new file mode 100644 index 00000000000..c714e999d93 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md @@ -0,0 +1,13 @@ +# InputMap + +```ts +type InputMap: object; +``` + +## Index signature + + \[`key`: `string`\]: `InputValue` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md new file mode 100644 index 00000000000..3eb360a78f1 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..fe2629ddc9f --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/docs/noir_js/getting_started/01_tiny_noir_app.md b/docs/docs/tutorials/00_noirjs_app.md similarity index 95% rename from docs/docs/noir_js/getting_started/01_tiny_noir_app.md rename to docs/docs/tutorials/00_noirjs_app.md index c51ed61de52..4a4161d70fc 100644 --- a/docs/docs/noir_js/getting_started/01_tiny_noir_app.md +++ b/docs/docs/tutorials/00_noirjs_app.md @@ -1,5 +1,5 @@ --- -title: End-to-end +title: Tiny NoirJS app description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] --- @@ -20,7 +20,7 @@ In this guide, we will be pinned to 0.17.0. Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). -First of all, follow the the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: +First of all, follow the the [Nargo guide](@site/docs/getting_started/00_installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: ```bash nargo compile diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js deleted file mode 100644 index 67c8233e316..00000000000 --- a/docs/docusaurus.config.js +++ /dev/null @@ -1,247 +0,0 @@ -// @ts-check -// Note: type annotations allow type checking and IDEs autocompletion - -const lightCodeTheme = require('prism-react-renderer/themes/github'); -const darkCodeTheme = require('prism-react-renderer/themes/dracula'); - -const math = require('remark-math'); -const katex = require('rehype-katex'); -const path = require('path'); - -/** @type {import('@docusaurus/types').Config} */ -const config = { - title: 'Noir Documentation', - tagline: 'The Universal ZK Circuit Language', - favicon: 'img/favicon.ico', - url: 'https://noir-lang.org', - // Set the // pathname under which your site is served - // For GitHub pages deployment, it is often '//' - baseUrl: '/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - - // Even if you don't use internalization, you can use this field to set useful - // metadata like html lang. For example, if your site is Chinese, you may want - // to replace "en" with "zh-Hans". - i18n: { - defaultLocale: 'en', - locales: ['en'], - }, - - presets: [ - [ - '@docusaurus/preset-classic', - { - // gtag: { - // trackingID: 'G-SZQHEQZK3L', - // anonymizeIP: true, - // }, - docs: { - sidebarPath: require.resolve('./sidebars.js'), - routeBasePath: '/docs', - remarkPlugins: [math], - rehypePlugins: [katex], - versions: { - current: { - label: 'dev', - path: 'dev', - }, - }, - editUrl: ({ versionDocsDirPath, docPath }) => - `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath}/${docPath}`, - }, - blog: false, - theme: { - customCss: require.resolve('./src/css/custom.css'), - }, - }, - ], - ], - - themeConfig: - /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - { - // Replace with your project's social card - navbar: { - logo: { - alt: 'Noir Logo', - src: 'img/logo.svg', - srcDark: 'img/logoDark.svg', - href: '/', - }, - items: [ - { - href: 'https://github.com/noir-lang/noir/tree/master/docs', - label: 'GitHub', - position: 'right', - }, - { - type: 'docsVersionDropdown', - position: 'left', - dropdownActiveClassDisabled: true, - }, - ], - }, - metadata: [ - { - name: 'Noir', - content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', - }, - ], - footer: { - style: 'dark', - links: [ - { - title: 'Community', - items: [ - { - label: 'Noir Forum', - href: 'https://discourse.aztec.network/c/noir/7', - }, - { - label: 'Twitter', - href: 'https://twitter.com/NoirLang', - }, - { - label: 'Discord', - href: 'https://discord.gg/JtqzkdeQ6G', - }, - ], - }, - { - title: 'Code', - items: [ - { - label: 'Noir GitHub', - href: 'https://github.com/noir-lang', - }, - { - label: 'Docs GitHub', - href: 'https://github.com/noir-lang/docs', - }, - ], - }, - ], - copyright: `Noir will be dual licensed under MIT/Apache (Version 2.0).`, - }, - prism: { - theme: lightCodeTheme, - darkTheme: darkCodeTheme, - additionalLanguages: ['rust', 'powershell', 'solidity', 'toml'], - }, - stylesheets: [ - { - href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', - type: 'text/css', - integrity: 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', - crossorigin: 'anonymous', - }, - ], - algolia: { - // The application ID provided by Algolia - appId: '97APAVUL6H', - - // Public API key: it is safe to commit it - apiKey: 'b9b94d2f1c58f7d509f0bc1f13b381fb', - - indexName: 'noir-lang', - }, - }, - plugins: [ - () => ({ - name: 'resolve-react', - configureWebpack() { - return { - resolve: { - alias: { - // assuming root node_modules is up from "./packages/ - react: path.resolve('../node_modules/react'), - }, - }, - optimization: { - innerGraph: false, - }, - }; - }, - }), - [ - 'docusaurus-plugin-typedoc', - { - id: 'noir_js', - entryPoints: ['../tooling/noir_js/src/index.ts'], - tsconfig: '../tooling/noir_js/tsconfig.json', - entryPointStrategy: 'resolve', - out: 'docs/noir_js/reference/noir_js', - plugin: ['typedoc-plugin-markdown'], - name: 'Noir JS', - disableSources: true, - excludePrivate: true, - - sidebar: { - filteredIds: ['noir_js/reference/noir_js/index'], - }, - readme: 'none', - hidePageHeader: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - useCodeBlocks: true, - typeDeclarationFormat: 'table', - propertiesFormat: 'table', - parametersFormat: 'table', - enumMembersFormat: 'table', - indexFormat: 'table', - outputFileStrategy: 'members', - memberPageTitle: '{name}', - membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], - }, - ], - [ - 'docusaurus-plugin-typedoc', - { - id: 'noir_js_backend_barretenberg', - entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], - tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', - entryPointStrategy: 'resolve', - out: 'docs/noir_js/reference/backend_barretenberg', - plugin: ['typedoc-plugin-markdown'], - name: 'Backend Barretenberg', - disableSources: true, - excludePrivate: true, - - sidebar: { - filteredIds: ['noir_js/reference/backend_barretenberg/index'], - }, - readme: 'none', - hidePageHeader: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - useCodeBlocks: true, - typeDeclarationFormat: 'table', - propertiesFormat: 'table', - parametersFormat: 'table', - enumMembersFormat: 'table', - indexFormat: 'table', - outputFileStrategy: 'members', - memberPageTitle: '{name}', - membersWithOwnFile: ['Interface', 'Class', 'TypeAlias'], - }, - ], - [ - '@docusaurus/plugin-content-pages', - { - id: 'pages', - path: 'src/pages', - routeBasePath: '/', - include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], - exclude: ['**/_*.{js,jsx,ts,tsx,md,mdx}', '**/_*/**', '**/*.test.{js,jsx,ts,tsx}', '**/__tests__/**'], - mdxPageComponent: '@theme/MDXPage', - remarkPlugins: [require('remark-math')], - rehypePlugins: [], - beforeDefaultRemarkPlugins: [], - beforeDefaultRehypePlugins: [], - }, - ], - ], -}; - -module.exports = config; diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts new file mode 100644 index 00000000000..14abaf04b47 --- /dev/null +++ b/docs/docusaurus.config.ts @@ -0,0 +1,202 @@ +import type { Config } from '@docusaurus/types'; + +const { themes } = require('prism-react-renderer'); +const lightTheme = themes.github; +const darkTheme = themes.dracula; + +import math from 'remark-math'; +import katex from 'rehype-katex'; + +export default { + title: 'Noir Documentation', + tagline: 'The Universal ZK Circuit Language', + favicon: 'img/favicon.ico', + url: 'https://noir-lang.org', + baseUrl: '/', + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'throw', + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + sidebarPath: './sidebars.js', + routeBasePath: '/docs', + remarkPlugins: [math], + rehypePlugins: [katex], + versions: { + current: { + label: 'dev', + path: 'dev', + }, + }, + editUrl: ({ versionDocsDirPath, docPath }) => + `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath}/${docPath}`, + }, + blog: false, + theme: { + customCss: './src/css/custom.css', + }, + }, + ], + ], + + themeConfig: { + navbar: { + logo: { + alt: 'Noir Logo', + src: 'img/logo.svg', + srcDark: 'img/logoDark.svg', + href: '/', + }, + items: [ + { + href: 'https://github.com/noir-lang/noir/tree/master/docs', + label: 'GitHub', + position: 'right', + }, + { + type: 'docsVersionDropdown', + position: 'left', + dropdownActiveClassDisabled: true, + }, + ], + }, + metadata: [ + { + name: 'Noir', + content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', + }, + ], + footer: { + style: 'dark', + links: [ + { + title: 'Community', + items: [ + { + label: 'Noir Forum', + href: 'https://discourse.aztec.network/c/noir/7', + }, + { + label: 'Twitter', + href: 'https://twitter.com/NoirLang', + }, + { + label: 'Discord', + href: 'https://discord.gg/JtqzkdeQ6G', + }, + ], + }, + { + title: 'Code', + items: [ + { + label: 'Noir GitHub', + href: 'https://github.com/noir-lang', + }, + { + label: 'Docs GitHub', + href: 'https://github.com/noir-lang/docs', + }, + ], + }, + ], + copyright: `Noir will be dual licensed under MIT/Apache (Version 2.0).`, + }, + prism: { + theme: lightTheme, + darkTheme: darkTheme, + additionalLanguages: ['rust', 'powershell', 'solidity', 'toml'], + }, + stylesheets: [ + { + href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', + type: 'text/css', + integrity: 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', + crossorigin: 'anonymous', + }, + ], + algolia: { + // The application ID provided by Algolia + appId: '97APAVUL6H', + + // Public API key: it is safe to commit it + apiKey: 'b9b94d2f1c58f7d509f0bc1f13b381fb', + + indexName: 'noir-lang', + }, + }, + plugins: [ + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_js', + entryPoints: ['../tooling/noir_js/src/index.ts'], + tsconfig: '../tooling/noir_js/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'docs/reference/NoirJS/noir_js', + plugin: ['typedoc-plugin-markdown'], + name: 'noir_js', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/NoirJS/noir_js/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], + }, + ], + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_js_backend_barretenberg', + entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], + tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'docs/reference/NoirJS/backend_barretenberg', + plugin: ['typedoc-plugin-markdown'], + name: 'backend_barretenberg', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/NoirJS/backend_barretenberg/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Interface', 'Class', 'TypeAlias'], + }, + ], + ], + markdown: { + format: 'detect', + }, +} satisfies Config; diff --git a/docs/package.json b/docs/package.json index 7ca074ac06a..6a95fcb89f5 100644 --- a/docs/package.json +++ b/docs/package.json @@ -5,36 +5,41 @@ "scripts": { "start": "docusaurus start", "build": "yarn version::stables && docusaurus build", - "version::stables": "node ./scripts/setStable.js" + "version::stables": "node --loader ts-node/esm ./scripts/setStable.ts" }, "dependencies": { - "@docusaurus/core": "^2.4.0", - "@docusaurus/plugin-content-pages": "^2.4.0", - "@docusaurus/plugin-google-gtag": "^2.4.0", - "@docusaurus/preset-classic": "^2.4.0", + "@docusaurus/core": "^3.0.1", + "@docusaurus/preset-classic": "^3.0.1", "@easyops-cn/docusaurus-search-local": "^0.35.0", - "@mdx-js/react": "^1.6.22", + "@mdx-js/react": "^3.0.0", + "@noir-lang/noir_js": "workspace:*", "@noir-lang/noirc_abi": "workspace:*", "@noir-lang/types": "workspace:*", "@signorecello/noir_playground": "^0.6.0", "axios": "^1.4.0", "clsx": "^1.2.1", - "docusaurus-plugin-typedoc": "1.0.0-next.18", "hast-util-is-element": "^1.1.0", - "prism-react-renderer": "^1.3.5", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "prism-react-renderer": "^2.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "react-spinners": "^0.13.8", - "rehype-katex": "^5.0.0", - "remark-math": "^3.0.1", + "rehype-katex": "^7.0.0", + "remark-math": "^6.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "^3.0.1", + "@docusaurus/tsconfig": "^3.0.1", + "@docusaurus/types": "^3.0.1", + "@types/prettier": "^3", + "docusaurus-plugin-typedoc": "1.0.0-next.18", + "eslint-plugin-prettier": "^5.0.0", + "prettier": "3.0.3", + "ts-node": "^10.9.1", "typedoc": "^0.25.0", "typedoc-plugin-frontmatter": "^0.0.2", "typedoc-plugin-markdown": "4.0.0-next.25", "typedoc-plugin-merge-modules": "^5.1.0", - "typescript": "^5.2.2" - }, - "devDependencies": { - "@docusaurus/module-type-aliases": "^2.4.0" + "typescript": "~5.2.2" }, "browserslist": { "production": [ @@ -49,6 +54,6 @@ ] }, "engines": { - "node": ">=16.14" + "node": ">=18-0" } } diff --git a/docs/scripts/setStable.js b/docs/scripts/setStable.ts similarity index 83% rename from docs/scripts/setStable.js rename to docs/scripts/setStable.ts index 4bbe283f4be..e23d990763a 100644 --- a/docs/scripts/setStable.js +++ b/docs/scripts/setStable.ts @@ -1,22 +1,18 @@ -/* eslint-disable */ const fs = require('fs'); const path = require('path'); const axios = require('axios'); -const { release } = require('os'); const IGNORE_VERSIONS = ['0.16.0']; const NUMBER_OF_VERSIONS_TO_SHOW = 4; async function main() { - const versionsFile = path.join(__dirname, '../versions.json'); + const versionsFile = path.resolve('../versions.json'); const axiosOpts = { params: { per_page: 100 }, + headers: {}, }; - console.log(process.env.GITHUB_TOKEN); - // cool if you have a GITHUB_TOKEN because of rate limiting - // but fine if you don't if (process.env.GITHUB_TOKEN) axiosOpts.headers = { Authorization: `token ${process.env.GITHUB_TOKEN}` }; const { data } = await axios.get('https://api.github.com/repos/noir-lang/noir/releases', axiosOpts); diff --git a/docs/sidebars.js b/docs/sidebars.js index 3fd391cf09c..fba1c9ae1e7 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -1,145 +1,81 @@ -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ - -// @ts-check - /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const sidebars = { +export default { sidebar: [ { type: 'doc', id: 'index', - label: 'Noir', }, { type: 'category', label: 'Getting Started', - items: [{ type: 'autogenerated', dirName: 'getting_started' }], - }, - { - type: 'category', - label: 'Examples', - items: [{ type: 'autogenerated', dirName: 'examples' }], - }, - { - type: 'category', - label: 'Nargo', - items: [{ type: 'autogenerated', dirName: 'nargo' }], - }, - { - type: 'category', - label: 'Language Concepts', items: [ { - type: 'category', - label: 'Data Types', - link: { - type: 'doc', - id: 'language_concepts/data_types', - }, - items: [ - { - type: 'autogenerated', - dirName: 'language_concepts/data_types', - }, - ], + type: 'autogenerated', + dirName: 'getting_started', }, - 'language_concepts/functions', - 'language_concepts/control_flow', - 'language_concepts/ops', - 'language_concepts/assert', - 'language_concepts/unconstrained', - 'language_concepts/generics', - 'language_concepts/mutability', - 'language_concepts/lambdas', - 'language_concepts/comments', - 'language_concepts/distinct', - 'language_concepts/shadowing', ], }, { type: 'category', - label: 'Noir Standard Library', + label: 'The Noir Language', items: [ { type: 'category', - label: 'Cryptographic Primitives', - link: { - type: 'doc', - id: 'standard_library/cryptographic_primitives', - }, + label: 'Language Concepts', items: [ { type: 'autogenerated', - dirName: 'standard_library/cryptographic_primitives', + dirName: 'explanations/00_noir', }, ], }, - 'standard_library/recursion', - 'standard_library/logging', - 'standard_library/merkle_trees', - 'standard_library/zeroed', - 'standard_library/black_box_fns', - 'standard_library/options', - ], - }, - { - type: 'category', - label: 'Modules, Packages and Crates', - items: [{ type: 'autogenerated', dirName: 'modules_packages_crates' }], - }, - { - type: 'category', - label: 'NoirJS', - link: { - type: 'doc', - id: 'noir_js/noir_js', - }, - items: [ { type: 'category', - label: 'Guides', + label: 'Standard Library', items: [ { type: 'autogenerated', - dirName: 'noir_js/getting_started', + dirName: 'explanations/01_standard_library', }, ], }, { type: 'category', - label: 'Reference', + label: 'Modules, Packages and Crates', items: [ { - type: 'category', - label: 'Noir JS', - link: { - type: 'doc', - id: 'noir_js/reference/noir_js/index', - }, - items: require('./docs/noir_js/reference/noir_js/typedoc-sidebar.cjs'), - }, - { - type: 'category', - label: 'Backend Barretenberg', - link: { - type: 'doc', - id: 'noir_js/reference/backend_barretenberg/index', - }, - items: require('./docs/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs'), + type: 'autogenerated', + dirName: 'explanations/02_modules_packages_crates', }, ], }, ], }, + { + type: 'category', + label: 'How To Guides', + items: [ + { + type: 'autogenerated', + dirName: 'how_to', + }, + ], + }, + { + type: 'category', + label: 'Tutorials', + items: [ + { + type: 'autogenerated', + dirName: 'tutorials', + }, + ], + }, + { + type: 'category', + label: 'Reference', + items: [{ type: 'autogenerated', dirName: 'reference' }], + }, { type: 'doc', id: 'migration_notes', @@ -147,5 +83,3 @@ const sidebars = { }, ], }; - -module.exports = sidebars; diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 00000000000..01b56ec5988 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": "." + }, +} diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md index de30869732d..dc412cdc6fa 100644 --- a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [TypeScript](../typescr ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation @@ -275,11 +275,4 @@ If you installed Noir with Nix or from source, you can remove the binary located rm ~/.nix-profile/bin/nargo ``` -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install [noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.10.5/index.md b/docs/versioned_docs/version-v0.10.5/index.md index e56b24bccd8..028df708bd5 100644 --- a/docs/versioned_docs/version-v0.10.5/index.md +++ b/docs/versioned_docs/version-v0.10.5/index.md @@ -71,7 +71,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md index 4ff5fc46334..f4ca361d3c4 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md index 9ebe1d54944..ddbee58f6e4 100644 --- a/docs/versioned_docs/version-v0.17.0/index.md +++ b/docs/versioned_docs/version-v0.17.0/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.17.0/migration_notes.md b/docs/versioned_docs/version-v0.17.0/migration_notes.md index 48a8abcf22e..69782cba388 100644 --- a/docs/versioned_docs/version-v0.17.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.17.0/migration_notes.md @@ -70,7 +70,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md index d9e5a0c6115..11fef2bf8b5 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md @@ -74,8 +74,8 @@ async execute(inputs) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `witness` | Promise | The witness | -| `returnValue` | Promise | The return value | +| `witness` | Promise \ | The witness | +| `returnValue` | Promise \ | The return value | ### Usage @@ -103,7 +103,7 @@ async generateFinalproof(input) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof. | +| `proof` | Promise \ | An array with the byte representation of the proof. | ### Usage @@ -133,7 +133,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md index 21c2ff32b57..f444eab1772 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md @@ -70,7 +70,7 @@ async generateFinalProof(decompressedWitness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the final proof. | +| `proof` | Promise\ | An array with the byte representation of the final proof. | ### Usage @@ -98,7 +98,7 @@ async generateIntermediateProof(witness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the intermediate proof | +| `proof` | Promise\ | An array with the byte representation of the intermediate proof | ### Usage @@ -127,7 +127,7 @@ async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) | Return value | Type | Description | | ------------ | -------------------- | -------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof | +| `proof` | Promise\ | An array with the byte representation of the proof | ### Usage @@ -186,7 +186,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage @@ -214,7 +214,7 @@ async verifyIntermediateProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md index 725c5f4d373..349756d60c0 100644 --- a/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.0/index.md b/docs/versioned_docs/version-v0.19.0/index.md index 75e1abf2932..4e2f4043892 100644 --- a/docs/versioned_docs/version-v0.19.0/index.md +++ b/docs/versioned_docs/version-v0.19.0/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.0/migration_notes.md b/docs/versioned_docs/version-v0.19.0/migration_notes.md index e87eb1feaba..0d7e0af0efd 100644 --- a/docs/versioned_docs/version-v0.19.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.0/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md index 0d6d5abbbff..ccdd53f2bcc 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md @@ -77,8 +77,8 @@ async execute(inputs, foreignCallHandler) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `witness` | Promise | The witness | -| `returnValue` | Promise | The return value | +| `witness` | Promise \ | The witness | +| `returnValue` | Promise \ | The return value | ### Usage @@ -107,7 +107,7 @@ async generateFinalproof(input) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof. | +| `proof` | Promise \ | An array with the byte representation of the proof. | ### Usage @@ -137,7 +137,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md index 21c2ff32b57..f444eab1772 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md @@ -70,7 +70,7 @@ async generateFinalProof(decompressedWitness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the final proof. | +| `proof` | Promise\ | An array with the byte representation of the final proof. | ### Usage @@ -98,7 +98,7 @@ async generateIntermediateProof(witness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the intermediate proof | +| `proof` | Promise\ | An array with the byte representation of the intermediate proof | ### Usage @@ -127,7 +127,7 @@ async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) | Return value | Type | Description | | ------------ | -------------------- | -------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof | +| `proof` | Promise\ | An array with the byte representation of the proof | ### Usage @@ -186,7 +186,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage @@ -214,7 +214,7 @@ async verifyIntermediateProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md index 725c5f4d373..349756d60c0 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md index 75e1abf2932..4e2f4043892 100644 --- a/docs/versioned_docs/version-v0.19.1/index.md +++ b/docs/versioned_docs/version-v0.19.1/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.1/migration_notes.md b/docs/versioned_docs/version-v0.19.1/migration_notes.md index e87eb1feaba..0d7e0af0efd 100644 --- a/docs/versioned_docs/version-v0.19.1/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.1/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md index 725c5f4d373..349756d60c0 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md index 75e1abf2932..4e2f4043892 100644 --- a/docs/versioned_docs/version-v0.19.2/index.md +++ b/docs/versioned_docs/version-v0.19.2/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.2/migration_notes.md b/docs/versioned_docs/version-v0.19.2/migration_notes.md index e87eb1feaba..0d7e0af0efd 100644 --- a/docs/versioned_docs/version-v0.19.2/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.2/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md index 725c5f4d373..349756d60c0 100644 --- a/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.3/index.md b/docs/versioned_docs/version-v0.19.3/index.md index 75e1abf2932..4e2f4043892 100644 --- a/docs/versioned_docs/version-v0.19.3/index.md +++ b/docs/versioned_docs/version-v0.19.3/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.3/migration_notes.md b/docs/versioned_docs/version-v0.19.3/migration_notes.md index e87eb1feaba..0d7e0af0efd 100644 --- a/docs/versioned_docs/version-v0.19.3/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.3/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md index 725c5f4d373..349756d60c0 100644 --- a/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.4/index.md b/docs/versioned_docs/version-v0.19.4/index.md index 75e1abf2932..4e2f4043892 100644 --- a/docs/versioned_docs/version-v0.19.4/index.md +++ b/docs/versioned_docs/version-v0.19.4/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md index 658a0441ffb..78d3d2af166 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.4/migration_notes.md b/docs/versioned_docs/version-v0.19.4/migration_notes.md index e87eb1feaba..0d7e0af0efd 100644 --- a/docs/versioned_docs/version-v0.19.4/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.4/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md index 432884b709e..76f7701ba55 100644 --- a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [TypeScript](../typescr ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation @@ -211,6 +211,7 @@ Now that your environment is set up, you can get to work on the project. ```sh git clone git@github.com:noir-lang/noir ``` + > Replacing `noir` with whichever repository you want to work on. 2. Navigate to the directory: @@ -218,9 +219,10 @@ git clone git@github.com:noir-lang/noir ```sh cd noir ``` + > Replacing `noir` with whichever repository you cloned. -3. You should see a __direnv error__ because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: ```sh direnv allow @@ -272,12 +274,5 @@ If you installed Noir with Nix or from source, you can remove the binary located rm ~/.nix-profile/bin/nargo ``` -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install [noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.noir-programming-language-syntax-highlighter -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md index d08df2094a5..2e374e0bf88 100644 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md @@ -28,11 +28,11 @@ keywords: | / | Divides two private input types together | Types must be private input | | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md index 7cea9846102..3ecf043033c 100644 --- a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md +++ b/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md @@ -142,7 +142,7 @@ fn main() { ## sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md index fb86a966e75..868ceffd989 100644 --- a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [TypeScript](../typescr ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation @@ -274,11 +274,4 @@ If you installed Noir with Nix or from source, you can remove the binary located rm ~/.nix-profile/bin/nargo ``` -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install [noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.7.1/index.md b/docs/versioned_docs/version-v0.7.1/index.md index e56b24bccd8..028df708bd5 100644 --- a/docs/versioned_docs/version-v0.7.1/index.md +++ b/docs/versioned_docs/version-v0.7.1/index.md @@ -71,7 +71,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md index 4d1cdc953e9..dedeea4cd9a 100644 --- a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md +++ b/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md @@ -142,7 +142,7 @@ fn main() { ## sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md index de30869732d..dc412cdc6fa 100644 --- a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [TypeScript](../typescr ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation @@ -275,11 +275,4 @@ If you installed Noir with Nix or from source, you can remove the binary located rm ~/.nix-profile/bin/nargo ``` -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install [noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.9.0/index.md b/docs/versioned_docs/version-v0.9.0/index.md index e56b24bccd8..028df708bd5 100644 --- a/docs/versioned_docs/version-v0.9.0/index.md +++ b/docs/versioned_docs/version-v0.9.0/index.md @@ -71,7 +71,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md index da02b126059..d5caa463765 100644 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md index 4d1cdc953e9..dedeea4cd9a 100644 --- a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md +++ b/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md @@ -142,7 +142,7 @@ fn main() { ## sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versions.json b/docs/versions.json index 1e6583b2b13..7e140c94b73 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,6 +1,4 @@ [ "v0.19.4", - "v0.19.3", - "v0.19.2", - "v0.19.1" -] \ No newline at end of file + "v0.17.0" +] diff --git a/versions.json b/versions.json new file mode 100644 index 00000000000..a1c826264f4 --- /dev/null +++ b/versions.json @@ -0,0 +1,4 @@ +[ + "v0.19.4", + "v0.17.0" +] \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 22ad5ac50ce..7454ec947c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -276,7 +276,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.18.6, @babel/core@npm:^7.19.6": +"@babel/core@npm:^7.18.6, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.3": version: 7.23.5 resolution: "@babel/core@npm:7.23.5" dependencies: @@ -299,7 +299,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.12.5, @babel/generator@npm:^7.18.7, @babel/generator@npm:^7.23.5": +"@babel/generator@npm:^7.12.5, @babel/generator@npm:^7.18.7, @babel/generator@npm:^7.23.3, @babel/generator@npm:^7.23.5": version: 7.23.5 resolution: "@babel/generator@npm:7.23.5" dependencies: @@ -578,7 +578,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.12.7, @babel/parser@npm:^7.18.8, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": +"@babel/parser@npm:^7.12.7, @babel/parser@npm:^7.18.8, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.5": version: 7.23.5 resolution: "@babel/parser@npm:7.23.5" bin: @@ -1414,7 +1414,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:^7.18.6": +"@babel/plugin-transform-runtime@npm:^7.18.6, @babel/plugin-transform-runtime@npm:^7.22.9": version: 7.23.4 resolution: "@babel/plugin-transform-runtime@npm:7.23.4" dependencies: @@ -1547,7 +1547,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:^7.18.6, @babel/preset-env@npm:^7.19.4": +"@babel/preset-env@npm:^7.18.6, @babel/preset-env@npm:^7.19.4, @babel/preset-env@npm:^7.22.9": version: 7.23.5 resolution: "@babel/preset-env@npm:7.23.5" dependencies: @@ -1650,7 +1650,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-react@npm:^7.18.6": +"@babel/preset-react@npm:^7.18.6, @babel/preset-react@npm:^7.22.5": version: 7.23.3 resolution: "@babel/preset-react@npm:7.23.3" dependencies: @@ -1666,7 +1666,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.18.6": +"@babel/preset-typescript@npm:^7.18.6, @babel/preset-typescript@npm:^7.22.5": version: 7.23.3 resolution: "@babel/preset-typescript@npm:7.23.3" dependencies: @@ -1688,7 +1688,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime-corejs3@npm:^7.18.6": +"@babel/runtime-corejs3@npm:^7.18.6, @babel/runtime-corejs3@npm:^7.22.6": version: 7.23.5 resolution: "@babel/runtime-corejs3@npm:7.23.5" dependencies: @@ -1698,7 +1698,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.8.4": +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.8.4": version: 7.23.5 resolution: "@babel/runtime@npm:7.23.5" dependencies: @@ -1718,7 +1718,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.18.8, @babel/traverse@npm:^7.23.5": +"@babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.18.8, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.5": version: 7.23.5 resolution: "@babel/traverse@npm:7.23.5" dependencies: @@ -1823,7 +1823,7 @@ __metadata: languageName: node linkType: hard -"@docsearch/react@npm:^3.1.1": +"@docsearch/react@npm:^3.5.2": version: 3.5.2 resolution: "@docsearch/react@npm:3.5.2" dependencies: @@ -1849,7 +1849,7 @@ __metadata: languageName: node linkType: hard -"@docusaurus/core@npm:2.4.3, @docusaurus/core@npm:^2.4.0": +"@docusaurus/core@npm:2.4.3": version: 2.4.3 resolution: "@docusaurus/core@npm:2.4.3" dependencies: @@ -1933,6 +1933,88 @@ __metadata: languageName: node linkType: hard +"@docusaurus/core@npm:3.0.1, @docusaurus/core@npm:^3.0.1": + version: 3.0.1 + resolution: "@docusaurus/core@npm:3.0.1" + dependencies: + "@babel/core": ^7.23.3 + "@babel/generator": ^7.23.3 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-transform-runtime": ^7.22.9 + "@babel/preset-env": ^7.22.9 + "@babel/preset-react": ^7.22.5 + "@babel/preset-typescript": ^7.22.5 + "@babel/runtime": ^7.22.6 + "@babel/runtime-corejs3": ^7.22.6 + "@babel/traverse": ^7.22.8 + "@docusaurus/cssnano-preset": 3.0.1 + "@docusaurus/logger": 3.0.1 + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/react-loadable": 5.5.2 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-common": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + "@slorber/static-site-generator-webpack-plugin": ^4.0.7 + "@svgr/webpack": ^6.5.1 + autoprefixer: ^10.4.14 + babel-loader: ^9.1.3 + babel-plugin-dynamic-import-node: ^2.3.3 + boxen: ^6.2.1 + chalk: ^4.1.2 + chokidar: ^3.5.3 + clean-css: ^5.3.2 + cli-table3: ^0.6.3 + combine-promises: ^1.1.0 + commander: ^5.1.0 + copy-webpack-plugin: ^11.0.0 + core-js: ^3.31.1 + css-loader: ^6.8.1 + css-minimizer-webpack-plugin: ^4.2.2 + cssnano: ^5.1.15 + del: ^6.1.1 + detect-port: ^1.5.1 + escape-html: ^1.0.3 + eta: ^2.2.0 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + html-minifier-terser: ^7.2.0 + html-tags: ^3.3.1 + html-webpack-plugin: ^5.5.3 + leven: ^3.1.0 + lodash: ^4.17.21 + mini-css-extract-plugin: ^2.7.6 + postcss: ^8.4.26 + postcss-loader: ^7.3.3 + prompts: ^2.4.2 + react-dev-utils: ^12.0.1 + react-helmet-async: ^1.3.0 + react-loadable: "npm:@docusaurus/react-loadable@5.5.2" + react-loadable-ssr-addon-v5-slorber: ^1.0.1 + react-router: ^5.3.4 + react-router-config: ^5.1.1 + react-router-dom: ^5.3.4 + rtl-detect: ^1.0.4 + semver: ^7.5.4 + serve-handler: ^6.1.5 + shelljs: ^0.8.5 + terser-webpack-plugin: ^5.3.9 + tslib: ^2.6.0 + update-notifier: ^6.0.2 + url-loader: ^4.1.1 + webpack: ^5.88.1 + webpack-bundle-analyzer: ^4.9.0 + webpack-dev-server: ^4.15.1 + webpack-merge: ^5.9.0 + webpackbar: ^5.0.2 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + bin: + docusaurus: bin/docusaurus.mjs + checksum: 56767f7e629edce4d23c19403abf4039daeea25db20c695fb7c3a1ce04a90f182f14ea1f70286afb221b8c1593823ebb0d28cbc2ca5d9d38d707a0338d544f64 + languageName: node + linkType: hard + "@docusaurus/cssnano-preset@npm:2.4.3": version: 2.4.3 resolution: "@docusaurus/cssnano-preset@npm:2.4.3" @@ -1945,6 +2027,18 @@ __metadata: languageName: node linkType: hard +"@docusaurus/cssnano-preset@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/cssnano-preset@npm:3.0.1" + dependencies: + cssnano-preset-advanced: ^5.3.10 + postcss: ^8.4.26 + postcss-sort-media-queries: ^4.4.1 + tslib: ^2.6.0 + checksum: 3a04606d362c84398a5af9a98de4995958e2705086af83388479feaa157cbe3164281006e64036f9337e96b0cec62bd1362fc0f910075e6eeec930f0a519801d + languageName: node + linkType: hard + "@docusaurus/logger@npm:2.4.3": version: 2.4.3 resolution: "@docusaurus/logger@npm:2.4.3" @@ -1955,6 +2049,16 @@ __metadata: languageName: node linkType: hard +"@docusaurus/logger@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/logger@npm:3.0.1" + dependencies: + chalk: ^4.1.2 + tslib: ^2.6.0 + checksum: 4d4ffcd08f9c76c105d2d2b95974f5c33941e5346c5de1b19ee3f55a4f5011bb7db3875349e25da02750cea5fb357ba00be271ea24368c75b8e29189d04e9f7c + languageName: node + linkType: hard + "@docusaurus/mdx-loader@npm:2.4.3": version: 2.4.3 resolution: "@docusaurus/mdx-loader@npm:2.4.3" @@ -1983,7 +2087,44 @@ __metadata: languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:2.4.3, @docusaurus/module-type-aliases@npm:^2.4.0": +"@docusaurus/mdx-loader@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/mdx-loader@npm:3.0.1" + dependencies: + "@babel/parser": ^7.22.7 + "@babel/traverse": ^7.22.8 + "@docusaurus/logger": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + "@mdx-js/mdx": ^3.0.0 + "@slorber/remark-comment": ^1.0.0 + escape-html: ^1.0.3 + estree-util-value-to-estree: ^3.0.1 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + image-size: ^1.0.2 + mdast-util-mdx: ^3.0.0 + mdast-util-to-string: ^4.0.0 + rehype-raw: ^7.0.0 + remark-directive: ^3.0.0 + remark-emoji: ^4.0.0 + remark-frontmatter: ^5.0.0 + remark-gfm: ^4.0.0 + stringify-object: ^3.3.0 + tslib: ^2.6.0 + unified: ^11.0.3 + unist-util-visit: ^5.0.0 + url-loader: ^4.1.1 + vfile: ^6.0.1 + webpack: ^5.88.1 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 8ba9774cd2cc7216f645d54a6f6f6cba34e39e371f0de09e56f60a27dde95a8e42ab92cf0a6f384dce01960c68a1e720868c56b6aa8929d23bafe9f523941151 + languageName: node + linkType: hard + +"@docusaurus/module-type-aliases@npm:2.4.3": version: 2.4.3 resolution: "@docusaurus/module-type-aliases@npm:2.4.3" dependencies: @@ -2002,34 +2143,80 @@ __metadata: languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/plugin-content-blog@npm:2.4.3" +"@docusaurus/module-type-aliases@npm:3.0.1, @docusaurus/module-type-aliases@npm:^3.0.1": + version: 3.0.1 + resolution: "@docusaurus/module-type-aliases@npm:3.0.1" dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/logger": 2.4.3 - "@docusaurus/mdx-loader": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-common": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 + "@docusaurus/react-loadable": 5.5.2 + "@docusaurus/types": 3.0.1 + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router-config": "*" + "@types/react-router-dom": "*" + react-helmet-async: "*" + react-loadable: "npm:@docusaurus/react-loadable@5.5.2" + peerDependencies: + react: "*" + react-dom: "*" + checksum: 08895f8b100df772bb9c9a8fcf9cd3ee83f0deafeb76fb9b14efd5cdd3313abb4a02032868bd458cb3a5f345942fd9f4c44833ce5042279b2241d462a1bf4cc2 + languageName: node + linkType: hard + +"@docusaurus/plugin-content-blog@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-content-blog@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/logger": 3.0.1 + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-common": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 - fs-extra: ^10.1.0 + fs-extra: ^11.1.1 lodash: ^4.17.21 reading-time: ^1.5.0 - tslib: ^2.4.0 - unist-util-visit: ^2.0.3 + srcset: ^4.0.0 + tslib: ^2.6.0 + unist-util-visit: ^5.0.0 utility-types: ^3.10.0 - webpack: ^5.73.0 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 9fd41331c609b9488eea363e617e3763a814c75f83eb1b858cef402a0f5b96f67a342e25ff8c333489e550eb4d379eae09a88b986a97c25170fe203662e2f1ae + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 20985fac48d2f77d560483d06d8fc21ea8c3a009be8d040da76bd4363279ad7fe8f98353bc6a50504403be3315508344faa62123ac3691912d27710fe3c6ec90 + languageName: node + linkType: hard + +"@docusaurus/plugin-content-docs@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-content-docs@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/logger": 3.0.1 + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/module-type-aliases": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + "@types/react-router-config": ^5.0.7 + combine-promises: ^1.1.0 + fs-extra: ^11.1.1 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + tslib: ^2.6.0 + utility-types: ^3.10.0 + webpack: ^5.88.1 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: ee3a12a49df2db112798e8d080365c9cc2afc4959f28772abe03eb9c806b919a9837669354b04a1ff99bf473cab1aa3b8b6ad740947a440a6b9cae09823ef6b2 languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:2.4.3, @docusaurus/plugin-content-docs@npm:^2.0.0-rc.1": +"@docusaurus/plugin-content-docs@npm:^2.0.0-rc.1": version: 2.4.3 resolution: "@docusaurus/plugin-content-docs@npm:2.4.3" dependencies: @@ -2056,128 +2243,129 @@ __metadata: languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:2.4.3, @docusaurus/plugin-content-pages@npm:^2.4.0": - version: 2.4.3 - resolution: "@docusaurus/plugin-content-pages@npm:2.4.3" - dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/mdx-loader": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - fs-extra: ^10.1.0 - tslib: ^2.4.0 - webpack: ^5.73.0 +"@docusaurus/plugin-content-pages@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-content-pages@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + fs-extra: ^11.1.1 + tslib: ^2.6.0 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 00439c2e1a1f345cd549739db13a3610b6d9f7ffa6cf7507ad6ac1f3c8d24041947acc2a446be7edf1a613cf354a50d1133aa28ddf64a0eff6ed8a31bf1a542f + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 0a3bd568e4b9df11b5926c5be10f2ced08b241f1a6b8a08f556c57ce707ebb788b19937ec1d884474c4e275dc71affb91dd55a2965ad02a03545e3eae4976141 languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/plugin-debug@npm:2.4.3" +"@docusaurus/plugin-debug@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-debug@npm:3.0.1" dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils": 2.4.3 - fs-extra: ^10.1.0 - react-json-view: ^1.21.3 - tslib: ^2.4.0 + "@docusaurus/core": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + fs-extra: ^11.1.1 + react-json-view-lite: ^1.2.0 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 88955828b72e463e04501cc6bedf802208e377ae0f4d72735625bcbb47918afc4f2588355c6914064cfdbe4945d3da6473ce76319aa1f66dd975b3b43c4c39b0 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 419f2bb61aceca70ffbba03e5e885303cea72055a41328d09d78fa2e40e7d5feb0ee4d66f056d54ac01f8d2361e890a072da6570da16f290c84746ced1582823 languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/plugin-google-analytics@npm:2.4.3" +"@docusaurus/plugin-google-analytics@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-google-analytics@npm:3.0.1" dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - tslib: ^2.4.0 + "@docusaurus/core": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 6e30de6b5c479493614a5552a295f07ffb9c83f3740a68c7d4dbac378b8288da7430f26cdc246d763855c6084ad86a6f87286e6c8b40f4817794bb1a04e109ea + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 850930ed0860411142fe058562040f0b3a776be755670790273f48bfa37c7ee904d9107ec23d2ce210904610b72769ce0996a558c89414ac3687bd38bb50edf4 languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:2.4.3, @docusaurus/plugin-google-gtag@npm:^2.4.0": - version: 2.4.3 - resolution: "@docusaurus/plugin-google-gtag@npm:2.4.3" +"@docusaurus/plugin-google-gtag@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-google-gtag@npm:3.0.1" dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - tslib: ^2.4.0 + "@docusaurus/core": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + "@types/gtag.js": ^0.0.12 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 4aaac4d262b3bb7fc3f16620c5329b90db92bf28361ced54f2945fc0e4669483e2f36b076332e0ee9d11b6233cd2c81ca35c953119bad42171e62571c1692d6a + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 579a19a6dad3940801a170efc7e5c763c7f90b68d5ecdb2707b61311af321122e84cd0bb5ceb45669e76df712ea1747d6d30fa5a0574b69a7f337dd66b346a04 languageName: node linkType: hard -"@docusaurus/plugin-google-tag-manager@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/plugin-google-tag-manager@npm:2.4.3" +"@docusaurus/plugin-google-tag-manager@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-google-tag-manager@npm:3.0.1" dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - tslib: ^2.4.0 + "@docusaurus/core": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: c3af89b4d41fab463d853cbfbe8f43d384f702dd09fd914fffcca01fdf94c282d1b98d762c9142fe21f6471f5dd643679e8d11344c95fdf6657aff0618c3c7a5 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 1e3faf9496f75d43a81a5ff2921e783c87ef13d852cf678b54275fa0f79d70efdc127df6ae9c90ddce58b81384f39ec62de75d7e64e34ae96ea938cf234268c0 languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/plugin-sitemap@npm:2.4.3" - dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/logger": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-common": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - fs-extra: ^10.1.0 +"@docusaurus/plugin-sitemap@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/plugin-sitemap@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/logger": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-common": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + fs-extra: ^11.1.1 sitemap: ^7.1.1 - tslib: ^2.4.0 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: cf96b9f0e32cefa58e37a4bc2f0a112ea657f06faf47b780ec2ba39d5e2daca6486a73f3b376c56ad3bb42f3f0c3f70a783f1ce1964b74e2ba273e6f439e439b + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 464359fa44143f3e686d02cd70f86741cdd4a74f29f212b83767617fc1dacbfddfa4321c16e0c253849ff41a75078fabbfdf8637d7a141fb1a0354360db2b2bb languageName: node linkType: hard -"@docusaurus/preset-classic@npm:^2.4.0": - version: 2.4.3 - resolution: "@docusaurus/preset-classic@npm:2.4.3" - dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/plugin-content-blog": 2.4.3 - "@docusaurus/plugin-content-docs": 2.4.3 - "@docusaurus/plugin-content-pages": 2.4.3 - "@docusaurus/plugin-debug": 2.4.3 - "@docusaurus/plugin-google-analytics": 2.4.3 - "@docusaurus/plugin-google-gtag": 2.4.3 - "@docusaurus/plugin-google-tag-manager": 2.4.3 - "@docusaurus/plugin-sitemap": 2.4.3 - "@docusaurus/theme-classic": 2.4.3 - "@docusaurus/theme-common": 2.4.3 - "@docusaurus/theme-search-algolia": 2.4.3 - "@docusaurus/types": 2.4.3 +"@docusaurus/preset-classic@npm:^3.0.1": + version: 3.0.1 + resolution: "@docusaurus/preset-classic@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/plugin-content-blog": 3.0.1 + "@docusaurus/plugin-content-docs": 3.0.1 + "@docusaurus/plugin-content-pages": 3.0.1 + "@docusaurus/plugin-debug": 3.0.1 + "@docusaurus/plugin-google-analytics": 3.0.1 + "@docusaurus/plugin-google-gtag": 3.0.1 + "@docusaurus/plugin-google-tag-manager": 3.0.1 + "@docusaurus/plugin-sitemap": 3.0.1 + "@docusaurus/theme-classic": 3.0.1 + "@docusaurus/theme-common": 3.0.1 + "@docusaurus/theme-search-algolia": 3.0.1 + "@docusaurus/types": 3.0.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: a321badc44696adf4ab2d4a5d6c93f595e8c17988aec9609d325928a1d60f5e0205b23fe849b28ddaed24f7935829e86c402f6b761d6e65db4224270b9dd443c + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 03e75324c92a70aea9980f29a993e79967e5ca85d2db1b18bcb00e6c3d8711fec1a1728f92247d4d35a119ae5c3fb5b5d728ea33591f36e8bd43fa6acb1c791c languageName: node linkType: hard @@ -2193,97 +2381,106 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/theme-classic@npm:2.4.3" - dependencies: - "@docusaurus/core": 2.4.3 - "@docusaurus/mdx-loader": 2.4.3 - "@docusaurus/module-type-aliases": 2.4.3 - "@docusaurus/plugin-content-blog": 2.4.3 - "@docusaurus/plugin-content-docs": 2.4.3 - "@docusaurus/plugin-content-pages": 2.4.3 - "@docusaurus/theme-common": 2.4.3 - "@docusaurus/theme-translations": 2.4.3 - "@docusaurus/types": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-common": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - "@mdx-js/react": ^1.6.22 - clsx: ^1.2.1 - copy-text-to-clipboard: ^3.0.1 +"@docusaurus/theme-classic@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/theme-classic@npm:3.0.1" + dependencies: + "@docusaurus/core": 3.0.1 + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/module-type-aliases": 3.0.1 + "@docusaurus/plugin-content-blog": 3.0.1 + "@docusaurus/plugin-content-docs": 3.0.1 + "@docusaurus/plugin-content-pages": 3.0.1 + "@docusaurus/theme-common": 3.0.1 + "@docusaurus/theme-translations": 3.0.1 + "@docusaurus/types": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-common": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + "@mdx-js/react": ^3.0.0 + clsx: ^2.0.0 + copy-text-to-clipboard: ^3.2.0 infima: 0.2.0-alpha.43 lodash: ^4.17.21 nprogress: ^0.2.0 - postcss: ^8.4.14 - prism-react-renderer: ^1.3.5 - prismjs: ^1.28.0 - react-router-dom: ^5.3.3 - rtlcss: ^3.5.0 - tslib: ^2.4.0 + postcss: ^8.4.26 + prism-react-renderer: ^2.3.0 + prismjs: ^1.29.0 + react-router-dom: ^5.3.4 + rtlcss: ^4.1.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 215b7fa416f40ce68773265a168af47fa770583ebe33ec7b34c7e082dfe7c79252b589a6b26532cb0ab7dd089611a9cd0e20c94df097be320a227b98e3b3fbb8 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 86cef28b5f93d01f15cb134283b8d1006466d661cc39c09c585e56a6a98b09816f8e7cef24b164e8a378b6deb4ed8984fdc329d09fdcbe83fa51529091ccfad8 languageName: node linkType: hard -"@docusaurus/theme-common@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/theme-common@npm:2.4.3" - dependencies: - "@docusaurus/mdx-loader": 2.4.3 - "@docusaurus/module-type-aliases": 2.4.3 - "@docusaurus/plugin-content-blog": 2.4.3 - "@docusaurus/plugin-content-docs": 2.4.3 - "@docusaurus/plugin-content-pages": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-common": 2.4.3 +"@docusaurus/theme-common@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/theme-common@npm:3.0.1" + dependencies: + "@docusaurus/mdx-loader": 3.0.1 + "@docusaurus/module-type-aliases": 3.0.1 + "@docusaurus/plugin-content-blog": 3.0.1 + "@docusaurus/plugin-content-docs": 3.0.1 + "@docusaurus/plugin-content-pages": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-common": 3.0.1 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" - clsx: ^1.2.1 + clsx: ^2.0.0 parse-numeric-range: ^1.3.0 - prism-react-renderer: ^1.3.5 - tslib: ^2.4.0 - use-sync-external-store: ^1.2.0 + prism-react-renderer: ^2.3.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 76817f548705542124d708c804e724674ec9bf996a5cb2a5c9a2919416367567cca4a3fa6055589990c339f6e1fb9d3944e25ed30b79fabe191db00d6ef986ca + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 99fb138fd2fb499d53ee81ae717768b5cb6556ddd337b6d1a399815cb428eed2c04d2823e2040fd4db27bc79681f6333ac1ea78d760ff7fc4475d16d1790552a languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:2.4.3": - version: 2.4.3 - resolution: "@docusaurus/theme-search-algolia@npm:2.4.3" - dependencies: - "@docsearch/react": ^3.1.1 - "@docusaurus/core": 2.4.3 - "@docusaurus/logger": 2.4.3 - "@docusaurus/plugin-content-docs": 2.4.3 - "@docusaurus/theme-common": 2.4.3 - "@docusaurus/theme-translations": 2.4.3 - "@docusaurus/utils": 2.4.3 - "@docusaurus/utils-validation": 2.4.3 - algoliasearch: ^4.13.1 - algoliasearch-helper: ^3.10.0 - clsx: ^1.2.1 - eta: ^2.0.0 - fs-extra: ^10.1.0 +"@docusaurus/theme-search-algolia@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/theme-search-algolia@npm:3.0.1" + dependencies: + "@docsearch/react": ^3.5.2 + "@docusaurus/core": 3.0.1 + "@docusaurus/logger": 3.0.1 + "@docusaurus/plugin-content-docs": 3.0.1 + "@docusaurus/theme-common": 3.0.1 + "@docusaurus/theme-translations": 3.0.1 + "@docusaurus/utils": 3.0.1 + "@docusaurus/utils-validation": 3.0.1 + algoliasearch: ^4.18.0 + algoliasearch-helper: ^3.13.3 + clsx: ^2.0.0 + eta: ^2.2.0 + fs-extra: ^11.1.1 lodash: ^4.17.21 - tslib: ^2.4.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 665d244c25bff21dd45c983c9b85f9827d2dd58945b802d645370b5e7092820532faf488c0bc0ce88e8fc0088c7f56eb9abb96589cf3857372c1b61bba6cbed7 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 24a38dbd7085ea78c412e50c94dda7e0ecb80046dd18c1fdb515d81b21be5cdbc706705a5155600510b0814698abb234885a576d90e0db9cf3c5983d0bf51462 + languageName: node + linkType: hard + +"@docusaurus/theme-translations@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/theme-translations@npm:3.0.1" + dependencies: + fs-extra: ^11.1.1 + tslib: ^2.6.0 + checksum: a1df314ddaeb7f453867c5ee5424b36d31c6d6541f86b3927881b77333e997b87e720c0285f3be507283cb851537ff154ce0ddbd5e771c184c8aa10af721d7c2 languageName: node linkType: hard -"@docusaurus/theme-translations@npm:2.4.3, @docusaurus/theme-translations@npm:^2.0.0-rc.1": +"@docusaurus/theme-translations@npm:^2.0.0-rc.1": version: 2.4.3 resolution: "@docusaurus/theme-translations@npm:2.4.3" dependencies: @@ -2293,6 +2490,13 @@ __metadata: languageName: node linkType: hard +"@docusaurus/tsconfig@npm:^3.0.1": + version: 3.0.1 + resolution: "@docusaurus/tsconfig@npm:3.0.1" + checksum: a191e527740ea09cc4783ab45f106989f692d100e83768a4398fc08d3d41f0645afdce83aa89a1b251d5899544105af09e795af4d0db54247403a180f3c43098 + languageName: node + linkType: hard + "@docusaurus/types@npm:2.4.3, @docusaurus/types@npm:^2.4.1": version: 2.4.3 resolution: "@docusaurus/types@npm:2.4.3" @@ -2312,6 +2516,25 @@ __metadata: languageName: node linkType: hard +"@docusaurus/types@npm:3.0.1, @docusaurus/types@npm:^3.0.1": + version: 3.0.1 + resolution: "@docusaurus/types@npm:3.0.1" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + commander: ^5.1.0 + joi: ^17.9.2 + react-helmet-async: ^1.3.0 + utility-types: ^3.10.0 + webpack: ^5.88.1 + webpack-merge: ^5.9.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 1874e66435e986262ad06639b812d49aa5c81a29815b27d31370d055335cebdad77ee0276504497b1765c489e5c5faf9795df97e52649af931d1cf381c4afa77 + languageName: node + linkType: hard + "@docusaurus/utils-common@npm:2.4.3, @docusaurus/utils-common@npm:^2.0.0-rc.1": version: 2.4.3 resolution: "@docusaurus/utils-common@npm:2.4.3" @@ -2326,6 +2549,20 @@ __metadata: languageName: node linkType: hard +"@docusaurus/utils-common@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/utils-common@npm:3.0.1" + dependencies: + tslib: ^2.6.0 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: 7d4eb39258539d594cf1432d07be0325de5a02c2a00418e022b0cd2d4374788a7cc5dd3febad6f34744e5a1e76646ae909ffbdf2024284f31c579d1f1ff055d8 + languageName: node + linkType: hard + "@docusaurus/utils-validation@npm:2.4.3, @docusaurus/utils-validation@npm:^2.0.0-rc.1": version: 2.4.3 resolution: "@docusaurus/utils-validation@npm:2.4.3" @@ -2339,6 +2576,19 @@ __metadata: languageName: node linkType: hard +"@docusaurus/utils-validation@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/utils-validation@npm:3.0.1" + dependencies: + "@docusaurus/logger": 3.0.1 + "@docusaurus/utils": 3.0.1 + joi: ^17.9.2 + js-yaml: ^4.1.0 + tslib: ^2.6.0 + checksum: c52edd61906ee004cea95ca33f81ec10a40276cad29f1aef505220cea4b922c1734b765d9c55b0889822351876ea545a73f7f3a4fbbb574f625fe455f8387033 + languageName: node + linkType: hard + "@docusaurus/utils@npm:2.4.3, @docusaurus/utils@npm:^2.0.0-rc.1": version: 2.4.3 resolution: "@docusaurus/utils@npm:2.4.3" @@ -2368,9 +2618,39 @@ __metadata: languageName: node linkType: hard -"@easyops-cn/autocomplete.js@npm:^0.38.1": - version: 0.38.1 - resolution: "@easyops-cn/autocomplete.js@npm:0.38.1" +"@docusaurus/utils@npm:3.0.1": + version: 3.0.1 + resolution: "@docusaurus/utils@npm:3.0.1" + dependencies: + "@docusaurus/logger": 3.0.1 + "@svgr/webpack": ^6.5.1 + escape-string-regexp: ^4.0.0 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + github-slugger: ^1.5.0 + globby: ^11.1.0 + gray-matter: ^4.0.3 + jiti: ^1.20.0 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + micromatch: ^4.0.5 + resolve-pathname: ^3.0.0 + shelljs: ^0.8.5 + tslib: ^2.6.0 + url-loader: ^4.1.1 + webpack: ^5.88.1 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: 5a8c5d8dd9cf1ad9ed1cecff3be3cbe041ebf8f51e2744af8aa006df67367f24d0888181566ed9ab2837b931a4fb135d943eadfde99708468f90f18795d413b5 + languageName: node + linkType: hard + +"@easyops-cn/autocomplete.js@npm:^0.38.1": + version: 0.38.1 + resolution: "@easyops-cn/autocomplete.js@npm:0.38.1" dependencies: cssesc: ^3.0.0 immediate: ^3.2.3 @@ -3355,12 +3635,46 @@ __metadata: languageName: node linkType: hard -"@mdx-js/react@npm:^1.6.22": - version: 1.6.22 - resolution: "@mdx-js/react@npm:1.6.22" +"@mdx-js/mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "@mdx-js/mdx@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdx": ^2.0.0 + collapse-white-space: ^2.0.0 + devlop: ^1.0.0 + estree-util-build-jsx: ^3.0.0 + estree-util-is-identifier-name: ^3.0.0 + estree-util-to-js: ^2.0.0 + estree-walker: ^3.0.0 + hast-util-to-estree: ^3.0.0 + hast-util-to-jsx-runtime: ^2.0.0 + markdown-extensions: ^2.0.0 + periscopic: ^3.0.0 + remark-mdx: ^3.0.0 + remark-parse: ^11.0.0 + remark-rehype: ^11.0.0 + source-map: ^0.7.0 + unified: ^11.0.0 + unist-util-position-from-estree: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + checksum: da4305dcfd9012521170e0ed439eb336900fb84a5784e5e3dac2144855fa603325477855e17a04b7c673cc24699cf2bfd611c958f591bb3a9afb5608c259bbd3 + languageName: node + linkType: hard + +"@mdx-js/react@npm:^3.0.0": + version: 3.0.0 + resolution: "@mdx-js/react@npm:3.0.0" + dependencies: + "@types/mdx": ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - checksum: bc84bd514bc127f898819a0c6f1a6915d9541011bd8aefa1fcc1c9bea8939f31051409e546bdec92babfa5b56092a16d05ef6d318304ac029299df5181dc94c8 + "@types/react": ">=16" + react: ">=16" + checksum: a780cff9d7f7639d6fc21c9d4e0a6ac1370c3209ea0db176923df7f9145785309591cf871f227f5135d1fe2accce0d5df9a22fc0530e5dda0c7b4b105705f20d languageName: node linkType: hard @@ -4158,10 +4472,37 @@ __metadata: languageName: node linkType: hard +"@pnpm/config.env-replace@npm:^1.1.0": + version: 1.1.0 + resolution: "@pnpm/config.env-replace@npm:1.1.0" + checksum: a3d2b57e35eec9543d9eb085854f6e33e8102dac99fdef2fad2eebdbbfc345e93299f0c20e8eb61c1b4c7aa123bfd47c175678626f161cda65dd147c2b6e1fa0 + languageName: node + linkType: hard + +"@pnpm/network.ca-file@npm:^1.0.1": + version: 1.0.2 + resolution: "@pnpm/network.ca-file@npm:1.0.2" + dependencies: + graceful-fs: 4.2.10 + checksum: d8d0884646500576bd5390464d13db1bb9a62e32a1069293e5bddb2ad8354b354b7e2d2a35e12850025651e795e6a80ce9e601c66312504667b7e3ee7b52becc + languageName: node + linkType: hard + +"@pnpm/npm-conf@npm:^2.1.0": + version: 2.2.2 + resolution: "@pnpm/npm-conf@npm:2.2.2" + dependencies: + "@pnpm/config.env-replace": ^1.1.0 + "@pnpm/network.ca-file": ^1.0.1 + config-chain: ^1.1.11 + checksum: d64aa4464be584caa855eafa8f109509390489997e36d602d6215784e2973b896bef3968426bb00896cf4ae7d440fed2cee7bb4e0dbc90362f024ea3f9e27ab1 + languageName: node + linkType: hard + "@polka/url@npm:^1.0.0-next.20": - version: 1.0.0-next.23 - resolution: "@polka/url@npm:1.0.0-next.23" - checksum: 4b0330de1ceecd1002c7e7449094d0c41f2ed0e21765f4835ccc7b003f2f024ac557d503b9ffdf0918cf50b80d5b8c99dfc5a91927e7b3c468b09c6bb42a3c41 + version: 1.0.0-next.24 + resolution: "@polka/url@npm:1.0.0-next.24" + checksum: 00baec4458ac86ca27edf7ce807ccfad97cd1d4b67bdedaf3401a9e755757588f3331e891290d1deea52d88df2bf2387caf8d94a6835b614d5b37b638a688273 languageName: node linkType: hard @@ -4385,6 +4726,31 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/is@npm:^4.6.0": + version: 4.6.0 + resolution: "@sindresorhus/is@npm:4.6.0" + checksum: 83839f13da2c29d55c97abc3bc2c55b250d33a0447554997a85c539e058e57b8da092da396e252b11ec24a0279a0bed1f537fa26302209327060643e327f81d2 + languageName: node + linkType: hard + +"@sindresorhus/is@npm:^5.2.0": + version: 5.6.0 + resolution: "@sindresorhus/is@npm:5.6.0" + checksum: 2e6e0c3acf188dcd9aea0f324ac1b6ad04c9fc672392a7b5a1218512fcde066965797eba8b9fe2108657a504388bd4a6664e6e6602555168e828a6df08b9f10e + languageName: node + linkType: hard + +"@slorber/remark-comment@npm:^1.0.0": + version: 1.0.0 + resolution: "@slorber/remark-comment@npm:1.0.0" + dependencies: + micromark-factory-space: ^1.0.0 + micromark-util-character: ^1.1.0 + micromark-util-symbol: ^1.0.1 + checksum: c96f1533d09913c57381859966f10a706afd8eb680923924af1c451f3b72f22c31e394028d7535131c10f8682d3c60206da95c50fb4f016fbbd04218c853cc88 + languageName: node + linkType: hard + "@slorber/static-site-generator-webpack-plugin@npm:^4.0.7": version: 4.0.7 resolution: "@slorber/static-site-generator-webpack-plugin@npm:4.0.7" @@ -4536,7 +4902,7 @@ __metadata: languageName: node linkType: hard -"@svgr/webpack@npm:^6.2.1": +"@svgr/webpack@npm:^6.2.1, @svgr/webpack@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/webpack@npm:6.5.1" dependencies: @@ -4561,6 +4927,15 @@ __metadata: languageName: node linkType: hard +"@szmarczak/http-timer@npm:^5.0.1": + version: 5.0.1 + resolution: "@szmarczak/http-timer@npm:5.0.1" + dependencies: + defer-to-connect: ^2.0.1 + checksum: fc9cb993e808806692e4a3337c90ece0ec00c89f4b67e3652a356b89730da98bc824273a6d67ca84d5f33cd85f317dcd5ce39d8cc0a2f060145a608a7cb8ce92 + languageName: node + linkType: hard + "@trysound/sax@npm:0.2.0": version: 0.2.0 resolution: "@trysound/sax@npm:0.2.0" @@ -4605,6 +4980,15 @@ __metadata: languageName: node linkType: hard +"@types/acorn@npm:^4.0.0": + version: 4.0.6 + resolution: "@types/acorn@npm:4.0.6" + dependencies: + "@types/estree": "*" + checksum: 60e1fd28af18d6cb54a93a7231c7c18774a9a8739c9b179e9e8750dca631e10cbef2d82b02830ea3f557b1d121e6406441e9e1250bd492dc81d4b3456e76e4d4 + languageName: node + linkType: hard + "@types/babel__code-frame@npm:^7.0.2": version: 7.0.6 resolution: "@types/babel__code-frame@npm:7.0.6" @@ -4734,6 +5118,15 @@ __metadata: languageName: node linkType: hard +"@types/debug@npm:^4.0.0": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" + dependencies: + "@types/ms": "*" + checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 + languageName: node + linkType: hard + "@types/eslint-scope@npm:^3.7.3": version: 3.7.7 resolution: "@types/eslint-scope@npm:3.7.7" @@ -4754,6 +5147,15 @@ __metadata: languageName: node linkType: hard +"@types/estree-jsx@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/estree-jsx@npm:1.0.3" + dependencies: + "@types/estree": "*" + checksum: 6887a134308b6db4a33a147b56c9d0a47c17ea7e810bdd7c498c306a0fd00bcf2619cb0f57f74009d03dda974b3cd7e414767f85332b1d1b2be30a3ef9e1cca9 + languageName: node + linkType: hard + "@types/estree@npm:*, @types/estree@npm:^1.0.0": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" @@ -4801,6 +5203,13 @@ __metadata: languageName: node linkType: hard +"@types/gtag.js@npm:^0.0.12": + version: 0.0.12 + resolution: "@types/gtag.js@npm:0.0.12" + checksum: 34efc27fbfd0013255b8bfd4af38ded9d5a6ba761130c76f17fd3a9585d83acc88d8005aab667cfec4bdec0e7c7217f689739799a8f61aed0edb929be58b162e + languageName: node + linkType: hard + "@types/hast@npm:^2.0.0": version: 2.3.8 resolution: "@types/hast@npm:2.3.8" @@ -4810,6 +5219,15 @@ __metadata: languageName: node linkType: hard +"@types/hast@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/hast@npm:3.0.3" + dependencies: + "@types/unist": "*" + checksum: ca204207550fd6848ee20b5ba2018fd54f515d59a8b80375cdbe392ba2b4b130dac25fdfbaf9f2a70d2aec9d074a34dc14d4d59d31fa3ede80ef9850afad5d3c + languageName: node + linkType: hard + "@types/history@npm:^4.7.11": version: 4.7.11 resolution: "@types/history@npm:4.7.11" @@ -4831,6 +5249,13 @@ __metadata: languageName: node linkType: hard +"@types/http-cache-semantics@npm:^4.0.2": + version: 4.0.4 + resolution: "@types/http-cache-semantics@npm:4.0.4" + checksum: 7f4dd832e618bc1e271be49717d7b4066d77c2d4eed5b81198eb987e532bb3e1c7e02f45d77918185bad936f884b700c10cebe06305f50400f382ab75055f9e8 + languageName: node + linkType: hard + "@types/http-errors@npm:*": version: 2.0.4 resolution: "@types/http-errors@npm:2.0.4" @@ -4879,10 +5304,10 @@ __metadata: languageName: node linkType: hard -"@types/katex@npm:^0.11.0": - version: 0.11.1 - resolution: "@types/katex@npm:0.11.1" - checksum: 1e51988b4b386a1b6fa8e22826ab4705bf3e6c9fb03461f2c91d28cb31095232bdeff491069ac9bc74bc4c26110be6a11a41e12ca77a2e4169f3afd8cd349355 +"@types/katex@npm:^0.16.0": + version: 0.16.7 + resolution: "@types/katex@npm:0.16.7" + checksum: 4fd15d93553be97c02c064e16be18d7ccbabf66ec72a9dc7fd5bfa47f0c7581da2f942f693c7cb59499de4c843c2189796e49c9647d336cbd52b777b6722a95a languageName: node linkType: hard @@ -4950,6 +5375,22 @@ __metadata: languageName: node linkType: hard +"@types/mdast@npm:^4.0.0, @types/mdast@npm:^4.0.2": + version: 4.0.3 + resolution: "@types/mdast@npm:4.0.3" + dependencies: + "@types/unist": "*" + checksum: 345c5a22fccf05f35239ea6313ee4aaf6ebed5927c03ac79744abccb69b9ba5e692f9b771e36a012b79e17429082cada30f579e9c43b8a54e0ffb365431498b6 + languageName: node + linkType: hard + +"@types/mdx@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/mdx@npm:2.0.10" + checksum: 3e2fb24b7bfae739a59573344171292b6c31256ad9afddc00232e9de4fbc97b270e1a11d13cb935cba0d9bbb9bc7348793eda82ee752233c5d2289f4b897f719 + languageName: node + linkType: hard + "@types/mime@npm:*": version: 3.0.4 resolution: "@types/mime@npm:3.0.4" @@ -4985,6 +5426,13 @@ __metadata: languageName: node linkType: hard +"@types/ms@npm:*": + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + languageName: node + linkType: hard + "@types/node-forge@npm:^1.3.0": version: 1.3.10 resolution: "@types/node-forge@npm:1.3.10" @@ -4995,11 +5443,11 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:^20.5.7, @types/node@npm:^20.6.2": - version: 20.10.3 - resolution: "@types/node@npm:20.10.3" + version: 20.10.4 + resolution: "@types/node@npm:20.10.4" dependencies: undici-types: ~5.26.4 - checksum: 34a329494f0ea239af05eeb6f00f396963725b3eb9a2f79c5e6a6d37e823f2ab85e1079c2ee56723a37d8b89e7bbe2bd050c97144e5bb06dab93fd1cace65c97 + checksum: 054b296417e771ab524bea63cf3289559c6bdf290d45428f7cc68e9b00030ff7a0ece47b8c99a26b4f47a443919813bcf42beadff2f0bea7d8125fa541d92eb0 languageName: node linkType: hard @@ -5018,11 +5466,11 @@ __metadata: linkType: hard "@types/node@npm:^18.7.20": - version: 18.19.2 - resolution: "@types/node@npm:18.19.2" + version: 18.19.3 + resolution: "@types/node@npm:18.19.3" dependencies: undici-types: ~5.26.4 - checksum: 6ae1e456f469bd50cac55d01ec17cddca3e60a1ae8cf6a95c8f2c49668ac358fd68d53af32076e37418f3b07cf6d2b245a48e3b77998ac51cc6a797d9d1a4367 + checksum: 58c4fa45a78fcec75c78182a4b266395905957633654eb0311c5f9c30ac15c179ea2287ab1af034e46c2db7bb0589ef0000ee64c1de8f568a0aad29eaadb100c languageName: node linkType: hard @@ -5065,6 +5513,13 @@ __metadata: languageName: node linkType: hard +"@types/prismjs@npm:^1.26.0": + version: 1.26.3 + resolution: "@types/prismjs@npm:1.26.3" + checksum: c627fa9d9f4277ce413bb8347944152cddfc892702e34ff4b099dc1cf3f00c09514d36349c23529b903b0e57f3b2e0dc91ee66e98af07fbbe1e3fe8346b23370 + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.11 resolution: "@types/prop-types@npm:15.7.11" @@ -5093,14 +5548,14 @@ __metadata: languageName: node linkType: hard -"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6": - version: 5.0.10 - resolution: "@types/react-router-config@npm:5.0.10" +"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6, @types/react-router-config@npm:^5.0.7": + version: 5.0.11 + resolution: "@types/react-router-config@npm:5.0.11" dependencies: "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router": ^5.1.0 - checksum: 3fbfbf76aa3a359150daaad218ffb7e073f770f076e6f4d07601d0657e0f86d17702a76cd29c8db3d70f89c863e883c170fcfe09c42e409ff34c290672eab751 + checksum: 4b72d9b71e0576e193c11e5085bbdac43f31debfa3b6ebc24666f3d646ef25c1f57f16c29b1ddd3051c881e85f8e0d4ab5a7bbd5fc215b9377f57675b210be7c languageName: node linkType: hard @@ -5126,13 +5581,13 @@ __metadata: linkType: hard "@types/react@npm:*": - version: 18.2.41 - resolution: "@types/react@npm:18.2.41" + version: 18.2.43 + resolution: "@types/react@npm:18.2.43" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: fcf4c598e5adc1be1dafaa5977ff7698b5b69c6b1473ce524a28d57fa04af3f1a1aa1193cf284542451d98ae5338d26270f8c6e1f7afda5bbbe6c3a4ba40b1d8 + checksum: e7e4da18c7b14e4b8b1ea630d1d8224835698f2bb2485766455bfb9dea93b8ee6cc549a9fe1cb10c984e62685db44fcfb61e8fac913b008cd30a92087f25b9df languageName: node linkType: hard @@ -5242,6 +5697,13 @@ __metadata: languageName: node linkType: hard +"@types/unist@npm:*, @types/unist@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 3d04d0be69316e5f14599a0d993a208606c12818cf631fd399243d1dc7a9bd8a3917d6066baa6abc290814afbd744621484756803c80cba892c39cd4b4a85616 + languageName: node + linkType: hard + "@types/unist@npm:^2, @types/unist@npm:^2.0.0, @types/unist@npm:^2.0.2, @types/unist@npm:^2.0.3": version: 2.0.10 resolution: "@types/unist@npm:2.0.10" @@ -5300,14 +5762,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.7.3": - version: 6.13.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.13.1" + version: 6.13.2 + resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.13.1 - "@typescript-eslint/type-utils": 6.13.1 - "@typescript-eslint/utils": 6.13.1 - "@typescript-eslint/visitor-keys": 6.13.1 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/type-utils": 6.13.2 + "@typescript-eslint/utils": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -5320,44 +5782,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 568093d76c200a8502047d74f29300110a59b9f2a5cbf995a6cbe419c803a7ec22220e9592a884401d2dde72c79346b4cc0ee393e7b422924ad4a8a2040af3b0 + checksum: e50cbbe7104eecef59faf3355ab981d9f353b19327f0b4607dfd829b4726f9e694b536fe43ab55f50bb00fbfdd2e4268a7e2a568b28d5fcd0d2a32a8d2466218 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.7.3": - version: 6.13.1 - resolution: "@typescript-eslint/parser@npm:6.13.1" + version: 6.13.2 + resolution: "@typescript-eslint/parser@npm:6.13.2" dependencies: - "@typescript-eslint/scope-manager": 6.13.1 - "@typescript-eslint/types": 6.13.1 - "@typescript-eslint/typescript-estree": 6.13.1 - "@typescript-eslint/visitor-keys": 6.13.1 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 58b7fef6f2d02c8f4737f9908a8d335a20bee20dba648233a69f28e7b39237791d2b9fbb818e628dcc053ddf16507b161ace7f1139e093d72365f1270c426de3 + checksum: aeafc414d295d7855384f10d57abb4f5f2ff35b57991b5c8854f43268761b3cc995e62af585dea1dc48295d762f466b565b5ae5699bfe642585d3f83ba8e1515 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/scope-manager@npm:6.13.1" +"@typescript-eslint/scope-manager@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/scope-manager@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.13.1 - "@typescript-eslint/visitor-keys": 6.13.1 - checksum: 109a213f82719e10f8c6a0168f2e105dc1369c7e0c075c1f30af137030fc866a3a585a77ff78a9a3538afc213061c8aedbb4462a91f26cbd90eefbab8b89ea10 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + checksum: ff8fd64ddf324e296e2e0e34a8f73149c9a5f14d1761ea8e8665fc5998faa2b0bbbd1a5d416aa10d725f13c804032d532f68e39a0ca6cc36d1c9b9c0aea94311 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/type-utils@npm:6.13.1" +"@typescript-eslint/type-utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/type-utils@npm:6.13.2" dependencies: - "@typescript-eslint/typescript-estree": 6.13.1 - "@typescript-eslint/utils": 6.13.1 + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/utils": 6.13.2 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -5365,23 +5827,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: e39d28dd2f3b47a26b4f6aa2c7a301bdd769ce9148d734be93441a813c3d1111eba1d655677355bba5519f3d4dbe93e4ff4e46830216b0302df0070bf7a80057 + checksum: ba54e5746139f778c35e4058e523ec8c20b68cf6472b3a7784170328e48c228f0761d2fc7e43dab053ca7d85ac4378b6965567774e6afedf551e600638404215 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/types@npm:6.13.1" - checksum: bb1d52f1646bab9acd3ec874567ffbaaaf7fe4a5f79845bdacbfea46d15698e58d45797da05b08c23f9496a17229b7f2c1363d000fd89ce4e79874fd57ba1d4a +"@typescript-eslint/types@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/types@npm:6.13.2" + checksum: 4493ff06fa07c68c5adbcbd842f6dd6f5c88f14d160b53c3379b6b703e6f62808fab7fdebcc06ff06a56f20ab432b6ceeb0afb8931dc97d4061cb417e787f2c1 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.13.1" +"@typescript-eslint/typescript-estree@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/typescript-estree@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.13.1 - "@typescript-eslint/visitor-keys": 6.13.1 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -5390,38 +5852,38 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 09aa0f5cbd60e84df4f58f3d479be352549600b24dbefe75c686ea89252526c52c1c06ce1ae56c0405dd7337002e741c2ba02b71fb1caa3b94a740a70fcc8699 + checksum: 0c18ee5ef594a2411a788fe9d7bc6d51a03bce38d9d764bcb24ab557e5bc1942c2ddf9bd6fb4877eb102b0ae488974fb7b7fe72daa70a2054bf04d3cc6803546 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/utils@npm:6.13.1" +"@typescript-eslint/utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/utils@npm:6.13.2" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.13.1 - "@typescript-eslint/types": 6.13.1 - "@typescript-eslint/typescript-estree": 6.13.1 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 14f64840869c8755af4d287cfc74abc424dc139559e87ca1a8b0e850f4fa56311d99dfb61a43dd4433eae5914be12b4b3390e55de1f236dce6701830d17e31c9 + checksum: b66bcf2a945e9c55f3dccb48af49565863d974837ee23b2f01ce7f3fb2462eb8a5871784d4a2fcc80dac7d5cd4ed90c8d01431cd177c0249de89a448f6663fc8 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.13.1" +"@typescript-eslint/visitor-keys@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/visitor-keys@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.13.1 + "@typescript-eslint/types": 6.13.2 eslint-visitor-keys: ^3.4.1 - checksum: d15d362203a2fe995ea62a59d5b44c15c8fb1fb30ff59dd1542a980f75b3b62035303dfb781d83709921613f6ac8cc5bf57b70f6e20d820aec8b7911f07152e9 + checksum: 4b4def7acd7451e6a18dab3ee13f06504b3d23e51f195fced7c544f2203ee8a83426c82fa57ab6b58725c70fdedaf7a3eccb69793180be35756eed0f2c69fe04 languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.2.0": +"@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 @@ -5948,7 +6410,7 @@ __metadata: languageName: node linkType: hard -"acorn-jsx@npm:^5.3.2": +"acorn-jsx@npm:^5.0.0, acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" peerDependencies: @@ -5958,13 +6420,13 @@ __metadata: linkType: hard "acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.2.0": - version: 8.3.0 - resolution: "acorn-walk@npm:8.3.0" - checksum: 15ea56ab6529135be05e7d018f935ca80a572355dd3f6d3cd717e36df3346e0f635a93ae781b1c7942607693e2e5f3ef81af5c6fc697bbadcc377ebda7b7f5f6 + version: 8.3.1 + resolution: "acorn-walk@npm:8.3.1" + checksum: 5c8926ddb5400bc825b6baca782931f9df4ace603ba1a517f5243290fd9cdb089d52877840687b5d5c939591ebc314e2e63721514feaa37c6829c828f2b940ce languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.11.2 resolution: "acorn@npm:8.11.2" bin: @@ -6097,18 +6559,18 @@ __metadata: languageName: node linkType: hard -"algoliasearch-helper@npm:^3.10.0": - version: 3.15.0 - resolution: "algoliasearch-helper@npm:3.15.0" +"algoliasearch-helper@npm:^3.13.3": + version: 3.16.0 + resolution: "algoliasearch-helper@npm:3.16.0" dependencies: "@algolia/events": ^4.0.1 peerDependencies: algoliasearch: ">= 3.1 < 6" - checksum: 3caad0dac3807e1f1c7737bdfa75c1faa3c8f5aa0bf55c11da252b2aa927c1df079b36f0c4962798fef6b80920ab627297cbc107c9082c9765a28e0fcd8c409a + checksum: e024ad33c65d1eb7a31290bcf0bec37f2485154364e90ada45e07242ac35155313fe913fabd08cdb4d69e2794cc7d09dda03878566cea286cfac8fd4cc61f33f languageName: node linkType: hard -"algoliasearch@npm:^4.13.1, algoliasearch@npm:^4.19.1": +"algoliasearch@npm:^4.18.0, algoliasearch@npm:^4.19.1": version: 4.20.0 resolution: "algoliasearch@npm:4.20.0" dependencies: @@ -6320,13 +6782,6 @@ __metadata: languageName: node linkType: hard -"asap@npm:~2.0.3": - version: 2.0.6 - resolution: "asap@npm:2.0.6" - checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d - languageName: node - linkType: hard - "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -6341,6 +6796,15 @@ __metadata: languageName: node linkType: hard +"astring@npm:^1.8.0": + version: 1.8.6 + resolution: "astring@npm:1.8.6" + bin: + astring: bin/astring + checksum: 6f034d2acef1dac8bb231e7cc26c573d3c14e1975ea6e04f20312b43d4f462f963209bc64187d25d477a182dc3c33277959a0156ab7a3617aa79b1eac4d88e1f + languageName: node + linkType: hard + "async@npm:^2.6.4": version: 2.6.4 resolution: "async@npm:2.6.4" @@ -6364,7 +6828,7 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.7": +"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.14, autoprefixer@npm:^10.4.7": version: 10.4.16 resolution: "autoprefixer@npm:10.4.16" dependencies: @@ -6475,6 +6939,19 @@ __metadata: languageName: node linkType: hard +"babel-loader@npm:^9.1.3": + version: 9.1.3 + resolution: "babel-loader@npm:9.1.3" + dependencies: + find-cache-dir: ^4.0.0 + schema-utils: ^4.0.0 + peerDependencies: + "@babel/core": ^7.12.0 + webpack: ">=5" + checksum: b168dde5b8cf11206513371a79f86bb3faa7c714e6ec9fffd420876b61f3d7f5f4b976431095ef6a14bc4d324505126deb91045fd41e312ba49f4deaa166fe28 + languageName: node + linkType: hard + "babel-plugin-apply-mdx-type-prop@npm:1.6.22": version: 1.6.22 resolution: "babel-plugin-apply-mdx-type-prop@npm:1.6.22" @@ -6548,6 +7025,13 @@ __metadata: languageName: node linkType: hard +"bail@npm:^2.0.0": + version: 2.0.2 + resolution: "bail@npm:2.0.2" + checksum: aab4e8ccdc8d762bf3fdfce8e706601695620c0c2eda256dd85088dc0be3cfd7ff126f6e99c2bee1f24f5d418414aacf09d7f9702f16d6963df2fa488cda8824 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -6564,13 +7048,6 @@ __metadata: languageName: node linkType: hard -"base16@npm:^1.0.0": - version: 1.0.0 - resolution: "base16@npm:1.0.0" - checksum: 0cd449a2db0f0f957e4b6b57e33bc43c9e20d4f1dd744065db94b5da35e8e71fa4dc4bc7a901e59a84d5f8b6936e3c520e2471787f667fc155fb0f50d8540f5d - languageName: node - linkType: hard - "base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -6730,6 +7207,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:^7.0.0": + version: 7.1.1 + resolution: "boxen@npm:7.1.1" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.1 + chalk: ^5.2.0 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.1.0 + checksum: ad8833d5f2845b0a728fdf8a0bc1505dff0c518edcb0fd56979a08774b1f26cf48b71e66532179ccdfb9ed95b64aa008689cca26f7776f93f002b8000a683d76 + languageName: node + linkType: hard + "bplist-parser@npm:^0.2.0": version: 0.2.0 resolution: "bplist-parser@npm:0.2.0" @@ -6807,7 +7300,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.2": version: 4.22.2 resolution: "browserslist@npm:4.22.2" dependencies: @@ -6942,6 +7435,28 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^7.0.0": + version: 7.0.0 + resolution: "cacheable-lookup@npm:7.0.0" + checksum: 9e2856763fc0a7347ab34d704c010440b819d4bb5e3593b664381b7433e942dd22e67ee5581f12256f908e79b82d30b86ebbacf40a081bfe10ee93fbfbc2d6a9 + languageName: node + linkType: hard + +"cacheable-request@npm:^10.2.8": + version: 10.2.14 + resolution: "cacheable-request@npm:10.2.14" + dependencies: + "@types/http-cache-semantics": ^4.0.2 + get-stream: ^6.0.1 + http-cache-semantics: ^4.1.1 + keyv: ^4.5.3 + mimic-response: ^4.0.0 + normalize-url: ^8.0.0 + responselike: ^3.0.0 + checksum: 56f2b8e1c497c91f8391f0b099d19907a7dde25e71087e622b23e45fc8061736c2a6964ef121b16f377c3c61079cf8dc17320ab54004209d1343e4d26aba7015 + languageName: node + linkType: hard + "cacheable-request@npm:^6.0.0": version: 6.1.0 resolution: "cacheable-request@npm:6.1.0" @@ -7006,6 +7521,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^7.0.1": + version: 7.0.1 + resolution: "camelcase@npm:7.0.1" + checksum: 86ab8f3ebf08bcdbe605a211a242f00ed30d8bfb77dab4ebb744dd36efbc84432d1c4adb28975ba87a1b8be40a80fbd1e60e2f06565315918fa7350011a26d3d + languageName: node + linkType: hard + "caniuse-api@npm:^3.0.0": version: 3.0.0 resolution: "caniuse-api@npm:3.0.0" @@ -7019,9 +7541,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": - version: 1.0.30001566 - resolution: "caniuse-lite@npm:1.0.30001566" - checksum: 0f9084bf9f7d5c0a9ddb200c2baddb25dd2ad5a2f205f01e7b971f3e98e9a7bb23c2d86bae48237e9bc9782b682cffaaf3406d936937ab9844987dbe2a6401f2 + version: 1.0.30001568 + resolution: "caniuse-lite@npm:1.0.30001568" + checksum: 7092aaa246dc8531fbca5b47be91e92065db7e5c04cc9e3d864e848f8f1be769ac6754429e843a5e939f7331a771e8b0a1bc3b13495c66b748c65e2f5bdb1220 languageName: node linkType: hard @@ -7055,6 +7577,13 @@ __metadata: languageName: node linkType: hard +"ccount@npm:^2.0.0": + version: 2.0.1 + resolution: "ccount@npm:2.0.1" + checksum: 48193dada54c9e260e0acf57fc16171a225305548f9ad20d5471e0f7a8c026aedd8747091dccb0d900cde7df4e4ddbd235df0d8de4a64c71b12f0d3303eeafd4 + languageName: node + linkType: hard + "chai-as-promised@npm:^7.1.1": version: 7.1.1 resolution: "chai-as-promised@npm:7.1.1" @@ -7118,6 +7647,20 @@ __metadata: languageName: node linkType: hard +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"character-entities-html4@npm:^2.0.0": + version: 2.1.0 + resolution: "character-entities-html4@npm:2.1.0" + checksum: 7034aa7c7fa90309667f6dd50499c8a760c3d3a6fb159adb4e0bada0107d194551cdbad0714302f62d06ce4ed68565c8c2e15fdef2e8f8764eb63fa92b34b11d + languageName: node + linkType: hard + "character-entities-legacy@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-legacy@npm:1.1.4" @@ -7125,6 +7668,13 @@ __metadata: languageName: node linkType: hard +"character-entities-legacy@npm:^3.0.0": + version: 3.0.0 + resolution: "character-entities-legacy@npm:3.0.0" + checksum: 7582af055cb488b626d364b7d7a4e46b06abd526fb63c0e4eb35bcb9c9799cc4f76b39f34fdccef2d1174ac95e53e9ab355aae83227c1a2505877893fce77731 + languageName: node + linkType: hard + "character-entities@npm:^1.0.0": version: 1.2.4 resolution: "character-entities@npm:1.2.4" @@ -7132,6 +7682,13 @@ __metadata: languageName: node linkType: hard +"character-entities@npm:^2.0.0": + version: 2.0.2 + resolution: "character-entities@npm:2.0.2" + checksum: cf1643814023697f725e47328fcec17923b8f1799102a8a79c1514e894815651794a2bffd84bb1b3a4b124b050154e4529ed6e81f7c8068a734aecf07a6d3def + languageName: node + linkType: hard + "character-reference-invalid@npm:^1.0.0": version: 1.1.4 resolution: "character-reference-invalid@npm:1.1.4" @@ -7139,6 +7696,13 @@ __metadata: languageName: node linkType: hard +"character-reference-invalid@npm:^2.0.0": + version: 2.0.1 + resolution: "character-reference-invalid@npm:2.0.1" + checksum: 98d3b1a52ae510b7329e6ee7f6210df14f1e318c5415975d4c9e7ee0ef4c07875d47c6e74230c64551f12f556b4a8ccc24d9f3691a2aa197019e72a95e9297ee + languageName: node + linkType: hard + "check-error@npm:^1.0.2, check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -7294,7 +7858,7 @@ __metadata: languageName: node linkType: hard -"clean-css@npm:^5.2.2, clean-css@npm:^5.3.0": +"clean-css@npm:^5.2.2, clean-css@npm:^5.3.0, clean-css@npm:^5.3.2, clean-css@npm:~5.3.2": version: 5.3.3 resolution: "clean-css@npm:5.3.3" dependencies: @@ -7349,7 +7913,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.2": +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -7428,6 +7992,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "co-body@npm:^6.1.0": version: 6.1.0 resolution: "co-body@npm:6.1.0" @@ -7463,6 +8034,13 @@ __metadata: languageName: node linkType: hard +"collapse-white-space@npm:^2.0.0": + version: 2.1.0 + resolution: "collapse-white-space@npm:2.1.0" + checksum: c8978b1f4e7d68bf846cfdba6c6689ce8910511df7d331eb6e6757e51ceffb52768d59a28db26186c91dcf9594955b59be9f8ccd473c485790f5d8b90dc6726f + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -7539,6 +8117,13 @@ __metadata: languageName: node linkType: hard +"comma-separated-tokens@npm:^2.0.0": + version: 2.0.3 + resolution: "comma-separated-tokens@npm:2.0.3" + checksum: e3bf9e0332a5c45f49b90e79bcdb4a7a85f28d6a6f0876a94f1bb9b2bfbdbbb9292aac50e1e742d8c0db1e62a0229a106f57917e2d067fca951d81737651700d + languageName: node + linkType: hard + "command-exists@npm:^1.2.8": version: 1.2.9 resolution: "command-exists@npm:1.2.9" @@ -7589,7 +8174,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^10.0.1": +"commander@npm:^10.0.0, commander@npm:^10.0.1": version: 10.0.1 resolution: "commander@npm:10.0.1" checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 @@ -7617,7 +8202,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^8.0.0, commander@npm:^8.3.0": +"commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 @@ -7685,6 +8270,16 @@ __metadata: languageName: node linkType: hard +"config-chain@npm:^1.1.11": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" + dependencies: + ini: ^1.3.4 + proto-list: ~1.2.1 + checksum: 828137a28e7c2fc4b7fb229bd0cd6c1397bcf83434de54347e608154008f411749041ee392cbe42fab6307e02de4c12480260bf769b7d44b778fdea3839eafab + languageName: node + linkType: hard + "configstore@npm:^5.0.1": version: 5.0.1 resolution: "configstore@npm:5.0.1" @@ -7699,6 +8294,19 @@ __metadata: languageName: node linkType: hard +"configstore@npm:^6.0.0": + version: 6.0.0 + resolution: "configstore@npm:6.0.0" + dependencies: + dot-prop: ^6.0.1 + graceful-fs: ^4.2.6 + unique-string: ^3.0.0 + write-file-atomic: ^3.0.3 + xdg-basedir: ^5.0.1 + checksum: 81995351c10bc04c58507f17748477aeac6f47465109d20e3534cebc881d22e927cfd29e73dd852c46c55f62c2b7be4cd1fe6eb3a93ba51f7f9813c218f9bae0 + languageName: node + linkType: hard + "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -7788,7 +8396,7 @@ __metadata: languageName: node linkType: hard -"copy-text-to-clipboard@npm:^3.0.1": +"copy-text-to-clipboard@npm:^3.2.0": version: 3.2.0 resolution: "copy-text-to-clipboard@npm:3.2.0" checksum: df7115c197a166d51f59e4e20ab2a68a855ae8746d25ff149b5465c694d9a405c7e6684b73a9f87ba8d653070164e229c15dfdb9fd77c30be1ff0da569661060 @@ -7812,25 +8420,25 @@ __metadata: linkType: hard "core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": - version: 3.33.3 - resolution: "core-js-compat@npm:3.33.3" + version: 3.34.0 + resolution: "core-js-compat@npm:3.34.0" dependencies: - browserslist: ^4.22.1 - checksum: cb121e83f0f5f18b2b75428cdfb19524936a18459f1e0358f9124c8ff8b75d6a5901495cb996560cfde3a416103973f78eb5947777bb8b2fd877cdf84471465d + browserslist: ^4.22.2 + checksum: 6281f7f57a72f254c06611ec088445e11cf84e0b4edfb5f43dece1a1ff8b0ed0e81ed0bc291024761cd90c39d0f007d8bc46548265139808081d311c7cbc9c81 languageName: node linkType: hard "core-js-pure@npm:^3.30.2": - version: 3.33.3 - resolution: "core-js-pure@npm:3.33.3" - checksum: 369f01a8b544f413da96c606039c1b9beea57fd7252b56524fcfa4276103e3e6a0f857452ed9cc5638e9d203763e2a6f8466c6915c95b64b88b3aa976467b325 + version: 3.34.0 + resolution: "core-js-pure@npm:3.34.0" + checksum: 4c44ac4beff42e07f41eef3c9ecefc8ee3f9e91e1b9f278bf8520cc1fb37afb663cff77c182541dc42d58737f93ab0f30a33a5fe661fb161fdd8aa7fe78a5edf languageName: node linkType: hard -"core-js@npm:^3.23.3": - version: 3.33.3 - resolution: "core-js@npm:3.33.3" - checksum: 070b9c696f5a9b22bab0208daf9fcdffbc3b4f4c89ed2be512b7d99d4be363accfbb26fa6eec7261055d89e8ea0a5bcfccad5923fe43f1f2eafca9f568cc5596 +"core-js@npm:^3.23.3, core-js@npm:^3.31.1": + version: 3.34.0 + resolution: "core-js@npm:3.34.0" + checksum: 26b0d103716b33fc660ee8737da7bc9475fbc655f93bbf1360ab692966449d18f2fc393805095937283db9f919ca2aa5c88d86d16f2846217983ad7da707e31e languageName: node linkType: hard @@ -7936,15 +8544,6 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:^3.1.5": - version: 3.1.8 - resolution: "cross-fetch@npm:3.1.8" - dependencies: - node-fetch: ^2.6.12 - checksum: 78f993fa099eaaa041122ab037fe9503ecbbcb9daef234d1d2e0b9230a983f64d645d088c464e21a247b825a08dc444a6e7064adfa93536d3a9454b4745b3632 - languageName: node - linkType: hard - "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" @@ -7963,6 +8562,15 @@ __metadata: languageName: node linkType: hard +"crypto-random-string@npm:^4.0.0": + version: 4.0.0 + resolution: "crypto-random-string@npm:4.0.0" + dependencies: + type-fest: ^1.0.1 + checksum: 91f148f27bcc8582798f0fb3e75a09d9174557f39c3c40a89dd1bd70fb5a14a02548245aa26fa7d663c426ac5026f4729841231c84f9e30e8c8ece5e38656741 + languageName: node + linkType: hard + "css-declaration-sorter@npm:^6.3.1": version: 6.4.1 resolution: "css-declaration-sorter@npm:6.4.1" @@ -7972,7 +8580,7 @@ __metadata: languageName: node linkType: hard -"css-loader@npm:^6.7.1": +"css-loader@npm:^6.7.1, css-loader@npm:^6.8.1": version: 6.8.1 resolution: "css-loader@npm:6.8.1" dependencies: @@ -7990,7 +8598,7 @@ __metadata: languageName: node linkType: hard -"css-minimizer-webpack-plugin@npm:^4.0.0": +"css-minimizer-webpack-plugin@npm:^4.0.0, css-minimizer-webpack-plugin@npm:^4.2.2": version: 4.2.2 resolution: "css-minimizer-webpack-plugin@npm:4.2.2" dependencies: @@ -8071,7 +8679,7 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-advanced@npm:^5.3.8": +"cssnano-preset-advanced@npm:^5.3.10, cssnano-preset-advanced@npm:^5.3.8": version: 5.3.10 resolution: "cssnano-preset-advanced@npm:5.3.10" dependencies: @@ -8135,7 +8743,7 @@ __metadata: languageName: node linkType: hard -"cssnano@npm:^5.1.12, cssnano@npm:^5.1.8": +"cssnano@npm:^5.1.12, cssnano@npm:^5.1.15, cssnano@npm:^5.1.8": version: 5.1.15 resolution: "cssnano@npm:5.1.15" dependencies: @@ -8158,9 +8766,9 @@ __metadata: linkType: hard "csstype@npm:^3.0.2": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 languageName: node linkType: hard @@ -8205,7 +8813,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -8233,6 +8841,15 @@ __metadata: languageName: node linkType: hard +"decode-named-character-reference@npm:^1.0.0": + version: 1.0.2 + resolution: "decode-named-character-reference@npm:1.0.2" + dependencies: + character-entities: ^2.0.0 + checksum: f4c71d3b93105f20076052f9cb1523a22a9c796b8296cd35eef1ca54239c78d182c136a848b83ff8da2071e3ae2b1d300bf29d00650a6d6e675438cc31b11d78 + languageName: node + linkType: hard + "decompress-response@npm:^3.3.0": version: 3.3.0 resolution: "decompress-response@npm:3.3.0" @@ -8242,6 +8859,15 @@ __metadata: languageName: node linkType: hard +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: ^3.1.0 + checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 + languageName: node + linkType: hard + "deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" @@ -8317,6 +8943,13 @@ __metadata: languageName: node linkType: hard +"defer-to-connect@npm:^2.0.1": + version: 2.0.1 + resolution: "defer-to-connect@npm:2.0.1" + checksum: 8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b + languageName: node + linkType: hard + "define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": version: 1.1.1 resolution: "define-data-property@npm:1.1.1" @@ -8447,7 +9080,7 @@ __metadata: languageName: node linkType: hard -"detect-port@npm:^1.3.0": +"detect-port@npm:^1.3.0, detect-port@npm:^1.5.1": version: 1.5.1 resolution: "detect-port@npm:1.5.1" dependencies: @@ -8460,6 +9093,15 @@ __metadata: languageName: node linkType: hard +"devlop@npm:^1.0.0, devlop@npm:^1.1.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: ^2.0.0 + checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 + languageName: node + linkType: hard + "devtools-protocol@npm:0.0.1107588": version: 0.0.1107588 resolution: "devtools-protocol@npm:0.0.1107588" @@ -8517,31 +9159,36 @@ __metadata: version: 0.0.0-use.local resolution: "docs@workspace:docs" dependencies: - "@docusaurus/core": ^2.4.0 - "@docusaurus/module-type-aliases": ^2.4.0 - "@docusaurus/plugin-content-pages": ^2.4.0 - "@docusaurus/plugin-google-gtag": ^2.4.0 - "@docusaurus/preset-classic": ^2.4.0 + "@docusaurus/core": ^3.0.1 + "@docusaurus/module-type-aliases": ^3.0.1 + "@docusaurus/preset-classic": ^3.0.1 + "@docusaurus/tsconfig": ^3.0.1 + "@docusaurus/types": ^3.0.1 "@easyops-cn/docusaurus-search-local": ^0.35.0 - "@mdx-js/react": ^1.6.22 + "@mdx-js/react": ^3.0.0 + "@noir-lang/noir_js": "workspace:*" "@noir-lang/noirc_abi": "workspace:*" "@noir-lang/types": "workspace:*" "@signorecello/noir_playground": ^0.6.0 + "@types/prettier": ^3 axios: ^1.4.0 clsx: ^1.2.1 docusaurus-plugin-typedoc: 1.0.0-next.18 + eslint-plugin-prettier: ^5.0.0 hast-util-is-element: ^1.1.0 - prism-react-renderer: ^1.3.5 - react: ^17.0.2 - react-dom: ^17.0.2 + prettier: 3.0.3 + prism-react-renderer: ^2.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 react-spinners: ^0.13.8 - rehype-katex: ^5.0.0 - remark-math: ^3.0.1 + rehype-katex: ^7.0.0 + remark-math: ^6.0.0 + ts-node: ^10.9.1 typedoc: ^0.25.0 typedoc-plugin-frontmatter: ^0.0.2 typedoc-plugin-markdown: 4.0.0-next.25 typedoc-plugin-merge-modules: ^5.1.0 - typescript: ^5.2.2 + typescript: ~5.2.2 languageName: unknown linkType: soft @@ -8662,6 +9309,15 @@ __metadata: languageName: node linkType: hard +"dot-prop@npm:^6.0.1": + version: 6.0.1 + resolution: "dot-prop@npm:6.0.1" + dependencies: + is-obj: ^2.0.0 + checksum: 0f47600a4b93e1dc37261da4e6909652c008832a5d3684b5bf9a9a0d3f4c67ea949a86dceed9b72f5733ed8e8e6383cc5958df3bbd0799ee317fd181f2ece700 + languageName: node + linkType: hard + "duplexer3@npm:^0.1.4": version: 0.1.5 resolution: "duplexer3@npm:0.1.5" @@ -8691,9 +9347,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.601": - version: 1.4.601 - resolution: "electron-to-chromium@npm:1.4.601" - checksum: 6c6d090afaab83f49fe413c2558a3294e7dfce6a9d8afda3496a80ba59377901279ea7903122558399d5f5dbbdcca8562e3e826b7b78e7ec0b561fcc02c45f73 + version: 1.4.609 + resolution: "electron-to-chromium@npm:1.4.609" + checksum: 4ef3c32b11adc01ed8227d7bdbe0978b436b817e6b3bd09f19b42afbf9affdb6ddf99f4d20a3b28a494772a2985df12ec95abca849a38cccb217c4ee338561bb languageName: node linkType: hard @@ -8733,6 +9389,13 @@ __metadata: languageName: node linkType: hard +"emojilib@npm:^2.4.0": + version: 2.4.0 + resolution: "emojilib@npm:2.4.0" + checksum: ea241c342abda5a86ffd3a15d8f4871a616d485f700e03daea38c6ce38205847cea9f6ff8d5e962c00516b004949cc96c6e37b05559ea71a0a496faba53b56da + languageName: node + linkType: hard + "emojis-list@npm:^3.0.0": version: 3.0.0 resolution: "emojis-list@npm:3.0.0" @@ -8747,9 +9410,16 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2": - version: 1.0.2 - resolution: "encodeurl@npm:1.0.2" +"emoticon@npm:^4.0.1": + version: 4.0.1 + resolution: "emoticon@npm:4.0.1" + checksum: 991ab6421927601af4eb44036b60e3125759a4d81f32d2ad96b66e3491e2fdb6a026eeb6bffbfa66724592dca95235570785963607d16961ea73a62ecce715e2 + languageName: node + linkType: hard + +"encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c languageName: node linkType: hard @@ -9011,6 +9681,13 @@ __metadata: languageName: node linkType: hard +"escape-goat@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-goat@npm:4.0.0" + checksum: 7034e0025eec7b751074b837f10312c5b768493265bdad046347c0aadbc1e652776f7e5df94766473fecb5d3681169cc188fe9ccc1e22be53318c18be1671cc0 + languageName: node + linkType: hard + "escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -9193,6 +9870,65 @@ __metadata: languageName: node linkType: hard +"estree-util-attach-comments@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-attach-comments@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + checksum: 56254eaef39659e6351919ebc2ae53a37a09290a14571c19e373e9d5fad343a3403d9ad0c23ae465d6e7d08c3e572fd56fb8c793efe6434a261bf1489932dbd5 + languageName: node + linkType: hard + +"estree-util-build-jsx@npm:^3.0.0": + version: 3.0.1 + resolution: "estree-util-build-jsx@npm:3.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + estree-walker: ^3.0.0 + checksum: 185eff060eda2ba32cecd15904db4f5ba0681159fbdf54f0f6586cd9411e77e733861a833d0aee3415e1d1fd4b17edf08bc9e9872cee98e6ec7b0800e1a85064 + languageName: node + linkType: hard + +"estree-util-is-identifier-name@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-is-identifier-name@npm:3.0.0" + checksum: ea3909f0188ea164af0aadeca87c087e3e5da78d76da5ae9c7954ff1340ea3e4679c4653bbf4299ffb70caa9b322218cc1128db2541f3d2976eb9704f9857787 + languageName: node + linkType: hard + +"estree-util-to-js@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-to-js@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + astring: ^1.8.0 + source-map: ^0.7.0 + checksum: 833edc94ab9978e0918f90261e0a3361bf4564fec4901f326d2237a9235d3f5fc6482da3be5acc545e702c8c7cb8bc5de5c7c71ba3b080eb1975bcfdf3923d79 + languageName: node + linkType: hard + +"estree-util-value-to-estree@npm:^3.0.1": + version: 3.0.1 + resolution: "estree-util-value-to-estree@npm:3.0.1" + dependencies: + "@types/estree": ^1.0.0 + is-plain-obj: ^4.0.0 + checksum: 7ab89084aa2c5677aeb0d7350ff21e71c9bbc424dc872a55bb4f25f63a7fd99fc7861626dd89b5544db3d3696212154bcf2b12b63ecd5a59dbfd07915c88aee4 + languageName: node + linkType: hard + +"estree-util-visit@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-visit@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/unist": ^3.0.0 + checksum: 6444b38f224322945a6d19ea81a8828a0eec64aefb2bf1ea791fe20df496f7b7c543408d637df899e6a8e318b638f66226f16378a33c4c2b192ba5c3f891121f + languageName: node + linkType: hard + "estree-walker@npm:^1.0.1": version: 1.0.1 resolution: "estree-walker@npm:1.0.1" @@ -9200,6 +9936,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.0": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2, esutils@npm:^2.0.3": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -9207,7 +9952,7 @@ __metadata: languageName: node linkType: hard -"eta@npm:^2.0.0": +"eta@npm:^2.0.0, eta@npm:^2.2.0": version: 2.2.0 resolution: "eta@npm:2.2.0" checksum: 6a09631481d4f26a9662a1eb736a65cc1cbc48e24935e6ff5d83a83b0cb509ea56d588d66d7c087d590601dc59bdabdac2356936b1b789d020eb0cf2d8304d54 @@ -9573,6 +10318,15 @@ __metadata: languageName: node linkType: hard +"fault@npm:^2.0.0": + version: 2.0.1 + resolution: "fault@npm:2.0.1" + dependencies: + format: ^0.2.0 + checksum: c9b30f47d95769177130a9409976a899ed31eb598450fbad5b0d39f2f5f56d5f4a9ff9257e0bee8407cb0fc3ce37165657888c6aa6d78472e403893104329b72 + languageName: node + linkType: hard + "faye-websocket@npm:^0.11.3": version: 0.11.4 resolution: "faye-websocket@npm:0.11.4" @@ -9582,37 +10336,6 @@ __metadata: languageName: node linkType: hard -"fbemitter@npm:^3.0.0": - version: 3.0.0 - resolution: "fbemitter@npm:3.0.0" - dependencies: - fbjs: ^3.0.0 - checksum: 069690b8cdff3521ade3c9beb92ba0a38d818a86ef36dff8690e66749aef58809db4ac0d6938eb1cacea2dbef5f2a508952d455669590264cdc146bbe839f605 - languageName: node - linkType: hard - -"fbjs-css-vars@npm:^1.0.0": - version: 1.0.2 - resolution: "fbjs-css-vars@npm:1.0.2" - checksum: 72baf6d22c45b75109118b4daecb6c8016d4c83c8c0f23f683f22e9d7c21f32fff6201d288df46eb561e3c7d4bb4489b8ad140b7f56444c453ba407e8bd28511 - languageName: node - linkType: hard - -"fbjs@npm:^3.0.0, fbjs@npm:^3.0.1": - version: 3.0.5 - resolution: "fbjs@npm:3.0.5" - dependencies: - cross-fetch: ^3.1.5 - fbjs-css-vars: ^1.0.0 - loose-envify: ^1.0.0 - object-assign: ^4.1.0 - promise: ^7.1.1 - setimmediate: ^1.0.5 - ua-parser-js: ^1.0.35 - checksum: e609b5b64686bc96495a5c67728ed9b2710b9b3d695c5759c5f5e47c9483d1c323543ac777a86459e3694efc5712c6ce7212e944feb19752867d699568bb0e54 - languageName: node - linkType: hard - "fd-slicer@npm:~1.1.0": version: 1.1.0 resolution: "fd-slicer@npm:1.1.0" @@ -9721,6 +10444,16 @@ __metadata: languageName: node linkType: hard +"find-cache-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "find-cache-dir@npm:4.0.0" + dependencies: + common-path-prefix: ^3.0.0 + pkg-dir: ^7.0.0 + checksum: 52a456a80deeb27daa3af6e06059b63bdb9cc4af4d845fc6d6229887e505ba913cd56000349caa60bc3aa59dacdb5b4c37903d4ba34c75102d83cab330b70d2f + languageName: node + linkType: hard + "find-replace@npm:^3.0.0": version: 3.0.0 resolution: "find-replace@npm:3.0.0" @@ -9768,7 +10501,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^6.0.0": +"find-up@npm:^6.0.0, find-up@npm:^6.3.0": version: 6.3.0 resolution: "find-up@npm:6.3.0" dependencies: @@ -9805,18 +10538,6 @@ __metadata: languageName: node linkType: hard -"flux@npm:^4.0.1": - version: 4.0.4 - resolution: "flux@npm:4.0.4" - dependencies: - fbemitter: ^3.0.0 - fbjs: ^3.0.1 - peerDependencies: - react: ^15.0.2 || ^16.0.0 || ^17.0.0 - checksum: 8fa5c2f9322258de3e331f67c6f1078a7f91c4dec9dbe8a54c4b8a80eed19a4f91889028b768668af4a796e8f2ee75e461e1571b8615432a3920ae95cc4ff794 - languageName: node - linkType: hard - "follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.15.0": version: 1.15.3 resolution: "follow-redirects@npm:1.15.3" @@ -9868,6 +10589,13 @@ __metadata: languageName: node linkType: hard +"form-data-encoder@npm:^2.1.2": + version: 2.1.4 + resolution: "form-data-encoder@npm:2.1.4" + checksum: e0b3e5950fb69b3f32c273944620f9861f1933df9d3e42066e038e26dfb343d0f4465de9f27e0ead1a09d9df20bc2eed06a63c2ca2f8f00949e7202bae9e29dd + languageName: node + linkType: hard + "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -9879,6 +10607,13 @@ __metadata: languageName: node linkType: hard +"format@npm:^0.2.0": + version: 0.2.2 + resolution: "format@npm:0.2.2" + checksum: 646a60e1336250d802509cf24fb801e43bd4a70a07510c816fa133aa42cdbc9c21e66e9cc0801bb183c5b031c9d68be62e7fbb6877756e52357850f92aa28799 + languageName: node + linkType: hard + "formdata-polyfill@npm:^4.0.10": version: 4.0.10 resolution: "formdata-polyfill@npm:4.0.10" @@ -9961,6 +10696,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.1.1": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 + languageName: node + linkType: hard + "fs-extra@npm:^7.0.1": version: 7.0.1 resolution: "fs-extra@npm:7.0.1" @@ -10149,7 +10895,7 @@ __metadata: languageName: node linkType: hard -"github-slugger@npm:^1.4.0": +"github-slugger@npm:^1.4.0, github-slugger@npm:^1.5.0": version: 1.5.0 resolution: "github-slugger@npm:1.5.0" checksum: c70988224578b3bdaa25df65973ffc8c24594a77a28550c3636e495e49d17aef5cdb04c04fa3f1744babef98c61eecc6a43299a13ea7f3cc33d680bf9053ffbe @@ -10261,11 +11007,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: ^0.20.2 - checksum: 194c97cf8d1ef6ba59417234c2386549c4103b6e5f24b1ff1952de61a4753e5d2069435ba629de711a6480b1b1d114a98e2ab27f85e966d5a10c319c3bbd3dc3 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c languageName: node linkType: hard @@ -10305,6 +11051,25 @@ __metadata: languageName: node linkType: hard +"got@npm:^12.1.0": + version: 12.6.1 + resolution: "got@npm:12.6.1" + dependencies: + "@sindresorhus/is": ^5.2.0 + "@szmarczak/http-timer": ^5.0.1 + cacheable-lookup: ^7.0.0 + cacheable-request: ^10.2.8 + decompress-response: ^6.0.0 + form-data-encoder: ^2.1.2 + get-stream: ^6.0.1 + http2-wrapper: ^2.1.10 + lowercase-keys: ^3.0.0 + p-cancelable: ^3.0.0 + responselike: ^3.0.0 + checksum: 3c37f5d858aca2859f9932e7609d35881d07e7f2d44c039d189396f0656896af6c77c22f2c51c563f8918be483f60ff41e219de742ab4642d4b106711baccbd5 + languageName: node + linkType: hard + "got@npm:^9.6.0": version: 9.6.0 resolution: "got@npm:9.6.0" @@ -10324,6 +11089,13 @@ __metadata: languageName: node linkType: hard +"graceful-fs@npm:4.2.10": + version: 4.2.10 + resolution: "graceful-fs@npm:4.2.10" + checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da + languageName: node + linkType: hard + "graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -10367,8 +11139,8 @@ __metadata: linkType: hard "hardhat@npm:^2.17.4": - version: 2.19.1 - resolution: "hardhat@npm:2.19.1" + version: 2.19.2 + resolution: "hardhat@npm:2.19.2" dependencies: "@ethersproject/abi": ^5.1.2 "@metamask/eth-sig-util": ^4.0.0 @@ -10428,7 +11200,7 @@ __metadata: optional: true bin: hardhat: internal/cli/bootstrap.js - checksum: 0c12069e8eae47419d595e38d22716049136cf74390f9e89121ae73fdc716ffcb6cd3283e3ca8676ce00e3ff90804dfa95473830d96340ec01860dfa6237d8d3 + checksum: 0b5499890e46750ca8c51bbe1205599b1424a2e5293b40c9f7cb56320d56b9935fbd4e276de370e07664ae81fa57dc7ab227bf2b2363f5732ef9f06df1a9a6d9 languageName: node linkType: hard @@ -10485,6 +11257,13 @@ __metadata: languageName: node linkType: hard +"has-yarn@npm:^3.0.0": + version: 3.0.0 + resolution: "has-yarn@npm:3.0.0" + checksum: b9e14e78e0a37bc070550c862b201534287bc10e62a86ec9c1f455ffb082db42817ce9aed914bd73f1d589bbf268520e194629ff2f62ff6b98a482c4bd2dcbfb + languageName: node + linkType: hard + "hash-base@npm:^3.0.0": version: 3.1.0 resolution: "hash-base@npm:3.1.0" @@ -10530,6 +11309,43 @@ __metadata: languageName: node linkType: hard +"hast-util-from-dom@npm:^5.0.0": + version: 5.0.0 + resolution: "hast-util-from-dom@npm:5.0.0" + dependencies: + "@types/hast": ^3.0.0 + hastscript: ^8.0.0 + web-namespaces: ^2.0.0 + checksum: bf8f96c480a598b42156227be2210bbb7a08da519ae4d57814385c8560b01e2b6b5fbde2afce808ce7ba7c5cd172822d4285b8f5edde2d13089bc9c3177c0d09 + languageName: node + linkType: hard + +"hast-util-from-html-isomorphic@npm:^2.0.0": + version: 2.0.0 + resolution: "hast-util-from-html-isomorphic@npm:2.0.0" + dependencies: + "@types/hast": ^3.0.0 + hast-util-from-dom: ^5.0.0 + hast-util-from-html: ^2.0.0 + unist-util-remove-position: ^5.0.0 + checksum: a98d02890bd1b5a804a1b2aaacd0332a6563f2a8df620450e38ab8962728cda0485cd29435824840621d1e653943776864e912d78d24cce6a7f484011ee7cef0 + languageName: node + linkType: hard + +"hast-util-from-html@npm:^2.0.0": + version: 2.0.1 + resolution: "hast-util-from-html@npm:2.0.1" + dependencies: + "@types/hast": ^3.0.0 + devlop: ^1.1.0 + hast-util-from-parse5: ^8.0.0 + parse5: ^7.0.0 + vfile: ^6.0.0 + vfile-message: ^4.0.0 + checksum: 8decdec1f2750d3d8d4933a4d06d78846a9fb3c97cded07395d160adae22bacfc69eaf113fd95a6ad696d1e5877580f2ac83a4161fa9f3becb0fafe2cec8b0ea + languageName: node + linkType: hard + "hast-util-from-parse5@npm:^6.0.0": version: 6.0.1 resolution: "hast-util-from-parse5@npm:6.0.1" @@ -10544,13 +11360,38 @@ __metadata: languageName: node linkType: hard -"hast-util-is-element@npm:^1.0.0, hast-util-is-element@npm:^1.1.0": +"hast-util-from-parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "hast-util-from-parse5@npm:8.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + hastscript: ^8.0.0 + property-information: ^6.0.0 + vfile: ^6.0.0 + vfile-location: ^5.0.0 + web-namespaces: ^2.0.0 + checksum: fdd1ab8b03af13778ecb94ef9a58b1e3528410cdfceb3d6bb7600508967d0d836b451bc7bc3baf66efb7c730d3d395eea4bb1b30352b0162823d9f0de976774b + languageName: node + linkType: hard + +"hast-util-is-element@npm:^1.1.0": version: 1.1.0 resolution: "hast-util-is-element@npm:1.1.0" checksum: 30fad3f65e7ab2f0efd5db9e7344d0820b70971988dfe79f62d8447598b2a1ce8a59cd4bfc05ae0d9a1c451b9b53cbe1023743d7eac764d64720b6b73475f62f languageName: node linkType: hard +"hast-util-is-element@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-is-element@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 82569a420eda5877c52fdbbdbe26675f012c02d70813dfd19acffdee328e42e4bd0b7ae34454cfcbcb932b2bedbd7ddc119f943a0cfb234120f9456d6c0c4331 + languageName: node + linkType: hard + "hast-util-parse-selector@npm:^2.0.0": version: 2.2.5 resolution: "hast-util-parse-selector@npm:2.2.5" @@ -10558,6 +11399,15 @@ __metadata: languageName: node linkType: hard +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 76087670d3b0b50b23a6cb70bca53a6176d6608307ccdbb3ed18b650b82e7c3513bfc40348f1389dc0c5ae872b9a768851f4335f44654abd7deafd6974c52402 + languageName: node + linkType: hard + "hast-util-raw@npm:6.0.1": version: 6.0.1 resolution: "hast-util-raw@npm:6.0.1" @@ -10576,6 +11426,74 @@ __metadata: languageName: node linkType: hard +"hast-util-raw@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-util-raw@npm:9.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + "@ungap/structured-clone": ^1.0.0 + hast-util-from-parse5: ^8.0.0 + hast-util-to-parse5: ^8.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + parse5: ^7.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 4b486eb4782eafb471ae639d45c14ac8797676518cf5da16adc973f52d7b8e1075a1451558c023b390820bd9fd213213e6248a2dae71b68ac5040b277509b8d9 + languageName: node + linkType: hard + +"hast-util-to-estree@npm:^3.0.0": + version: 3.1.0 + resolution: "hast-util-to-estree@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-attach-comments: ^3.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^0.4.0 + unist-util-position: ^5.0.0 + zwitch: ^2.0.0 + checksum: 61272f7c18c9d2a5e34df7cfd2c97cbf12f6e9d05114d60e4dedd64e5576565eb1e35c78b9213c909bb8f984f0f8e9c49b568f04bdb444b83d0bca9159e14f3c + languageName: node + linkType: hard + +"hast-util-to-jsx-runtime@npm:^2.0.0": + version: 2.3.0 + resolution: "hast-util-to-jsx-runtime@npm:2.3.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^1.0.0 + unist-util-position: ^5.0.0 + vfile-message: ^4.0.0 + checksum: 599a97c6ec61c1430776813d7fb42e6f96032bf4a04dfcbb8eceef3bc8d1845ecf242387a4426b9d3f52320dbbfa26450643b81124b3d6a0b9bbb0fff4d0ba83 + languageName: node + linkType: hard + "hast-util-to-parse5@npm:^6.0.0": version: 6.0.0 resolution: "hast-util-to-parse5@npm:6.0.0" @@ -10589,14 +11507,39 @@ __metadata: languageName: node linkType: hard -"hast-util-to-text@npm:^2.0.0": - version: 2.0.1 - resolution: "hast-util-to-text@npm:2.0.1" +"hast-util-to-parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "hast-util-to-parse5@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 137469209cb2b32b57387928878dc85310fbd5afa4807a8da69529199bb1d19044bfc95b50c3dc68d4fb2b6cb8bf99b899285597ab6ab318f50422eefd5599dd + languageName: node + linkType: hard + +"hast-util-to-text@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-to-text@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + hast-util-is-element: ^3.0.0 + unist-util-find-after: ^5.0.0 + checksum: 3beedbdf20e2ecc9352cdd0963848b741294c1f3872d43400125bc0ca2d7938d5358081b0f9c252ec15c22368f30a4e7e6ca0ce5a57d4d2bcdd02adbf884e2af + languageName: node + linkType: hard + +"hast-util-whitespace@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-whitespace@npm:3.0.0" dependencies: - hast-util-is-element: ^1.0.0 - repeat-string: ^1.0.0 - unist-util-find-after: ^3.0.0 - checksum: 4e7960b414b7a6b2f0180e4af416cd8ae3c7ba1531d7eaec7e6dc9509daf88308784bbf5b94885384dccc42abcb74cc6cc26755c76914d646f32aa6bc32ea34b + "@types/hast": ^3.0.0 + checksum: 41d93ccce218ba935dc3c12acdf586193c35069489c8c8f50c2aa824c00dec94a3c78b03d1db40fa75381942a189161922e4b7bca700b3a2cc779634c351a1e4 languageName: node linkType: hard @@ -10613,6 +11556,19 @@ __metadata: languageName: node linkType: hard +"hastscript@npm:^8.0.0": + version: 8.0.0 + resolution: "hastscript@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-parse-selector: ^4.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + checksum: ae3c20223e7b847320c0f98b6fb3c763ebe1bf3913c5805fbc176cf84553a9db1117ca34cf842a5235890b4b9ae0e94501bfdc9a9b870a5dbf5fc52426db1097 + languageName: node + linkType: hard + "he@npm:1.2.0, he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -10699,7 +11655,24 @@ __metadata: languageName: node linkType: hard -"html-tags@npm:^3.2.0": +"html-minifier-terser@npm:^7.2.0": + version: 7.2.0 + resolution: "html-minifier-terser@npm:7.2.0" + dependencies: + camel-case: ^4.1.2 + clean-css: ~5.3.2 + commander: ^10.0.0 + entities: ^4.4.0 + param-case: ^3.0.4 + relateurl: ^0.2.7 + terser: ^5.15.1 + bin: + html-minifier-terser: cli.js + checksum: 39feed354b5a8aafc8e910977d68cfd961d6db330a8e1a5b16a528c86b8ee7745d8945134822cf00acf7bf0d0135bf1abad650bf308bee4ea73adb003f5b8656 + languageName: node + linkType: hard + +"html-tags@npm:^3.2.0, html-tags@npm:^3.3.1": version: 3.3.1 resolution: "html-tags@npm:3.3.1" checksum: b4ef1d5a76b678e43cce46e3783d563607b1d550cab30b4f511211564574770aa8c658a400b100e588bc60b8234e59b35ff72c7851cc28f3b5403b13a2c6cbce @@ -10713,9 +11686,16 @@ __metadata: languageName: node linkType: hard -"html-webpack-plugin@npm:^5.5.0": - version: 5.5.3 - resolution: "html-webpack-plugin@npm:5.5.3" +"html-void-elements@npm:^3.0.0": + version: 3.0.0 + resolution: "html-void-elements@npm:3.0.0" + checksum: 59be397525465a7489028afa064c55763d9cccd1d7d9f630cca47137317f0e897a9ca26cef7e745e7cff1abc44260cfa407742b243a54261dfacd42230e94fce + languageName: node + linkType: hard + +"html-webpack-plugin@npm:^5.5.0, html-webpack-plugin@npm:^5.5.3": + version: 5.5.4 + resolution: "html-webpack-plugin@npm:5.5.4" dependencies: "@types/html-minifier-terser": ^6.0.0 html-minifier-terser: ^6.0.2 @@ -10724,7 +11704,7 @@ __metadata: tapable: ^2.0.0 peerDependencies: webpack: ^5.20.0 - checksum: ccf685195739c372ad641bbd0c9100a847904f34eedc7aff3ece7856cd6c78fd3746d2d615af1bb71e5727993fe711b89e9b744f033ed3fde646540bf5d5e954 + checksum: b49befb73d67a3716fd0e6f7776b108d2b0b7050fb8221f05cd114cbae13c03150a13b7cdf5e76170be040ce7936a1cf76f7a4bfd9ebe1552b72d7889a74c374 languageName: node linkType: hard @@ -10860,6 +11840,16 @@ __metadata: languageName: node linkType: hard +"http2-wrapper@npm:^2.1.10": + version: 2.2.1 + resolution: "http2-wrapper@npm:2.2.1" + dependencies: + quick-lru: ^5.1.1 + resolve-alpn: ^1.2.0 + checksum: e95e55e22c6fd61182ce81fecb9b7da3af680d479febe8ad870d05f7ebbc9f076e455193766f4e7934e50913bf1d8da3ba121fb5cd2928892390b58cf9d5c509 + languageName: node + linkType: hard + "https-proxy-agent@npm:5.0.1, https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -10942,7 +11932,7 @@ __metadata: languageName: node linkType: hard -"image-size@npm:^1.0.1": +"image-size@npm:^1.0.1, image-size@npm:^1.0.2": version: 1.0.2 resolution: "image-size@npm:1.0.2" dependencies: @@ -10991,6 +11981,13 @@ __metadata: languageName: node linkType: hard +"import-lazy@npm:^4.0.0": + version: 4.0.0 + resolution: "import-lazy@npm:4.0.0" + checksum: 22f5e51702134aef78890156738454f620e5fe7044b204ebc057c614888a1dd6fdf2ede0fdcca44d5c173fd64f65c985f19a51775b06967ef58cc3d26898df07 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -11057,7 +12054,7 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.5, ini@npm:~1.3.0": +"ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 @@ -11071,6 +12068,13 @@ __metadata: languageName: node linkType: hard +"inline-style-parser@npm:0.2.2": + version: 0.2.2 + resolution: "inline-style-parser@npm:0.2.2" + checksum: 698893d6542d4e7c0377936a1c7daec34a197765bd77c5599384756a95ce8804e6b79347b783aa591d5e9c6f3d33dae74c6d4cad3a94647eb05f3a785e927a3f + languageName: node + linkType: hard + "integration-tests@workspace:compiler/integration-tests": version: 0.0.0-use.local resolution: "integration-tests@workspace:compiler/integration-tests" @@ -11162,6 +12166,13 @@ __metadata: languageName: node linkType: hard +"is-alphabetical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphabetical@npm:2.0.1" + checksum: 56207db8d9de0850f0cd30f4966bf731eb82cedfe496cbc2e97e7c3bacaf66fc54a972d2d08c0d93bb679cb84976a05d24c5ad63de56fabbfc60aadae312edaa + languageName: node + linkType: hard + "is-alphanumerical@npm:^1.0.0": version: 1.0.4 resolution: "is-alphanumerical@npm:1.0.4" @@ -11172,6 +12183,16 @@ __metadata: languageName: node linkType: hard +"is-alphanumerical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphanumerical@npm:2.0.1" + dependencies: + is-alphabetical: ^2.0.0 + is-decimal: ^2.0.0 + checksum: 87acc068008d4c9c4e9f5bd5e251041d42e7a50995c77b1499cf6ed248f971aadeddb11f239cabf09f7975ee58cac7a48ffc170b7890076d8d227b24a68663c9 + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -11215,6 +12236,17 @@ __metadata: languageName: node linkType: hard +"is-ci@npm:^3.0.1": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: ^3.2.0 + bin: + is-ci: bin.js + checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e + languageName: node + linkType: hard + "is-core-module@npm:^2.13.0": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" @@ -11231,6 +12263,13 @@ __metadata: languageName: node linkType: hard +"is-decimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-decimal@npm:2.0.1" + checksum: 97132de7acdce77caa7b797632970a2ecd649a88e715db0e4dbc00ab0708b5e7574ba5903962c860cd4894a14fd12b100c0c4ac8aed445cf6f55c6cf747a4158 + languageName: node + linkType: hard + "is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": version: 2.2.1 resolution: "is-docker@npm:2.2.1" @@ -11316,6 +12355,13 @@ __metadata: languageName: node linkType: hard +"is-hexadecimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-hexadecimal@npm:2.0.1" + checksum: 66a2ea85994c622858f063f23eda506db29d92b52580709eb6f4c19550552d4dcf3fb81952e52f7cf972097237959e00adc7bb8c9400cd12886e15bf06145321 + languageName: node + linkType: hard + "is-inside-container@npm:^1.0.0": version: 1.0.0 resolution: "is-inside-container@npm:1.0.0" @@ -11358,6 +12404,13 @@ __metadata: languageName: node linkType: hard +"is-npm@npm:^6.0.0": + version: 6.0.0 + resolution: "is-npm@npm:6.0.0" + checksum: fafe1ddc772345f5460514891bb8014376904ccdbddd59eee7525c9adcc08d426933f28b087bef3e17524da7ebf35c03ef484ff3b6ba9d5fecd8c6e6a7d4bf11 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -11407,6 +12460,13 @@ __metadata: languageName: node linkType: hard +"is-plain-obj@npm:^4.0.0": + version: 4.1.0 + resolution: "is-plain-obj@npm:4.1.0" + checksum: 6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce + languageName: node + linkType: hard + "is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -11430,6 +12490,15 @@ __metadata: languageName: node linkType: hard +"is-reference@npm:^3.0.0": + version: 3.0.2 + resolution: "is-reference@npm:3.0.2" + dependencies: + "@types/estree": "*" + checksum: ac3bf5626fe9d0afbd7454760d73c47f16b9f471401b9749721ad3b66f0a39644390382acf88ca9d029c95782c1e2ec65662855e3ba91acf52d82231247a7fd3 + languageName: node + linkType: hard + "is-regexp@npm:^1.0.0": version: 1.0.0 resolution: "is-regexp@npm:1.0.0" @@ -11509,6 +12578,13 @@ __metadata: languageName: node linkType: hard +"is-yarn-global@npm:^0.4.0": + version: 0.4.1 + resolution: "is-yarn-global@npm:0.4.1" + checksum: 79ec4e6f581c53d4fefdf5f6c237f9a3ad8db29c85cdc4659e76ae345659317552052a97b7e56952aa5d94a23c798ebec8ccad72fb14d3b26dc647ddceddd716 + languageName: node + linkType: hard + "isarray@npm:0.0.1": version: 0.0.1 resolution: "isarray@npm:0.0.1" @@ -11629,7 +12705,7 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^1.18.2": +"jiti@npm:^1.18.2, jiti@npm:^1.20.0": version: 1.21.0 resolution: "jiti@npm:1.21.0" bin: @@ -11638,7 +12714,7 @@ __metadata: languageName: node linkType: hard -"joi@npm:^17.6.0": +"joi@npm:^17.6.0, joi@npm:^17.9.2": version: 17.11.0 resolution: "joi@npm:17.11.0" dependencies: @@ -11822,14 +12898,14 @@ __metadata: languageName: node linkType: hard -"katex@npm:^0.13.0": - version: 0.13.24 - resolution: "katex@npm:0.13.24" +"katex@npm:^0.16.0": + version: 0.16.9 + resolution: "katex@npm:0.16.9" dependencies: - commander: ^8.0.0 + commander: ^8.3.0 bin: katex: cli.js - checksum: 1b7c8295867073d0db4f6fb41ef1c0e3418b8e23924ff61b446b36134cb74cdadc7242dfbfb922d9c32f0b15eda6160a08cd30948c4e78141966ca2991a1726b + checksum: 861194dfd4d86505e657f688fb73048d46ac498edafce71199502a35b03c0ecc35ba930c631be79c4a09d90a0d23476673cd52f6bc367c7a161854d64005fa95 languageName: node linkType: hard @@ -12001,6 +13077,15 @@ __metadata: languageName: node linkType: hard +"latest-version@npm:^7.0.0": + version: 7.0.0 + resolution: "latest-version@npm:7.0.0" + dependencies: + package-json: ^8.1.0 + checksum: 1f0deba00d5a34394cce4463c938811f51bbb539b131674f4bb2062c63f2cc3b80bccd56ecade3bd5932d04a34cf0a5a8a2ccc4ec9e5e6b285a9a7b3e27d0d66 + languageName: node + linkType: hard + "launch-editor@npm:^2.6.0": version: 2.6.1 resolution: "launch-editor@npm:2.6.1" @@ -12172,13 +13257,6 @@ __metadata: languageName: node linkType: hard -"lodash.curry@npm:^4.0.1": - version: 4.1.1 - resolution: "lodash.curry@npm:4.1.1" - checksum: 9192b70fe7df4d1ff780c0260bee271afa9168c93fe4fa24bc861900240531b59781b5fdaadf4644fea8f4fbcd96f0700539ab294b579ffc1022c6c15dcc462a - languageName: node - linkType: hard - "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -12186,13 +13264,6 @@ __metadata: languageName: node linkType: hard -"lodash.flow@npm:^3.3.0": - version: 3.5.0 - resolution: "lodash.flow@npm:3.5.0" - checksum: a9a62ad344e3c5a1f42bc121da20f64dd855aaafecee24b1db640f29b88bd165d81c37ff7e380a7191de6f70b26f5918abcebbee8396624f78f3618a0b18634c - languageName: node - linkType: hard - "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -12250,9 +13321,16 @@ __metadata: languageName: node linkType: hard -"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" +"longest-streak@npm:^3.0.0": + version: 3.1.0 + resolution: "longest-streak@npm:3.1.0" + checksum: d7f952ed004cbdb5c8bcfc4f7f5c3d65449e6c5a9e9be4505a656e3df5a57ee125f284286b4bf8ecea0c21a7b3bf2b8f9001ad506c319b9815ad6a63a47d0fd0 + languageName: node + linkType: hard + +"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" dependencies: js-tokens: ^3.0.0 || ^4.0.0 bin: @@ -12293,6 +13371,13 @@ __metadata: languageName: node linkType: hard +"lowercase-keys@npm:^3.0.0": + version: 3.0.0 + resolution: "lowercase-keys@npm:3.0.0" + checksum: 67a3f81409af969bc0c4ca0e76cd7d16adb1e25aa1c197229587eaf8671275c8c067cd421795dbca4c81be0098e4c426a086a05e30de8a9c587b7a13c0c7ccc5 + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.1.0 resolution: "lru-cache@npm:10.1.0" @@ -12406,196 +13491,990 @@ __metadata: languageName: node linkType: hard -"mark.js@npm:^8.11.1": - version: 8.11.1 - resolution: "mark.js@npm:8.11.1" - checksum: aa6b9ae1c67245348d5b7abd253ef2acd6bb05c6be358d7d192416d964e42665fc10e0e865591c6f93ab9b57e8da1f23c23216e8ebddb580905ea7a0c0df15d4 +"mark.js@npm:^8.11.1": + version: 8.11.1 + resolution: "mark.js@npm:8.11.1" + checksum: aa6b9ae1c67245348d5b7abd253ef2acd6bb05c6be358d7d192416d964e42665fc10e0e865591c6f93ab9b57e8da1f23c23216e8ebddb580905ea7a0c0df15d4 + languageName: node + linkType: hard + +"markdown-escapes@npm:^1.0.0": + version: 1.0.4 + resolution: "markdown-escapes@npm:1.0.4" + checksum: 6833a93d72d3f70a500658872312c6fa8015c20cc835a85ae6901fa232683fbc6ed7118ebe920fea7c80039a560f339c026597d96eee0e9de602a36921804997 + languageName: node + linkType: hard + +"markdown-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "markdown-extensions@npm:2.0.0" + checksum: ec4ffcb0768f112e778e7ac74cb8ef22a966c168c3e6c29829f007f015b0a0b5c79c73ee8599a0c72e440e7f5cfdbf19e80e2d77b9a313b8f66e180a330cf1b2 + languageName: node + linkType: hard + +"markdown-table@npm:^3.0.0": + version: 3.0.3 + resolution: "markdown-table@npm:3.0.3" + checksum: 8fcd3d9018311120fbb97115987f8b1665a603f3134c93fbecc5d1463380c8036f789e2a62c19432058829e594fff8db9ff81c88f83690b2f8ed6c074f8d9e10 + languageName: node + linkType: hard + +"marked@npm:^4.3.0": + version: 4.3.0 + resolution: "marked@npm:4.3.0" + bin: + marked: bin/marked.js + checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 + languageName: node + linkType: hard + +"marky@npm:^1.2.2": + version: 1.2.5 + resolution: "marky@npm:1.2.5" + checksum: 823b946677749551cdfc3b5221685478b5d1b9cc0dc03eff977c6f9a615fb05c67559f9556cb3c0fcb941a9ea0e195e37befd83026443396ccee8b724f54f4c5 + languageName: node + linkType: hard + +"matcher@npm:^5.0.0": + version: 5.0.0 + resolution: "matcher@npm:5.0.0" + dependencies: + escape-string-regexp: ^5.0.0 + checksum: 28f191c2d23fee0f6f32fd0181d9fe173b0ab815a919edba55605438a2f9fa40372e002574a1b17add981b0a8669c75bc6194318d065ed2dceffd8b160c38118 + languageName: node + linkType: hard + +"mcl-wasm@npm:^0.7.1": + version: 0.7.9 + resolution: "mcl-wasm@npm:0.7.9" + checksum: 6b6ed5084156b98b2db70b223e1ba2c01953970b48a2e0c4ea3eeb9296610e6b3bfb2a2cce9e92e2d7ad61778b5f5a630e705e663835e915ba188c174a0a37fa + languageName: node + linkType: hard + +"md5-hex@npm:^3.0.1": + version: 3.0.1 + resolution: "md5-hex@npm:3.0.1" + dependencies: + blueimp-md5: ^2.10.0 + checksum: 6799a19e8bdd3e0c2861b94c1d4d858a89220488d7885c1fa236797e367d0c2e5f2b789e05309307083503f85be3603a9686a5915568a473137d6b4117419cc2 + languageName: node + linkType: hard + +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: ^3.0.0 + inherits: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c + languageName: node + linkType: hard + +"mdast-squeeze-paragraphs@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-squeeze-paragraphs@npm:4.0.0" + dependencies: + unist-util-remove: ^2.0.0 + checksum: dfe8ec8e8a62171f020e82b088cc35cb9da787736dc133a3b45ce8811782a93e69bf06d147072e281079f09fac67be8a36153ffffd9bfbf89ed284e4c4f56f75 + languageName: node + linkType: hard + +"mdast-util-definitions@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-definitions@npm:4.0.0" + dependencies: + unist-util-visit: ^2.0.0 + checksum: 2325f20b82b3fb8cb5fda77038ee0bbdd44f82cfca7c48a854724b58bc1fe5919630a3ce7c45e210726df59d46c881d020b2da7a493bfd1ee36eb2bbfef5d78e + languageName: node + linkType: hard + +"mdast-util-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 593afdc4f39f99bb198f3774bf4648cb546cb99a055e40c82262a7faab10926d2529a725d0d3945300ed0a1f07c6c84215a3f76b899a89b3f410ec7375bbab17 + languageName: node + linkType: hard + +"mdast-util-find-and-replace@npm:^3.0.0, mdast-util-find-and-replace@npm:^3.0.1": + version: 3.0.1 + resolution: "mdast-util-find-and-replace@npm:3.0.1" + dependencies: + "@types/mdast": ^4.0.0 + escape-string-regexp: ^5.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 05d5c4ff02e31db2f8a685a13bcb6c3f44e040bd9dfa54c19a232af8de5268334c8755d79cb456ed4cced1300c4fb83e88444c7ae8ee9ff16869a580f29d08cd + languageName: node + linkType: hard + +"mdast-util-from-markdown@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-from-markdown@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + mdast-util-to-string: ^4.0.0 + micromark: ^4.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-decode-string: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 4e8d8a46b4b588486c41b80c39da333a91593bc8d60cd7421c6cd3c22003b8e5a62478292fb7bc97b9255b6301a2250cca32340ef43c309156e215453c5b92be + languageName: node + linkType: hard + +"mdast-util-frontmatter@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-frontmatter@npm:2.0.1" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + escape-string-regexp: ^5.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + checksum: 86a7c8d9eb183be2621d6d9134b9d33df2a3647e3255f68a9796e2425e25643ffae00a501e36c57d9c10973087b94aa5a2ffd865d33cdd274cc9b88cd2d90a2e + languageName: node + linkType: hard + +"mdast-util-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-autolink-literal@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + ccount: ^2.0.0 + devlop: ^1.0.0 + mdast-util-find-and-replace: ^3.0.0 + micromark-util-character: ^2.0.0 + checksum: 10322662e5302964bed7c9829c5fd3b0c9899d4f03e63fb8620ab141cf4f3de9e61fcb4b44d46aacc8a23f82bcd5d900980a211825dfe026b1dab5fdbc3e8742 + languageName: node + linkType: hard + +"mdast-util-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-footnote@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + checksum: 45d26b40e7a093712e023105791129d76e164e2168d5268e113298a22de30c018162683fb7893cdc04ab246dac0087eed708b2a136d1d18ed2b32b3e0cae4a79 + languageName: node + linkType: hard + +"mdast-util-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-strikethrough@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: fe9b1d0eba9b791ff9001c008744eafe3dd7a81b085f2bf521595ce4a8e8b1b44764ad9361761ad4533af3e5d913d8ad053abec38172031d9ee32a8ebd1c7dbd + languageName: node + linkType: hard + +"mdast-util-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-table@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + markdown-table: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 063a627fd0993548fd63ca0c24c437baf91ba7d51d0a38820bd459bc20bf3d13d7365ef8d28dca99176dd5eb26058f7dde51190479c186dfe6af2e11202957c9 + languageName: node + linkType: hard + +"mdast-util-gfm-task-list-item@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-task-list-item@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 37db90c59b15330fc54d790404abf5ef9f2f83e8961c53666fe7de4aab8dd5e6b3c296b6be19797456711a89a27840291d8871ff0438e9b4e15c89d170efe072 + languageName: node + linkType: hard + +"mdast-util-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-gfm@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-gfm-autolink-literal: ^2.0.0 + mdast-util-gfm-footnote: ^2.0.0 + mdast-util-gfm-strikethrough: ^2.0.0 + mdast-util-gfm-table: ^2.0.0 + mdast-util-gfm-task-list-item: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 62039d2f682ae3821ea1c999454863d31faf94d67eb9b746589c7e136076d7fb35fabc67e02f025c7c26fd7919331a0ee1aabfae24f565d9a6a9ebab3371c626 + languageName: node + linkType: hard + +"mdast-util-math@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-math@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + longest-streak: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.1.0 + unist-util-remove-position: ^5.0.0 + checksum: dc7dfb14aec2ec143420f2d92f80c5e6d69293d7cfb6b8180e7f411ce4e1314b5cf4a8d3345eefe06ab0ddd95e3c7801c4174b343fd2c26741180ca4dbad5371 + languageName: node + linkType: hard + +"mdast-util-mdx-expression@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-mdx-expression@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 4e1183000e183e07a7264e192889b4fd57372806103031c71b9318967f85fd50a5dd0f92ef14f42c331e77410808f5de3341d7bc8ad4ee91b7fa8f0a30043a8a + languageName: node + linkType: hard + +"mdast-util-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx-jsx@npm:3.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + ccount: ^2.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-remove-position: ^5.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 48fe1ba617205f3776ca2030d195adbdb42bb6c53326534db3f5bdd28abe7895103af8c4dfda7cbe2911e8cd71921bc8a82fe40856565e57af8b4f8a79c8c126 + languageName: node + linkType: hard + +"mdast-util-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: e2b007d826fcd49fd57ed03e190753c8b0f7d9eff6c7cb26ba609cde15cd3a472c0cd5e4a1ee3e39a40f14be22fdb57de243e093cea0c064d6f3366cff3e3af2 + languageName: node + linkType: hard + +"mdast-util-mdxjs-esm@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-mdxjs-esm@npm:2.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 1f9dad04d31d59005332e9157ea9510dc1d03092aadbc607a10475c7eec1c158b475aa0601a3a4f74e13097ca735deb8c2d9d37928ddef25d3029fd7c9e14dc3 + languageName: node + linkType: hard + +"mdast-util-phrasing@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-phrasing@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + unist-util-is: ^6.0.0 + checksum: 95d5d8e18d5ea6dbfe2ee4ed1045961372efae9077e5c98e10bfef7025ee3fd9449f9a82840068ff50aa98fa43af0a0a14898ae10b5e46e96edde01e2797df34 + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:10.0.1": + version: 10.0.1 + resolution: "mdast-util-to-hast@npm:10.0.1" + dependencies: + "@types/mdast": ^3.0.0 + "@types/unist": ^2.0.0 + mdast-util-definitions: ^4.0.0 + mdurl: ^1.0.0 + unist-builder: ^2.0.0 + unist-util-generated: ^1.0.0 + unist-util-position: ^3.0.0 + unist-util-visit: ^2.0.0 + checksum: e5f385757df7e9b37db4d6f326bf7b4fc1b40f9ad01fc335686578f44abe0ba46d3e60af4d5e5b763556d02e65069ef9a09c49db049b52659203a43e7fa9084d + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:^13.0.0": + version: 13.0.2 + resolution: "mdast-util-to-hast@npm:13.0.2" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@ungap/structured-clone": ^1.0.0 + devlop: ^1.0.0 + micromark-util-sanitize-uri: ^2.0.0 + trim-lines: ^3.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + checksum: 8fef6c3752476461d9c00b1dea4f141bc7d980e1b3bac7bd965bc68f532b6d30fb1c9e810433327c167176e68e071b8f4ab5a45355954857dc095c878421f35e + languageName: node + linkType: hard + +"mdast-util-to-markdown@npm:^2.0.0, mdast-util-to-markdown@npm:^2.1.0": + version: 2.1.0 + resolution: "mdast-util-to-markdown@npm:2.1.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + longest-streak: ^3.0.0 + mdast-util-phrasing: ^4.0.0 + mdast-util-to-string: ^4.0.0 + micromark-util-decode-string: ^2.0.0 + unist-util-visit: ^5.0.0 + zwitch: ^2.0.0 + checksum: 3a2cf3957e23b34e2e092e6e76ae72ee0b8745955bd811baba6814cf3a3d916c3fd52264b4b58f3bb3d512a428f84a1e998b6fc7e28434e388a9ae8fb6a9c173 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-to-string@npm:2.0.0" + checksum: 0b2113ada10e002fbccb014170506dabe2f2ddacaacbe4bc1045c33f986652c5a162732a2c057c5335cdb58419e2ad23e368e5be226855d4d4e280b81c4e9ec2 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-to-string@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + checksum: 35489fb5710d58cbc2d6c8b6547df161a3f81e0f28f320dfb3548a9393555daf07c310c0c497708e67ed4dfea4a06e5655799e7d631ca91420c288b4525d6c29 + languageName: node + linkType: hard + +"mdn-data@npm:2.0.14": + version: 2.0.14 + resolution: "mdn-data@npm:2.0.14" + checksum: 9d0128ed425a89f4cba8f787dca27ad9408b5cb1b220af2d938e2a0629d17d879a34d2cb19318bdb26c3f14c77dd5dfbae67211f5caaf07b61b1f2c5c8c7dc16 + languageName: node + linkType: hard + +"mdurl@npm:^1.0.0": + version: 1.0.1 + resolution: "mdurl@npm:1.0.1" + checksum: 71731ecba943926bfbf9f9b51e28b5945f9411c4eda80894221b47cc105afa43ba2da820732b436f0798fd3edbbffcd1fc1415843c41a87fea08a41cc1e3d02b + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + +"mem@npm:^9.0.2": + version: 9.0.2 + resolution: "mem@npm:9.0.2" + dependencies: + map-age-cleaner: ^0.1.3 + mimic-fn: ^4.0.0 + checksum: 07829bb182af0e3ecf748dc2edb1c3b10a256ef10458f7e24d06561a2adc2b3ef34d14abe81678bbcedb46faa477e7370223f118b1a5e1252da5fe43496f3967 + languageName: node + linkType: hard + +"memfs@npm:^3.1.2, memfs@npm:^3.4.3": + version: 3.5.3 + resolution: "memfs@npm:3.5.3" + dependencies: + fs-monkey: ^1.0.4 + checksum: 18dfdeacad7c8047b976a6ccd58bc98ba76e122ad3ca0e50a21837fe2075fc0d9aafc58ab9cf2576c2b6889da1dd2503083f2364191b695273f40969db2ecc44 + languageName: node + linkType: hard + +"memory-level@npm:^1.0.0": + version: 1.0.0 + resolution: "memory-level@npm:1.0.0" + dependencies: + abstract-level: ^1.0.0 + functional-red-black-tree: ^1.0.1 + module-error: ^1.0.1 + checksum: 80b1b7aedaf936e754adbcd7b9303018c3684fb32f9992fd967c448f145d177f16c724fbba9ed3c3590a9475fd563151eae664d69b83d2ad48714852e9fc5c72 + languageName: node + linkType: hard + +"memorystream@npm:^0.3.1": + version: 0.3.1 + resolution: "memorystream@npm:0.3.1" + checksum: f18b42440d24d09516d01466c06adf797df7873f0d40aa7db02e5fb9ed83074e5e65412d0720901d7069363465f82dc4f8bcb44f0cde271567a61426ce6ca2e9 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 + 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" + checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a + languageName: node + linkType: hard + +"micromark-core-commonmark@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-core-commonmark@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-factory-destination: ^2.0.0 + micromark-factory-label: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-title: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-html-tag-name: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9c12fb580cf4ce71f60872043bd2794efe129f44d7b2b73afa155bbc0a66b7bc35655ba8cef438a6bd068441837ed3b6dc6ad7e5a18f815462c1750793e03a42 + languageName: node + linkType: hard + +"micromark-extension-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-directive@npm:3.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + parse-entities: ^4.0.0 + checksum: 8350106bdf039a544cba64cf7932261a710e07d73d43d6c645dd2b16577f30ebd04abf762e8ca74266f5de19938e1eeff6c237d79f8244dea23aef7f90df2c31 + languageName: node + linkType: hard + +"micromark-extension-frontmatter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-frontmatter@npm:2.0.0" + dependencies: + fault: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: f68032df38c00ae47de15b63bcd72515bfcce39de4a9262a3a1ac9c5990f253f8e41bdc65fd17ec4bb3d144c32529ce0829571331e4901a9a413f1a53785d1e8 + languageName: node + linkType: hard + +"micromark-extension-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-autolink-literal@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: fa16d59528239262d6d04d539a052baf1f81275954ec8bfadea40d81bfc25667d5c8e68b225a5358626df5e30a3933173a67fdad2fed011d37810a10b770b0b2 + languageName: node + linkType: hard + +"micromark-extension-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-footnote@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: a426fddecfac6144fc622b845cd2dc09d46faa75be5b76ff022cb76a03301b1d4929a5e5e41e071491787936be65e03d0b03c7aebc0e0136b3cdbfadadd6632c + languageName: node + linkType: hard + +"micromark-extension-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-strikethrough@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4e35fbbf364bfce08066b70acd94b9d393a8fd09a5afbe0bae70d0c8a174640b1ba86ab6b78ee38f411a813e2a718b07959216cf0063d823ba1c569a7694e5ad + languageName: node + linkType: hard + +"micromark-extension-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-table@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 71484dcf8db7b189da0528f472cc81e4d6d1a64ae43bbe7fcb7e2e1dba758a0a4f785f9f1afb9459fe5b4a02bbe023d78c95c05204414a14083052eb8219e5eb + languageName: node + linkType: hard + +"micromark-extension-gfm-tagfilter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-tagfilter@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: cf21552f4a63592bfd6c96ae5d64a5f22bda4e77814e3f0501bfe80e7a49378ad140f827007f36044666f176b3a0d5fea7c2e8e7973ce4b4579b77789f01ae95 + languageName: node + linkType: hard + +"micromark-extension-gfm-task-list-item@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-extension-gfm-task-list-item@npm:2.0.1" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 80e569ab1a1d1f89d86af91482e9629e24b7e3f019c9d7989190f36a9367c6de723b2af48e908c1b73479f35b2215d3d38c1fdbf02ab01eb2fc90a59d1cf4465 + languageName: node + linkType: hard + +"micromark-extension-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-gfm@npm:3.0.0" + dependencies: + micromark-extension-gfm-autolink-literal: ^2.0.0 + micromark-extension-gfm-footnote: ^2.0.0 + micromark-extension-gfm-strikethrough: ^2.0.0 + micromark-extension-gfm-table: ^2.0.0 + micromark-extension-gfm-tagfilter: ^2.0.0 + micromark-extension-gfm-task-list-item: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 2060fa62666a09532d6b3a272d413bc1b25bbb262f921d7402795ac021e1362c8913727e33d7528d5b4ccaf26922ec51208c43f795a702964817bc986de886c9 + languageName: node + linkType: hard + +"micromark-extension-math@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-math@npm:3.0.0" + dependencies: + "@types/katex": ^0.16.0 + devlop: ^1.0.0 + katex: ^0.16.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 14d313ea58f711d69c567951870f8d8517384cd90318d8b608b4eabb2fea2278c7de1ca38fa86067704cba679b5a82be243680436c1bc26c4c4978b28fdf647c + languageName: node + linkType: hard + +"micromark-extension-mdx-expression@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-expression@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: abd6ba0acdebc03bc0836c51a1ec4ca28e0be86f10420dd8cfbcd6c10dd37cd3f31e7c8b9792e9276e7526748883f4a30d0803d72b6285dae47d4e5348c23a10 + languageName: node + linkType: hard + +"micromark-extension-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-jsx@npm:3.0.0" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 5e2f45d381d1ce43afadc5376427b42ef8cd2a574ca3658473254eabe84db99ef1abc03055b3d86728fac7f1edfb1076e6f2f322ed8bfb1f2f14cafc2c8f0d0e + languageName: node + linkType: hard + +"micromark-extension-mdx-md@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-mdx-md@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 7daf03372fd7faddf3f0ac87bdb0debb0bb770f33b586f72251e1072b222ceee75400ab6194c0e130dbf1e077369a5b627be6e9130d7a2e9e6b849f0d18ff246 + languageName: node + linkType: hard + +"micromark-extension-mdxjs-esm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs-esm@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: fb33d850200afce567b95c90f2f7d42259bd33eea16154349e4fa77c3ec934f46c8e5c111acea16321dce3d9f85aaa4c49afe8b810e31b34effc11617aeee8f6 + languageName: node + linkType: hard + +"micromark-extension-mdxjs@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs@npm:3.0.0" + dependencies: + acorn: ^8.0.0 + acorn-jsx: ^5.0.0 + micromark-extension-mdx-expression: ^3.0.0 + micromark-extension-mdx-jsx: ^3.0.0 + micromark-extension-mdx-md: ^2.0.0 + micromark-extension-mdxjs-esm: ^3.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 7da6f0fb0e1e0270a2f5ad257e7422cc16e68efa7b8214c63c9d55bc264cb872e9ca4ac9a71b9dfd13daf52e010f730bac316086f4340e4fcc6569ec699915bf + languageName: node + linkType: hard + +"micromark-factory-destination@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-destination@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: d36e65ed1c072ff4148b016783148ba7c68a078991154625723e24bda3945160268fb91079fb28618e1613c2b6e70390a8ddc544c45410288aa27b413593071a + languageName: node + linkType: hard + +"micromark-factory-label@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-label@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: c021dbd0ed367610d35f2bae21209bc804d1a6d1286ffce458fd6a717f4d7fe581a7cba7d5c2d7a63757c44eb927c80d6a571d6ea7969fae1b48ab6461d109c4 + languageName: node + linkType: hard + +"micromark-factory-mdx-expression@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-factory-mdx-expression@npm:2.0.1" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 2ba0ae939d0174a5e5331b1a4c203b96862ccf06e8903d6bdcc2d51f75515e52d407cd394afcd182f9ff0e877dc2a14e3fa430ced0131e156650d45104de8311 + languageName: node + linkType: hard + +"micromark-factory-space@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-space@npm:1.1.0" + dependencies: + micromark-util-character: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: b58435076b998a7e244259a4694eb83c78915581206b6e7fc07b34c6abd36a1726ade63df8972fbf6c8fa38eecb9074f4e17be8d53f942e3b3d23d1a0ecaa941 languageName: node linkType: hard -"markdown-escapes@npm:^1.0.0": - version: 1.0.4 - resolution: "markdown-escapes@npm:1.0.4" - checksum: 6833a93d72d3f70a500658872312c6fa8015c20cc835a85ae6901fa232683fbc6ed7118ebe920fea7c80039a560f339c026597d96eee0e9de602a36921804997 +"micromark-factory-space@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-space@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4ffdcdc2f759887bbb356500cb460b3915ecddcb5d85c3618d7df68ad05d13ed02b1153ee1845677b7d8126df8f388288b84fcf0d943bd9c92bcc71cd7222e37 languageName: node linkType: hard -"marked@npm:^4.3.0": - version: 4.3.0 - resolution: "marked@npm:4.3.0" - bin: - marked: bin/marked.js - checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 +"micromark-factory-title@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-title@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 39e1ac23af3554e6e652e56065579bc7faf21ade7b8704b29c175871b4152b7109b790bb3cae0f7e088381139c6bac9553b8400772c3d322e4fa635f813a3578 languageName: node linkType: hard -"marky@npm:^1.2.2": - version: 1.2.5 - resolution: "marky@npm:1.2.5" - checksum: 823b946677749551cdfc3b5221685478b5d1b9cc0dc03eff977c6f9a615fb05c67559f9556cb3c0fcb941a9ea0e195e37befd83026443396ccee8b724f54f4c5 +"micromark-factory-whitespace@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-whitespace@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9587c2546d1a58b4d5472b42adf05463f6212d0449455285662d63cd8eaed89c6b159ac82713fcee5f9dd88628c24307d9533cccd8971a2f3f4d48702f8f850a languageName: node linkType: hard -"matcher@npm:^5.0.0": - version: 5.0.0 - resolution: "matcher@npm:5.0.0" +"micromark-util-character@npm:^1.0.0, micromark-util-character@npm:^1.1.0": + version: 1.2.0 + resolution: "micromark-util-character@npm:1.2.0" dependencies: - escape-string-regexp: ^5.0.0 - checksum: 28f191c2d23fee0f6f32fd0181d9fe173b0ab815a919edba55605438a2f9fa40372e002574a1b17add981b0a8669c75bc6194318d065ed2dceffd8b160c38118 + micromark-util-symbol: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: 089e79162a19b4a28731736246579ab7e9482ac93cd681c2bfca9983dcff659212ef158a66a5957e9d4b1dba957d1b87b565d85418a5b009f0294f1f07f2aaac languageName: node linkType: hard -"mcl-wasm@npm:^0.7.1": - version: 0.7.9 - resolution: "mcl-wasm@npm:0.7.9" - checksum: 6b6ed5084156b98b2db70b223e1ba2c01953970b48a2e0c4ea3eeb9296610e6b3bfb2a2cce9e92e2d7ad61778b5f5a630e705e663835e915ba188c174a0a37fa +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 318d6e16fdcbe9d89e18b8e7796568d986abbb10a9f3037b7ac9b92a236bcc962f3cd380e26a7c49df40fd1d9ca33eb546268956345b662f4c4ca4962c7695f2 languageName: node linkType: hard -"md5-hex@npm:^3.0.1": - version: 3.0.1 - resolution: "md5-hex@npm:3.0.1" +"micromark-util-chunked@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-chunked@npm:2.0.0" dependencies: - blueimp-md5: ^2.10.0 - checksum: 6799a19e8bdd3e0c2861b94c1d4d858a89220488d7885c1fa236797e367d0c2e5f2b789e05309307083503f85be3603a9686a5915568a473137d6b4117419cc2 + micromark-util-symbol: ^2.0.0 + checksum: 324f95cccdae061332a8241936eaba6ef0782a1e355bac5c607ad2564fd3744929be7dc81651315a2921535747a33243e6a5606bcb64b7a56d49b6d74ea1a3d4 languageName: node linkType: hard -"md5.js@npm:^1.3.4": - version: 1.3.5 - resolution: "md5.js@npm:1.3.5" +"micromark-util-classify-character@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-classify-character@npm:2.0.0" dependencies: - hash-base: ^3.0.0 - inherits: ^2.0.1 - safe-buffer: ^5.1.2 - checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 086e52904deffebb793fb1c08c94aabb8901f76958142dfc3a6282890ebaa983b285e69bd602b9d507f1b758ed38e75a994d2ad9fbbefa7de2584f67a16af405 languageName: node linkType: hard -"mdast-squeeze-paragraphs@npm:^4.0.0": - version: 4.0.0 - resolution: "mdast-squeeze-paragraphs@npm:4.0.0" +"micromark-util-combine-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-combine-extensions@npm:2.0.0" dependencies: - unist-util-remove: ^2.0.0 - checksum: dfe8ec8e8a62171f020e82b088cc35cb9da787736dc133a3b45ce8811782a93e69bf06d147072e281079f09fac67be8a36153ffffd9bfbf89ed284e4c4f56f75 + micromark-util-chunked: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 107c47700343f365b4ed81551e18bc3458b573c500e56ac052b2490bd548adc475216e41d2271633a8867fac66fc22ba3e0a2d74a31ed79b9870ca947eb4e3ba languageName: node linkType: hard -"mdast-util-definitions@npm:^4.0.0": - version: 4.0.0 - resolution: "mdast-util-definitions@npm:4.0.0" +"micromark-util-decode-numeric-character-reference@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-decode-numeric-character-reference@npm:2.0.1" dependencies: - unist-util-visit: ^2.0.0 - checksum: 2325f20b82b3fb8cb5fda77038ee0bbdd44f82cfca7c48a854724b58bc1fe5919630a3ce7c45e210726df59d46c881d020b2da7a493bfd1ee36eb2bbfef5d78e + micromark-util-symbol: ^2.0.0 + checksum: 9512507722efd2033a9f08715eeef787fbfe27e23edf55db21423d46d82ab46f76c89b4f960be3f5e50a2d388d89658afc0647989cf256d051e9ea01277a1adb languageName: node linkType: hard -"mdast-util-to-hast@npm:10.0.1": - version: 10.0.1 - resolution: "mdast-util-to-hast@npm:10.0.1" +"micromark-util-decode-string@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-string@npm:2.0.0" dependencies: - "@types/mdast": ^3.0.0 - "@types/unist": ^2.0.0 - mdast-util-definitions: ^4.0.0 - mdurl: ^1.0.0 - unist-builder: ^2.0.0 - unist-util-generated: ^1.0.0 - unist-util-position: ^3.0.0 - unist-util-visit: ^2.0.0 - checksum: e5f385757df7e9b37db4d6f326bf7b4fc1b40f9ad01fc335686578f44abe0ba46d3e60af4d5e5b763556d02e65069ef9a09c49db049b52659203a43e7fa9084d + decode-named-character-reference: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: a75daf32a4a6b549e9f19b4d833ebfeb09a32a9a1f9ce50f35dec6b6a3e4f9f121f49024ba7f9c91c55ebe792f7c7a332fc9604795181b6a612637df0df5b959 languageName: node linkType: hard -"mdast-util-to-string@npm:^2.0.0": +"micromark-util-encode@npm:^2.0.0": version: 2.0.0 - resolution: "mdast-util-to-string@npm:2.0.0" - checksum: 0b2113ada10e002fbccb014170506dabe2f2ddacaacbe4bc1045c33f986652c5a162732a2c057c5335cdb58419e2ad23e368e5be226855d4d4e280b81c4e9ec2 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: 853a3f33fce72aaf4ffa60b7f2b6fcfca40b270b3466e1b96561b02185d2bd8c01dd7948bc31a24ac014f4cc854e545ca9a8e9cf7ea46262f9d24c9e88551c66 languageName: node linkType: hard -"mdn-data@npm:2.0.14": - version: 2.0.14 - resolution: "mdn-data@npm:2.0.14" - checksum: 9d0128ed425a89f4cba8f787dca27ad9408b5cb1b220af2d938e2a0629d17d879a34d2cb19318bdb26c3f14c77dd5dfbae67211f5caaf07b61b1f2c5c8c7dc16 +"micromark-util-events-to-acorn@npm:^2.0.0": + version: 2.0.2 + resolution: "micromark-util-events-to-acorn@npm:2.0.2" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + estree-util-visit: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: bcb3eeac52a4ae5c3ca3d8cff514de3a7d1f272d9a94cce26a08c578bef64df4d61820874c01207e92fcace9eae5c9a7ecdddef0c6e10014b255a07b7880bf94 languageName: node linkType: hard -"mdurl@npm:^1.0.0": - version: 1.0.1 - resolution: "mdurl@npm:1.0.1" - checksum: 71731ecba943926bfbf9f9b51e28b5945f9411c4eda80894221b47cc105afa43ba2da820732b436f0798fd3edbbffcd1fc1415843c41a87fea08a41cc1e3d02b +"micromark-util-html-tag-name@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-html-tag-name@npm:2.0.0" + checksum: d786d4486f93eb0ac5b628779809ca97c5dc60f3c9fc03eb565809831db181cf8cb7f05f9ac76852f3eb35461af0f89fa407b46f3a03f4f97a96754d8dc540d8 languageName: node linkType: hard -"media-typer@npm:0.3.0": - version: 0.3.0 - resolution: "media-typer@npm:0.3.0" - checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 +"micromark-util-normalize-identifier@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-normalize-identifier@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: b36da2d3fd102053dadd953ce5c558328df12a63a8ac0e5aad13d4dda8e43b6a5d4a661baafe0a1cd8a260bead4b4a8e6e0e74193dd651e8484225bd4f4e68aa languageName: node linkType: hard -"mem@npm:^9.0.2": - version: 9.0.2 - resolution: "mem@npm:9.0.2" +"micromark-util-resolve-all@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-resolve-all@npm:2.0.0" dependencies: - map-age-cleaner: ^0.1.3 - mimic-fn: ^4.0.0 - checksum: 07829bb182af0e3ecf748dc2edb1c3b10a256ef10458f7e24d06561a2adc2b3ef34d14abe81678bbcedb46faa477e7370223f118b1a5e1252da5fe43496f3967 + micromark-util-types: ^2.0.0 + checksum: 31fe703b85572cb3f598ebe32750e59516925c7ff1f66cfe6afaebe0771a395a9eaa770787f2523d3c46082ea80e6c14f83643303740b3d650af7c96ebd30ccc languageName: node linkType: hard -"memfs@npm:^3.1.2, memfs@npm:^3.4.3": - version: 3.5.3 - resolution: "memfs@npm:3.5.3" +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" dependencies: - fs-monkey: ^1.0.4 - checksum: 18dfdeacad7c8047b976a6ccd58bc98ba76e122ad3ca0e50a21837fe2075fc0d9aafc58ab9cf2576c2b6889da1dd2503083f2364191b695273f40969db2ecc44 + micromark-util-character: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: ea4c28bbffcf2430e9aff2d18554296789a8b0a1f54ac24020d1dde76624a7f93e8f2a83e88cd5a846b6d2c4287b71b1142d1b89fa7f1b0363a9b33711a141fe languageName: node linkType: hard -"memory-level@npm:^1.0.0": - version: 1.0.0 - resolution: "memory-level@npm:1.0.0" +"micromark-util-subtokenize@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-subtokenize@npm:2.0.0" dependencies: - abstract-level: ^1.0.0 - functional-red-black-tree: ^1.0.1 - module-error: ^1.0.1 - checksum: 80b1b7aedaf936e754adbcd7b9303018c3684fb32f9992fd967c448f145d177f16c724fbba9ed3c3590a9475fd563151eae664d69b83d2ad48714852e9fc5c72 + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 77d9c7d59c05a20468d49ce2a3640e9cb268c083ccad02322f26c84e1094c25b44f4b8139ef0a247ca11a4fef7620c5bf82fbffd98acdb2989e79cbe7bd8f1db languageName: node linkType: hard -"memorystream@npm:^0.3.1": - version: 0.3.1 - resolution: "memorystream@npm:0.3.1" - checksum: f18b42440d24d09516d01466c06adf797df7873f0d40aa7db02e5fb9ed83074e5e65412d0720901d7069363465f82dc4f8bcb44f0cde271567a61426ce6ca2e9 +"micromark-util-symbol@npm:^1.0.0, micromark-util-symbol@npm:^1.0.1": + version: 1.1.0 + resolution: "micromark-util-symbol@npm:1.1.0" + checksum: 02414a753b79f67ff3276b517eeac87913aea6c028f3e668a19ea0fc09d98aea9f93d6222a76ca783d20299af9e4b8e7c797fe516b766185dcc6e93290f11f88 languageName: node linkType: hard -"merge-descriptors@npm:1.0.1": - version: 1.0.1 - resolution: "merge-descriptors@npm:1.0.1" - checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: fa4a05bff575d9fbf0ad96a1013003e3bb6087ed6b34b609a141b6c0d2137b57df594aca409a95f4c5fda199f227b56a7d8b1f82cea0768df161d8a3a3660764 languageName: node linkType: hard -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 +"micromark-util-types@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-types@npm:1.1.0" + checksum: b0ef2b4b9589f15aec2666690477a6a185536927ceb7aa55a0f46475852e012d75a1ab945187e5c7841969a842892164b15d58ff8316b8e0d6cc920cabd5ede7 languageName: node linkType: hard -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: 819fef3ab5770c37893d2a60381fb2694396c8d22803b6e103c830c3a1bc1490363c2b0470bb2acaaddad776dfbc2fc1fcfde39cb63c4f54d95121611672e3d0 languageName: node linkType: hard -"methods@npm:~1.1.2": - version: 1.1.2 - resolution: "methods@npm:1.1.2" - checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a +"micromark@npm:^4.0.0": + version: 4.0.0 + resolution: "micromark@npm:4.0.0" + dependencies: + "@types/debug": ^4.0.0 + debug: ^4.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: b84ab5ab1a0b28c063c52e9c2c9d7d44b954507235c10c9492d66e0b38f7de24bf298f914a1fbdf109f2a57a88cf0412de217c84cfac5fd60e3e42a74dbac085 languageName: node linkType: hard @@ -12671,7 +14550,21 @@ __metadata: languageName: node linkType: hard -"mini-css-extract-plugin@npm:^2.6.1": +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 + languageName: node + linkType: hard + +"mimic-response@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-response@npm:4.0.0" + checksum: 33b804cc961efe206efdb1fca6a22540decdcfce6c14eb5c0c50e5ae9022267ab22ce8f5568b1f7247ba67500fe20d523d81e0e9f009b321ccd9d472e78d1850 + languageName: node + linkType: hard + +"mini-css-extract-plugin@npm:^2.6.1, mini-css-extract-plugin@npm:^2.7.6": version: 2.7.6 resolution: "mini-css-extract-plugin@npm:2.7.6" dependencies: @@ -13059,6 +14952,18 @@ __metadata: languageName: node linkType: hard +"node-emoji@npm:^2.1.0": + version: 2.1.3 + resolution: "node-emoji@npm:2.1.3" + dependencies: + "@sindresorhus/is": ^4.6.0 + char-regex: ^1.0.2 + emojilib: ^2.4.0 + skin-tone: ^2.0.0 + checksum: 9ae5a1fb12fd5ce6885f251f345986115de4bb82e7d06fdc943845fb19260d89d0aaaccbaf85cae39fe7aaa1fc391640558865ba690c9bb8a7236c3ac10bbab0 + languageName: node + linkType: hard + "node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -13084,20 +14989,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.12": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 - languageName: node - linkType: hard - "node-forge@npm:^1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -13189,6 +15080,13 @@ __metadata: languageName: node linkType: hard +"normalize-url@npm:^8.0.0": + version: 8.0.0 + resolution: "normalize-url@npm:8.0.0" + checksum: 24c20b75ebfd526d8453084692720b49d111c63c0911f1b7447427829597841eef5a8ba3f6bb93d6654007b991c1f5cd85da2c907800e439e2e2ec6c2abd0fc0 + languageName: node + linkType: hard + "npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" @@ -13223,7 +15121,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": +"object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f @@ -13405,6 +15303,13 @@ __metadata: languageName: node linkType: hard +"p-cancelable@npm:^3.0.0": + version: 3.0.0 + resolution: "p-cancelable@npm:3.0.0" + checksum: 2b5ae34218f9c2cf7a7c18e5d9a726ef9b165ef07e6c959f6738371509e747334b5f78f3bcdeb03d8a12dcb978faf641fd87eb21486ed7d36fb823b8ddef3219 + languageName: node + linkType: hard + "p-defer@npm:^1.0.0": version: 1.0.0 resolution: "p-defer@npm:1.0.0" @@ -13563,6 +15468,18 @@ __metadata: languageName: node linkType: hard +"package-json@npm:^8.1.0": + version: 8.1.1 + resolution: "package-json@npm:8.1.1" + dependencies: + got: ^12.1.0 + registry-auth-token: ^5.0.1 + registry-url: ^6.0.0 + semver: ^7.3.7 + checksum: 28bec6f42bf9fba66b7c8fea07576fc23d08ec7923433f7835d6cd8654e72169d74f9738b3785107d18a476ae76712e0daeb1dddcd6930e69f9e4b47eba7c0ca + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -13596,6 +15513,22 @@ __metadata: languageName: node linkType: hard +"parse-entities@npm:^4.0.0": + version: 4.0.1 + resolution: "parse-entities@npm:4.0.1" + dependencies: + "@types/unist": ^2.0.0 + character-entities: ^2.0.0 + character-entities-legacy: ^3.0.0 + character-reference-invalid: ^2.0.0 + decode-named-character-reference: ^1.0.0 + is-alphanumerical: ^2.0.0 + is-decimal: ^2.0.0 + is-hexadecimal: ^2.0.0 + checksum: 32a6ff5b9acb9d2c4d71537308521fd265e685b9215691df73feedd9edfe041bb6da9f89bd0c35c4a2bc7d58e3e76e399bb6078c2fd7d2a343ff1dd46edbf1bd + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -13797,6 +15730,17 @@ __metadata: languageName: node linkType: hard +"periscopic@npm:^3.0.0": + version: 3.1.0 + resolution: "periscopic@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^3.0.0 + is-reference: ^3.0.0 + checksum: 2153244352e58a0d76e7e8d9263e66fe74509495f809af388da20045fb30aa3e93f2f94468dc0b9166ecf206fcfc0d73d2c7641c6fbedc07b1de858b710142cb + languageName: node + linkType: hard + "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -13830,6 +15774,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^7.0.0": + version: 7.0.0 + resolution: "pkg-dir@npm:7.0.0" + dependencies: + find-up: ^6.3.0 + checksum: 94298b20a446bfbbd66604474de8a0cdd3b8d251225170970f15d9646f633e056c80520dd5b4c1d1050c9fed8f6a9e5054b141c93806439452efe72e57562c03 + languageName: node + linkType: hard + "pkg-up@npm:^3.1.0": version: 3.1.0 resolution: "pkg-up@npm:3.1.0" @@ -13968,7 +15921,7 @@ __metadata: languageName: node linkType: hard -"postcss-loader@npm:^7.0.0": +"postcss-loader@npm:^7.0.0, postcss-loader@npm:^7.3.3": version: 7.3.3 resolution: "postcss-loader@npm:7.3.3" dependencies: @@ -14267,7 +16220,7 @@ __metadata: languageName: node linkType: hard -"postcss-sort-media-queries@npm:^4.2.1": +"postcss-sort-media-queries@npm:^4.2.1, postcss-sort-media-queries@npm:^4.4.1": version: 4.4.1 resolution: "postcss-sort-media-queries@npm:4.4.1" dependencies: @@ -14317,7 +16270,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.3.11, postcss@npm:^8.4.14, postcss@npm:^8.4.17, postcss@npm:^8.4.21": +"postcss@npm:^8.4.14, postcss@npm:^8.4.17, postcss@npm:^8.4.21, postcss@npm:^8.4.26": version: 8.4.32 resolution: "postcss@npm:8.4.32" dependencies: @@ -14352,11 +16305,11 @@ __metadata: linkType: hard "prettier@npm:*": - version: 3.1.0 - resolution: "prettier@npm:3.1.0" + version: 3.1.1 + resolution: "prettier@npm:3.1.1" bin: prettier: bin/prettier.cjs - checksum: 44b556bd56f74d7410974fbb2418bb4e53a894d3e7b42f6f87779f69f27a6c272fa7fc27cec0118cd11730ef3246478052e002cbd87e9a253f9cd04a56aa7d9b + checksum: e386855e3a1af86a748e16953f168be555ce66d6233f4ba54eb6449b88eb0c6b2ca79441b11eae6d28a7f9a5c96440ce50864b9d5f6356d331d39d6bb66c648e languageName: node linkType: hard @@ -14395,16 +16348,19 @@ __metadata: languageName: node linkType: hard -"prism-react-renderer@npm:^1.3.5": - version: 1.3.5 - resolution: "prism-react-renderer@npm:1.3.5" +"prism-react-renderer@npm:^2.1.0, prism-react-renderer@npm:^2.3.0": + version: 2.3.0 + resolution: "prism-react-renderer@npm:2.3.0" + dependencies: + "@types/prismjs": ^1.26.0 + clsx: ^2.0.0 peerDependencies: - react: ">=0.14.9" - checksum: c18806dcbc4c0b4fd6fd15bd06b4f7c0a6da98d93af235c3e970854994eb9b59e23315abb6cfc29e69da26d36709a47e25da85ab27fed81b6812f0a52caf6dfa + react: ">=16.0.0" + checksum: 29b24eb5015c09e1b7e3fa2941584ead6fceb5556fdfbe7c34548d96886e0b291290bda93a421aab8b26ce6aae677387aac294982d11349a050843f6dbbc7449 languageName: node linkType: hard -"prismjs@npm:^1.28.0": +"prismjs@npm:^1.29.0": version: 1.29.0 resolution: "prismjs@npm:1.29.0" checksum: 007a8869d4456ff8049dc59404e32d5666a07d99c3b0e30a18bd3b7676dfa07d1daae9d0f407f20983865fd8da56de91d09cb08e6aa61f5bc420a27c0beeaf93 @@ -14442,15 +16398,6 @@ __metadata: languageName: node linkType: hard -"promise@npm:^7.1.1": - version: 7.3.1 - resolution: "promise@npm:7.3.1" - dependencies: - asap: ~2.0.3 - checksum: 475bb069130179fbd27ed2ab45f26d8862376a137a57314cf53310bdd85cc986a826fd585829be97ebc0aaf10e9d8e68be1bfe5a4a0364144b1f9eedfa940cf1 - languageName: node - linkType: hard - "prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" @@ -14481,6 +16428,20 @@ __metadata: languageName: node linkType: hard +"property-information@npm:^6.0.0": + version: 6.4.0 + resolution: "property-information@npm:6.4.0" + checksum: b5aed9a40e87730995f3ceed29839f137fa73b2a4cccfb8ed72ab8bddb8881cad05c3487c4aa168d7cb49a53db8089790c9f00f59d15b8380d2bb5383cdd1f24 + languageName: node + linkType: hard + +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: 4d4826e1713cbfa0f15124ab0ae494c91b597a3c458670c9714c36e8baddf5a6aad22842776f2f5b137f259c8533e741771445eb8df82e861eea37a6eaba03f7 + languageName: node + linkType: hard + "proxy-addr@npm:~2.0.7": version: 2.0.7 resolution: "proxy-addr@npm:2.0.7" @@ -14542,6 +16503,15 @@ __metadata: languageName: node linkType: hard +"pupa@npm:^3.1.0": + version: 3.1.0 + resolution: "pupa@npm:3.1.0" + dependencies: + escape-goat: ^4.0.0 + checksum: 0e4f4ab6bbdce600fa6d23b1833f1af57b2641246ff4cbe10f9d66e4e5479b0de2864a88d5bd629eef59524eda3c6680726acd7f3f873d9ed46b7f095d0bb5f6 + languageName: node + linkType: hard + "puppeteer-core@npm:^19.8.1": version: 19.11.1 resolution: "puppeteer-core@npm:19.11.1" @@ -14566,13 +16536,6 @@ __metadata: languageName: node linkType: hard -"pure-color@npm:^1.2.0": - version: 1.3.0 - resolution: "pure-color@npm:1.3.0" - checksum: 646d8bed6e6eab89affdd5e2c11f607a85b631a7fb03c061dfa658eb4dc4806881a15feed2ac5fd8c0bad8c00c632c640d5b1cb8b9a972e6e947393a1329371b - languageName: node - linkType: hard - "qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" @@ -14607,6 +16570,13 @@ __metadata: languageName: node linkType: hard +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + "randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -14668,18 +16638,6 @@ __metadata: languageName: node linkType: hard -"react-base16-styling@npm:^0.6.0": - version: 0.6.0 - resolution: "react-base16-styling@npm:0.6.0" - dependencies: - base16: ^1.0.0 - lodash.curry: ^4.0.1 - lodash.flow: ^3.3.0 - pure-color: ^1.2.0 - checksum: 00a12dddafc8a9025cca933b0dcb65fca41c81fa176d1fc3a6a9d0242127042e2c0a604f4c724a3254dd2c6aeb5ef55095522ff22f5462e419641c1341a658e4 - languageName: node - linkType: hard - "react-dev-utils@npm:^12.0.1": version: 12.0.1 resolution: "react-dev-utils@npm:12.0.1" @@ -14712,16 +16670,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.2.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -14776,25 +16733,12 @@ __metadata: languageName: node linkType: hard -"react-json-view@npm:^1.21.3": - version: 1.21.3 - resolution: "react-json-view@npm:1.21.3" - dependencies: - flux: ^4.0.1 - react-base16-styling: ^0.6.0 - react-lifecycles-compat: ^3.0.4 - react-textarea-autosize: ^8.3.2 +"react-json-view-lite@npm:^1.2.0": + version: 1.2.1 + resolution: "react-json-view-lite@npm:1.2.1" peerDependencies: - react: ^17.0.0 || ^16.3.0 || ^15.5.4 - react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 - checksum: 5718bcd9210ad5b06eb9469cf8b9b44be9498845a7702e621343618e8251f26357e6e1c865532cf170db6165df1cb30202787e057309d8848c220bc600ec0d1a - languageName: node - linkType: hard - -"react-lifecycles-compat@npm:^3.0.4": - version: 3.0.4 - resolution: "react-lifecycles-compat@npm:3.0.4" - checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 9441260033ec07991b0121281d846f9d3e8db9061ea0dc3938f7003630f515d47870a465d90f1f9300ebe406679986657a4062c009c2a2084e2e145e6fa05a47 languageName: node linkType: hard @@ -14822,7 +16766,7 @@ __metadata: languageName: node linkType: hard -"react-router-dom@npm:^5.3.3": +"react-router-dom@npm:^5.3.3, react-router-dom@npm:^5.3.4": version: 5.3.4 resolution: "react-router-dom@npm:5.3.4" dependencies: @@ -14839,7 +16783,7 @@ __metadata: languageName: node linkType: hard -"react-router@npm:5.3.4, react-router@npm:^5.3.3": +"react-router@npm:5.3.4, react-router@npm:^5.3.3, react-router@npm:^5.3.4": version: 5.3.4 resolution: "react-router@npm:5.3.4" dependencies: @@ -14868,19 +16812,6 @@ __metadata: languageName: node linkType: hard -"react-textarea-autosize@npm:^8.3.2": - version: 8.5.3 - resolution: "react-textarea-autosize@npm:8.5.3" - dependencies: - "@babel/runtime": ^7.20.13 - use-composed-ref: ^1.3.0 - use-latest: ^1.2.1 - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: b317c3763f37a89621bbafd0e6e2d068e7876790a5ae77f497adfd6ba9334ceea138c8a0b7d907bae0f79c765cb24e8b2ca2b8033b4144c0bce28571a3658921 - languageName: node - linkType: hard - "react-toastify@npm:^9.1.3": version: 9.1.3 resolution: "react-toastify@npm:9.1.3" @@ -14893,13 +16824,12 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -15020,8 +16950,17 @@ __metadata: version: 4.2.2 resolution: "registry-auth-token@npm:4.2.2" dependencies: - rc: 1.2.8 - checksum: c5030198546ecfdcbcb0722cbc3e260c4f5f174d8d07bdfedd4620e79bfdf17a2db735aa230d600bd388fce6edd26c0a9ed2eb7e9b4641ec15213a28a806688b + rc: 1.2.8 + checksum: c5030198546ecfdcbcb0722cbc3e260c4f5f174d8d07bdfedd4620e79bfdf17a2db735aa230d600bd388fce6edd26c0a9ed2eb7e9b4641ec15213a28a806688b + languageName: node + linkType: hard + +"registry-auth-token@npm:^5.0.1": + version: 5.0.2 + resolution: "registry-auth-token@npm:5.0.2" + dependencies: + "@pnpm/npm-conf": ^2.1.0 + checksum: 0d7683b71ee418993e7872b389024b13645c4295eb7bb850d10728eaf46065db24ea4d47dc6cbb71a60d1aa4bef077b0d8b7363c9ac9d355fdba47bebdfb01dd languageName: node linkType: hard @@ -15034,6 +16973,15 @@ __metadata: languageName: node linkType: hard +"registry-url@npm:^6.0.0": + version: 6.0.1 + resolution: "registry-url@npm:6.0.1" + dependencies: + rc: 1.2.8 + checksum: 33712aa1b489aab7aba2191c1cdadfdd71f5bf166d4792d81744a6be332c160bd7d9273af8269d8a01284b9562f14a5b31b7abcf7ad9306c44887ecff51c89ab + languageName: node + linkType: hard + "regjsparser@npm:^0.9.1": version: 0.9.1 resolution: "regjsparser@npm:0.9.1" @@ -15045,27 +16993,29 @@ __metadata: languageName: node linkType: hard -"rehype-katex@npm:^5.0.0": - version: 5.0.0 - resolution: "rehype-katex@npm:5.0.0" +"rehype-katex@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-katex@npm:7.0.0" dependencies: - "@types/katex": ^0.11.0 - hast-util-to-text: ^2.0.0 - katex: ^0.13.0 - rehype-parse: ^7.0.0 - unified: ^9.0.0 - unist-util-visit: ^2.0.0 - checksum: b20e24c5326a718581619761057a30d03615519eccd0693ada2c7c710064dceaf08f038ae3a1131550f1f7c47ca54a254ba8e45547da384867e956ceca73f6bf + "@types/hast": ^3.0.0 + "@types/katex": ^0.16.0 + hast-util-from-html-isomorphic: ^2.0.0 + hast-util-to-text: ^4.0.0 + katex: ^0.16.0 + unist-util-visit-parents: ^6.0.0 + vfile: ^6.0.0 + checksum: 3184cf7635e63039a5d455e27718cbc99998cc7bfcc15422badf5da892887f4200f3ee54a6617aa231aa15d46cb678716c112b6b7f9cef11a8653e5d518ad6f0 languageName: node linkType: hard -"rehype-parse@npm:^7.0.0": - version: 7.0.1 - resolution: "rehype-parse@npm:7.0.1" +"rehype-raw@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-raw@npm:7.0.0" dependencies: - hast-util-from-parse5: ^6.0.0 - parse5: ^6.0.0 - checksum: c3c914aa9281853290eff6b09e0bed6843934e788b957e25219e91f0bf244a183d2f5e042c7d21543276571f9b49a6bae90f4640b8f885f2773392ffa57baf4b + "@types/hast": ^3.0.0 + hast-util-raw: ^9.0.0 + vfile: ^6.0.0 + checksum: f9e28dcbf4c6c7d91a97c10a840310f18ef3268aa45abb3e0428b6b191ff3c4fa8f753b910d768588a2dac5c7da7e557b4ddc3f1b6cd252e8d20cb62d60c65ed languageName: node linkType: hard @@ -15085,6 +17035,18 @@ __metadata: languageName: unknown linkType: soft +"remark-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-directive: ^3.0.0 + micromark-extension-directive: ^3.0.0 + unified: ^11.0.0 + checksum: 744d12bbe924bd0492a2481cbaf9250aa6622c0d2cc090bb7bc39975e355c8a46ae13cc4793204ada39f0af64c953f6b730a55420a50375e0f74a5dd5d201089 + languageName: node + linkType: hard + "remark-emoji@npm:^2.2.0": version: 2.2.0 resolution: "remark-emoji@npm:2.2.0" @@ -15096,6 +17058,19 @@ __metadata: languageName: node linkType: hard +"remark-emoji@npm:^4.0.0": + version: 4.0.1 + resolution: "remark-emoji@npm:4.0.1" + dependencies: + "@types/mdast": ^4.0.2 + emoticon: ^4.0.1 + mdast-util-find-and-replace: ^3.0.1 + node-emoji: ^2.1.0 + unified: ^11.0.4 + checksum: 2c02d8c0b694535a9f0c4fe39180cb89a8fbd07eb873c94842c34dfde566b8a6703df9d28fe175a8c28584f96252121de722862baa756f2d875f2f1a4352c1f4 + languageName: node + linkType: hard + "remark-footnotes@npm:2.0.0": version: 2.0.0 resolution: "remark-footnotes@npm:2.0.0" @@ -15103,10 +17078,41 @@ __metadata: languageName: node linkType: hard -"remark-math@npm:^3.0.1": - version: 3.0.1 - resolution: "remark-math@npm:3.0.1" - checksum: 690256f27f2b42dadcf41806fec443056e09592454622ae77f03b1a8474e8c83cc7610e694be7e17de92c96cc272c61209e59a6e7a24e3af6ede47d48b185ccd +"remark-frontmatter@npm:^5.0.0": + version: 5.0.0 + resolution: "remark-frontmatter@npm:5.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-frontmatter: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + unified: ^11.0.0 + checksum: b36e11d528d1d0172489c74ce7961bb6073f7272e71ea1349f765fc79c4246a758aef949174d371a088c48e458af776fcfbb3b043c49cd1120ca8239aeafe16a + languageName: node + linkType: hard + +"remark-gfm@npm:^4.0.0": + version: 4.0.0 + resolution: "remark-gfm@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-gfm: ^3.0.0 + micromark-extension-gfm: ^3.0.0 + remark-parse: ^11.0.0 + remark-stringify: ^11.0.0 + unified: ^11.0.0 + checksum: 84bea84e388061fbbb697b4b666089f5c328aa04d19dc544c229b607446bc10902e46b67b9594415a1017bbbd7c811c1f0c30d36682c6d1a6718b66a1558261b + languageName: node + linkType: hard + +"remark-math@npm:^6.0.0": + version: 6.0.0 + resolution: "remark-math@npm:6.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-math: ^3.0.0 + micromark-extension-math: ^3.0.0 + unified: ^11.0.0 + checksum: fef489acb6cae6e40af05012367dc22a846ce16301e8a96006c6d78935887bdb3e6c5018b6514884ecee57f9c7a51f97a10862526ab0a0f5f7b7d339fe0eb20f languageName: node linkType: hard @@ -15126,6 +17132,16 @@ __metadata: languageName: node linkType: hard +"remark-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-mdx@npm:3.0.0" + dependencies: + mdast-util-mdx: ^3.0.0 + micromark-extension-mdxjs: ^3.0.0 + checksum: 8b9b3e5297e5cb4c312553f42c3720280ada96ae60ede880606924a0aad2e773106aba1ef45a0c179c218f8da6f58dac3c789a9c4f791649ca7a183706cde5b8 + languageName: node + linkType: hard + "remark-parse@npm:8.0.3": version: 8.0.3 resolution: "remark-parse@npm:8.0.3" @@ -15150,6 +17166,31 @@ __metadata: languageName: node linkType: hard +"remark-parse@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-parse@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + micromark-util-types: ^2.0.0 + unified: ^11.0.0 + checksum: d83d245290fa84bb04fb3e78111f09c74f7417e7c012a64dd8dc04fccc3699036d828fbd8eeec8944f774b6c30cc1d925c98f8c46495ebcee7c595496342ab7f + languageName: node + linkType: hard + +"remark-rehype@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-rehype@npm:11.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + mdast-util-to-hast: ^13.0.0 + unified: ^11.0.0 + vfile: ^6.0.0 + checksum: 0ff0fd948759cbde9d507ca1581028d0b89da0b5f610b35a6cb0a511f8d11621449b6eca573b11ddaea77afd37edd4755f3f1eb086ad49a6f7b970b4a4634e13 + languageName: node + linkType: hard + "remark-squeeze-paragraphs@npm:4.0.0": version: 4.0.0 resolution: "remark-squeeze-paragraphs@npm:4.0.0" @@ -15159,6 +17200,17 @@ __metadata: languageName: node linkType: hard +"remark-stringify@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-stringify@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-to-markdown: ^2.0.0 + unified: ^11.0.0 + checksum: 59e07460eb629d6c3b3c0f438b0b236e7e6858fd5ab770303078f5a556ec00354d9c7fb9ef6d5f745a4617ac7da1ab618b170fbb4dac120e183fecd9cc86bce6 + languageName: node + linkType: hard + "renderkid@npm:^3.0.0": version: 3.0.0 resolution: "renderkid@npm:3.0.0" @@ -15172,7 +17224,7 @@ __metadata: languageName: node linkType: hard -"repeat-string@npm:^1.0.0, repeat-string@npm:^1.5.4": +"repeat-string@npm:^1.5.4": version: 1.6.1 resolution: "repeat-string@npm:1.6.1" checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 @@ -15207,6 +17259,13 @@ __metadata: languageName: node linkType: hard +"resolve-alpn@npm:^1.2.0": + version: 1.2.1 + resolution: "resolve-alpn@npm:1.2.1" + checksum: f558071fcb2c60b04054c99aebd572a2af97ef64128d59bef7ab73bd50d896a222a056de40ffc545b633d99b304c259ea9d0c06830d5c867c34f0bfa60b8eae0 + languageName: node + linkType: hard + "resolve-cwd@npm:^3.0.0": version: 3.0.0 resolution: "resolve-cwd@npm:3.0.0" @@ -15307,6 +17366,15 @@ __metadata: languageName: node linkType: hard +"responselike@npm:^3.0.0": + version: 3.0.0 + resolution: "responselike@npm:3.0.0" + dependencies: + lowercase-keys: ^3.0.0 + checksum: e0cc9be30df4f415d6d83cdede3c5c887cd4a73e7cc1708bcaab1d50a28d15acb68460ac5b02bcc55a42f3d493729c8856427dcf6e57e6e128ad05cba4cfb95e + languageName: node + linkType: hard + "restore-cursor@npm:^3.1.0": version: 3.1.0 resolution: "restore-cursor@npm:3.1.0" @@ -15402,17 +17470,17 @@ __metadata: languageName: node linkType: hard -"rtlcss@npm:^3.5.0": - version: 3.5.0 - resolution: "rtlcss@npm:3.5.0" +"rtlcss@npm:^4.1.0": + version: 4.1.1 + resolution: "rtlcss@npm:4.1.1" dependencies: - find-up: ^5.0.0 + escalade: ^3.1.1 picocolors: ^1.0.0 - postcss: ^8.3.11 + postcss: ^8.4.21 strip-json-comments: ^3.1.1 bin: rtlcss: bin/rtlcss.js - checksum: a3763cad2cb58ce1b950de155097c3c294e7aefc8bf328b58d0cc8d5efb88bf800865edc158a78ace6d1f7f99fea6fd66fb4a354d859b172dadd3dab3e0027b3 + checksum: dcf37d76265b5c84d610488afa68a2506d008f95feac968b35ccae9aa49e7019ae0336a80363303f8f8bbf60df3ecdeb60413548b049114a24748319b68aefde languageName: node linkType: hard @@ -15496,13 +17564,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -15606,6 +17673,15 @@ __metadata: languageName: node linkType: hard +"semver-diff@npm:^4.0.0": + version: 4.0.0 + resolution: "semver-diff@npm:4.0.0" + dependencies: + semver: ^7.3.5 + checksum: 4a958d6f76c7e7858268e1e2cf936712542441c9e003e561b574167279eee0a9bd55cc7eae1bfb31d3e7ad06a9fc370e7dd412fcfefec8c0daf1ce5aea623559 + languageName: node + linkType: hard + "semver@npm:^5.4.1, semver@npm:^5.5.0": version: 5.7.2 resolution: "semver@npm:5.7.2" @@ -15683,7 +17759,7 @@ __metadata: languageName: node linkType: hard -"serve-handler@npm:^6.1.3": +"serve-handler@npm:^6.1.3, serve-handler@npm:^6.1.5": version: 6.1.5 resolution: "serve-handler@npm:6.1.5" dependencies: @@ -15824,14 +17900,14 @@ __metadata: linkType: hard "shiki@npm:^0.14.1": - version: 0.14.5 - resolution: "shiki@npm:0.14.5" + version: 0.14.6 + resolution: "shiki@npm:0.14.6" dependencies: ansi-sequence-parser: ^1.1.0 jsonc-parser: ^3.2.0 vscode-oniguruma: ^1.7.0 vscode-textmate: ^8.0.0 - checksum: 41d847817cfc9bb6d8bf190316896698d250303656546446659cc02caed8dcc171b10cd113bb5da82425b51d0032e87aafcdc36c3dd61dadc123170b438da736 + checksum: 24d9e29f93546118f1c07659e8a38f7dbf57b06479a0a9245e0823f7c988c825be53ad0b83a820e2eda5edbf3f0c6d17fad398b825130de1c11973e0bd7075fc languageName: node linkType: hard @@ -15892,6 +17968,15 @@ __metadata: languageName: node linkType: hard +"skin-tone@npm:^2.0.0": + version: 2.0.0 + resolution: "skin-tone@npm:2.0.0" + dependencies: + unicode-emoji-modifier-base: ^1.0.0 + checksum: 19de157586b8019cacc55eb25d9d640f00fc02415761f3e41a4527142970fd4e7f6af0333bc90e879858766c20a976107bb386ffd4c812289c01d51f2c8d182c + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -16030,7 +18115,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.7.3": +"source-map@npm:^0.7.0, source-map@npm:^0.7.3": version: 0.7.4 resolution: "source-map@npm:0.7.4" checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 @@ -16044,6 +18129,13 @@ __metadata: languageName: node linkType: hard +"space-separated-tokens@npm:^2.0.0": + version: 2.0.2 + resolution: "space-separated-tokens@npm:2.0.2" + checksum: 202e97d7ca1ba0758a0aa4fe226ff98142073bcceeff2da3aad037968878552c3bbce3b3231970025375bbba5aee00c5b8206eda408da837ab2dc9c0f26be990 + languageName: node + linkType: hard + "spdy-transport@npm:^3.0.0": version: 3.0.0 resolution: "spdy-transport@npm:3.0.0" @@ -16087,6 +18179,13 @@ __metadata: languageName: node linkType: hard +"srcset@npm:^4.0.0": + version: 4.0.0 + resolution: "srcset@npm:4.0.0" + checksum: aceb898c9281101ef43bfbf96bf04dfae828e1bf942a45df6fad74ae9f8f0a425f4bca1480e0d22879beb40dd2bc6947e0e1e5f4d307a714666196164bc5769d + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" @@ -16228,6 +18327,16 @@ __metadata: languageName: node linkType: hard +"stringify-entities@npm:^4.0.0": + version: 4.0.3 + resolution: "stringify-entities@npm:4.0.3" + dependencies: + character-entities-html4: ^2.0.0 + character-entities-legacy: ^3.0.0 + checksum: 59e8f523b403bf7d415690e72ae52982decd6ea5426bd8b3f5c66225ddde73e766c0c0d91627df082d0794e30b19dd907ffb5864cef3602e4098d6777d7ca3c2 + languageName: node + linkType: hard + "stringify-object@npm:^3.3.0": version: 3.3.0 resolution: "stringify-object@npm:3.3.0" @@ -16310,6 +18419,24 @@ __metadata: languageName: node linkType: hard +"style-to-object@npm:^0.4.0": + version: 0.4.4 + resolution: "style-to-object@npm:0.4.4" + dependencies: + inline-style-parser: 0.1.1 + checksum: 41656c06f93ac0a7ac260ebc2f9d09a8bd74b8ec1836f358cc58e169235835a3a356977891d2ebbd76f0e08a53616929069199f9cce543214d3dc98346e19c9a + languageName: node + linkType: hard + +"style-to-object@npm:^1.0.0": + version: 1.0.5 + resolution: "style-to-object@npm:1.0.5" + dependencies: + inline-style-parser: 0.2.2 + checksum: 6201063204b6a94645f81b189452b2ca3e63d61867ec48523f4d52609c81e96176739fa12020d97fbbf023efb57a6f7ec3a15fb3a7fb7eb3ffea0b52b9dd6b8c + languageName: node + linkType: hard + "stylehacks@npm:^5.1.1": version: 5.1.1 resolution: "stylehacks@npm:5.1.1" @@ -16498,7 +18625,7 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7": +"terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7, terser-webpack-plugin@npm:^5.3.9": version: 5.3.9 resolution: "terser-webpack-plugin@npm:5.3.9" dependencies: @@ -16520,9 +18647,9 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.10.0, terser@npm:^5.16.8": - version: 5.24.0 - resolution: "terser@npm:5.24.0" +"terser@npm:^5.10.0, terser@npm:^5.15.1, terser@npm:^5.16.8": + version: 5.26.0 + resolution: "terser@npm:5.26.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -16530,7 +18657,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: d88f774b6fa711a234fcecefd7657f99189c367e17dbe95a51c2776d426ad0e4d98d1ffe6edfdf299877c7602e495bdd711d21b2caaec188410795e5447d0f6c + checksum: 02a9bb896f04df828025af8f0eced36c315d25d310b6c2418e7dad2bed19ddeb34a9cea9b34e7c24789830fa51e1b6a9be26679980987a9c817a7e6d9cd4154b languageName: node linkType: hard @@ -16652,6 +18779,13 @@ __metadata: languageName: node linkType: hard +"trim-lines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-lines@npm:3.0.1" + checksum: e241da104682a0e0d807222cc1496b92e716af4db7a002f4aeff33ae6a0024fef93165d49eab11aa07c71e1347c42d46563f91dfaa4d3fb945aa535cdead53ed + languageName: node + linkType: hard + "trim-trailing-lines@npm:^1.0.0": version: 1.1.4 resolution: "trim-trailing-lines@npm:1.1.4" @@ -16673,6 +18807,13 @@ __metadata: languageName: node linkType: hard +"trough@npm:^2.0.0": + version: 2.1.0 + resolution: "trough@npm:2.1.0" + checksum: a577bb561c2b401cc0e1d9e188fcfcdf63b09b151ff56a668da12197fe97cac15e3d77d5b51f426ccfd94255744a9118e9e9935afe81a3644fa1be9783c82886 + languageName: node + linkType: hard + "ts-api-utils@npm:^1.0.1": version: 1.0.3 resolution: "ts-api-utils@npm:1.0.3" @@ -16697,8 +18838,8 @@ __metadata: linkType: hard "ts-node@npm:^10.9.1": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" dependencies: "@cspotcode/source-map-support": ^0.8.0 "@tsconfig/node10": ^1.0.7 @@ -16730,7 +18871,7 @@ __metadata: ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 + checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac languageName: node linkType: hard @@ -16872,7 +19013,14 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.5.0": +"type-fest@npm:^1.0.1": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 + languageName: node + linkType: hard + +"type-fest@npm:^2.13.0, type-fest@npm:^2.5.0": version: 2.19.0 resolution: "type-fest@npm:2.19.0" checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 @@ -16962,12 +19110,22 @@ __metadata: linkType: hard "typescript@npm:^5.0.4, typescript@npm:^5.2.2": - version: 5.3.2 - resolution: "typescript@npm:5.3.2" + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + languageName: node + linkType: hard + +"typescript@npm:~5.2.2": + version: 5.2.2 + resolution: "typescript@npm:5.2.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: d92534dda639eb825db013203404c1fabca8ac630564283c9e7dc9e64fd9c9346c2de95ecebdf3e6e8c1c32941bca1cfe0da37877611feb9daf8feeaea58d230 + checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c languageName: node linkType: hard @@ -16992,12 +19150,22 @@ __metadata: linkType: hard "typescript@patch:typescript@^5.0.4#~builtin, typescript@patch:typescript@^5.2.2#~builtin": - version: 5.3.2 - resolution: "typescript@patch:typescript@npm%3A5.3.2#~builtin::version=5.3.2&hash=f3b441" + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=f3b441" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + languageName: node + linkType: hard + +"typescript@patch:typescript@~5.2.2#~builtin": + version: 5.2.2 + resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=f3b441" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: c034461079fbfde3cb584ddee52afccb15b6e32a0ce186d0b2719968786f7ca73e1b07f71fac4163088790b16811c6ccf79680de190664ef66ff0ba9c1fe4a23 + checksum: 0f4da2f15e6f1245e49db15801dbee52f2bbfb267e1c39225afdab5afee1a72839cd86000e65ee9d7e4dfaff12239d28beaf5ee431357fcced15fb08583d72ca languageName: node linkType: hard @@ -17022,7 +19190,7 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^1.0.33, ua-parser-js@npm:^1.0.35": +"ua-parser-js@npm:^1.0.33": version: 1.0.37 resolution: "ua-parser-js@npm:1.0.37" checksum: 4d481c720d523366d7762dc8a46a1b58967d979aacf786f9ceceb1cd767de069f64a4bdffb63956294f1c0696eb465ddb950f28ba90571709e33521b4bd75e07 @@ -17072,6 +19240,13 @@ __metadata: languageName: node linkType: hard +"unicode-emoji-modifier-base@npm:^1.0.0": + version: 1.0.0 + resolution: "unicode-emoji-modifier-base@npm:1.0.0" + checksum: 6e1521d35fa69493207eb8b41f8edb95985d8b3faf07c01d820a1830b5e8403e20002563e2f84683e8e962a49beccae789f0879356bf92a4ec7a4dd8e2d16fdb + languageName: node + linkType: hard + "unicode-match-property-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-match-property-ecmascript@npm:2.0.0" @@ -17110,7 +19285,22 @@ __metadata: languageName: node linkType: hard -"unified@npm:^9.0.0, unified@npm:^9.2.2": +"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": + version: 11.0.4 + resolution: "unified@npm:11.0.4" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: cfb023913480ac2bd5e787ffb8c27782c43e6be4a55f8f1c288233fce46a7ebe7718ccc5adb80bf8d56b7ef85f5fc32239c7bfccda006f9f2382e0cc2e2a77e4 + languageName: node + linkType: hard + +"unified@npm:^9.2.2": version: 9.2.2 resolution: "unified@npm:9.2.2" dependencies: @@ -17151,6 +19341,15 @@ __metadata: languageName: node linkType: hard +"unique-string@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-string@npm:3.0.0" + dependencies: + crypto-random-string: ^4.0.0 + checksum: 1a1e2e7d02eab1bb10f720475da735e1990c8a5ff34edd1a3b6bc31590cb4210b7a1233d779360cc622ce11c211e43afa1628dd658f35d3e6a89964b622940df + languageName: node + linkType: hard + "unist-builder@npm:2.0.3, unist-builder@npm:^2.0.0": version: 2.0.3 resolution: "unist-builder@npm:2.0.3" @@ -17158,12 +19357,13 @@ __metadata: languageName: node linkType: hard -"unist-util-find-after@npm:^3.0.0": - version: 3.0.0 - resolution: "unist-util-find-after@npm:3.0.0" +"unist-util-find-after@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-find-after@npm:5.0.0" dependencies: - unist-util-is: ^4.0.0 - checksum: daa9a28f6cdf533a72ce7ec4864dbe0f11f0fd3efd337b54c08a8a9a47cdc8d10a299cd984d7f512a57e97af012df052210a51aab7c9afd6b1e24da3b2d0a714 + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: e64bd5ebee7ac021cf990bf33e9ec29fc6452159187d4a7fa0f77334bea8e378fea7a7fb0bcf957300b2ffdba902ff25b62c165fc8b86309613da35ad793ada0 languageName: node linkType: hard @@ -17181,6 +19381,24 @@ __metadata: languageName: node linkType: hard +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 + languageName: node + linkType: hard + +"unist-util-position-from-estree@npm:^2.0.0": + version: 2.0.0 + resolution: "unist-util-position-from-estree@npm:2.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: d3b3048a5727c2367f64ef6dcc5b20c4717215ef8b1372ff9a7c426297c5d1e5776409938acd01531213e2cd2543218d16e73f9f862f318e9496e2c73bb18354 + languageName: node + linkType: hard + "unist-util-position@npm:^3.0.0": version: 3.1.0 resolution: "unist-util-position@npm:3.1.0" @@ -17188,6 +19406,15 @@ __metadata: languageName: node linkType: hard +"unist-util-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f89b27989b19f07878de9579cd8db2aa0194c8360db69e2c99bd2124a480d79c08f04b73a64daf01a8fb3af7cba65ff4b45a0b978ca243226084ad5f5d441dde + languageName: node + linkType: hard + "unist-util-remove-position@npm:^2.0.0": version: 2.0.1 resolution: "unist-util-remove-position@npm:2.0.1" @@ -17197,6 +19424,16 @@ __metadata: languageName: node linkType: hard +"unist-util-remove-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-remove-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-visit: ^5.0.0 + checksum: 8aabdb9d0e3e744141bc123d8f87b90835d521209ad3c6c4619d403b324537152f0b8f20dda839b40c3aa0abfbf1828b3635a7a8bb159c3ed469e743023510ee + languageName: node + linkType: hard + "unist-util-remove@npm:^2.0.0": version: 2.1.0 resolution: "unist-util-remove@npm:2.1.0" @@ -17215,6 +19452,15 @@ __metadata: languageName: node linkType: hard +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^3.0.0": version: 3.1.1 resolution: "unist-util-visit-parents@npm:3.1.1" @@ -17225,6 +19471,16 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 + languageName: node + linkType: hard + "unist-util-visit@npm:2.0.3, unist-util-visit@npm:^2.0.0, unist-util-visit@npm:^2.0.3": version: 2.0.3 resolution: "unist-util-visit@npm:2.0.3" @@ -17236,6 +19492,17 @@ __metadata: languageName: node linkType: hard +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 + languageName: node + linkType: hard + "universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" @@ -17300,6 +19567,28 @@ __metadata: languageName: node linkType: hard +"update-notifier@npm:^6.0.2": + version: 6.0.2 + resolution: "update-notifier@npm:6.0.2" + dependencies: + boxen: ^7.0.0 + chalk: ^5.0.1 + configstore: ^6.0.0 + has-yarn: ^3.0.0 + import-lazy: ^4.0.0 + is-ci: ^3.0.1 + is-installed-globally: ^0.4.0 + is-npm: ^6.0.0 + is-yarn-global: ^0.4.0 + latest-version: ^7.0.0 + pupa: ^3.1.0 + semver: ^7.3.7 + semver-diff: ^4.0.0 + xdg-basedir: ^5.1.0 + checksum: 4bae7b3eca7b2068b6b87dde88c9dad24831fa913a5b83ecb39a7e4702c93e8b05fd9bcac5f1a005178f6e5dc859e0b3817ddda833d2a7ab92c6485e078b3cc8 + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -17335,50 +19624,6 @@ __metadata: languageName: node linkType: hard -"use-composed-ref@npm:^1.3.0": - version: 1.3.0 - resolution: "use-composed-ref@npm:1.3.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: f771cbadfdc91e03b7ab9eb32d0fc0cc647755711801bf507e891ad38c4bbc5f02b2509acadf9c965ec9c5f2f642fd33bdfdfb17b0873c4ad0a9b1f5e5e724bf - languageName: node - linkType: hard - -"use-isomorphic-layout-effect@npm:^1.1.1": - version: 1.1.2 - resolution: "use-isomorphic-layout-effect@npm:1.1.2" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: a6532f7fc9ae222c3725ff0308aaf1f1ddbd3c00d685ef9eee6714fd0684de5cb9741b432fbf51e61a784e2955424864f7ea9f99734a02f237b17ad3e18ea5cb - languageName: node - linkType: hard - -"use-latest@npm:^1.2.1": - version: 1.2.1 - resolution: "use-latest@npm:1.2.1" - dependencies: - use-isomorphic-layout-effect: ^1.1.1 - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: ed3f2ddddf6f21825e2ede4c2e0f0db8dcce5129802b69d1f0575fc1b42380436e8c76a6cd885d4e9aa8e292e60fb8b959c955f33c6a9123b83814a1a1875367 - languageName: node - linkType: hard - -"use-sync-external-store@npm:^1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -17469,6 +19714,16 @@ __metadata: languageName: node linkType: hard +"vfile-location@npm:^5.0.0": + version: 5.0.2 + resolution: "vfile-location@npm:5.0.2" + dependencies: + "@types/unist": ^3.0.0 + vfile: ^6.0.0 + checksum: b61c048cedad3555b4f007f390412c6503f58a6a130b58badf4ee340c87e0d7421e9c86bbc1494c57dedfccadb60f5176cc60ba3098209d99fb3a3d8804e4c38 + languageName: node + linkType: hard + "vfile-message@npm:^2.0.0": version: 2.0.4 resolution: "vfile-message@npm:2.0.4" @@ -17479,6 +19734,16 @@ __metadata: languageName: node linkType: hard +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 964e7e119f4c0e0270fc269119c41c96da20afa01acb7c9809a88365c8e0c64aa692fafbd952669382b978002ecd7ad31ef4446d85e8a22cdb62f6df20186c2d + languageName: node + linkType: hard + "vfile@npm:^4.0.0": version: 4.2.1 resolution: "vfile@npm:4.2.1" @@ -17491,6 +19756,17 @@ __metadata: languageName: node linkType: hard +"vfile@npm:^6.0.0, vfile@npm:^6.0.1": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 05ccee73aeb00402bc8a5d0708af299e9f4a33f5132805449099295085e3ca3b0d018328bad9ff44cf2e6f4cd364f1d558d3fb9b394243a25b2739207edcb0ed + languageName: node + linkType: hard + "vscode-oniguruma@npm:^1.7.0": version: 1.7.0 resolution: "vscode-oniguruma@npm:1.7.0" @@ -17546,6 +19822,13 @@ __metadata: languageName: node linkType: hard +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: b6d9f02f1a43d0ef0848a812d89c83801d5bbad57d8bb61f02eb6d7eb794c3736f6cc2e1191664bb26136594c8218ac609f4069722c6f56d9fc2d808fa9271c6 + languageName: node + linkType: hard + "web-streams-polyfill@npm:^3.0.3": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" @@ -17567,7 +19850,7 @@ __metadata: languageName: node linkType: hard -"webpack-bundle-analyzer@npm:^4.5.0": +"webpack-bundle-analyzer@npm:^4.5.0, webpack-bundle-analyzer@npm:^4.9.0": version: 4.10.1 resolution: "webpack-bundle-analyzer@npm:4.10.1" dependencies: @@ -17605,7 +19888,7 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^4.9.3": +"webpack-dev-server@npm:^4.15.1, webpack-dev-server@npm:^4.9.3": version: 4.15.1 resolution: "webpack-dev-server@npm:4.15.1" dependencies: @@ -17652,7 +19935,7 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:^5.8.0": +"webpack-merge@npm:^5.8.0, webpack-merge@npm:^5.9.0": version: 5.10.0 resolution: "webpack-merge@npm:5.10.0" dependencies: @@ -17670,7 +19953,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.73.0": +"webpack@npm:^5.73.0, webpack@npm:^5.88.1": version: 5.89.0 resolution: "webpack@npm:5.89.0" dependencies: @@ -17888,7 +20171,7 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^3.0.0": +"write-file-atomic@npm:^3.0.0, write-file-atomic@npm:^3.0.3": version: 3.0.3 resolution: "write-file-atomic@npm:3.0.3" dependencies: @@ -17971,8 +20254,8 @@ __metadata: linkType: hard "ws@npm:^8.13.0": - version: 8.14.2 - resolution: "ws@npm:8.14.2" + version: 8.15.0 + resolution: "ws@npm:8.15.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -17981,7 +20264,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b + checksum: ca15c590aa49bc0197223b8ab7d15e7362ae6c4011d91ed0e5cd5867cdd5497fd71470ea36314833b4b078929fe64dc4ba7748b1e58e50a0f8e41f147db2b464 languageName: node linkType: hard @@ -17992,6 +20275,13 @@ __metadata: languageName: node linkType: hard +"xdg-basedir@npm:^5.0.1, xdg-basedir@npm:^5.1.0": + version: 5.1.0 + resolution: "xdg-basedir@npm:5.1.0" + checksum: b60e8a2c663ccb1dac77c2d913f3b96de48dafbfa083657171d3d50e10820b8a04bb4edfe9f00808c8c20e5f5355e1927bea9029f03136e29265cb98291e1fea + languageName: node + linkType: hard + "xml-js@npm:^1.6.11": version: 1.6.11 resolution: "xml-js@npm:1.6.11" @@ -18168,6 +20458,13 @@ __metadata: languageName: node linkType: hard +"zwitch@npm:^2.0.0": + version: 2.0.4 + resolution: "zwitch@npm:2.0.4" + checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6 + languageName: node + linkType: hard + "zx@npm:7.1.1": version: 7.1.1 resolution: "zx@npm:7.1.1" From 9b5b6861c3aa0e154e17598ac9994d3970f0e752 Mon Sep 17 00:00:00 2001 From: Hayley Kwan Date: Tue, 12 Dec 2023 11:11:22 +0000 Subject: [PATCH 021/137] feat: avoid overflow checks on boolean multiplication (#3745) # Description ## Problem\* ## Summary\* Currently multiplication of booleans adds in a range check which is unnecessary as the result cannot be larger than the inputs. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 260ee129e86..501a03bcb5c 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -341,7 +341,9 @@ impl<'a> FunctionContext<'a> { _ => unreachable!("operator {} should not overflow", operator), }; - if operator == BinaryOpKind::ShiftLeft { + if operator == BinaryOpKind::Multiply && bit_size == 1 { + result + } else if operator == BinaryOpKind::ShiftLeft { self.check_left_shift_overflow(result, rhs, bit_size, location) } else { let message = format!("attempt to {} with overflow", op_name); From 059ce4cb2bea9041edff7d6ce4d1a936557cda49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Tue, 12 Dec 2023 14:47:42 +0000 Subject: [PATCH 022/137] chore: removing old docs (#3778) # Description Removes old versions from the docs --- .../version-v0.10.5/examples/merkle-proof.mdx | 48 --- .../getting_started/00_nargo_installation.md | 278 ------------ .../getting_started/01_hello_world.md | 147 ------- .../getting_started/02_breakdown.md | 200 --------- .../getting_started/03_language_server.md | 36 -- docs/versioned_docs/version-v0.10.5/index.md | 103 ----- .../language_concepts/01_functions.md | 99 ----- .../language_concepts/02_control_flow.md | 42 -- .../language_concepts/03_ops.md | 97 ----- .../language_concepts/04_assert.md | 34 -- .../language_concepts/05_unconstrained.md | 96 ----- .../language_concepts/06_generics.md | 113 ----- .../language_concepts/07_mutability.md | 92 ---- .../language_concepts/08_lambdas.md | 80 ---- .../language_concepts/09_comments.md | 32 -- .../language_concepts/10_distinct.md | 63 --- .../language_concepts/11_shadowing.md | 43 -- .../language_concepts/data_types.md | 96 ----- .../language_concepts/data_types/00_fields.md | 165 ------- .../data_types/01_integers.md | 33 -- .../data_types/02_booleans.md | 30 -- .../data_types/03_strings.md | 43 -- .../language_concepts/data_types/04_arrays.md | 237 ---------- .../language_concepts/data_types/05_slices.md | 157 ------- .../data_types/06_vectors.md | 34 -- .../language_concepts/data_types/07_tuples.md | 47 -- .../data_types/08_structs.md | 73 ---- .../data_types/09_references.md | 22 - .../data_types/10_function_types.md | 25 -- .../crates_and_packages.md | 42 -- .../modules_packages_crates/dependencies.md | 123 ------ .../modules_packages_crates/modules.md | 104 ----- .../modules_packages_crates/workspaces.md | 39 -- .../version-v0.10.5/nargo/01_commands.md | 223 ---------- .../version-v0.10.5/nargo/02_testing.md | 42 -- .../nargo/03_solidity_verifier.md | 129 ------ .../standard_library/black_box_fns.md | 45 -- .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 146 ------- .../cryptographic_primitives/01_scalar.mdx | 33 -- .../cryptographic_primitives/02_schnorr.mdx | 37 -- .../03_ecdsa_sig_verification.mdx | 45 -- .../04_ec_primitives.md | 101 ----- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../common/_blackbox.mdx | 5 - .../standard_library/logging.md | 62 --- .../standard_library/merkle_trees.md | 58 --- .../standard_library/options.md | 99 ----- .../standard_library/recursion.md | 96 ----- .../standard_library/zeroed.md | 25 -- .../version-v0.10.5/typescript.md | 237 ---------- .../version-v0.6.0/examples/merkle-proof.md | 48 --- .../getting_started/00_nargo_installation.md | 278 ------------ .../getting_started/01_hello_world.md | 147 ------- .../getting_started/02_breakdown.md | 103 ----- docs/versioned_docs/version-v0.6.0/index.md | 65 --- .../language_concepts/00_data_types.md | 301 ------------- .../language_concepts/01_functions.md | 88 ---- .../language_concepts/02_control_flow.md | 42 -- .../language_concepts/03_ops.md | 96 ----- .../language_concepts/04_assert.md | 34 -- .../language_concepts/05_constrain.md | 40 -- .../language_concepts/06_generics.md | 116 ----- .../language_concepts/07_mutability.md | 118 ----- .../language_concepts/08_comments.md | 27 -- .../language_concepts/09_distinct.md | 63 --- .../crates_and_packages.md | 35 -- .../modules_packages_crates/dependencies.md | 85 ---- .../modules_packages_crates/modules.md | 104 ----- .../version-v0.6.0/nargo/01_commands.md | 130 ------ .../version-v0.6.0/nargo/02_testing.md | 32 -- .../nargo/03_solidity_verifier.md | 116 ----- .../standard_library/array_methods.md | 180 -------- .../standard_library/black_box_fns.md | 44 -- .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 149 ------- .../cryptographic_primitives/01_scalar.mdx | 33 -- .../cryptographic_primitives/02_schnorr.mdx | 37 -- .../03_ecdsa_secp256k1.mdx | 25 -- .../04_ec_primitives.md | 102 ----- .../common/_blackbox.mdx | 5 - .../standard_library/field_methods.md | 149 ------- .../standard_library/logging.md | 55 --- .../standard_library/merkle_trees.md | 59 --- .../version-v0.6.0/standard_library/zeroed.md | 25 -- .../version-v0.6.0/typescript.md | 262 ----------- .../version-v0.7.1/examples/merkle-proof.md | 48 --- .../getting_started/00_nargo_installation.md | 277 ------------ .../getting_started/01_hello_world.md | 147 ------- .../getting_started/02_breakdown.md | 122 ------ .../getting_started/03_language_server.md | 31 -- docs/versioned_docs/version-v0.7.1/index.md | 103 ----- .../language_concepts/00_data_types.md | 305 ------------- .../language_concepts/01_functions.md | 88 ---- .../language_concepts/02_control_flow.md | 42 -- .../language_concepts/03_ops.md | 97 ----- .../language_concepts/04_assert.md | 34 -- .../language_concepts/06_generics.md | 116 ----- .../language_concepts/07_mutability.md | 118 ----- .../language_concepts/08_comments.md | 27 -- .../language_concepts/09_distinct.md | 63 --- .../crates_and_packages.md | 35 -- .../modules_packages_crates/dependencies.md | 110 ----- .../modules_packages_crates/modules.md | 104 ----- .../version-v0.7.1/nargo/01_commands.md | 132 ------ .../version-v0.7.1/nargo/02_testing.md | 32 -- .../nargo/03_solidity_verifier.md | 129 ------ .../standard_library/array_methods.md | 180 -------- .../standard_library/black_box_fns.md | 44 -- .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 146 ------- .../cryptographic_primitives/01_scalar.mdx | 33 -- .../cryptographic_primitives/02_schnorr.mdx | 37 -- .../03_ecdsa_secp256k1.mdx | 17 - .../04_ec_primitives.md | 101 ----- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../common/_blackbox.mdx | 5 - .../standard_library/field_methods.md | 149 ------- .../standard_library/logging.md | 55 --- .../standard_library/merkle_trees.md | 59 --- .../version-v0.7.1/standard_library/zeroed.md | 25 -- .../version-v0.7.1/typescript.md | 262 ----------- .../version-v0.9.0/examples/merkle-proof.mdx | 48 --- .../getting_started/00_nargo_installation.md | 278 ------------ .../getting_started/01_hello_world.md | 147 ------- .../getting_started/02_breakdown.md | 154 ------- .../getting_started/03_language_server.md | 31 -- docs/versioned_docs/version-v0.9.0/index.md | 103 ----- .../language_concepts/00_data_types.md | 405 ------------------ .../language_concepts/01_functions.md | 88 ---- .../language_concepts/02_control_flow.md | 42 -- .../language_concepts/03_ops.md | 97 ----- .../language_concepts/04_assert.md | 34 -- .../language_concepts/05_unconstrained.md | 96 ----- .../language_concepts/06_generics.md | 116 ----- .../language_concepts/07_mutability.md | 120 ------ .../language_concepts/08_comments.md | 32 -- .../language_concepts/09_distinct.md | 63 --- .../language_concepts/10_shadowing.md | 43 -- .../crates_and_packages.md | 35 -- .../modules_packages_crates/dependencies.md | 110 ----- .../modules_packages_crates/modules.md | 104 ----- .../version-v0.9.0/nargo/01_commands.md | 139 ------ .../version-v0.9.0/nargo/02_testing.md | 32 -- .../nargo/03_solidity_verifier.md | 129 ------ .../standard_library/black_box_fns.md | 45 -- .../cryptographic_primitives.md | 14 - .../cryptographic_primitives/00_hashes.mdx | 146 ------- .../cryptographic_primitives/01_scalar.mdx | 33 -- .../cryptographic_primitives/02_schnorr.mdx | 37 -- .../03_ecdsa_sig_verification.mdx | 45 -- .../04_ec_primitives.md | 101 ----- .../cryptographic_primitives/05_eddsa.mdx | 17 - .../common/_blackbox.mdx | 5 - .../standard_library/field_methods.md | 149 ------- .../standard_library/logging.md | 42 -- .../standard_library/merkle_trees.md | 58 --- .../standard_library/recursion.md | 96 ----- .../standard_library/slice_methods.md | 279 ------------ .../version-v0.9.0/standard_library/zeroed.md | 25 -- .../version-v0.9.0/typescript.md | 243 ----------- .../version-v0.10.5-sidebars.json | 111 ----- .../version-v0.6.0-sidebars.json | 90 ---- .../version-v0.7.1-sidebars.json | 90 ---- .../version-v0.9.0-sidebars.json | 91 ---- 165 files changed, 14961 deletions(-) delete mode 100644 docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md delete mode 100644 docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md delete mode 100644 docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md delete mode 100644 docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md delete mode 100644 docs/versioned_docs/version-v0.10.5/index.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md delete mode 100644 docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md delete mode 100644 docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md delete mode 100644 docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md delete mode 100644 docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md delete mode 100644 docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md delete mode 100644 docs/versioned_docs/version-v0.10.5/nargo/01_commands.md delete mode 100644 docs/versioned_docs/version-v0.10.5/nargo/02_testing.md delete mode 100644 docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/logging.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/options.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/recursion.md delete mode 100644 docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md delete mode 100644 docs/versioned_docs/version-v0.10.5/typescript.md delete mode 100644 docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md delete mode 100644 docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md delete mode 100644 docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md delete mode 100644 docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md delete mode 100644 docs/versioned_docs/version-v0.6.0/index.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md delete mode 100644 docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md delete mode 100644 docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md delete mode 100644 docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md delete mode 100644 docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md delete mode 100644 docs/versioned_docs/version-v0.6.0/nargo/01_commands.md delete mode 100644 docs/versioned_docs/version-v0.6.0/nargo/02_testing.md delete mode 100644 docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/logging.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md delete mode 100644 docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md delete mode 100644 docs/versioned_docs/version-v0.6.0/typescript.md delete mode 100644 docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md delete mode 100644 docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md delete mode 100644 docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md delete mode 100644 docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md delete mode 100644 docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md delete mode 100644 docs/versioned_docs/version-v0.7.1/index.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md delete mode 100644 docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md delete mode 100644 docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md delete mode 100644 docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md delete mode 100644 docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md delete mode 100644 docs/versioned_docs/version-v0.7.1/nargo/01_commands.md delete mode 100644 docs/versioned_docs/version-v0.7.1/nargo/02_testing.md delete mode 100644 docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/logging.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md delete mode 100644 docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md delete mode 100644 docs/versioned_docs/version-v0.7.1/typescript.md delete mode 100644 docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md delete mode 100644 docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md delete mode 100644 docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md delete mode 100644 docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md delete mode 100644 docs/versioned_docs/version-v0.9.0/index.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md delete mode 100644 docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md delete mode 100644 docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md delete mode 100644 docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md delete mode 100644 docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md delete mode 100644 docs/versioned_docs/version-v0.9.0/nargo/01_commands.md delete mode 100644 docs/versioned_docs/version-v0.9.0/nargo/02_testing.md delete mode 100644 docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/logging.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/recursion.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md delete mode 100644 docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md delete mode 100644 docs/versioned_docs/version-v0.9.0/typescript.md delete mode 100644 docs/versioned_sidebars/version-v0.10.5-sidebars.json delete mode 100644 docs/versioned_sidebars/version-v0.6.0-sidebars.json delete mode 100644 docs/versioned_sidebars/version-v0.7.1-sidebars.json delete mode 100644 docs/versioned_sidebars/version-v0.9.0-sidebars.json diff --git a/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx deleted file mode 100644 index 6430780817c..00000000000 --- a/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md deleted file mode 100644 index dc412cdc6fa..00000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md deleted file mode 100644 index 8b4416beba1..00000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program: - -```sh -nargo prove -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`.proof`, where the project name is defined in Nargo.toml. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof by running: - -```sh -nargo verify -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md deleted file mode 100644 index 3fa3a35766b..00000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noirstarter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` (optional) - specifies the version of the compiler to use. This is not currently enforced by the compiler, but will be in future versions. -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md deleted file mode 100644 index 49bd1d24675..00000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -When you language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.10.5/index.md b/docs/versioned_docs/version-v0.10.5/index.md deleted file mode 100644 index 028df708bd5..00000000000 --- a/docs/versioned_docs/version-v0.10.5/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md deleted file mode 100644 index 069d86c46d0..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md deleted file mode 100644 index d5caa463765..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md deleted file mode 100644 index a25a946123d..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md deleted file mode 100644 index 6b621eda3eb..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md deleted file mode 100644 index 9fb4177c2a8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Generics -description: Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md deleted file mode 100644 index ad902c42c9b..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md deleted file mode 100644 index ae1e6aecab1..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Lambdas -description: Learn how to use anonymous functions in Noir programming language. -keywords: [Noir programming language, lambda, closure, function, anonymous function] ---- - -## Introduction - -Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -A block can be used as the body of a lambda, allowing you to declare local variables inside it: - -```rust -let cool = || { - let x = 100; - let y = 100; - x + y -} - -assert(cool() == 200); -``` - -## Closures - -Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: - -```rust -fn main() { - let x = 100; - let closure = || x + 150; - assert(closure() == 250); -} -``` - -## Passing closures to higher-order functions - -It may catch you by surprise that the following code fails to compile: - -```rust -fn foo(f: fn () -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // error :( -} -``` - -The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` -expects a regular function as an argument - those are incompatible. -:::note - -Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. - -E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. - -::: -The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - -in this example that's `(Field, Field)`. - -The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called -with closures with any environment, as well as with regular functions: - -```rust -fn foo(f: fn[Env]() -> Field) -> Field { - f() -} - -fn main() { - let (x, y) = (50, 50); - assert(foo(|| x + y) == 100); // compiles fine - assert(foo(|| 60) == 60); // compiles fine -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md deleted file mode 100644 index d546cc463a8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md deleted file mode 100644 index 78d3d2af166..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md deleted file mode 100644 index d9c5e20e795..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Integers -description: - Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: - [ - noir, - integer types, - methods, - examples, - arithmetic, - ] ---- - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md deleted file mode 100644 index 885db167d83..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Booleans -description: - Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. -keywords: - [ - noir, - boolean type, - methods, - examples, - logical operations, - ] ---- - - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md deleted file mode 100644 index ee69853bfba..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md deleted file mode 100644 index f826b39bf39..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md deleted file mode 100644 index bc7f5c531e7..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: Slices -description: - Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: - [ - noir, - slice type, - methods, - examples, - subarrays, - ] ---- - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here]([test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md deleted file mode 100644 index c5b74c877f8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Vectors -description: - Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: - [ - noir, - vector type, - methods, - examples, - dynamic arrays, - ] ---- - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md deleted file mode 100644 index 5f6cab974a8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Tuples -description: - Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. -keywords: - [ - noir, - tuple type, - methods, - examples, - multi-value containers, - ] ---- - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md deleted file mode 100644 index 85649dfb389..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Structs -description: - Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. -keywords: - [ - noir, - struct type, - methods, - examples, - data structures, - ] ---- - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md deleted file mode 100644 index b0c35ce2cb9..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: References ---- - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md deleted file mode 100644 index 1ec92efd594..00000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Function types ---- - -Noir supports higher-order functions. The syntax for a function type is as follows: - -```rust -fn(arg1_type, arg2_type, ...) -> return_type -``` - -Example: - -```rust -fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field - assert(f() == 100); -} - -fn main() { - assert_returns_100(|| 100); // ok - assert_returns_100(|| 150); // fails -} -``` - -A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index fb83a33d94e..00000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Crates and Packages -description: Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in several forms: binaries, libraries or contracts. - -#### Binaries - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -#### Libraries - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -#### Contracts - -Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts). - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md deleted file mode 100644 index 9e6463801b7..00000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md deleted file mode 100644 index 147c9b284e8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree - -All modules are accessible from the `crate::` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` - -In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md deleted file mode 100644 index eaa09506698..00000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. We just don't have a way to consume libraries from inside a workspace as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md b/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md deleted file mode 100644 index 425a73a34c8..00000000000 --- a/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - --show-ssa Emit debug information for the intermediate SSA IR - --deny-warnings Quit execution when warnings are emitted - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -**Options** - -``` - --package The name of the package to check - --workspace Check all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -**Options** - -``` - --package The name of the package to codegen - --workspace Codegen all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -**Options** - -``` - --include-keys Include Proving and Verification keys in the build artifacts - --package The name of the package to compile - --workspace Compile all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -``` - The path to save the new project -``` - -**Options** - -``` - --name Name of the package [default: package directory name] - --lib Use a library template - --bin Use a binary template [default] - --contract Use a contract template --h, --help Print help -``` - -## `nargo init` - -Creates a new Noir project in the current directory. - -**Options** - -``` - --name Name of the package [default: current directory name] - --lib Use a library template - --bin Use a binary template [default] - --contract Use a contract template --h, --help Print help -``` - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -``` -[WITNESS_NAME] Write the execution witness to named file -``` - -**Options** - -``` --p, --prover-name The name of the toml file which contains the inputs for the prover [default: Prover] - --package The name of the package to execute - --workspace Execute all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove` - -Creates a proof for the program. - -**Options** - -``` --p, --prover-name The name of the toml file which contains the inputs for the prover [default: Prover] --v, --verifier-name The name of the toml file which contains the inputs for the verifier [default: Verifier] - --verify Verify proof after proving - --package The name of the package to prove - --workspace Prove all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -**Options** - -``` --v, --verifier-name The name of the toml file which contains the inputs for the verifier [default: Verifier] - --package The name of the package verify - --workspace Verify all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing). - -**Options** - -``` - --show-output Display output of `println` statements - --exact Only run tests that match exactly - --package The name of the package to test - --workspace Test all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md b/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md deleted file mode 100644 index 106952c44c0..00000000000 --- a/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md deleted file mode 100644 index c758846b688..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 1d9b1c7f09c..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1e..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5ff..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 3934a0338d0..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 6e6b19b6861..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed3316..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbff..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/logging.md b/docs/versioned_docs/version-v0.10.5/standard_library/logging.md deleted file mode 100644 index 7e2fd9b9aff..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/logging.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). - -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` - -You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: - -```rust - let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); - - let s = myStruct { y: x, x: y }; - std::println(s); - - std::println(f"i: {i}, s: {s}"); - - std::println(x); - std::println([x, y]); - - let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); -``` diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md deleted file mode 100644 index 57d8c4a9e4f..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/options.md b/docs/versioned_docs/version-v0.10.5/standard_library/options.md deleted file mode 100644 index 3d3139fb98b..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/options.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Option Type ---- - -The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. - -```rust -struct Option { - None, - Some(T), -} -``` - -You can import the Option type into your Noir program like so: - -```rust -use dep::std::option::Option; - -fn main() { - let none = Option::none(); - let some = Option::some(3); -} -``` - -See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. - -## Methods - -### none - -Constructs a none value. - -### some - -Constructs a some wrapper around a given value. - -### is_none - -Returns true if the Option is None. - -### is_some - -Returns true of the Option is Some. - -### unwrap - -Asserts `self.is_some()` and returns the wrapped value. - -### unwrap_unchecked - -Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. - -### unwrap_or - -Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. - -### unwrap_or_else - -Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. - -### map - -If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. - -### map_or - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. - -### map_or_else - -If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. - -### and - -Returns None if self is None. Otherwise, this returns `other`. - -### and_then - -If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. - -### or - -If self is Some, return self. Otherwise, return `other`. - -### or_else - -If self is Some, return self. Otherwise, return `default()`. - -### xor - -If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. - -### filter - -Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. - -### flatten - -Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/recursion.md b/docs/versioned_docs/version-v0.10.5/standard_library/recursion.md deleted file mode 100644 index ff4c63acaa7..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md b/docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.10.5/typescript.md b/docs/versioned_docs/version-v0.10.5/typescript.md deleted file mode 100644 index 258a2160e92..00000000000 --- a/docs/versioned_docs/version-v0.10.5/typescript.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -You can check the complete code for this tutorial here: [browser with next.js](https://github.com/signorecello/noir-min-browser-example) and [node.js](https://github.com/signorecello/noir-min-nodejs-example). If you want just a browser boilerplate to start with, check out the [noir-starter](https://github.com/noir-lang/noir-starter) for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -Make sure you are using Noir version >= 0.10.1. - -You can check your current version by running `nargo --version`. - -See the [Installation page](./getting_started/nargo_installation) for more info. - -We're assuming you're using ES6 and ESM for both browser (for example with React), or nodejs. Install [Node.js](https://nodejs.org/en). Init a new project with `npm init` and add `"type": "module"` to your `package.json`, to let `node` know we're using the new ESM sytem: - -```json -{ - "type": "module" - // the rest of your package.json -} -``` - -Install Noir dependencies in your project by running: - -```bash -npm i @aztec/bb.js@0.3.6 https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42 fflate ethers@5.7.2 -``` - -This will install the `acvm-simulator` that will generate our witness, and the proving backend barretenberg `bb.js`. - -We're also installing `ethers` because we're too lazy to write a function that pads public inputs with 32bytes, and `fflate` to help us decompress our circuit bytecode. - -Since we're with typescript and using `nodejs` types, we also recommend to install the `@types/node` package, otherwise your IDE will scream at you. - -```bash -npm i --save-dev @types/node -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, run `nargo init` to create a new Noir project. - -We will use a Standard Noir Example and place it in the `src` folder. This program simply multiplies input `x` with input `y` and returns the result `z`. The verifier doesn't know the value of `x`: we're proving that we know it without making it public. - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Compiling - -In order to start proving, we need to compile our circuit into the intermediate representation used by our backend. As of today, you have to do that with `nargo`. Just hop to your circuits folder and run `nargo compile`. - -:::info - -At this time, you need to use a nightly version of nargo. Using [noirup](./getting_started/00_nargo_installation.md#option-1-noirup) you can do this simply by running `noirup -n`. - -::: - -You should have a `json` file in `target/` with your circuit's bytecode. The json file is name based on the project name specified in Nargo.toml, so for a project named "test", it will be at `target/test.json`. You can then import that file normally. - -```ts -import circuit from '../target/test.json' assert { type: 'json' }; -``` - -## Decompressing the circuit - -The compiled circuit comes compressed. We need to decompress it, that's where `fflate` comes in. - -```ts -import { decompressSync } from 'fflate'; - -const acirBuffer = Buffer.from(circuit.bytecode, 'base64'); -const acirBufferUncompressed = decompressSync(acirBuffer); -``` - -From here, it's highly recommended you store `acirBuffer` and `acirBufferUncompressed` close by, as they will be used for witness generation and proving. - -## Initializing ACVM and BB.JS - -:::note - -This step will eventually be abstracted away as Noir tooling matures. For now, you should be fine just literally copy-pasting most of this into your own code. - -::: - -Before proving, `bb.js` needs to be initialized. We need to import some functions and use them - -```ts -import { Crs, newBarretenbergApiAsync, RawBuffer } from '@aztec/bb.js/dest/node/index.js'; - -const api = await newBarretenbergApiAsync(4); - -const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed); -const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize))); -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); -``` - -We should take two very useful objects from here: `api` and `acirComposer`. Make sure to keep these close by! - -:::info - -On the browser, you also need to init the ACVM. You can do that by importing it and calling it like: - -```ts -import initACVM, { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -await initACVM(); -// the rest of your code -``` - -::: - -## Generating witnesses - -Witness generation is what allows us to prove with arbitrary inputs (like user inputs on a form, game, etc). In this example, our input is a simple object with our circuit inputs `x`, `y`, and return `z` (fun fact: the return value in Noir is actually a public input!). We're wrapping it in a function, so it can be conveniently called later on. - -```ts -import { ethers } from 'ethers'; // I'm lazy so I'm using ethers to pad my input -import { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -async function generateWitness(input: any, acirBuffer: Buffer): Promise { - const initialWitness = new Map(); - initialWitness.set(1, ethers.utils.hexZeroPad(`0x${input.x.toString(16)}`, 32)); - initialWitness.set(2, ethers.utils.hexZeroPad(`0x${input.y.toString(16)}`, 32)); - - const witnessMap = await executeCircuit(acirBuffer, initialWitness, () => { - throw Error('unexpected oracle'); - }); - - const witnessBuff = compressWitness(witnessMap); - return witnessBuff; -} -``` - -## Proving - -Finally, we're ready to prove with our backend. Just like with the witness generation, could be useful to wrap it in its own function: - -```ts -async function generateProof(witness: Uint8Array) { - const proof = await api.acirCreateProof( - acirComposer, - acirBufferUncompressed, - decompressSync(witness), - false, - ); - return proof; -} -``` - -## Verifying - -Our backend should also be ready to verify our proof: - -```ts -async function verifyProof(proof: Uint8Array) { - await api.acirInitProvingKey(acirComposer, acirBufferUncompressed); - const verified = await api.acirVerifyProof(acirComposer, proof, false); - return verified; -} -``` - -## Now for the fun part - -Let's call our functions, and destroy our API! - -```ts -const input = { x: 3, y: 4 }; -const witness = await generateWitness(input, acirBuffer); -console.log('Witness generated!'); -const proof = await generateProof(witness); -console.log('Proof generated!'); -await verifyProof(proof); -console.log('Proof verified!'); -api.destroy(); -``` - -You can use [this](https://gist.github.com/critesjosh/6f3ba19fdc9298b24e90ba4f736247dc) tsconfig.json. You can see the script [here](https://gist.github.com/critesjosh/4aa36e87a0cc3f09feaf1febb4d11348). - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -This assumes you've already ran `nargo codegen-verifier`, got your smart contract, and deployed it with Hardhat, Foundry, or your tool of choice. You can then verify a Noir proof by simply calling it. - -Currently, `bb.js` appends the public inputs to the proof. However, these inputs need to be fed separately to the verifier contract. A simple solution is to just slice them from the resulting proof, like this: - -```ts -import { ethers } from 'ethers'; // example using ethers v5 -import artifacts from '../artifacts/circuits/contract/plonk_vk.sol/UltraVerifier.json'; // I compiled using Hardhat, so I'm getting my abi from here - -const verifierAddress = '0x123455'; // your verifier address -const provider = new ethers.providers.Web3Provider(window.ethereum); -const signer = this.provider.getSigner(); - -const contract = new ethers.Contract(verifierAddress, artifacts.abi, signer); - -const publicInputs = proof.slice(0, 32); -const slicedProof = proof.slice(32); -await contract.verify(slicedProof, [publicInputs]); -``` diff --git a/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md b/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md deleted file mode 100644 index 4696b4a1426..00000000000 --- a/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[view an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md deleted file mode 100644 index 76f7701ba55..00000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -v 0.6.0 -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: - https://marketplace.visualstudio.com/items?itemName=noir-lang.noir-programming-language-syntax-highlighter diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad45569..00000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md deleted file mode 100644 index 5f4f00a3f36..00000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. -Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - constrain x != y; -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `constrain` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `constrain x != y`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). diff --git a/docs/versioned_docs/version-v0.6.0/index.md b/docs/versioned_docs/version-v0.6.0/index.md deleted file mode 100644 index f4706182ffa..00000000000 --- a/docs/versioned_docs/version-v0.6.0/index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a domain specific language for creating and verifying proofs. It's design choices are -influenced heavily by Rust. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges -within the design process, but allows one to decouple the programming language completely from the -backend. This is similar in theory to LLVM. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Ethereum Developers - -Noir currently includes a command to publish a contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the `contract` command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md deleted file mode 100644 index 3a711fc8922..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `constrain` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Constrain Statement](./constrain) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `constrain` statements, `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md deleted file mode 100644 index 171b7d3dbda..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - constrain s.sum() == 42; -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -constrain MyStruct::sum(s) == 42 -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md deleted file mode 100644 index 29108dd2634..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditonal to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - constrain x == 5; -} -constrain x == 2; -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md deleted file mode 100644 index 2e374e0bf88..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -constrain flag == 1; - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -constrain flag == 0; -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md deleted file mode 100644 index a25a946123d..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md b/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md deleted file mode 100644 index 9ba1e260e8c..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Constrain Statements -description: - Learn about the constrain keyword in Noir, which can be used to explicitly constrain the predicate - or comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: - [Noir programming language, constrain statement, predicate expression, comparison expression] ---- - -:::danger - -In versions >=0.5.0 use the [`assert`](./04_assert.md) syntax. The `constrain` statement will be -maintained for some time for backwards compatibility but will be deprecated in the future. - -::: - -Noir includes a special keyword `constrain` which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Constrain statement example - -```rust -fn main(x : Field, y : Field) { - constrain x == y; -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -fn main(x : Field, y : Field) { - constrain x + y; -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md deleted file mode 100644 index 4d6c01fd797..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - constrain first.limbs != second.limbs; - first - - fn second(first: BigInt, second: Self) -> Self { - constrain first.limbs != second.limbs; - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - constrain array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - constrain array_eq(array, array, MyStruct::eq); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md deleted file mode 100644 index a7240a54e5c..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -# Mutability - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime values - -Comptime value are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Note that variables declared as mutable may not be comptime: - -```rust -fn main() { - // error: Cannot mark a comptime type as mutable - let mut a: comptime Field = 5; - - // a inferred as a private Field here - let mut a = 5; -} -``` - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - constrain res == y[0]; - - let res2 = x * mysubmodule::N; - constrain res != res2; -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md deleted file mode 100644 index 5b1d9fa38f2..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir doesn't have multi-line comments, but you can emulate them via using `//` on each line - -```rust -// This is a multi line -// comment, that is ignored by -// the compiler -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md deleted file mode 100644 index 03759d4bb4a..00000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `disctinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a71148..00000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md deleted file mode 100644 index f3b40eb849b..00000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.2.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use. For example, -demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import just the `Point` and the `Curve` that you want to use. - -```rust -use dep::std::ec::tecurve::affine::Curve; -use dep::std::ec::tecurve::affine::Point; -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- BigInt -- "`ecrecover`" -- sparse merkle tree verifier diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md deleted file mode 100644 index e429b336511..00000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md deleted file mode 100644 index f9d9ddb77ff..00000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program - -## `nargo new [path]` - -Creates a new Noir project. - -_Arguments_ - -- `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo print-acir` - -Print a compiled circuit to stdout such that the ACIR can be inspected. diff --git a/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md deleted file mode 100644 index 73f91c72bfd..00000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - constrain add(2,2) == 4; - constrain add(0,1) == 1; - constrain add(1,0) == 1; -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 69a5607f1b2..00000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do *not* currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md deleted file mode 100644 index 701590ccf54..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Array Methods -description: - Learn about the commonly used methods available for arrays in Noir, including len, sort, fold, - reduce, all, and any. -keywords: [rust, array, methods, len, sort, fold, reduce, all, any] ---- - -# Array - -For convenience, the STD provides some ready-to-use, common methods for arrays[^migrationnote]: - -## len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - constrain array.len() == 2; -} -``` - -## sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted = arr.sort(); - constrain sorted == [32, 42]; -} -``` - -## sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - constrain sorted_ascending == [32, 42]; // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - constrain sorted_descending == [32, 42]; // does not verify -} -``` - -## map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2) // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2,2,2,2,2] - let folded = arr.fold(0, |a, b| a + b); - constrain folded == 10; -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,2] - let reduced = arr.reduce(|a, b| a + b); - constrain reduced == 10; -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,2] - let all = arr.all(|a| a == 2); - constrain all; -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,5] - let any = arr.any(|a| a == 5); - constrain any; -} - -``` - -[^migrationnote]: - Migration Note: These methods were previously free functions, called via `std::array::len()`. - For the sake of ease of use and readability, these functions are now methods and the old syntax - for them is now deprecated. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md deleted file mode 100644 index 3063e71c147..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_secp256k1) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index c373f10ca6a..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, blake2s, pedersen, mimc_bn254 and mimc -keywords: - [ - cryptographic primitives, - Noir project, - sha256, - blake2s, - pedersen, - mimc_bn254, - mimc, - hash - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes (`[u8; 32]`). - -```rust -fn keccak256(_input : [u8; N]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::keccak256(x); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - constrain hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a; -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1e..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c2c6f3ae19a..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> Field -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx deleted file mode 100644 index 88892712fb6..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: ECDSA Verification -description: - Learn about the cryptographic primitives regarding ECDSA over the secp256k1 curve -keywords: - [ - cryptographic primitives, - Noir project, - ecdsa, - secp256k1, - signatures, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> Field -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 2d4ed0f8fae..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::Curve; -use dep::std::ec::tecurve::affine::Point; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbff..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md deleted file mode 100644 index 3ecf043033c..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - constrain pow == 16; -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/logging.md b/docs/versioned_docs/version-v0.6.0/standard_library/logging.md deleted file mode 100644 index 649d35a3f0b..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/logging.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement only works for fields, integers and arrays (including strings). - -```rust -use dep::std; - -fn main(string: pub str<5>) { - let x = 5; - std::println(x) -} - -``` - -To view the output of the `println` statement you need to set the `--show-output` flag. - -``` -$ nargo prove --help -Create proof for this program. The proof is returned as a hex encoded string - -Usage: nargo prove [OPTIONS] [PROOF_NAME] [CIRCUIT_NAME] - -Arguments: - [PROOF_NAME] The name of the proof - [CIRCUIT_NAME] The name of the circuit build files (ACIR, proving and verification keys) - -Options: - -v, --verify Verify proof after proving - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md deleted file mode 100644 index fc8909a4795..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Merkle Trees -description: - Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.6.0/typescript.md b/docs/versioned_docs/version-v0.6.0/typescript.md deleted file mode 100644 index fae002dfd28..00000000000 --- a/docs/versioned_docs/version-v0.6.0/typescript.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -This guide is based on the [noir-starter](https://github.com/signorecello/noir-starter) example. -Please refer to it for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -We're assuming you're using ES6 for both browser (for example with React), or nodejs. - -Install [Yarn](https://yarnpkg.com/) or [Node.js](https://nodejs.org/en). Init a new project with -`npm init`. Install Noir dependencies in your project by running: - -```bash -npm i @noir-lang/noir_wasm@0.3.2-fa0e9cff github:noir-lang/barretenberg#39a1547875f941ef6640217a42d8f34972425c97 @noir-lang/aztec_backend@0.1.0-0c3b2f2 -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, we will use the _Standard Noir Example_ and place it in the `src` folder. Feel -free to use any other, as long as you refactor the below examples accordingly. - -This standard example is a program that multiplies input `x` with input `y` and returns the result: - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Imports - -We need some imports, for both the `noir_wasm` library (which will compile the circuit into `wasm` -executables) and `aztec_backend` which is the actual proving backend we will be using. - -We also need to tell the compiler where to find the `.nr` files, so we need to import -`initialiseResolver`. - -```ts -import initNoirWasm, { acir_read_bytes, compile } from '@noir-lang/noir_wasm'; -import initialiseAztecBackend from '@noir-lang/aztec_backend'; -import { initialiseResolver } from '@noir-lang/noir-source-resolver'; -``` - -## Compiling - -We'll go over the code line-by-line later: - -```ts -export const compileCircuit = async () => { - await initNoirWasm(); - - return await fetch(new URL('../src/main.nr', import.meta.url)) - .then(r => r.text()) - .then(code => { - initialiseResolver((id: any) => { - return code; - }); - }) - .then(() => { - try { - const compiled_noir = compile({}); - return compiled_noir; - } catch (e) { - console.log('Error while compiling:', e); - } - }); -}; -``` - -1. First we're calling `initNoirWasm`. This is required on the browser only. -2. We then pass an URL that points to our `main.nr` file, and call `.then` on it so we can get the - actual text of the source code -3. We call `initialiseResolver` returning the source code -4. Finally, we can call the `compile` function - -This function should return us the compiled circuit. - -:::note - -You can use as many files as you need, -[importing them as you would do with Nargo](./modules_packages_crates/dependencies), and you don't -need to set them up in the `src` folder. Just mind the following particularities about -`initialiseResolver`: - -1. The `compile` function expects a `main.nr` file as an entry point. If you need another one, just - pass it as a `entry_point` parameter to `compile`. Check the - [noir starter](https://github.com/signorecello/noir-starter) for an example on multiple files and - a non-default entry point. -2. `initialiseResolver` needs to be synchronous -3. Different frameworks use different ways of fetching files. It's beyond the scope of this guide to - explain why and how, but for reference, - [noir starter](https://github.com/signorecello/noir-starter) uses both Next.js and node.js for - testing. - -Quick tip: an easy way to deal with `initialiseResolver` is just to prepare a -`{fileName: "literally_the_code"}` object beforehand - -::: - -## ACIR - -Noir compiles to two properties: - -1. The ACIR, which is the intermediate language used by backends such as Barretenberg -2. The ABI, which tells you which inputs are to be read - -Let's write a little function that gets us both, initializes the backend, and returns the ACIR as -bytes: - -```ts -export const getAcir = async () => { - const { circuit, abi } = await compileCircuit(); - await initialiseAztecBackend(); - - let acir_bytes = new Uint8Array(Buffer.from(circuit, 'hex')); - return acir_read_bytes(acir_bytes); -}; -``` - -Calling `getAcir()` now should return us the ACIR of the circuit, ready to be used in proofs. - -## Initializing Prover & Verifier - -Prior to proving and verifying, the prover and verifier have to first be initialized by calling -`barretenberg`'s `setup_generic_prover_and_verifier` with your Noir program's ACIR: - -```ts -let [prover, verifier] = await setup_generic_prover_and_verifier(acir); -``` - -This is probably a good time to store this prover and verifier into your state like React Context, -Redux, or others. - -## Proving - -The Noir program can then be executed and proved by calling `barretenberg`'s `create_proof` -function: - -```ts -const proof = await create_proof(prover, acir, abi); -``` - -On the browser, this proof can fail as it requires heavy loads to be run on worker threads. Here's a -quick example of a worker: - -```ts -// worker.ts -onmessage = async event => { - try { - await initializeAztecBackend(); - const { acir, input } = event.data; - const [prover, verifier] = await setup_generic_prover_and_verifier(acir); - const proof = await create_proof(prover, acir, input); - postMessage(proof); - } catch (er) { - postMessage(er); - } finally { - close(); - } -}; -``` - -Which would be called like this, for example: - -```ts -// index.ts -const worker = new Worker(new URL('./worker.ts', import.meta.url)); -worker.onmessage = e => { - if (e.data instanceof Error) { - // oh no! - } else { - // yey! - } -}; -worker.postMessage({ acir, input: { x: 3, y: 4 } }); -``` - -## Verifying - -The `proof` obtained can be verified by calling `barretenberg`'s `verify_proof` function: - -```ts -// 1_mul.ts -const verified = await verify_proof(verifier, proof); -``` - -The function should return `true` if the entire process is working as intended, which can be -asserted if you are writing a test script: - -```ts -expect(verified).eq(true); -``` - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -To generate the verifier smart contract using typescript: - -```ts -// generator.ts -import { writeFileSync } from 'fs'; - -const sc = verifier.SmartContract(); -syncWriteFile('../contracts/plonk_vk.sol', sc); - -function syncWriteFile(filename: string, data: any) { - writeFileSync(join(__dirname, filename), data, { - flag: 'w', - }); -} -``` - -You can then verify a Noir proof using the verifier contract, for example using Hardhat: - -```ts -// verifier.ts -import { ethers } from 'hardhat'; -import { Contract, ContractFactory, utils } from 'ethers'; - -let Verifier: ContractFactory; -let verifierContract: Contract; - -before(async () => { - Verifier = await ethers.getContractFactory('TurboVerifier'); - verifierContract = await Verifier.deploy(); -}); - -// Verify proof -const sc_verified = await verifierContract.verify(proof); -``` diff --git a/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md b/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md deleted file mode 100644 index 4696b4a1426..00000000000 --- a/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[view an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md deleted file mode 100644 index 868ceffd989..00000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad45569..00000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md deleted file mode 100644 index 64d04c4e062..00000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates proof `p`: - -```bash -nargo prove p -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof `pp`: - -```bash -nargo prove -p OtherProver pp -``` - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md deleted file mode 100644 index e6f5dfc2faa..00000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.7.1/index.md b/docs/versioned_docs/version-v0.7.1/index.md deleted file mode 100644 index 028df708bd5..00000000000 --- a/docs/versioned_docs/version-v0.7.1/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md deleted file mode 100644 index 6ac494ad404..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md +++ /dev/null @@ -1,305 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Assert Function](./assert) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: - -### BigInt - -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md deleted file mode 100644 index 8fd63293c13..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a8..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md deleted file mode 100644 index d5caa463765..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md deleted file mode 100644 index a25a946123d..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md deleted file mode 100644 index 66f2e85e16b..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md deleted file mode 100644 index 90a1f3379a2..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in Noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -Comptime values are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Comptime is slightly different from Rust's `const`. Namely, it is a bit more flexible in that normal functions can accept comptime parameters. For example, this is used to verify an array index is known at compile-time. Note that the "known at compile-time" here means "known after function inlining is performed while optimizing the program" and not "known during type-checking." - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Note that variables declared as mutable may not be comptime: - -```rust -fn main() { - // error: Cannot mark a comptime type as mutable - let mut a: comptime Field = 5; - - // a inferred as a private Field here - let mut a = 5; -} -``` - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md deleted file mode 100644 index 5b1d9fa38f2..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir doesn't have multi-line comments, but you can emulate them via using `//` on each line - -```rust -// This is a multi line -// comment, that is ignored by -// the compiler -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md deleted file mode 100644 index 03759d4bb4a..00000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `disctinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a71148..00000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md deleted file mode 100644 index 2807ad52046..00000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md deleted file mode 100644 index e429b336511..00000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md b/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md deleted file mode 100644 index 8efa286b5f0..00000000000 --- a/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program -- `--print-acir` - Displays the ACIR for the compiled circuit - -## `nargo new [path]` - -Creates a new Noir project. - -_Arguments_ - -- `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md deleted file mode 100644 index ba0bebd658b..00000000000 --- a/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md deleted file mode 100644 index 8d8a9531243..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Array Methods -description: - Learn about the commonly used methods available for arrays in Noir, including len, sort, fold, - reduce, all, and any. -keywords: [rust, array, methods, len, sort, fold, reduce, all, any] ---- - -# Array - -For convenience, the STD provides some ready-to-use, common methods for arrays[^migrationnote]: - -## len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -## sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -## sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -## map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` - -[^migrationnote]: - Migration Note: These methods were previously free functions, called via `std::array::len()`. - For the sake of ease of use and readability, these functions are now methods and the old syntax - for them is now deprecated. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md deleted file mode 100644 index 3063e71c147..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_secp256k1) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 31a84cdb753..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1e..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5ff..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx deleted file mode 100644 index 0b800fdbc5f..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: ECDSA Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 curve -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 26fb4c09e88..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed3316..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbff..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md deleted file mode 100644 index dedeea4cd9a..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/logging.md b/docs/versioned_docs/version-v0.7.1/standard_library/logging.md deleted file mode 100644 index 649d35a3f0b..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/logging.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement only works for fields, integers and arrays (including strings). - -```rust -use dep::std; - -fn main(string: pub str<5>) { - let x = 5; - std::println(x) -} - -``` - -To view the output of the `println` statement you need to set the `--show-output` flag. - -``` -$ nargo prove --help -Create proof for this program. The proof is returned as a hex encoded string - -Usage: nargo prove [OPTIONS] [PROOF_NAME] [CIRCUIT_NAME] - -Arguments: - [PROOF_NAME] The name of the proof - [CIRCUIT_NAME] The name of the circuit build files (ACIR, proving and verification keys) - -Options: - -v, --verify Verify proof after proving - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md deleted file mode 100644 index fc8909a4795..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Merkle Trees -description: - Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md b/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.7.1/typescript.md b/docs/versioned_docs/version-v0.7.1/typescript.md deleted file mode 100644 index fae002dfd28..00000000000 --- a/docs/versioned_docs/version-v0.7.1/typescript.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -This guide is based on the [noir-starter](https://github.com/signorecello/noir-starter) example. -Please refer to it for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -We're assuming you're using ES6 for both browser (for example with React), or nodejs. - -Install [Yarn](https://yarnpkg.com/) or [Node.js](https://nodejs.org/en). Init a new project with -`npm init`. Install Noir dependencies in your project by running: - -```bash -npm i @noir-lang/noir_wasm@0.3.2-fa0e9cff github:noir-lang/barretenberg#39a1547875f941ef6640217a42d8f34972425c97 @noir-lang/aztec_backend@0.1.0-0c3b2f2 -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, we will use the _Standard Noir Example_ and place it in the `src` folder. Feel -free to use any other, as long as you refactor the below examples accordingly. - -This standard example is a program that multiplies input `x` with input `y` and returns the result: - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Imports - -We need some imports, for both the `noir_wasm` library (which will compile the circuit into `wasm` -executables) and `aztec_backend` which is the actual proving backend we will be using. - -We also need to tell the compiler where to find the `.nr` files, so we need to import -`initialiseResolver`. - -```ts -import initNoirWasm, { acir_read_bytes, compile } from '@noir-lang/noir_wasm'; -import initialiseAztecBackend from '@noir-lang/aztec_backend'; -import { initialiseResolver } from '@noir-lang/noir-source-resolver'; -``` - -## Compiling - -We'll go over the code line-by-line later: - -```ts -export const compileCircuit = async () => { - await initNoirWasm(); - - return await fetch(new URL('../src/main.nr', import.meta.url)) - .then(r => r.text()) - .then(code => { - initialiseResolver((id: any) => { - return code; - }); - }) - .then(() => { - try { - const compiled_noir = compile({}); - return compiled_noir; - } catch (e) { - console.log('Error while compiling:', e); - } - }); -}; -``` - -1. First we're calling `initNoirWasm`. This is required on the browser only. -2. We then pass an URL that points to our `main.nr` file, and call `.then` on it so we can get the - actual text of the source code -3. We call `initialiseResolver` returning the source code -4. Finally, we can call the `compile` function - -This function should return us the compiled circuit. - -:::note - -You can use as many files as you need, -[importing them as you would do with Nargo](./modules_packages_crates/dependencies), and you don't -need to set them up in the `src` folder. Just mind the following particularities about -`initialiseResolver`: - -1. The `compile` function expects a `main.nr` file as an entry point. If you need another one, just - pass it as a `entry_point` parameter to `compile`. Check the - [noir starter](https://github.com/signorecello/noir-starter) for an example on multiple files and - a non-default entry point. -2. `initialiseResolver` needs to be synchronous -3. Different frameworks use different ways of fetching files. It's beyond the scope of this guide to - explain why and how, but for reference, - [noir starter](https://github.com/signorecello/noir-starter) uses both Next.js and node.js for - testing. - -Quick tip: an easy way to deal with `initialiseResolver` is just to prepare a -`{fileName: "literally_the_code"}` object beforehand - -::: - -## ACIR - -Noir compiles to two properties: - -1. The ACIR, which is the intermediate language used by backends such as Barretenberg -2. The ABI, which tells you which inputs are to be read - -Let's write a little function that gets us both, initializes the backend, and returns the ACIR as -bytes: - -```ts -export const getAcir = async () => { - const { circuit, abi } = await compileCircuit(); - await initialiseAztecBackend(); - - let acir_bytes = new Uint8Array(Buffer.from(circuit, 'hex')); - return acir_read_bytes(acir_bytes); -}; -``` - -Calling `getAcir()` now should return us the ACIR of the circuit, ready to be used in proofs. - -## Initializing Prover & Verifier - -Prior to proving and verifying, the prover and verifier have to first be initialized by calling -`barretenberg`'s `setup_generic_prover_and_verifier` with your Noir program's ACIR: - -```ts -let [prover, verifier] = await setup_generic_prover_and_verifier(acir); -``` - -This is probably a good time to store this prover and verifier into your state like React Context, -Redux, or others. - -## Proving - -The Noir program can then be executed and proved by calling `barretenberg`'s `create_proof` -function: - -```ts -const proof = await create_proof(prover, acir, abi); -``` - -On the browser, this proof can fail as it requires heavy loads to be run on worker threads. Here's a -quick example of a worker: - -```ts -// worker.ts -onmessage = async event => { - try { - await initializeAztecBackend(); - const { acir, input } = event.data; - const [prover, verifier] = await setup_generic_prover_and_verifier(acir); - const proof = await create_proof(prover, acir, input); - postMessage(proof); - } catch (er) { - postMessage(er); - } finally { - close(); - } -}; -``` - -Which would be called like this, for example: - -```ts -// index.ts -const worker = new Worker(new URL('./worker.ts', import.meta.url)); -worker.onmessage = e => { - if (e.data instanceof Error) { - // oh no! - } else { - // yey! - } -}; -worker.postMessage({ acir, input: { x: 3, y: 4 } }); -``` - -## Verifying - -The `proof` obtained can be verified by calling `barretenberg`'s `verify_proof` function: - -```ts -// 1_mul.ts -const verified = await verify_proof(verifier, proof); -``` - -The function should return `true` if the entire process is working as intended, which can be -asserted if you are writing a test script: - -```ts -expect(verified).eq(true); -``` - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -To generate the verifier smart contract using typescript: - -```ts -// generator.ts -import { writeFileSync } from 'fs'; - -const sc = verifier.SmartContract(); -syncWriteFile('../contracts/plonk_vk.sol', sc); - -function syncWriteFile(filename: string, data: any) { - writeFileSync(join(__dirname, filename), data, { - flag: 'w', - }); -} -``` - -You can then verify a Noir proof using the verifier contract, for example using Hardhat: - -```ts -// verifier.ts -import { ethers } from 'hardhat'; -import { Contract, ContractFactory, utils } from 'ethers'; - -let Verifier: ContractFactory; -let verifierContract: Contract; - -before(async () => { - Verifier = await ethers.getContractFactory('TurboVerifier'); - verifierContract = await Verifier.deploy(); -}); - -// Verify proof -const sc_verified = await verifierContract.verify(proof); -``` diff --git a/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx deleted file mode 100644 index 6430780817c..00000000000 --- a/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md deleted file mode 100644 index dc412cdc6fa..00000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad45569..00000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md deleted file mode 100644 index 7c320cef9c5..00000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates proof `p`: - -```bash -nargo prove p -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof `pp`: - -```bash -nargo prove -p OtherProver pp -``` - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md deleted file mode 100644 index e6f5dfc2faa..00000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.9.0/index.md b/docs/versioned_docs/version-v0.9.0/index.md deleted file mode 100644 index 028df708bd5..00000000000 --- a/docs/versioned_docs/version-v0.9.0/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md deleted file mode 100644 index abbadca86be..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md +++ /dev/null @@ -1,405 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Assert Function](./assert) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Slices - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -Slices are part of the [noir standard library](../standard_library/slice_methods) so you need to import the respective module in order to work with it. For example: - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -### Vectors - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: - -### Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. - -## References - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md deleted file mode 100644 index 8fd63293c13..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a8..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md deleted file mode 100644 index d5caa463765..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| \<\< | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md deleted file mode 100644 index a25a946123d..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md deleted file mode 100644 index 6b621eda3eb..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Unconstrained Functions -description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." - -keywords: [Noir programming language, unconstrained, open] ---- - - - -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. - -## Why? - -Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. - -Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. - -Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. - -A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. - -## Example - -An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. - -Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 -Backend circuit size: 3619 -``` - -A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. - -```rust -fn main(num: u72) -> pub [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8)) as u8; - } - - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 -Backend circuit size: 3143 -``` - -Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. - -It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. - -We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: - -```rust -fn main(num: u72) -> pub [u8; 8] { - let out = u72_to_u8(num); - - let mut reconstructed_num: u72 = 0; - for i in 0..8 { - reconstructed_num += (out[i] as u72 << (56 - (8 * i))); - } - assert(num == reconstructed_num); - out -} - -unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { - let mut out: [u8; 8] = [0; 8]; - for i in 0..8 { - out[i] = (num >> (56 - (i * 8))) as u8; - } - out -} -``` - -``` -Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 -Backend circuit size: 2902 -``` - -This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). - -Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md deleted file mode 100644 index 66f2e85e16b..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md deleted file mode 100644 index a9c93e61167..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> pub Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -Comptime values are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Comptime is slightly different from Rust's `const`. Namely, it is a bit more flexible in that normal functions can accept comptime parameters. For example, this is used to verify an array index is known at compile-time. Note that the "known at compile-time" here means "known after function inlining is performed while optimizing the program" and not "known during type-checking." - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Comptime variables can be mutuable, but must be known at compile time: - -```rust -fn main(runtime_var: Field) -> pub Field { - let known_at_compile_time: comptime Field = 1; - - // The next line will cause an error - let bad_var: comptime Field = runtime_var; - -} -``` - -As `runtime_var` is a argument to the circuit it cannot be known at compile time and so assigning it to a comptime variable should fail. A circuit's arguments is the only way in which non-comptime variables can enter the circuit (excluding [brillig](./unconstrained) foreign calls). - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md deleted file mode 100644 index 3bb4d2f25a4..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. - -Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. - -```rust -/* - This is a block comment describing a complex function. -*/ -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md deleted file mode 100644 index e7ff7f5017a..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md b/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md deleted file mode 100644 index efd743e764f..00000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Shadowing ---- - -Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. - -For example, the following function is valid in Noir: - -```rust -fn main() { - let x = 5; - - { - let x = x * 2; - assert (x == 10); - } - - assert (x == 5); -} -``` - -In this example, a variable x is first defined with the value 5. - -The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. - -When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. - -## Temporal mutability - -One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. - -```rust -fn main() { - let age = 30; - // age = age + 5; // Would error as `age` is immutable by default. - - let mut age = age + 5; // Temporarily mutates `age` with a new value. - - let age = age; // Locks `age`'s mutability again. - - assert (age == 35); -} -``` diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a71148..00000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md deleted file mode 100644 index 2807ad52046..00000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md deleted file mode 100644 index e429b336511..00000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md deleted file mode 100644 index d550e137258..00000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile. - -For example, `nargo build `. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program -- `--print-acir` - Displays the ACIR for the compiled circuit - -## `nargo new [path]` - -Creates a new Noir project in a new folder called `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo init` - -Creates a new Noir project in the current directory. - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md deleted file mode 100644 index ba0bebd658b..00000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba7..00000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md deleted file mode 100644 index c758846b688..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f929474..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 31a84cdb753..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1e..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5ff..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 3934a0338d0..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 6e6b19b6861..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed3316..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbff..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md deleted file mode 100644 index dedeea4cd9a..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/logging.md b/docs/versioned_docs/version-v0.9.0/standard_library/logging.md deleted file mode 100644 index 42a84be1992..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/logging.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md deleted file mode 100644 index 57d8c4a9e4f..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md deleted file mode 100644 index 4705ae6c575..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/Savio-Sou/recursion-demo/tree/main). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md deleted file mode 100644 index 8b93d8ea427..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Slice Methods -description: - Learn about the commonly used methods available for slices in Noir, including push_back, len, srt, map, fold, reduce, all, and any. -keywords: [rust, slice, methods, push_back, len, sort, fold, reduce, all, any] ---- - -For convenience, the STD provides some ready-to-use, common methods for slices: - -## push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -## push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -## pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -## pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -## insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust - new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -## remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -View the corresponding test file [here]([test-file]. - -## len - -Returns the length of a slice - -```rust -fn len(_slice: [T]) -> comptime Field -``` - -Example: - -```rust -fn main() { - let slic = [42, 42] - assert(slic.len() == 2); -} -``` - -## sort - -Returns a new sorted slice. The original slice remains untouched. Notice that this function will -only work for slices of fields or integers, not for any arbitrary type. This is because the sorting -logic the function uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_slice: [T]) -> [T] -``` - -Example: - -```rust -fn main() { - let slic = [42, 32] - let sorted = slic.sort(); - assert(sorted == [32, 42]); -} -``` - -## sort_via - -Sorts the slice with a custom comparison function - -```rust -fn sort_via(mut a: [T], ordering: fn(T, T) -> bool) -> [T] -``` - -Example: - -```rust -fn main() { - let slic = [42, 32] - let sorted_ascending = slic.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = slic.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -## map - -Applies a function to each element of the slice, returning a new slice containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U] -``` - -Example: - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2) // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the slice, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the slice, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -Example: - -```rust - -fn main() { - let slic = [2,2,2,2,2] - let folded = slic.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,2] - let reduced = slic.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,2] - let all = slic.all(|a| a == 2); - assert(all); -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,5] - let any = slic.any(|a| a == 5); - assert(any); -} - -``` - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac2..00000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.9.0/typescript.md b/docs/versioned_docs/version-v0.9.0/typescript.md deleted file mode 100644 index 8608783784c..00000000000 --- a/docs/versioned_docs/version-v0.9.0/typescript.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -You can check the complete code for this tutorial here: [browser with next.js](https://github.com/signorecello/noir-min-browser-example) and [node.js](https://github.com/signorecello/noir-min-nodejs-example). If you want just a browser boilerplate to start with, check out the [noir-starter](https://github.com/noir-lang/noir-starter) for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -Make sure you are using Noir version >= 0.10.1. - -You can check your current version by running `nargo --version`. - -You can install version 0.10.1 with noirup with - -```bash -noirup -v 0.10.1 -``` - -See the [Installation page](./getting_started/nargo_installation) for more info. - -We're assuming you're using ES6 and ESM for both browser (for example with React), or nodejs. Install [Node.js](https://nodejs.org/en). Init a new project with `npm init` and add `"type": "module"` to your `package.json`, to let `node` know we're using the new ESM sytem: - -```json -{ - "type": "module" - // the rest of your package.json -} -``` - -Install Noir dependencies in your project by running: - -```bash -npm i @aztec/bb.js@0.3.6 https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42 fflate ethers@5.7.2 -``` - -This will install the `acvm-simulator` that will generate our witness, and the proving backend barretenberg `bb.js`. - -We're also installing `ethers` because we're too lazy to write a function that pads public inputs with 32bytes, and `fflate` to help us decompress our circuit bytecode. - -Since we're with typescript and using `nodejs` types, we also recommend to install the `@types/node` package, otherwise your IDE will scream at you. - -```bash -npm i --save-dev @types/node -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, run `nargo init` to create a new Noir project. - -We will use a Standard Noir Example and place it in the `src` folder. This program simply multiplies input `x` with input `y` and returns the result `z`. The verifier doesn't know the value of `x`: we're proving that we know it without making it public. - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Compiling - -In order to start proving, we need to compile our circuit into the intermediate representation used by our backend. As of today, you have to do that with `nargo`. Just hop to your circuits folder and run `nargo compile`. - -:::info - -At this time, you need to use a nightly version of nargo. Using [noirup](./getting_started/00_nargo_installation.md#option-1-noirup) you can do this simply by running `noirup -n`. - -::: - -You should have a `json` file in `target/` with your circuit's bytecode. The json file is name based on the project name specified in Nargo.toml, so for a project named "test", it will be at `target/test.json`. You can then import that file normally. - -```ts -import circuit from '../target/test.json' assert { type: 'json' }; -``` - -## Decompressing the circuit - -The compiled circuit comes compressed. We need to decompress it, that's where `fflate` comes in. - -```ts -import { decompressSync } from 'fflate'; - -const acirBuffer = Buffer.from(circuit.bytecode, 'base64'); -const acirBufferUncompressed = decompressSync(acirBuffer); -``` - -From here, it's highly recommended you store `acirBuffer` and `acirBufferUncompressed` close by, as they will be used for witness generation and proving. - -## Initializing ACVM and BB.JS - -:::note - -This step will eventually be abstracted away as Noir tooling matures. For now, you should be fine just literally copy-pasting most of this into your own code. - -::: - -Before proving, `bb.js` needs to be initialized. We need to import some functions and use them - -```ts -import { Crs, newBarretenbergApiAsync, RawBuffer } from '@aztec/bb.js/dest/node/index.js'; - -const api = await newBarretenbergApiAsync(4); - -const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed); -const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize))); -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); -``` - -We should take two very useful objects from here: `api` and `acirComposer`. Make sure to keep these close by! - -:::info - -On the browser, you also need to init the ACVM. You can do that by importing it and calling it like: - -```ts -import initACVM, { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -await initACVM(); -// the rest of your code -``` - -::: - -## Generating witnesses - -Witness generation is what allows us to prove with arbitrary inputs (like user inputs on a form, game, etc). In this example, our input is a simple object with our circuit inputs `x`, `y`, and return `z` (fun fact: the return value in Noir is actually a public input!). We're wrapping it in a function, so it can be conveniently called later on. - -```ts -import { ethers } from 'ethers'; // I'm lazy so I'm using ethers to pad my input -import { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -async function generateWitness(input: any, acirBuffer: Buffer): Promise { - const initialWitness = new Map(); - initialWitness.set(1, ethers.utils.hexZeroPad(`0x${input.x.toString(16)}`, 32)); - initialWitness.set(2, ethers.utils.hexZeroPad(`0x${input.y.toString(16)}`, 32)); - - const witnessMap = await executeCircuit(acirBuffer, initialWitness, () => { - throw Error('unexpected oracle'); - }); - - const witnessBuff = compressWitness(witnessMap); - return witnessBuff; -} -``` - -## Proving - -Finally, we're ready to prove with our backend. Just like with the witness generation, could be useful to wrap it in its own function: - -```ts -async function generateProof(witness: Uint8Array) { - const proof = await api.acirCreateProof( - acirComposer, - acirBufferUncompressed, - decompressSync(witness), - false, - ); - return proof; -} -``` - -## Verifying - -Our backend should also be ready to verify our proof: - -```ts -async function verifyProof(proof: Uint8Array) { - await api.acirInitProvingKey(acirComposer, acirBufferUncompressed); - const verified = await api.acirVerifyProof(acirComposer, proof, false); - return verified; -} -``` - -## Now for the fun part - -Let's call our functions, and destroy our API! - -```ts -const input = { x: 3, y: 4 }; -const witness = await generateWitness(input, acirBuffer); -console.log('Witness generated!'); -const proof = await generateProof(witness); -console.log('Proof generated!'); -await verifyProof(proof); -console.log('Proof verified!'); -api.destroy(); -``` - -You can use [this](https://gist.github.com/critesjosh/6f3ba19fdc9298b24e90ba4f736247dc) tsconfig.json. You can see the script [here](https://gist.github.com/critesjosh/4aa36e87a0cc3f09feaf1febb4d11348). - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -This assumes you've already ran `nargo codegen-verifier`, got your smart contract, and deployed it with Hardhat, Foundry, or your tool of choice. You can then verify a Noir proof by simply calling it. - -Currently, `bb.js` appends the public inputs to the proof. However, these inputs need to be fed separately to the verifier contract. A simple solution is to just slice them from the resulting proof, like this: - -```ts -import { ethers } from 'ethers'; // example using ethers v5 -import artifacts from '../artifacts/circuits/contract/plonk_vk.sol/UltraVerifier.json'; // I compiled using Hardhat, so I'm getting my abi from here - -const verifierAddress = '0x123455'; // your verifier address -const provider = new ethers.providers.Web3Provider(window.ethereum); -const signer = this.provider.getSigner(); - -const contract = new ethers.Contract(verifierAddress, artifacts.abi, signer); - -const publicInputs = proof.slice(0, 32); -const slicedProof = proof.slice(32); -await contract.verify(slicedProof, [publicInputs]); -``` diff --git a/docs/versioned_sidebars/version-v0.10.5-sidebars.json b/docs/versioned_sidebars/version-v0.10.5-sidebars.json deleted file mode 100644 index a51ebf87643..00000000000 --- a/docs/versioned_sidebars/version-v0.10.5-sidebars.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.6.0-sidebars.json b/docs/versioned_sidebars/version-v0.6.0-sidebars.json deleted file mode 100644 index 7323ae1c504..00000000000 --- a/docs/versioned_sidebars/version-v0.6.0-sidebars.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/array_methods", - "standard_library/field_methods", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.7.1-sidebars.json b/docs/versioned_sidebars/version-v0.7.1-sidebars.json deleted file mode 100644 index 7323ae1c504..00000000000 --- a/docs/versioned_sidebars/version-v0.7.1-sidebars.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/array_methods", - "standard_library/field_methods", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.9.0-sidebars.json b/docs/versioned_sidebars/version-v0.9.0-sidebars.json deleted file mode 100644 index 190363917e0..00000000000 --- a/docs/versioned_sidebars/version-v0.9.0-sidebars.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/slice_methods", - "standard_library/field_methods", - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} From 5f0f81f7f49b021880e0bff648aa6c6d0fede46c Mon Sep 17 00:00:00 2001 From: kek kek kek Date: Tue, 12 Dec 2023 07:45:30 -0800 Subject: [PATCH 023/137] feat: add `prelude.nr` (#3693) # Description ## Additional Context ## Documentation Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- .../src/hir/def_collector/dc_crate.rs | 68 ++++++++++++++-- .../src/hir/def_collector/dc_mod.rs | 2 + .../src/hir/def_map/item_scope.rs | 77 +++++++++++-------- .../src/hir/def_map/module_data.rs | 17 +++- .../src/hir/def_map/module_def.rs | 7 ++ .../src/hir/def_map/namespace.rs | 8 +- .../src/hir/resolution/import.rs | 17 +++- .../src/hir/resolution/path_resolver.rs | 7 +- noir_stdlib/src/lib.nr | 2 + noir_stdlib/src/prelude.nr | 3 + .../execution_success/prelude/Nargo.toml | 7 ++ .../execution_success/prelude/src/main.nr | 32 ++++++++ 12 files changed, 194 insertions(+), 53 deletions(-) create mode 100644 noir_stdlib/src/prelude.nr create mode 100644 tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml create mode 100644 tooling/nargo_cli/tests/execution_success/prelude/src/main.nr diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index b9fd51dbb0f..a008874dc80 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -7,8 +7,8 @@ use crate::hir::resolution::errors::ResolverError; use crate::hir::resolution::import::{resolve_imports, ImportDirective}; use crate::hir::resolution::resolver::Resolver; use crate::hir::resolution::{ - collect_impls, collect_trait_impls, resolve_free_functions, resolve_globals, resolve_impls, - resolve_structs, resolve_trait_by_path, resolve_trait_impls, resolve_traits, + collect_impls, collect_trait_impls, path_resolver, resolve_free_functions, resolve_globals, + resolve_impls, resolve_structs, resolve_trait_by_path, resolve_trait_impls, resolve_traits, resolve_type_aliases, }; use crate::hir::type_check::{type_check_func, TypeCheckError, TypeChecker}; @@ -19,8 +19,9 @@ use crate::node_interner::{FuncId, NodeInterner, StmtId, StructId, TraitId, Type use crate::parser::{ParserError, SortedModule}; use crate::{ - ExpressionKind, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, NoirTypeAlias, - Path, Type, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, + NoirTypeAlias, Path, PathKind, Type, UnresolvedGenerics, UnresolvedTraitConstraint, + UnresolvedType, }; use fm::FileId; use iter_extended::vecmap; @@ -243,9 +244,20 @@ impl DefCollector { context, )); + let submodules = vecmap(def_collector.def_map.modules().iter(), |(index, _)| index); // Add the current crate to the collection of DefMaps context.def_maps.insert(crate_id, def_collector.def_map); + inject_prelude(crate_id, context, crate_root, &mut def_collector.collected_imports); + for submodule in submodules { + inject_prelude( + crate_id, + context, + LocalModuleId(submodule), + &mut def_collector.collected_imports, + ); + } + // Resolve unresolved imports collected from the crate let (resolved, unresolved_imports) = resolve_imports(crate_id, def_collector.collected_imports, &context.def_maps); @@ -264,8 +276,11 @@ impl DefCollector { for resolved_import in resolved { let name = resolved_import.name; for ns in resolved_import.resolved_namespace.iter_defs() { - let result = current_def_map.modules[resolved_import.module_scope.0] - .import(name.clone(), ns); + let result = current_def_map.modules[resolved_import.module_scope.0].import( + name.clone(), + ns, + resolved_import.is_prelude, + ); if let Err((first_def, second_def)) = result { let err = DefCollectorErrorKind::Duplicate { @@ -358,6 +373,47 @@ impl DefCollector { } } +fn inject_prelude( + crate_id: CrateId, + context: &Context, + crate_root: LocalModuleId, + collected_imports: &mut Vec, +) { + let segments: Vec<_> = "std::prelude" + .split("::") + .map(|segment| crate::Ident::new(segment.into(), Span::default())) + .collect(); + + let path = + Path { segments: segments.clone(), kind: crate::PathKind::Dep, span: Span::default() }; + + if !crate_id.is_stdlib() { + if let Ok(module_def) = path_resolver::resolve_path( + &context.def_maps, + ModuleId { krate: crate_id, local_id: crate_root }, + path, + ) { + let module_id = module_def.as_module().expect("std::prelude should be a module"); + let prelude = context.module(module_id).scope().names(); + + for path in prelude { + let mut segments = segments.clone(); + segments.push(Ident::new(path.to_string(), Span::default())); + + collected_imports.insert( + 0, + ImportDirective { + module_id: crate_root, + path: Path { segments, kind: PathKind::Dep, span: Span::default() }, + alias: None, + is_prelude: true, + }, + ); + } + } + } +} + /// Separate the globals Vec into two. The first element in the tuple will be the /// literal globals, except for arrays, and the second will be all other globals. /// We exclude array literals as they can contain complex types diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 4cf910221ec..39f6c5b9014 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -44,6 +44,7 @@ pub fn collect_defs( ) -> Vec<(CompilationError, FileId)> { let mut collector = ModCollector { def_collector, file_id, module_id }; let mut errors: Vec<(CompilationError, FileId)> = vec![]; + // First resolve the module declarations for decl in ast.module_decls { errors.extend(collector.parse_module_declaration(context, &decl, crate_id)); @@ -57,6 +58,7 @@ pub fn collect_defs( module_id: collector.module_id, path: import.path, alias: import.alias, + is_prelude: false, }); } diff --git a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index 42cca550651..523def89518 100644 --- a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -5,6 +5,8 @@ use crate::{ }; use std::collections::{hash_map::Entry, HashMap}; +type Scope = HashMap, (ModuleDefId, Visibility, bool /*is_prelude*/)>; + #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Visibility { Public, @@ -12,8 +14,8 @@ pub enum Visibility { #[derive(Default, Debug, PartialEq, Eq)] pub struct ItemScope { - types: HashMap, (ModuleDefId, Visibility)>>, - values: HashMap, (ModuleDefId, Visibility)>>, + types: HashMap, + values: HashMap, defs: Vec, } @@ -25,7 +27,7 @@ impl ItemScope { mod_def: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.add_item_to_namespace(name, mod_def, trait_id)?; + self.add_item_to_namespace(name, mod_def, trait_id, false)?; self.defs.push(mod_def); Ok(()) } @@ -38,25 +40,31 @@ impl ItemScope { name: Ident, mod_def: ModuleDefId, trait_id: Option, + is_prelude: bool, ) -> Result<(), (Ident, Ident)> { - let add_item = - |map: &mut HashMap, (ModuleDefId, Visibility)>>| { - if let Entry::Occupied(mut o) = map.entry(name.clone()) { - let trait_hashmap = o.get_mut(); - if let Entry::Occupied(_) = trait_hashmap.entry(trait_id) { - let old_ident = o.key(); - Err((old_ident.clone(), name)) - } else { - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public)); + let add_item = |map: &mut HashMap| { + if let Entry::Occupied(mut o) = map.entry(name.clone()) { + let trait_hashmap = o.get_mut(); + if let Entry::Occupied(mut n) = trait_hashmap.entry(trait_id) { + let is_prelude = std::mem::replace(&mut n.get_mut().2, is_prelude); + let old_ident = o.key(); + + if is_prelude { Ok(()) + } else { + Err((old_ident.clone(), name)) } } else { - let mut trait_hashmap = HashMap::new(); - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public)); - map.insert(name, trait_hashmap); + trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); Ok(()) } - }; + } else { + let mut trait_hashmap = HashMap::new(); + trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + map.insert(name, trait_hashmap); + Ok(()) + } + }; match mod_def { ModuleDefId::ModuleId(_) => add_item(&mut self.types), @@ -69,7 +77,7 @@ impl ItemScope { } pub fn find_module_with_name(&self, mod_name: &Ident) -> Option<&ModuleId> { - let (module_def, _) = self.types.get(mod_name)?.get(&None)?; + let (module_def, _, _) = self.types.get(mod_name)?.get(&None)?; match module_def { ModuleDefId::ModuleId(id) => Some(id), _ => None, @@ -81,13 +89,13 @@ impl ItemScope { // methods introduced without trait take priority and hide methods with the same name that come from a trait let a = trait_hashmap.get(&None); match a { - Some((module_def, _)) => match module_def { + Some((module_def, _, _)) => match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, }, None => { if trait_hashmap.len() == 1 { - let (module_def, _) = trait_hashmap.get(trait_hashmap.keys().last()?)?; + let (module_def, _, _) = trait_hashmap.get(trait_hashmap.keys().last()?)?; match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, @@ -105,7 +113,7 @@ impl ItemScope { func_name: &Ident, trait_id: &Option, ) -> Option { - let (module_def, _) = self.values.get(func_name)?.get(trait_id)?; + let (module_def, _, _) = self.values.get(func_name)?.get(trait_id)?; match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, @@ -115,20 +123,19 @@ impl ItemScope { pub fn find_name(&self, name: &Ident) -> PerNs { // Names, not associated with traits are searched first. If not found, we search for name, coming from a trait. // If we find only one name from trait, we return it. If there are multiple traits, providing the same name, we return None. - let find_name_in = - |a: &HashMap, (ModuleDefId, Visibility)>>| { - if let Some(t) = a.get(name) { - if let Some(tt) = t.get(&None) { - Some(*tt) - } else if t.len() == 1 { - t.values().last().cloned() - } else { - None - } + let find_name_in = |a: &HashMap| { + if let Some(t) = a.get(name) { + if let Some(tt) = t.get(&None) { + Some(*tt) + } else if t.len() == 1 { + t.values().last().cloned() } else { None } - }; + } else { + None + } + }; PerNs { types: find_name_in(&self.types), values: find_name_in(&self.values) } } @@ -144,15 +151,19 @@ impl ItemScope { } } + pub fn names(&self) -> impl Iterator { + self.types.keys().chain(self.values.keys()) + } + pub fn definitions(&self) -> Vec { self.defs.clone() } - pub fn types(&self) -> &HashMap, (ModuleDefId, Visibility)>> { + pub fn types(&self) -> &HashMap { &self.types } - pub fn values(&self) -> &HashMap, (ModuleDefId, Visibility)>> { + pub fn values(&self) -> &HashMap { &self.values } diff --git a/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 29b11e92c01..fbb5e5cf741 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -41,6 +41,10 @@ impl ModuleData { } } + pub(crate) fn scope(&self) -> &ItemScope { + &self.scope + } + fn declare( &mut self, name: Ident, @@ -104,8 +108,13 @@ impl ModuleData { self.scope.find_func_with_name(name) } - pub fn import(&mut self, name: Ident, id: ModuleDefId) -> Result<(), (Ident, Ident)> { - self.scope.add_item_to_namespace(name, id, None) + pub fn import( + &mut self, + name: Ident, + id: ModuleDefId, + is_prelude: bool, + ) -> Result<(), (Ident, Ident)> { + self.scope.add_item_to_namespace(name, id, None, is_prelude) } pub fn find_name(&self, name: &Ident) -> PerNs { @@ -113,12 +122,12 @@ impl ModuleData { } pub fn type_definitions(&self) -> impl Iterator + '_ { - self.definitions.types().values().flat_map(|a| a.values().map(|(id, _)| *id)) + self.definitions.types().values().flat_map(|a| a.values().map(|(id, _, _)| *id)) } /// Return an iterator over all definitions defined within this module, /// excluding any type definitions. pub fn value_definitions(&self) -> impl Iterator + '_ { - self.definitions.values().values().flat_map(|a| a.values().map(|(id, _)| *id)) + self.definitions.values().values().flat_map(|a| a.values().map(|(id, _, _)| *id)) } } diff --git a/compiler/noirc_frontend/src/hir/def_map/module_def.rs b/compiler/noirc_frontend/src/hir/def_map/module_def.rs index 659d7712ab4..3e5629639fa 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_def.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_def.rs @@ -61,6 +61,13 @@ impl ModuleDefId { ModuleDefId::GlobalId(_) => "global", } } + + pub fn as_module(&self) -> Option { + match self { + Self::ModuleId(v) => Some(*v), + _ => None, + } + } } impl From for ModuleDefId { diff --git a/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/compiler/noirc_frontend/src/hir/def_map/namespace.rs index 9221b389d84..ca14d9f8617 100644 --- a/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -3,13 +3,13 @@ use super::{item_scope::Visibility, ModuleDefId}; // This works exactly the same as in r-a, just simplified #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility)>, - pub values: Option<(ModuleDefId, Visibility)>, + pub types: Option<(ModuleDefId, Visibility, bool)>, + pub values: Option<(ModuleDefId, Visibility, bool)>, } impl PerNs { pub fn types(t: ModuleDefId) -> PerNs { - PerNs { types: Some((t, Visibility::Public)), values: None } + PerNs { types: Some((t, Visibility::Public, false)), values: None } } pub fn take_types(self) -> Option { @@ -24,7 +24,7 @@ impl PerNs { self.types.map(|it| it.0).into_iter().chain(self.values.map(|it| it.0)) } - pub fn iter_items(self) -> impl Iterator { + pub fn iter_items(self) -> impl Iterator { self.types.into_iter().chain(self.values) } diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index 5b59dcd2241..41fdac746bd 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -12,6 +12,7 @@ pub struct ImportDirective { pub module_id: LocalModuleId, pub path: Path, pub alias: Option, + pub is_prelude: bool, } pub type PathResolution = Result; @@ -30,6 +31,7 @@ pub struct ResolvedImport { pub resolved_namespace: PerNs, // The module which we must add the resolved namespace to pub module_scope: LocalModuleId, + pub is_prelude: bool, } impl From for CustomDiagnostic { @@ -66,7 +68,12 @@ pub fn resolve_imports( .map_err(|error| (error, module_scope))?; let name = resolve_path_name(&import_directive); - Ok(ResolvedImport { name, resolved_namespace, module_scope }) + Ok(ResolvedImport { + name, + resolved_namespace, + module_scope, + is_prelude: import_directive.is_prelude, + }) }) } @@ -207,8 +214,12 @@ fn resolve_external_dep( kind: PathKind::Plain, span: Span::default(), }; - let dep_directive = - ImportDirective { module_id: dep_module.local_id, path, alias: directive.alias.clone() }; + let dep_directive = ImportDirective { + module_id: dep_module.local_id, + path, + alias: directive.alias.clone(), + is_prelude: false, + }; let dep_def_map = def_maps.get(&dep_module.krate).unwrap(); diff --git a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs index 4c16edd56f1..4c5fa3bceef 100644 --- a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs @@ -57,14 +57,15 @@ pub fn resolve_path( path: Path, ) -> Result { // lets package up the path into an ImportDirective and resolve it using that - let import = ImportDirective { module_id: module_id.local_id, path, alias: None }; + let import = + ImportDirective { module_id: module_id.local_id, path, alias: None, is_prelude: false }; let allow_referencing_contracts = allow_referencing_contracts(def_maps, module_id.krate, module_id.local_id); let def_map = &def_maps[&module_id.krate]; let ns = resolve_path_to_ns(&import, def_map, def_maps, allow_referencing_contracts)?; - let function = ns.values.map(|(id, _)| id); - let id = function.or_else(|| ns.types.map(|(id, _)| id)); + let function = ns.values.map(|(id, _, _)| id); + let id = function.or_else(|| ns.types.map(|(id, _, _)| id)); Ok(id.expect("Found empty namespace")) } diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index fecdf77a4ec..3c47de61bab 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -19,6 +19,8 @@ mod compat; mod option; mod string; mod test; +mod prelude; + // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident #[oracle(print)] diff --git a/noir_stdlib/src/prelude.nr b/noir_stdlib/src/prelude.nr new file mode 100644 index 00000000000..f33a1f7e7f1 --- /dev/null +++ b/noir_stdlib/src/prelude.nr @@ -0,0 +1,3 @@ +use crate::collections::vec::Vec; +use crate::option::Option; +use crate::{print, println, assert_constant}; diff --git a/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml b/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml new file mode 100644 index 00000000000..35f223bce02 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "prelude" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr b/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr new file mode 100644 index 00000000000..9bf2ec18f3a --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr @@ -0,0 +1,32 @@ +fn main(x: Field, y: pub Field) { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); +} + +mod a { + // We don't want to give an error due to re-importing elements that are already in the prelude. + use dep::std::collections::vec::Vec; + use dep::std::option::Option; + use dep::{print, println}; + + fn main() { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); + } +} + +mod b { + fn main() { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); + } +} From 028d65ea71f9c11e69784d06e0f9768668455f83 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 12 Dec 2023 16:48:23 +0000 Subject: [PATCH 024/137] fix(ssa): Handle array arguments to side effectual constrain statements (#3740) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ffects # Description ## Problem\* Resolves the error that occurs in this PR (https://github.com/noir-lang/noir/pull/3739) No issue as was discovered and fixed quickly. ## Summary\* Using an array as an argument in a side effectual constrain statement will cause this panic: ``` Message: internal error: entered unreachable code: Can only cast to a numeric Location: compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs:1652 ``` Here is an example program which would previously fail that is included as a regression test: ``` struct Bar { inner: [u32; 3], } fn main(y: pub u32) { let bar = Bar { inner: [100, 101, 102] }; // The assert inside the if should be hit if y < 10 { assert(bar.inner == [100, 101, 102]); } // The assert inside the if should not be hit if y > 10 { assert(bar.inner == [0, 1, 2]); } } ``` Without this fix it is not possible to constrain arrays inside of if statements based upon witness conditions. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/opt/flatten_cfg.rs | 101 +++++++++++++++--- .../side_effects_constrain_array/Nargo.toml | 7 ++ .../side_effects_constrain_array/Prover.toml | 1 + .../side_effects_constrain_array/src/main.nr | 17 +++ 4 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 test_programs/execution_success/side_effects_constrain_array/Nargo.toml create mode 100644 test_programs/execution_success/side_effects_constrain_array/Prover.toml create mode 100644 test_programs/execution_success/side_effects_constrain_array/src/main.nr diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index b280ffa06e0..f0ad610948c 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -640,22 +640,9 @@ impl<'f> Context<'f> { match instruction { Instruction::Constrain(lhs, rhs, message) => { // Replace constraint `lhs == rhs` with `condition * lhs == condition * rhs`. + let lhs = self.handle_constrain_arg_side_effects(lhs, condition, &call_stack); + let rhs = self.handle_constrain_arg_side_effects(rhs, condition, &call_stack); - // Condition needs to be cast to argument type in order to multiply them together. - let argument_type = self.inserter.function.dfg.type_of_value(lhs); - let casted_condition = self.insert_instruction( - Instruction::Cast(condition, argument_type), - call_stack.clone(), - ); - - let lhs = self.insert_instruction( - Instruction::binary(BinaryOp::Mul, lhs, casted_condition), - call_stack.clone(), - ); - let rhs = self.insert_instruction( - Instruction::binary(BinaryOp::Mul, rhs, casted_condition), - call_stack, - ); Instruction::Constrain(lhs, rhs, message) } Instruction::Store { address, value } => { @@ -685,6 +672,90 @@ impl<'f> Context<'f> { } } + /// Given the arguments of a constrain instruction, multiplying them by the branch's condition + /// requires special handling in the case of complex types. + fn handle_constrain_arg_side_effects( + &mut self, + argument: ValueId, + condition: ValueId, + call_stack: &CallStack, + ) -> ValueId { + let argument_type = self.inserter.function.dfg.type_of_value(argument); + + match &argument_type { + Type::Numeric(_) => { + // Condition needs to be cast to argument type in order to multiply them together. + let casted_condition = self.insert_instruction( + Instruction::Cast(condition, argument_type), + call_stack.clone(), + ); + + self.insert_instruction( + Instruction::binary(BinaryOp::Mul, argument, casted_condition), + call_stack.clone(), + ) + } + Type::Array(_, _) => { + self.handle_array_constrain_arg(argument_type, argument, condition, call_stack) + } + Type::Slice(_) => { + panic!("Cannot use slices directly in a constrain statement") + } + Type::Reference(_) => { + panic!("Cannot use references directly in a constrain statement") + } + Type::Function => { + panic!("Cannot use functions directly in a constrain statement") + } + } + } + + fn handle_array_constrain_arg( + &mut self, + typ: Type, + argument: ValueId, + condition: ValueId, + call_stack: &CallStack, + ) -> ValueId { + let mut new_array = im::Vector::new(); + + let (element_types, len) = match &typ { + Type::Array(elements, len) => (elements, *len), + _ => panic!("Expected array type"), + }; + + for i in 0..len { + for (element_index, element_type) in element_types.iter().enumerate() { + let index = ((i * element_types.len() + element_index) as u128).into(); + let index = self.inserter.function.dfg.make_constant(index, Type::field()); + + let typevars = Some(vec![element_type.clone()]); + + let mut get_element = |array, typevars| { + let get = Instruction::ArrayGet { array, index }; + self.inserter + .function + .dfg + .insert_instruction_and_results( + get, + self.inserter.function.entry_block(), + typevars, + CallStack::new(), + ) + .first() + }; + + let element = get_element(argument, typevars); + + new_array.push_back( + self.handle_constrain_arg_side_effects(element, condition, call_stack), + ); + } + } + + self.inserter.function.dfg.make_array(new_array, typ) + } + fn undo_stores_in_then_branch(&mut self, then_branch: &Branch) { for (address, store) in &then_branch.store_values { let address = *address; diff --git a/test_programs/execution_success/side_effects_constrain_array/Nargo.toml b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml new file mode 100644 index 00000000000..fc817f0921f --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "side_effects_constrain_array" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/side_effects_constrain_array/Prover.toml b/test_programs/execution_success/side_effects_constrain_array/Prover.toml new file mode 100644 index 00000000000..7127baac5bf --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/Prover.toml @@ -0,0 +1 @@ +y = "3" diff --git a/test_programs/execution_success/side_effects_constrain_array/src/main.nr b/test_programs/execution_success/side_effects_constrain_array/src/main.nr new file mode 100644 index 00000000000..fb3c346a460 --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/src/main.nr @@ -0,0 +1,17 @@ +struct Bar { + inner: [Field; 3], +} + +fn main(y: pub u32) { + let bar = Bar { inner: [100, 101, 102] }; + + // The assert inside the if should be hit + if y < 10 { + assert(bar.inner == [100, 101, 102]); + } + + // The assert inside the if should not be hit + if y > 10 { + assert(bar.inner == [0, 1, 2]); + } +} \ No newline at end of file From 2fc46e2269bba8d9ad6ae5fcea10e64dce9b3745 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:49:41 +0000 Subject: [PATCH 025/137] feat: simplify explicit equality assertions to assert equality directly (#3708) # Description ## Problem\* Resolves ## Summary\* This PR adds 3 optimisations. 1. `x < 1` gets rewritten as `x == 0` for unsigned values of `x` (as this is the only value for which `x < 1` can be true) 2. constraining the result of an equality to be true gets rewritten as asserting this equality directly. 3. constraining the result of a boolean NOT gets rewritten to be in terms of the original value. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../noirc_evaluator/src/ssa/ir/instruction.rs | 83 +++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index af6bf2c4687..628ad638e64 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -433,12 +433,74 @@ impl Instruction { _ => None, } } - Instruction::Constrain(lhs, rhs, ..) => { + Instruction::Constrain(lhs, rhs, msg) => { if dfg.resolve(*lhs) == dfg.resolve(*rhs) { // Remove trivial case `assert_eq(x, x)` SimplifyResult::Remove } else { - SimplifyResult::None + match (&dfg[dfg.resolve(*lhs)], &dfg[dfg.resolve(*rhs)]) { + ( + Value::NumericConstant { constant, typ }, + Value::Instruction { instruction, .. }, + ) + | ( + Value::Instruction { instruction, .. }, + Value::NumericConstant { constant, typ }, + ) if *typ == Type::bool() => { + match dfg[*instruction] { + Instruction::Binary(Binary { + lhs, + rhs, + operator: BinaryOp::Eq, + }) if constant.is_one() => { + // Replace an explicit two step equality assertion + // + // v2 = eq v0, u32 v1 + // constrain v2 == u1 1 + // + // with a direct assertion of equality between the two values + // + // v2 = eq v0, u32 v1 + // constrain v0 == v1 + // + // Note that this doesn't remove the value `v2` as it may be used in other instructions, but it + // will likely be removed through dead instruction elimination. + + SimplifiedToInstruction(Instruction::Constrain( + lhs, + rhs, + msg.clone(), + )) + } + Instruction::Not(value) => { + // Replace an assertion that a not instruction is truthy + // + // v1 = not v0 + // constrain v1 == u1 1 + // + // with an assertion that the not instruction input is falsy + // + // v1 = not v0 + // constrain v0 == u1 0 + // + // Note that this doesn't remove the value `v1` as it may be used in other instructions, but it + // will likely be removed through dead instruction elimination. + let reversed_constant = FieldElement::from(!constant.is_one()); + let reversed_constant = + dfg.make_constant(reversed_constant, Type::bool()); + SimplifiedToInstruction(Instruction::Constrain( + value, + reversed_constant, + msg.clone(), + )) + } + + _ => None, + } + } + + _ => None, + } } } Instruction::ArrayGet { array, index } => { @@ -795,10 +857,19 @@ impl Binary { let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); return SimplifyResult::SimplifiedTo(zero); } - if operand_type.is_unsigned() && rhs_is_zero { - // Unsigned values cannot be less than zero. - let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); - return SimplifyResult::SimplifiedTo(zero); + if operand_type.is_unsigned() { + if rhs_is_zero { + // Unsigned values cannot be less than zero. + let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); + return SimplifyResult::SimplifiedTo(zero); + } else if rhs_is_one { + let zero = dfg.make_constant(FieldElement::zero(), operand_type); + return SimplifyResult::SimplifiedToInstruction(Instruction::binary( + BinaryOp::Eq, + self.lhs, + zero, + )); + } } } BinaryOp::And => { From ce57038f896bf125fdacbde05bed1031bf122940 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:20:28 +0000 Subject: [PATCH 026/137] chore: move debugger tests in submodule (#3780) # Description ## Problem\* Resolves ## Summary\* This PR just does some simple refactoring to make #3627's diff smaller. Test functions are placed inside a submodule which then holds all of the imports instead of them being in the functions themselves. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/debugger/src/context.rs | 409 ++++++++++++++++---------------- 1 file changed, 203 insertions(+), 206 deletions(-) diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 4c429ca2a67..1475827fbea 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -321,221 +321,218 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } #[cfg(test)] -struct StubbedSolver; - -#[cfg(test)] -impl BlackBoxFunctionSolver for StubbedSolver { - fn schnorr_verify( - &self, - _public_key_x: &FieldElement, - _public_key_y: &FieldElement, - _signature: &[u8], - _message: &[u8], - ) -> Result { - unimplemented!(); - } - - fn pedersen_commitment( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { - unimplemented!(); - } - - fn pedersen_hash( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result { - unimplemented!(); - } - - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { - unimplemented!(); - } -} - -#[cfg(test)] -#[test] -fn test_resolve_foreign_calls_stepping_into_brillig() { +mod tests { + use super::*; + use crate::context::{DebugCommandResult, DebugContext}; + + use acvm::{ + acir::{ + circuit::brillig::{Brillig, BrilligInputs, BrilligOutputs}, + native_types::Expression, + }, + brillig_vm::brillig::{ + BinaryFieldOp, Opcode as BrilligOpcode, RegisterIndex, RegisterOrMemory, + }, + }; + use nargo::{artifacts::debug::DebugArtifact, ops::DefaultForeignCallExecutor}; use std::collections::BTreeMap; - use acvm::acir::{ - brillig::{Opcode as BrilligOpcode, RegisterIndex, RegisterOrMemory}, - circuit::brillig::{Brillig, BrilligInputs}, - native_types::Expression, - }; + struct StubbedSolver; + + impl BlackBoxFunctionSolver for StubbedSolver { + fn schnorr_verify( + &self, + _public_key_x: &FieldElement, + _public_key_y: &FieldElement, + _signature: &[u8], + _message: &[u8], + ) -> Result { + unimplemented!(); + } - use nargo::ops::DefaultForeignCallExecutor; - - let fe_0 = FieldElement::zero(); - let fe_1 = FieldElement::one(); - let w_x = Witness(1); - - let blackbox_solver = &StubbedSolver; - - let brillig_opcodes = Brillig { - inputs: vec![BrilligInputs::Single(Expression { - linear_combinations: vec![(fe_1, w_x)], - ..Expression::default() - })], - outputs: vec![], - bytecode: vec![ - BrilligOpcode::Const { destination: RegisterIndex::from(1), value: Value::from(fe_0) }, - BrilligOpcode::ForeignCall { - function: "clear_mock".into(), - destinations: vec![], - inputs: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))], - }, - BrilligOpcode::Stop, - ], - predicate: None, - }; - let opcodes = vec![Opcode::Brillig(brillig_opcodes)]; - let current_witness_index = 2; - let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; - - let debug_symbols = vec![]; - let file_map = BTreeMap::new(); - let warnings = vec![]; - let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; - - let initial_witness = BTreeMap::from([(Witness(1), fe_1)]).into(); - - let mut context = DebugContext::new( - blackbox_solver, - circuit, - debug_artifact, - initial_witness, - Box::new(DefaultForeignCallExecutor::new(true)), - ); - - assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); - - // execute the first Brillig opcode (const) - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!( - context.get_current_opcode_location(), - Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) - ); - - // try to execute the second Brillig opcode (and resolve the foreign call) - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!( - context.get_current_opcode_location(), - Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) - ); - - // retry the second Brillig opcode (foreign call should be finished) - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!( - context.get_current_opcode_location(), - Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }) - ); - - // last Brillig opcode - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Done)); - assert_eq!(context.get_current_opcode_location(), None); -} + fn pedersen_commitment( + &self, + _inputs: &[FieldElement], + _domain_separator: u32, + ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { + unimplemented!(); + } -#[cfg(test)] -#[test] -fn test_break_brillig_block_while_stepping_acir_opcodes() { - use std::collections::BTreeMap; + fn pedersen_hash( + &self, + _inputs: &[FieldElement], + _domain_separator: u32, + ) -> Result { + unimplemented!(); + } - use acvm::acir::{ - brillig::{Opcode as BrilligOpcode, RegisterIndex}, - circuit::brillig::{Brillig, BrilligInputs, BrilligOutputs}, - native_types::Expression, - }; - use acvm::brillig_vm::brillig::BinaryFieldOp; - use nargo::ops::DefaultForeignCallExecutor; + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { + unimplemented!(); + } + } - let fe_0 = FieldElement::zero(); - let fe_1 = FieldElement::one(); - let w_x = Witness(1); - let w_y = Witness(2); - let w_z = Witness(3); + #[test] + fn test_resolve_foreign_calls_stepping_into_brillig() { + let fe_0 = FieldElement::zero(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); - let blackbox_solver = &StubbedSolver; + let blackbox_solver = &StubbedSolver; - // This Brillig block is equivalent to: z = x + y - let brillig_opcodes = Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { + let brillig_opcodes = Brillig { + inputs: vec![BrilligInputs::Single(Expression { linear_combinations: vec![(fe_1, w_x)], ..Expression::default() + })], + outputs: vec![], + bytecode: vec![ + BrilligOpcode::Const { + destination: RegisterIndex::from(1), + value: Value::from(fe_0), + }, + BrilligOpcode::ForeignCall { + function: "clear_mock".into(), + destinations: vec![], + inputs: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))], + }, + BrilligOpcode::Stop, + ], + predicate: None, + }; + let opcodes = vec![Opcode::Brillig(brillig_opcodes)]; + let current_witness_index = 2; + let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + let warnings = vec![]; + let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + + let initial_witness = BTreeMap::from([(Witness(1), fe_1)]).into(); + + let mut context = DebugContext::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + Box::new(DefaultForeignCallExecutor::new(true)), + ); + + assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); + + // execute the first Brillig opcode (const) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) + ); + + // try to execute the second Brillig opcode (and resolve the foreign call) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) + ); + + // retry the second Brillig opcode (foreign call should be finished) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }) + ); + + // last Brillig opcode + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_opcode_location(), None); + } + + #[test] + fn test_break_brillig_block_while_stepping_acir_opcodes() { + let fe_0 = FieldElement::zero(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); + let w_y = Witness(2); + let w_z = Witness(3); + + let blackbox_solver = &StubbedSolver; + + // This Brillig block is equivalent to: z = x + y + let brillig_opcodes = Brillig { + inputs: vec![ + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + }), + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_y)], + ..Expression::default() + }), + ], + outputs: vec![BrilligOutputs::Simple(w_z)], + bytecode: vec![ + BrilligOpcode::BinaryFieldOp { + destination: RegisterIndex::from(0), + op: BinaryFieldOp::Add, + lhs: RegisterIndex::from(0), + rhs: RegisterIndex::from(1), + }, + BrilligOpcode::Stop, + ], + predicate: None, + }; + let opcodes = vec![ + // z = x + y + Opcode::Brillig(brillig_opcodes), + // x + y - z = 0 + Opcode::Arithmetic(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], + q_c: fe_0, }), - BrilligInputs::Single(Expression { - linear_combinations: vec![(fe_1, w_y)], - ..Expression::default() - }), - ], - outputs: vec![BrilligOutputs::Simple(w_z)], - bytecode: vec![ - BrilligOpcode::BinaryFieldOp { - destination: RegisterIndex::from(0), - op: BinaryFieldOp::Add, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - }, - BrilligOpcode::Stop, - ], - predicate: None, - }; - let opcodes = vec![ - // z = x + y - Opcode::Brillig(brillig_opcodes), - // x + y - z = 0 - Opcode::Arithmetic(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], - q_c: fe_0, - }), - ]; - let current_witness_index = 3; - let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; - - let debug_symbols = vec![]; - let file_map = BTreeMap::new(); - let warnings = vec![]; - let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; - - let initial_witness = BTreeMap::from([(Witness(1), fe_1), (Witness(2), fe_1)]).into(); - - let mut context = DebugContext::new( - blackbox_solver, - circuit, - debug_artifact, - initial_witness, - Box::new(DefaultForeignCallExecutor::new(true)), - ); - - // set breakpoint - let breakpoint_location = OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }; - assert!(context.add_breakpoint(breakpoint_location)); - - // execute the first ACIR opcode (Brillig block) -> should reach the breakpoint instead - let result = context.step_acir_opcode(); - assert!(matches!(result, DebugCommandResult::BreakpointReached(_))); - assert_eq!(context.get_current_opcode_location(), Some(breakpoint_location)); - - // continue execution to the next ACIR opcode - let result = context.step_acir_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(1))); - - // last ACIR opcode - let result = context.step_acir_opcode(); - assert!(matches!(result, DebugCommandResult::Done)); - assert_eq!(context.get_current_opcode_location(), None); + ]; + let current_witness_index = 3; + let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + let warnings = vec![]; + let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + + let initial_witness = BTreeMap::from([(Witness(1), fe_1), (Witness(2), fe_1)]).into(); + + let mut context = DebugContext::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + Box::new(DefaultForeignCallExecutor::new(true)), + ); + + // set breakpoint + let breakpoint_location = OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }; + assert!(context.add_breakpoint(breakpoint_location)); + + // execute the first ACIR opcode (Brillig block) -> should reach the breakpoint instead + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::BreakpointReached(_))); + assert_eq!(context.get_current_opcode_location(), Some(breakpoint_location)); + + // continue execution to the next ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(1))); + + // last ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_opcode_location(), None); + } } From 2717f6f7cf8e7de55b30400f2f682bcda1408a5f Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 12 Dec 2023 19:25:46 +0000 Subject: [PATCH 027/137] chore: remove aztec compile time feature flag (#3596) # Description This is a followup to https://github.com/noir-lang/noir/pull/3578 where we move the feature flag from compile time to runtime producing a single binary. EDIT: This was initially was meant to change it to runtime flag, but there was quite a lot of effort to make this work. We can introduce an environment variable in the future to turn off all macros if this turn out to be a problem ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: Tom French --- .../workflows/build-aztec-feature-flag.yml | 45 ------------------- .github/workflows/publish-es-packages.yml | 5 --- Cargo.toml | 2 +- compiler/noirc_driver/Cargo.toml | 5 +-- compiler/noirc_driver/src/lib.rs | 20 ++++++--- tooling/lsp/src/notifications/mod.rs | 2 +- tooling/lsp/src/requests/code_lens_request.rs | 2 +- tooling/lsp/src/requests/goto_definition.rs | 2 +- tooling/lsp/src/requests/test_run.rs | 2 +- tooling/lsp/src/requests/tests.rs | 2 +- tooling/nargo_cli/src/cli/check_cmd.rs | 4 +- tooling/nargo_cli/src/cli/test_cmd.rs | 1 + 12 files changed, 25 insertions(+), 67 deletions(-) delete mode 100644 .github/workflows/build-aztec-feature-flag.yml diff --git a/.github/workflows/build-aztec-feature-flag.yml b/.github/workflows/build-aztec-feature-flag.yml deleted file mode 100644 index bacf74ba7b1..00000000000 --- a/.github/workflows/build-aztec-feature-flag.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build with aztec feature flag - -on: - pull_request: - merge_group: - push: - branches: - - master - -# This will cancel previous runs when a branch or PR is updated -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-aztec-feature-flag: - name: Test on ${{ matrix.os }} - runs-on: ${{ matrix.runner }} - timeout-minutes: 30 - - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu - runner: ubuntu-latest - target: x86_64-unknown-linux-gnu - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.71.1 - with: - targets: ${{ matrix.target }} - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.target }} - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Build with feature flag - run: cargo build --features="noirc_driver/aztec" diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml index f421672c799..e360654b46a 100644 --- a/.github/workflows/publish-es-packages.yml +++ b/.github/workflows/publish-es-packages.yml @@ -30,11 +30,6 @@ jobs: nix-cache-name: "noir" cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - name: Enable aztec features - if: ${{ inputs.npm-tag == 'aztec' }} - run: | - echo $'\n'"default = [\"aztec\"]"$'\n' >> compiler/noirc_driver/Cargo.toml - - name: Build wasm package run: | nix build -L .#noir_wasm diff --git a/Cargo.toml b/Cargo.toml index c97a7cc2d99..c42eeb9c002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,7 +96,7 @@ getrandom = "0.2" cfg-if = "1.0.0" -clap = { version = "4.3.19", features = ["derive"] } +clap = { version = "4.3.19", features = ["derive", "env"] } codespan = { version = "0.11.1", features = ["serialization"] } codespan-lsp = "0.11.1" codespan-reporting = "0.11.1" diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index c717efed6f5..8759e3f65e8 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -22,7 +22,4 @@ fm.workspace = true serde.workspace = true fxhash.workspace = true -aztec_macros ={path = "../../aztec_macros", optional = true} - -[features] -aztec = ["aztec_macros"] \ No newline at end of file +aztec_macros = { path = "../../aztec_macros" } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 23869fc2a61..298e9838a09 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -61,6 +61,10 @@ pub struct CompileOptions { /// Suppress warnings #[arg(long, conflicts_with = "deny_warnings")] pub silence_warnings: bool, + + /// Disables the builtin macros being used in the compiler + #[arg(long, hide = true)] + pub disable_macros: bool, } /// Helper type used to signify where only warnings are expected in file diagnostics @@ -121,11 +125,13 @@ pub fn check_crate( context: &mut Context, crate_id: CrateId, deny_warnings: bool, + disable_macros: bool, ) -> CompilationResult<()> { - #[cfg(not(feature = "aztec"))] - let macros: Vec<&dyn MacroProcessor> = Vec::new(); - #[cfg(feature = "aztec")] - let macros = vec![&aztec_macros::AztecMacro as &dyn MacroProcessor]; + let macros: Vec<&dyn MacroProcessor> = if disable_macros { + vec![] + } else { + vec![&aztec_macros::AztecMacro as &dyn MacroProcessor] + }; let mut errors = vec![]; let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros); @@ -161,7 +167,8 @@ pub fn compile_main( cached_program: Option, force_compile: bool, ) -> CompilationResult { - let (_, mut warnings) = check_crate(context, crate_id, options.deny_warnings)?; + let (_, mut warnings) = + check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; let main = context.get_main_function(&crate_id).ok_or_else(|| { // TODO(#2155): This error might be a better to exist in Nargo @@ -194,7 +201,8 @@ pub fn compile_contract( crate_id: CrateId, options: &CompileOptions, ) -> CompilationResult { - let (_, warnings) = check_crate(context, crate_id, options.deny_warnings)?; + let (_, warnings) = + check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; // TODO: We probably want to error if contracts is empty let contracts = context.get_all_contracts(&crate_id); diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index f6484f49d48..645d05d3d43 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -113,7 +113,7 @@ pub(super) fn on_did_save_text_document( .flat_map(|package| -> Vec { let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); - let file_diagnostics = match check_crate(&mut context, crate_id, false) { + let file_diagnostics = match check_crate(&mut context, crate_id, false, false) { Ok(((), warnings)) => warnings, Err(errors_and_warnings) => errors_and_warnings, }; diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs index 602ed268981..a47e9f82a63 100644 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -86,7 +86,7 @@ fn on_code_lens_request_inner( let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); // We ignore the warnings and errors produced by compilation for producing code lenses // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false); + let _ = check_crate(&mut context, crate_id, false, false); let fm = &context.file_manager; let files = fm.as_file_map(); diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 4e615cd4fe5..4b5ccddc613 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -56,7 +56,7 @@ fn on_goto_definition_inner( nargo::prepare_package(package, Box::new(crate::get_non_stdlib_asset)); // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false); + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); let files = context.file_manager.as_file_map(); let file_id = context.file_manager.name_to_id(file_path.clone()); diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 962fe99a49b..293b101eb85 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -52,7 +52,7 @@ fn on_test_run_request_inner( match workspace.into_iter().next() { Some(package) => { let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); - if check_crate(&mut context, crate_id, false).is_err() { + if check_crate(&mut context, crate_id, false, false).is_err() { let result = NargoTestRunResult { id: params.id.clone(), result: "error".to_string(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index 6b94b921a06..bed29ebe4e6 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -56,7 +56,7 @@ fn on_tests_request_inner( let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false); + let _ = check_crate(&mut context, crate_id, false, false); // We don't add test headings for a package if it contains no `#[test]` functions get_package_tests_in_crate(&context, &crate_id, &package.name) diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 57b36b8932b..20e51fe1b52 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -61,6 +61,7 @@ fn check_package(package: &Package, compile_options: &CompileOptions) -> Result< &mut context, crate_id, compile_options.deny_warnings, + compile_options.disable_macros, compile_options.silence_warnings, )?; @@ -182,9 +183,10 @@ pub(crate) fn check_crate_and_report_errors( context: &mut Context, crate_id: CrateId, deny_warnings: bool, + disable_macros: bool, silence_warnings: bool, ) -> Result<(), CompileError> { - let result = check_crate(context, crate_id, deny_warnings); + let result = check_crate(context, crate_id, deny_warnings, disable_macros); super::compile_cmd::report_errors( result, &context.file_manager, diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 1b6dbcab34a..7f7ae67d946 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -92,6 +92,7 @@ fn run_tests( &mut context, crate_id, compile_options.deny_warnings, + compile_options.disable_macros, compile_options.silence_warnings, )?; From a48d562b59aa2009a9c9b65dd71e11cdd8d06cf0 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 12 Dec 2023 22:34:49 +0000 Subject: [PATCH 028/137] fix: remove `noirc_driver/aztec` feature flag in docker (#3784) # Description This was not caught because the docker tests are not required checks and it was only being ran on master. They are not required because they need to be optimized a bit more with caching. I don't expect them to fail often, so in the interim, its okay to not have these as required (If this happens again and we have not migrated, then we can revisit) ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/test-cargo.yml | 9 ++++++++- .github/workflows/test-js.yml | 10 +++++++++- scripts/bootstrap_native.sh | 2 +- scripts/bootstrap_packages.sh | 2 -- scripts/test_js_packages.sh | 4 +--- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-cargo.yml b/.github/workflows/test-cargo.yml index e6c9f323b1f..8d414daa75b 100644 --- a/.github/workflows/test-cargo.yml +++ b/.github/workflows/test-cargo.yml @@ -1,9 +1,16 @@ name: Test cargo on: + pull_request: + merge_group: push: branches: - - 'master' + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true jobs: build: diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml index 07e5a4d5426..2f29e027156 100644 --- a/.github/workflows/test-js.yml +++ b/.github/workflows/test-js.yml @@ -1,9 +1,17 @@ name: Test JS packages on: + pull_request: + merge_group: push: branches: - - 'master' + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + jobs: build: diff --git a/scripts/bootstrap_native.sh b/scripts/bootstrap_native.sh index 693a9d9678e..481c76a263e 100755 --- a/scripts/bootstrap_native.sh +++ b/scripts/bootstrap_native.sh @@ -13,4 +13,4 @@ else fi # Build native. -cargo build --features="noirc_driver/aztec" --release +cargo build --release diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh index 5fce2675037..233aed7a039 100755 --- a/scripts/bootstrap_packages.sh +++ b/scripts/bootstrap_packages.sh @@ -14,8 +14,6 @@ else export GIT_COMMIT=$(git rev-parse --verify HEAD) fi -export cargoExtraArgs="--features noirc_driver/aztec" - yarn yarn build diff --git a/scripts/test_js_packages.sh b/scripts/test_js_packages.sh index a54e581b1c9..a5ec5b92a70 100755 --- a/scripts/test_js_packages.sh +++ b/scripts/test_js_packages.sh @@ -14,9 +14,7 @@ else export GIT_COMMIT=$(git rev-parse --verify HEAD) fi -export cargoExtraArgs="--features noirc_driver/aztec" - -cargo build --features="noirc_driver/aztec" --release +cargo build --release export PATH="${PATH}:/usr/src/noir/target/release/" yarn From 47186061b555ab8b4e8037936ae7fab226c197b2 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 23:21:03 +0000 Subject: [PATCH 029/137] chore(ci): use `actions/setup-node` for caching yarn dependencies (#2730) # Description ## Problem\* Resolves ## Summary\* This PR addresses https://github.com/noir-lang/noir/pull/2697#discussion_r1327635425 ## Documentation - [ ] This PR requires documentation updates when merged. - [ ] I will submit a noir-lang/docs PR. - [ ] I will request for and support Dev Rel's help in documenting this PR. ## Additional Context # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .github/actions/setup/action.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 5efe115ddcf..8e24b6738a9 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -4,13 +4,13 @@ description: Installs the workspace's yarn dependencies and caches them runs: using: composite steps: - - name: Cache - uses: actions/cache@v3 - id: cache + - uses: actions/setup-node@v3 + id: node with: - path: "**/node_modules" - key: yarn-v1-${{ hashFiles('**/yarn.lock') }} + node-version: 18.17.1 + cache: 'yarn' + cache-dependency-path: 'yarn.lock' + - name: Install run: yarn --immutable shell: bash - if: steps.cache.outputs.cache-hit != 'true' From 24ff886781157ab9a7d4c5b01a1e22d06371db19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Wed, 13 Dec 2023 07:07:55 +0000 Subject: [PATCH 030/137] chore: moving ordering to category jsons and frontmatters (#3777) # Description This big PR does a simple thing: It makes pages ordering respect metadata instead of filenames ## Problem\* A naive approach supported over the years at docusaurus was to simply have files prefixed with 00, 01, 02, which were removed automatically by docusaurus. This makes docs a bit harder to maintain if for some reason you decide to move pages around, as it breaks all the links. ## Summary\* - Renames all the folders and pages to remove the prefixes - Adds `sidebar_position` property in frontmatter, to order them - Adds `_category_.json` files to order folders - Removes ordering of top level folders in `sidebars.json` --- docs/docs/explanations/_category_.json | 5 + .../modules_packages_crates/_category_.json | 6 + .../crates_and_packages.md | 1 + .../dependencies.md | 1 + .../modules.md | 1 + .../workspaces.md | 3 +- docs/docs/explanations/noir/_category_.json | 6 + .../{00_noir/04_assert.md => noir/assert.md} | 1 + .../09_comments.md => noir/comments.md} | 1 + .../control_flow.md} | 1 + .../12_data_bus.md => noir/data_bus.md} | 4 +- .../noir/data_types/_category_.json | 5 + .../data_types/arrays.md} | 1 + .../data_types/booleans.md} | 1 + .../data_types/fields.md} | 1 + .../data_types/function_types.md} | 3 +- .../data_types}/index.md | 2 +- .../data_types/integers.md} | 1 + .../data_types/references.md} | 1 + .../data_types/slices.mdx} | 1 + .../data_types/strings.md} | 1 + .../data_types/structs.md} | 1 + .../data_types/tuples.md} | 1 + .../data_types/vectors.mdx} | 1 + .../10_distinct.md => noir/distinct.md} | 1 + .../01_functions.md => noir/functions.md} | 13 +- .../06_generics.md => noir/generics.md} | 1 + .../08_lambdas.md => noir/lambdas.md} | 5 +- .../07_mutability.md => noir/mutability.md} | 1 + .../{00_noir/03_ops.md => noir/ops.md} | 1 + .../11_shadowing.md => noir/shadowing.md} | 1 + .../unconstrained.md} | 3 +- .../standard_library/_category_.json | 6 + .../black_box_fns.md | 0 .../cryptographic_primitives/_category_.json | 5 + .../ec_primitives.md} | 1 + .../ecdsa_sig_verification.mdx} | 1 + .../cryptographic_primitives/eddsa.mdx} | 1 + .../cryptographic_primitives/hashes.mdx} | 1 + .../cryptographic_primitives}/index.md | 0 .../cryptographic_primitives/scalar.mdx} | 1 + .../cryptographic_primitives/schnorr.mdx} | 1 + .../logging.md | 0 .../merkle_trees.md | 2 +- .../options.md | 0 .../recursion.md | 0 .../zeroed.md | 0 docs/docs/getting_started/_category_.json | 5 + ...reate_a_project.md => create_a_project.md} | 8 +- .../installation/_category_.json | 6 + .../index.md | 0 .../other_install_methods.md | 5 +- ...ject_breakdown.md => project_breakdown.md} | 5 +- .../getting_started/tooling/_category_.json | 6 + .../{03_tooling => tooling}/index.md | 0 .../language_server.md} | 1 + .../01_testing.md => tooling/testing.md} | 1 + docs/docs/how_to/_category_.json | 5 + docs/docs/index.md | 5 +- docs/docs/migration_notes.md | 2 +- .../reference/NoirJS/noir_js/classes/Noir.md | 5 +- docs/docs/reference/_category_.json | 5 + ...00_nargo_commands.md => nargo_commands.md} | 5 +- .../{00_noirjs_app.md => noirjs_app.md} | 3 +- docs/docusaurus.config.ts | 10 ++ docs/package.json | 4 +- docs/sidebars.js | 30 +--- yarn.lock | 140 ++++++++++++++++-- 68 files changed, 274 insertions(+), 72 deletions(-) create mode 100644 docs/docs/explanations/_category_.json create mode 100644 docs/docs/explanations/modules_packages_crates/_category_.json rename docs/docs/explanations/{02_modules_packages_crates => modules_packages_crates}/crates_and_packages.md (99%) rename docs/docs/explanations/{02_modules_packages_crates => modules_packages_crates}/dependencies.md (99%) rename docs/docs/explanations/{02_modules_packages_crates => modules_packages_crates}/modules.md (99%) rename docs/docs/explanations/{02_modules_packages_crates => modules_packages_crates}/workspaces.md (96%) create mode 100644 docs/docs/explanations/noir/_category_.json rename docs/docs/explanations/{00_noir/04_assert.md => noir/assert.md} (98%) rename docs/docs/explanations/{00_noir/09_comments.md => noir/comments.md} (98%) rename docs/docs/explanations/{00_noir/02_control_flow.md => noir/control_flow.md} (97%) rename docs/docs/explanations/{00_noir/12_data_bus.md => noir/data_bus.md} (97%) create mode 100644 docs/docs/explanations/noir/data_types/_category_.json rename docs/docs/explanations/{00_noir/00_data_types/04_arrays.md => noir/data_types/arrays.md} (99%) rename docs/docs/explanations/{00_noir/00_data_types/02_booleans.md => noir/data_types/booleans.md} (97%) rename docs/docs/explanations/{00_noir/00_data_types/00_fields.md => noir/data_types/fields.md} (99%) rename docs/docs/explanations/{00_noir/00_data_types/10_function_types.md => noir/data_types/function_types.md} (87%) rename docs/docs/explanations/{00_noir/00_data_types => noir/data_types}/index.md (99%) rename docs/docs/explanations/{00_noir/00_data_types/01_integers.md => noir/data_types/integers.md} (99%) rename docs/docs/explanations/{00_noir/00_data_types/09_references.md => noir/data_types/references.md} (96%) rename docs/docs/explanations/{00_noir/00_data_types/05_slices.mdx => noir/data_types/slices.mdx} (99%) rename docs/docs/explanations/{00_noir/00_data_types/03_strings.md => noir/data_types/strings.md} (99%) rename docs/docs/explanations/{00_noir/00_data_types/08_structs.md => noir/data_types/structs.md} (98%) rename docs/docs/explanations/{00_noir/00_data_types/07_tuples.md => noir/data_types/tuples.md} (98%) rename docs/docs/explanations/{00_noir/00_data_types/06_vectors.mdx => noir/data_types/vectors.mdx} (99%) rename docs/docs/explanations/{00_noir/10_distinct.md => noir/distinct.md} (98%) rename docs/docs/explanations/{00_noir/01_functions.md => noir/functions.md} (90%) rename docs/docs/explanations/{00_noir/06_generics.md => noir/generics.md} (99%) rename docs/docs/explanations/{00_noir/08_lambdas.md => noir/lambdas.md} (98%) rename docs/docs/explanations/{00_noir/07_mutability.md => noir/mutability.md} (99%) rename docs/docs/explanations/{00_noir/03_ops.md => noir/ops.md} (99%) rename docs/docs/explanations/{00_noir/11_shadowing.md => noir/shadowing.md} (98%) rename docs/docs/explanations/{00_noir/05_unconstrained.md => noir/unconstrained.md} (97%) create mode 100644 docs/docs/explanations/standard_library/_category_.json rename docs/docs/explanations/{01_standard_library => standard_library}/black_box_fns.md (100%) create mode 100644 docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/04_ec_primitives.md => standard_library/cryptographic_primitives/ec_primitives.md} (99%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx => standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx} (98%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/05_eddsa.mdx => standard_library/cryptographic_primitives/eddsa.mdx} (96%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/00_hashes.mdx => standard_library/cryptographic_primitives/hashes.mdx} (99%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives => standard_library/cryptographic_primitives}/index.md (100%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/01_scalar.mdx => standard_library/cryptographic_primitives/scalar.mdx} (97%) rename docs/docs/explanations/{01_standard_library/00_cryptographic_primitives/02_schnorr.mdx => standard_library/cryptographic_primitives/schnorr.mdx} (98%) rename docs/docs/explanations/{01_standard_library => standard_library}/logging.md (100%) rename docs/docs/explanations/{01_standard_library => standard_library}/merkle_trees.md (93%) rename docs/docs/explanations/{01_standard_library => standard_library}/options.md (100%) rename docs/docs/explanations/{01_standard_library => standard_library}/recursion.md (100%) rename docs/docs/explanations/{01_standard_library => standard_library}/zeroed.md (100%) create mode 100644 docs/docs/getting_started/_category_.json rename docs/docs/getting_started/{01_create_a_project.md => create_a_project.md} (93%) create mode 100644 docs/docs/getting_started/installation/_category_.json rename docs/docs/getting_started/{00_installation => installation}/index.md (100%) rename docs/docs/getting_started/{00_installation => installation}/other_install_methods.md (98%) rename docs/docs/getting_started/{02_project_breakdown.md => project_breakdown.md} (96%) create mode 100644 docs/docs/getting_started/tooling/_category_.json rename docs/docs/getting_started/{03_tooling => tooling}/index.md (100%) rename docs/docs/getting_started/{03_tooling/00_language_server.md => tooling/language_server.md} (99%) rename docs/docs/getting_started/{03_tooling/01_testing.md => tooling/testing.md} (98%) create mode 100644 docs/docs/how_to/_category_.json create mode 100644 docs/docs/reference/_category_.json rename docs/docs/reference/{00_nargo_commands.md => nargo_commands.md} (99%) rename docs/docs/tutorials/{00_noirjs_app.md => noirjs_app.md} (96%) diff --git a/docs/docs/explanations/_category_.json b/docs/docs/explanations/_category_.json new file mode 100644 index 00000000000..151ee204894 --- /dev/null +++ b/docs/docs/explanations/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 3, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/modules_packages_crates/_category_.json b/docs/docs/explanations/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/02_modules_packages_crates/crates_and_packages.md b/docs/docs/explanations/modules_packages_crates/crates_and_packages.md similarity index 99% rename from docs/docs/explanations/02_modules_packages_crates/crates_and_packages.md rename to docs/docs/explanations/modules_packages_crates/crates_and_packages.md index fb83a33d94e..aae6795b229 100644 --- a/docs/docs/explanations/02_modules_packages_crates/crates_and_packages.md +++ b/docs/docs/explanations/modules_packages_crates/crates_and_packages.md @@ -2,6 +2,7 @@ title: Crates and Packages description: Learn how to use Crates and Packages in your Noir project keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 --- ## Crates diff --git a/docs/docs/explanations/02_modules_packages_crates/dependencies.md b/docs/docs/explanations/modules_packages_crates/dependencies.md similarity index 99% rename from docs/docs/explanations/02_modules_packages_crates/dependencies.md rename to docs/docs/explanations/modules_packages_crates/dependencies.md index 75f95aaa305..57f0f9fd420 100644 --- a/docs/docs/explanations/02_modules_packages_crates/dependencies.md +++ b/docs/docs/explanations/modules_packages_crates/dependencies.md @@ -4,6 +4,7 @@ description: Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub and use them easily in your project. keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 --- Nargo allows you to upload packages to GitHub and use them as dependencies. diff --git a/docs/docs/explanations/02_modules_packages_crates/modules.md b/docs/docs/explanations/modules_packages_crates/modules.md similarity index 99% rename from docs/docs/explanations/02_modules_packages_crates/modules.md rename to docs/docs/explanations/modules_packages_crates/modules.md index 147c9b284e8..f9f15aee8be 100644 --- a/docs/docs/explanations/02_modules_packages_crates/modules.md +++ b/docs/docs/explanations/modules_packages_crates/modules.md @@ -4,6 +4,7 @@ description: Learn how to organize your files using modules in Noir, following the same convention as Rust's module system. Examples included. keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 --- Noir's module system follows the same convention as the _newer_ version of Rust's module system. diff --git a/docs/docs/explanations/02_modules_packages_crates/workspaces.md b/docs/docs/explanations/modules_packages_crates/workspaces.md similarity index 96% rename from docs/docs/explanations/02_modules_packages_crates/workspaces.md rename to docs/docs/explanations/modules_packages_crates/workspaces.md index a979ef9f0a5..67a1dafa372 100644 --- a/docs/docs/explanations/02_modules_packages_crates/workspaces.md +++ b/docs/docs/explanations/modules_packages_crates/workspaces.md @@ -1,5 +1,6 @@ --- title: Workspaces +sidebar_position: 3 --- Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. @@ -36,4 +37,4 @@ default-member = "crates/a" Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. \ No newline at end of file +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/docs/explanations/noir/_category_.json b/docs/docs/explanations/noir/_category_.json new file mode 100644 index 00000000000..448d8987d1a --- /dev/null +++ b/docs/docs/explanations/noir/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Noir", + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/00_noir/04_assert.md b/docs/docs/explanations/noir/assert.md similarity index 98% rename from docs/docs/explanations/00_noir/04_assert.md rename to docs/docs/explanations/noir/assert.md index 7427ec6cc63..c5f9aff139c 100644 --- a/docs/docs/explanations/00_noir/04_assert.md +++ b/docs/docs/explanations/noir/assert.md @@ -5,6 +5,7 @@ description: comparison expression that follows to be true, and what happens if the expression is false at runtime. keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 --- Noir includes a special `assert` function which will explicitly constrain the predicate/comparison diff --git a/docs/docs/explanations/00_noir/09_comments.md b/docs/docs/explanations/noir/comments.md similarity index 98% rename from docs/docs/explanations/00_noir/09_comments.md rename to docs/docs/explanations/noir/comments.md index 3bb4d2f25a4..f76ab49094b 100644 --- a/docs/docs/explanations/00_noir/09_comments.md +++ b/docs/docs/explanations/noir/comments.md @@ -5,6 +5,7 @@ description: ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments are supported in Noir. keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 9 --- A comment is a line in your codebase which the compiler ignores, however it can be read by diff --git a/docs/docs/explanations/00_noir/02_control_flow.md b/docs/docs/explanations/noir/control_flow.md similarity index 97% rename from docs/docs/explanations/00_noir/02_control_flow.md rename to docs/docs/explanations/noir/control_flow.md index a7f85360197..4ce65236db3 100644 --- a/docs/docs/explanations/00_noir/02_control_flow.md +++ b/docs/docs/explanations/noir/control_flow.md @@ -4,6 +4,7 @@ description: Learn how to use loops and if expressions in the Noir programming language. Discover the syntax and examples for for loops and if-else statements. keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 --- ## Loops diff --git a/docs/docs/explanations/00_noir/12_data_bus.md b/docs/docs/explanations/noir/data_bus.md similarity index 97% rename from docs/docs/explanations/00_noir/12_data_bus.md rename to docs/docs/explanations/noir/data_bus.md index 9ef5c33fcf6..6c7e9b60891 100644 --- a/docs/docs/explanations/00_noir/12_data_bus.md +++ b/docs/docs/explanations/noir/data_bus.md @@ -1,5 +1,6 @@ --- title: Data Bus +sidebar_position: 12 --- **Disclaimer** this feature is experimental, do not use it! @@ -8,10 +9,8 @@ In order to use it, you must define some inputs of the program entry points (usu function) with the `call_data` modifier, and the return values with the `return_data` modifier. These modifiers are incompatible with `pub` and `mut` modifiers. - ## Example - ```rust fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { let a = z[x]; @@ -20,4 +19,3 @@ fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 ``` As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. - diff --git a/docs/docs/explanations/noir/data_types/_category_.json b/docs/docs/explanations/noir/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/docs/explanations/noir/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/00_noir/00_data_types/04_arrays.md b/docs/docs/explanations/noir/data_types/arrays.md similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/04_arrays.md rename to docs/docs/explanations/noir/data_types/arrays.md index bdbd1798bef..075d39dadd4 100644 --- a/docs/docs/explanations/00_noir/00_data_types/04_arrays.md +++ b/docs/docs/explanations/noir/data_types/arrays.md @@ -10,6 +10,7 @@ keywords: examples, indexing, ] +sidebar_position: 4 --- An array is one way of grouping together values into one compound type. Array types can be inferred diff --git a/docs/docs/explanations/00_noir/00_data_types/02_booleans.md b/docs/docs/explanations/noir/data_types/booleans.md similarity index 97% rename from docs/docs/explanations/00_noir/00_data_types/02_booleans.md rename to docs/docs/explanations/noir/data_types/booleans.md index 885db167d83..69826fcd724 100644 --- a/docs/docs/explanations/00_noir/00_data_types/02_booleans.md +++ b/docs/docs/explanations/noir/data_types/booleans.md @@ -10,6 +10,7 @@ keywords: examples, logical operations, ] +sidebar_position: 2 --- diff --git a/docs/docs/explanations/00_noir/00_data_types/00_fields.md b/docs/docs/explanations/noir/data_types/fields.md similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/00_fields.md rename to docs/docs/explanations/noir/data_types/fields.md index 78d3d2af166..a1c67945d66 100644 --- a/docs/docs/explanations/00_noir/00_data_types/00_fields.md +++ b/docs/docs/explanations/noir/data_types/fields.md @@ -10,6 +10,7 @@ keywords: examples, best practices, ] +sidebar_position: 0 --- The field type corresponds to the native field type of the proving backend. diff --git a/docs/docs/explanations/00_noir/00_data_types/10_function_types.md b/docs/docs/explanations/noir/data_types/function_types.md similarity index 87% rename from docs/docs/explanations/00_noir/00_data_types/10_function_types.md rename to docs/docs/explanations/noir/data_types/function_types.md index 1ec92efd594..f6121af17e2 100644 --- a/docs/docs/explanations/00_noir/00_data_types/10_function_types.md +++ b/docs/docs/explanations/noir/data_types/function_types.md @@ -1,5 +1,6 @@ --- title: Function types +sidebar_position: 10 --- Noir supports higher-order functions. The syntax for a function type is as follows: @@ -22,4 +23,4 @@ fn main() { ``` A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../08_lambdas.md) for more details. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/docs/explanations/00_noir/00_data_types/index.md b/docs/docs/explanations/noir/data_types/index.md similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/index.md rename to docs/docs/explanations/noir/data_types/index.md index 2eda54575f6..56ed55c444b 100644 --- a/docs/docs/explanations/00_noir/00_data_types/index.md +++ b/docs/docs/explanations/noir/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/explanations/00_noir/06_generics.md): +Type aliases can also be used with [generics](@site/docs/explanations/noir/generics.md): ```rust type Id = Size; diff --git a/docs/docs/explanations/00_noir/00_data_types/01_integers.md b/docs/docs/explanations/noir/data_types/integers.md similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/01_integers.md rename to docs/docs/explanations/noir/data_types/integers.md index b1e7ad11bfd..7d1e83cf4e9 100644 --- a/docs/docs/explanations/00_noir/00_data_types/01_integers.md +++ b/docs/docs/explanations/noir/data_types/integers.md @@ -2,6 +2,7 @@ title: Integers description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 --- An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. diff --git a/docs/docs/explanations/00_noir/00_data_types/09_references.md b/docs/docs/explanations/noir/data_types/references.md similarity index 96% rename from docs/docs/explanations/00_noir/00_data_types/09_references.md rename to docs/docs/explanations/noir/data_types/references.md index b0c35ce2cb9..a5293d11cfb 100644 --- a/docs/docs/explanations/00_noir/00_data_types/09_references.md +++ b/docs/docs/explanations/noir/data_types/references.md @@ -1,5 +1,6 @@ --- title: References +sidebar_position: 9 --- Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. diff --git a/docs/docs/explanations/00_noir/00_data_types/05_slices.mdx b/docs/docs/explanations/noir/data_types/slices.mdx similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/05_slices.mdx rename to docs/docs/explanations/noir/data_types/slices.mdx index 1be0ec4a137..4a6ee816aa2 100644 --- a/docs/docs/explanations/00_noir/00_data_types/05_slices.mdx +++ b/docs/docs/explanations/noir/data_types/slices.mdx @@ -2,6 +2,7 @@ title: Slices description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 --- import Experimental from '@site/src/components/Notes/_experimental.mdx'; diff --git a/docs/docs/explanations/00_noir/00_data_types/03_strings.md b/docs/docs/explanations/noir/data_types/strings.md similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/03_strings.md rename to docs/docs/explanations/noir/data_types/strings.md index e647a58472f..8d76d4ca654 100644 --- a/docs/docs/explanations/00_noir/00_data_types/03_strings.md +++ b/docs/docs/explanations/noir/data_types/strings.md @@ -10,6 +10,7 @@ keywords: examples, concatenation, ] +sidebar_position: 3 --- diff --git a/docs/docs/explanations/00_noir/00_data_types/08_structs.md b/docs/docs/explanations/noir/data_types/structs.md similarity index 98% rename from docs/docs/explanations/00_noir/00_data_types/08_structs.md rename to docs/docs/explanations/noir/data_types/structs.md index 35421734639..dbf68c99813 100644 --- a/docs/docs/explanations/00_noir/00_data_types/08_structs.md +++ b/docs/docs/explanations/noir/data_types/structs.md @@ -10,6 +10,7 @@ keywords: examples, data structures, ] +sidebar_position: 8 --- A struct also allows for grouping multiple values of different types. Unlike tuples, we can also diff --git a/docs/docs/explanations/00_noir/00_data_types/07_tuples.md b/docs/docs/explanations/noir/data_types/tuples.md similarity index 98% rename from docs/docs/explanations/00_noir/00_data_types/07_tuples.md rename to docs/docs/explanations/noir/data_types/tuples.md index 5f6cab974a8..2ec5c9c4113 100644 --- a/docs/docs/explanations/00_noir/00_data_types/07_tuples.md +++ b/docs/docs/explanations/noir/data_types/tuples.md @@ -10,6 +10,7 @@ keywords: examples, multi-value containers, ] +sidebar_position: 7 --- A tuple collects multiple values like an array, but with the added ability to collect values of diff --git a/docs/docs/explanations/00_noir/00_data_types/06_vectors.mdx b/docs/docs/explanations/noir/data_types/vectors.mdx similarity index 99% rename from docs/docs/explanations/00_noir/00_data_types/06_vectors.mdx rename to docs/docs/explanations/noir/data_types/vectors.mdx index 4617e90d038..10e35711b74 100644 --- a/docs/docs/explanations/00_noir/00_data_types/06_vectors.mdx +++ b/docs/docs/explanations/noir/data_types/vectors.mdx @@ -2,6 +2,7 @@ title: Vectors description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 --- import Experimental from '@site/src/components/Notes/_experimental.mdx'; diff --git a/docs/docs/explanations/00_noir/10_distinct.md b/docs/docs/explanations/noir/distinct.md similarity index 98% rename from docs/docs/explanations/00_noir/10_distinct.md rename to docs/docs/explanations/noir/distinct.md index e7ff7f5017a..b59e0296b23 100644 --- a/docs/docs/explanations/00_noir/10_distinct.md +++ b/docs/docs/explanations/noir/distinct.md @@ -1,5 +1,6 @@ --- title: Distinct Witnesses +sidebar_position: 10 --- The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures diff --git a/docs/docs/explanations/00_noir/01_functions.md b/docs/docs/explanations/noir/functions.md similarity index 90% rename from docs/docs/explanations/00_noir/01_functions.md rename to docs/docs/explanations/noir/functions.md index 9eeff5147d3..94f929038ee 100644 --- a/docs/docs/explanations/00_noir/01_functions.md +++ b/docs/docs/explanations/noir/functions.md @@ -4,6 +4,7 @@ description: Learn how to declare functions and methods in Noir, a programming language with Rust semantics. This guide covers parameter declaration, return types, call expressions, and more. keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 --- Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. @@ -14,7 +15,7 @@ To declare a function the `fn` keyword is used. fn foo() {} ``` -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](@site/docs/explanations/02_modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](@site/docs/explanations/modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: ```rust pub fn foo() {} @@ -61,7 +62,7 @@ fn main(x : [Field]) // can't compile, has variable size fn main(....// i think you got it by now ``` -Keep in mind [tests](@site/docs/getting_started/03_tooling/01_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: +Keep in mind [tests](@site/docs/getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: ```rust fn main(x : [Field]) { @@ -138,7 +139,7 @@ follows: assert(MyStruct::sum(s) == 42); ``` -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: ```rust struct Foo {} @@ -177,7 +178,7 @@ let add_50 = |val| val + 50; assert(add_50(100) == 150); ``` -See [Lambdas](./08_lambdas.md) for more details. +See [Lambdas](./lambdas.md) for more details. ## Attributes @@ -188,8 +189,8 @@ Supported attributes include: - **builtin**: the function is implemented by the compiler, for efficiency purposes. - **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` - **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](@site/docs/reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](@site/docs/getting_started/03_tooling/01_testing.md) for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](@site/docs/reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](@site/docs/getting_started/tooling/testing.md) for more details ### Field Attribute diff --git a/docs/docs/explanations/00_noir/06_generics.md b/docs/docs/explanations/noir/generics.md similarity index 99% rename from docs/docs/explanations/00_noir/06_generics.md rename to docs/docs/explanations/noir/generics.md index 9fb4177c2a8..443ca2b45a5 100644 --- a/docs/docs/explanations/00_noir/06_generics.md +++ b/docs/docs/explanations/noir/generics.md @@ -2,6 +2,7 @@ title: Generics description: Learn how to use Generics in Noir keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 6 --- Generics allow you to use the same functions with multiple different concrete data types. You can diff --git a/docs/docs/explanations/00_noir/08_lambdas.md b/docs/docs/explanations/noir/lambdas.md similarity index 98% rename from docs/docs/explanations/00_noir/08_lambdas.md rename to docs/docs/explanations/noir/lambdas.md index ae1e6aecab1..e0a267adfda 100644 --- a/docs/docs/explanations/00_noir/08_lambdas.md +++ b/docs/docs/explanations/noir/lambdas.md @@ -2,6 +2,7 @@ title: Lambdas description: Learn how to use anonymous functions in Noir programming language. keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 8 --- ## Introduction @@ -43,7 +44,7 @@ It may catch you by surprise that the following code fails to compile: ```rust fn foo(f: fn () -> Field) -> Field { - f() + f() } fn main() { @@ -69,7 +70,7 @@ with closures with any environment, as well as with regular functions: ```rust fn foo(f: fn[Env]() -> Field) -> Field { - f() + f() } fn main() { diff --git a/docs/docs/explanations/00_noir/07_mutability.md b/docs/docs/explanations/noir/mutability.md similarity index 99% rename from docs/docs/explanations/00_noir/07_mutability.md rename to docs/docs/explanations/noir/mutability.md index ad902c42c9b..58e9c1cecfb 100644 --- a/docs/docs/explanations/00_noir/07_mutability.md +++ b/docs/docs/explanations/noir/mutability.md @@ -4,6 +4,7 @@ description: Learn about mutable variables, constants, and globals in Noir programming language. Discover how to declare, modify, and use them in your programs. keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +sidebar_position: 7 --- Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned diff --git a/docs/docs/explanations/00_noir/03_ops.md b/docs/docs/explanations/noir/ops.md similarity index 99% rename from docs/docs/explanations/00_noir/03_ops.md rename to docs/docs/explanations/noir/ops.md index d5caa463765..977c8ba1203 100644 --- a/docs/docs/explanations/00_noir/03_ops.md +++ b/docs/docs/explanations/noir/ops.md @@ -14,6 +14,7 @@ keywords: short-circuiting, backend, ] +sidebar_position: 3 --- # Operations diff --git a/docs/docs/explanations/00_noir/11_shadowing.md b/docs/docs/explanations/noir/shadowing.md similarity index 98% rename from docs/docs/explanations/00_noir/11_shadowing.md rename to docs/docs/explanations/noir/shadowing.md index efd743e764f..b5a6b6b38b9 100644 --- a/docs/docs/explanations/00_noir/11_shadowing.md +++ b/docs/docs/explanations/noir/shadowing.md @@ -1,5 +1,6 @@ --- title: Shadowing +sidebar_position: 11 --- Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. diff --git a/docs/docs/explanations/00_noir/05_unconstrained.md b/docs/docs/explanations/noir/unconstrained.md similarity index 97% rename from docs/docs/explanations/00_noir/05_unconstrained.md rename to docs/docs/explanations/noir/unconstrained.md index 6b621eda3eb..7a61d3953ef 100644 --- a/docs/docs/explanations/00_noir/05_unconstrained.md +++ b/docs/docs/explanations/noir/unconstrained.md @@ -3,10 +3,9 @@ title: Unconstrained Functions description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 --- - - Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. ## Why? diff --git a/docs/docs/explanations/standard_library/_category_.json b/docs/docs/explanations/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/docs/explanations/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/01_standard_library/black_box_fns.md b/docs/docs/explanations/standard_library/black_box_fns.md similarity index 100% rename from docs/docs/explanations/01_standard_library/black_box_fns.md rename to docs/docs/explanations/standard_library/black_box_fns.md diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json b/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/04_ec_primitives.md b/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md similarity index 99% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/04_ec_primitives.md rename to docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md index 6e6b19b6861..8d573adb3be 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/04_ec_primitives.md +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md @@ -1,6 +1,7 @@ --- title: Elliptic Curve Primitives keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 --- Data structures and methods on them that allow you to carry out computations involving elliptic diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx similarity index 98% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx rename to docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx index 72bce984821..1376c51dfde 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -2,6 +2,7 @@ title: ECDSA Signature Verification description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 --- import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/05_eddsa.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx similarity index 96% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/05_eddsa.mdx rename to docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx index 9a5beb55ee9..a9c10da6c06 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/05_eddsa.mdx +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx @@ -2,6 +2,7 @@ title: EdDSA Verification description: Learn about the cryptographic primitives regarding EdDSA keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 --- import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx similarity index 99% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx rename to docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx index 38077af1ce1..9250cb4a0c0 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx @@ -5,6 +5,7 @@ description: blake2s, pedersen, mimc_bn254 and mimc keywords: [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 --- import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/index.md b/docs/docs/explanations/standard_library/cryptographic_primitives/index.md similarity index 100% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/index.md rename to docs/docs/explanations/standard_library/cryptographic_primitives/index.md diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/01_scalar.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx similarity index 97% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/01_scalar.mdx rename to docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx index c7eed820a80..1e686303c18 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/01_scalar.mdx +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx @@ -2,6 +2,7 @@ title: Scalar multiplication description: See how you can perform scalar multiplications over a fixed base in Noir keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 --- import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; diff --git a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/02_schnorr.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx similarity index 98% rename from docs/docs/explanations/01_standard_library/00_cryptographic_primitives/02_schnorr.mdx rename to docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx index c184ce28120..7a2c9c20226 100644 --- a/docs/docs/explanations/01_standard_library/00_cryptographic_primitives/02_schnorr.mdx +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx @@ -2,6 +2,7 @@ title: Schnorr Signatures description: Learn how you can verify Schnorr signatures using Noir keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 --- import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; diff --git a/docs/docs/explanations/01_standard_library/logging.md b/docs/docs/explanations/standard_library/logging.md similarity index 100% rename from docs/docs/explanations/01_standard_library/logging.md rename to docs/docs/explanations/standard_library/logging.md diff --git a/docs/docs/explanations/01_standard_library/merkle_trees.md b/docs/docs/explanations/standard_library/merkle_trees.md similarity index 93% rename from docs/docs/explanations/01_standard_library/merkle_trees.md rename to docs/docs/explanations/standard_library/merkle_trees.md index 86452a2ccb3..07fa2ccda79 100644 --- a/docs/docs/explanations/01_standard_library/merkle_trees.md +++ b/docs/docs/explanations/standard_library/merkle_trees.md @@ -17,7 +17,7 @@ keywords: ## compute_merkle_root -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](@site/docs/explanations/01_standard_library/00_cryptographic_primitives/00_hashes.mdx#pedersen_hash). +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](@site/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx#pedersen_hash). ```rust fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field diff --git a/docs/docs/explanations/01_standard_library/options.md b/docs/docs/explanations/standard_library/options.md similarity index 100% rename from docs/docs/explanations/01_standard_library/options.md rename to docs/docs/explanations/standard_library/options.md diff --git a/docs/docs/explanations/01_standard_library/recursion.md b/docs/docs/explanations/standard_library/recursion.md similarity index 100% rename from docs/docs/explanations/01_standard_library/recursion.md rename to docs/docs/explanations/standard_library/recursion.md diff --git a/docs/docs/explanations/01_standard_library/zeroed.md b/docs/docs/explanations/standard_library/zeroed.md similarity index 100% rename from docs/docs/explanations/01_standard_library/zeroed.md rename to docs/docs/explanations/standard_library/zeroed.md diff --git a/docs/docs/getting_started/_category_.json b/docs/docs/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/docs/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/01_create_a_project.md b/docs/docs/getting_started/create_a_project.md similarity index 93% rename from docs/docs/getting_started/01_create_a_project.md rename to docs/docs/getting_started/create_a_project.md index d32f397370c..76bed5be9b8 100644 --- a/docs/docs/getting_started/01_create_a_project.md +++ b/docs/docs/getting_started/create_a_project.md @@ -13,6 +13,8 @@ keywords: verify Noir program, step-by-step guide, ] +sidebar_position: 1 + --- Now that we have installed Nargo, it is time to make our first hello world program! @@ -67,7 +69,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](@site/docs/explanations/00_noir/00_data_types/index.md) section. +[Data Types](@site/docs/explanations/noir/data_types/index.md) section. The next line of the program specifies its body: @@ -77,7 +79,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](@site/docs/explanations/00_noir/09_comments.md) chapter. +For more Noir syntax, check the [Language Concepts](@site/docs/explanations/noir/comments.md) chapter. ## Build In/Output Files @@ -137,4 +139,4 @@ corresponding error instead. Congratulations, you have now created and verified a proof for your very first Noir program! -In the [next section](@site/docs/getting_started/02_project_breakdown.md), we will go into more detail on each step performed. +In the [next section](@site/docs/getting_started/project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/docs/getting_started/installation/_category_.json b/docs/docs/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/docs/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/00_installation/index.md b/docs/docs/getting_started/installation/index.md similarity index 100% rename from docs/docs/getting_started/00_installation/index.md rename to docs/docs/getting_started/installation/index.md diff --git a/docs/docs/getting_started/00_installation/other_install_methods.md b/docs/docs/getting_started/installation/other_install_methods.md similarity index 98% rename from docs/docs/getting_started/00_installation/other_install_methods.md rename to docs/docs/getting_started/installation/other_install_methods.md index cd27185a293..d90a10103d9 100644 --- a/docs/docs/getting_started/00_installation/other_install_methods.md +++ b/docs/docs/getting_started/installation/other_install_methods.md @@ -18,12 +18,13 @@ keywords: [ Uninstalling Nargo Noir vs code extension ] +sidebar_position: 1 --- ## Installation -The most common method of installing Nargo is through [Noirup](@site/docs/getting_started/00_installation/index.md) +The most common method of installing Nargo is through [Noirup](@site/docs/getting_started/installation/index.md) However, there are other methods for installing Nargo: @@ -166,7 +167,7 @@ The default backend for Noir (Barretenberg) doesn't provide Windows binaries at Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. -step 2: Follow the [Noirup instructions](@site/docs/getting_started/00_installation/index.md). +step 2: Follow the [Noirup instructions](@site/docs/getting_started/installation/index.md). ## Uninstalling Nargo diff --git a/docs/docs/getting_started/02_project_breakdown.md b/docs/docs/getting_started/project_breakdown.md similarity index 96% rename from docs/docs/getting_started/02_project_breakdown.md rename to docs/docs/getting_started/project_breakdown.md index 8e4bf39522e..026127b9ed0 100644 --- a/docs/docs/getting_started/02_project_breakdown.md +++ b/docs/docs/getting_started/project_breakdown.md @@ -5,6 +5,7 @@ description: files, and how to prove and verify your program. keywords: [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 --- This section breaks down our hello world program in section _1.2_. We elaborate on the project @@ -51,7 +52,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](@site/docs/explanations/02_modules_packages_crates/workspaces.md) will look a bit different. For example: +Nargo.toml for a [workspace](@site/docs/explanations/modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +75,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](@site/docs/explanations/02_modules_packages_crates/dependencies.md) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](@site/docs/explanations/modules_packages_crates/dependencies.md) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/docs/getting_started/tooling/_category_.json b/docs/docs/getting_started/tooling/_category_.json new file mode 100644 index 00000000000..dff520ebc41 --- /dev/null +++ b/docs/docs/getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 3, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/03_tooling/index.md b/docs/docs/getting_started/tooling/index.md similarity index 100% rename from docs/docs/getting_started/03_tooling/index.md rename to docs/docs/getting_started/tooling/index.md diff --git a/docs/docs/getting_started/03_tooling/00_language_server.md b/docs/docs/getting_started/tooling/language_server.md similarity index 99% rename from docs/docs/getting_started/03_tooling/00_language_server.md rename to docs/docs/getting_started/tooling/language_server.md index 48c01465f6e..81e0356ef8a 100644 --- a/docs/docs/getting_started/03_tooling/00_language_server.md +++ b/docs/docs/getting_started/tooling/language_server.md @@ -2,6 +2,7 @@ title: Language Server description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 --- This section helps you install and configure the Noir Language Server. diff --git a/docs/docs/getting_started/03_tooling/01_testing.md b/docs/docs/getting_started/tooling/testing.md similarity index 98% rename from docs/docs/getting_started/03_tooling/01_testing.md rename to docs/docs/getting_started/tooling/testing.md index da767274efd..868a061200d 100644 --- a/docs/docs/getting_started/03_tooling/01_testing.md +++ b/docs/docs/getting_started/tooling/testing.md @@ -2,6 +2,7 @@ title: Testing in Noir description: Learn how to use Nargo to test your Noir program in a quick and easy way keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 --- You can test your Noir programs using Noir circuits. diff --git a/docs/docs/how_to/_category_.json b/docs/docs/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/docs/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/index.md b/docs/docs/index.md index de04d263e41..754f9f6e31d 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -17,6 +17,7 @@ keywords: Proving System, Smart Contract Language, ] +sidebar_position: 0 --- ## What's new about Noir? @@ -37,7 +38,7 @@ programming. ### Solidity Developers Noir streamlines the creation of Solidity contracts that interface with SNARK systems. -[`Utilize the nargo codegen-verifier`](@site/docs/reference/00_nargo_commands.md#nargo-codegen-verifier) command to construct verifier +[`Utilize the nargo codegen-verifier`](@site/docs/reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim to modularize this process for even greater ease of use. @@ -81,4 +82,4 @@ Some libraries that are available today include: - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](@site/docs/explanations/02_modules_packages_crates/dependencies.md) for more information. +See the section on [dependencies](@site/docs/explanations/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 4964a85c833..a5fd10769f7 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -16,7 +16,7 @@ To update, please make sure this field in `Nargo.toml` matches the output of `na ## ≥0.14 -The index of the [for loops](@site/docs/explanations/00_noir/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: +The index of the [for loops](@site/docs/explanations/noir/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: ```rust for i in 0..10 { diff --git a/docs/docs/reference/NoirJS/noir_js/classes/Noir.md b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md index e54116fb1d8..34e20d99684 100644 --- a/docs/docs/reference/NoirJS/noir_js/classes/Noir.md +++ b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md @@ -75,7 +75,7 @@ async execute(inputs) ### generateFinalProof() ```ts -generateFinalProof(inputs): Promise +generateFinalProof(inputs, foreignCallHandler?): Promise ``` #### Parameters @@ -83,6 +83,7 @@ generateFinalProof(inputs): Promise | Parameter | Type | | :------ | :------ | | `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | #### Returns @@ -95,7 +96,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/docs/reference/_category_.json b/docs/docs/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/docs/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/reference/00_nargo_commands.md b/docs/docs/reference/nargo_commands.md similarity index 99% rename from docs/docs/reference/00_nargo_commands.md rename to docs/docs/reference/nargo_commands.md index 8c564ca494e..239e88d9691 100644 --- a/docs/docs/reference/00_nargo_commands.md +++ b/docs/docs/reference/nargo_commands.md @@ -1,5 +1,5 @@ --- -title: nargo +title: Nargo description: Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, generate Solidity verifier smart contract and compile into JSON file containing ACIR @@ -16,6 +16,7 @@ keywords: ABI of circuit, TypeScript, ] +sidebar_position: 0 --- ## General options @@ -212,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](@site/docs/getting_started/03_tooling/01_testing.md). +See an example on the [testing page](@site/docs/getting_started/tooling/testing.md). ### Options diff --git a/docs/docs/tutorials/00_noirjs_app.md b/docs/docs/tutorials/noirjs_app.md similarity index 96% rename from docs/docs/tutorials/00_noirjs_app.md rename to docs/docs/tutorials/noirjs_app.md index 4a4161d70fc..e0f674fa09c 100644 --- a/docs/docs/tutorials/00_noirjs_app.md +++ b/docs/docs/tutorials/noirjs_app.md @@ -2,6 +2,7 @@ title: Tiny NoirJS app description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] +sidebar_position: 0 --- NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. @@ -20,7 +21,7 @@ In this guide, we will be pinned to 0.17.0. Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). -First of all, follow the the [Nargo guide](@site/docs/getting_started/00_installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: +First of all, follow the the [Nargo guide](@site/docs/getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: ```bash nargo compile diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 14abaf04b47..98ef1fd680c 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -133,6 +133,16 @@ export default { }, }, plugins: [ + () => ({ + name: 'resolve-react', + configureWebpack() { + return { + optimization: { + innerGraph: false, + }, + }; + }, + }), [ 'docusaurus-plugin-typedoc', { diff --git a/docs/package.json b/docs/package.json index 6a95fcb89f5..86f15b0a311 100644 --- a/docs/package.json +++ b/docs/package.json @@ -5,7 +5,8 @@ "scripts": { "start": "docusaurus start", "build": "yarn version::stables && docusaurus build", - "version::stables": "node --loader ts-node/esm ./scripts/setStable.ts" + "version::stables": "node --loader ts-node/esm ./scripts/setStable.ts", + "serve": "serve build" }, "dependencies": { "@docusaurus/core": "^3.0.1", @@ -34,6 +35,7 @@ "docusaurus-plugin-typedoc": "1.0.0-next.18", "eslint-plugin-prettier": "^5.0.0", "prettier": "3.0.3", + "serve": "^14.2.1", "ts-node": "^10.9.1", "typedoc": "^0.25.0", "typedoc-plugin-frontmatter": "^0.0.2", diff --git a/docs/sidebars.js b/docs/sidebars.js index fba1c9ae1e7..016ead14a8f 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -20,34 +20,8 @@ export default { label: 'The Noir Language', items: [ { - type: 'category', - label: 'Language Concepts', - items: [ - { - type: 'autogenerated', - dirName: 'explanations/00_noir', - }, - ], - }, - { - type: 'category', - label: 'Standard Library', - items: [ - { - type: 'autogenerated', - dirName: 'explanations/01_standard_library', - }, - ], - }, - { - type: 'category', - label: 'Modules, Packages and Crates', - items: [ - { - type: 'autogenerated', - dirName: 'explanations/02_modules_packages_crates', - }, - ], + type: 'autogenerated', + dirName: 'explanations', }, ], }, diff --git a/yarn.lock b/yarn.lock index 7454ec947c8..bdb9c205d7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6369,6 +6369,13 @@ __metadata: languageName: node linkType: hard +"@zeit/schemas@npm:2.29.0": + version: 2.29.0 + resolution: "@zeit/schemas@npm:2.29.0" + checksum: 3cea06bb67d790336aca0cc17580fd492ff3fc66ef4d180dce7053ff7ff54ab81b56bf718ba6f537148c581161d06306a481ec218d540bff922e0e009844ffd1 + languageName: node + linkType: hard + "abbrev@npm:^2.0.0": version: 2.0.0 resolution: "abbrev@npm:2.0.0" @@ -6535,6 +6542,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:8.11.0": + version: 8.11.0 + resolution: "ajv@npm:8.11.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef + languageName: node + linkType: hard + "ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -6689,20 +6708,27 @@ __metadata: languageName: node linkType: hard -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 +"arch@npm:^2.2.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f languageName: node linkType: hard -"arg@npm:^5.0.0": +"arg@npm:5.0.2, arg@npm:^5.0.0": version: 5.0.2 resolution: "arg@npm:5.0.2" checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 languageName: node linkType: hard +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 + languageName: node + linkType: hard + "argparse@npm:^1.0.7": version: 1.0.10 resolution: "argparse@npm:1.0.10" @@ -7175,6 +7201,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:7.0.0": + version: 7.0.0 + resolution: "boxen@npm:7.0.0" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.0 + chalk: ^5.0.1 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.0.1 + checksum: b917cf7a168ef3149635a8c02d5c9717d66182348bd27038d85328ad12655151e3324db0f2815253846c33e5f0ddf28b6cd52d56a12b9f88617b7f8f722b946a + languageName: node + linkType: hard + "boxen@npm:^5.0.0": version: 5.1.2 resolution: "boxen@npm:5.1.2" @@ -7521,7 +7563,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^7.0.1": +"camelcase@npm:^7.0.0, camelcase@npm:^7.0.1": version: 7.0.1 resolution: "camelcase@npm:7.0.1" checksum: 86ab8f3ebf08bcdbe605a211a242f00ed30d8bfb77dab4ebb744dd36efbc84432d1c4adb28975ba87a1b8be40a80fbd1e60e2f06565315918fa7350011a26d3d @@ -7610,7 +7652,7 @@ __metadata: languageName: node linkType: hard -"chalk-template@npm:^0.4.0": +"chalk-template@npm:0.4.0, chalk-template@npm:^0.4.0": version: 0.4.0 resolution: "chalk-template@npm:0.4.0" dependencies: @@ -7619,6 +7661,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:5.0.1": + version: 5.0.1 + resolution: "chalk@npm:5.0.1" + checksum: 7b45300372b908f0471fbf7389ce2f5de8d85bb949026fd51a1b95b10d0ed32c7ed5aab36dd5e9d2bf3191867909b4404cef75c5f4d2d1daeeacd301dd280b76 + languageName: node + linkType: hard + "chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -7936,6 +7985,17 @@ __metadata: languageName: node linkType: hard +"clipboardy@npm:3.0.0": + version: 3.0.0 + resolution: "clipboardy@npm:3.0.0" + dependencies: + arch: ^2.2.0 + execa: ^5.1.1 + is-wsl: ^2.2.0 + checksum: 2c292acb59705494cbe07d7df7c8becff4f01651514d32ebd80f4aec2d20946d8f3824aac67ecdf2d09ef21fdf0eb24b6a7f033c137ccdceedc4661c54455c94 + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -8232,7 +8292,7 @@ __metadata: languageName: node linkType: hard -"compression@npm:^1.7.4": +"compression@npm:1.7.4, compression@npm:^1.7.4": version: 1.7.4 resolution: "compression@npm:1.7.4" dependencies: @@ -9183,6 +9243,7 @@ __metadata: react-spinners: ^0.13.8 rehype-katex: ^7.0.0 remark-math: ^6.0.0 + serve: ^14.2.1 ts-node: ^10.9.1 typedoc: ^0.25.0 typedoc-plugin-frontmatter: ^0.0.2 @@ -10139,7 +10200,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -12483,6 +12544,13 @@ __metadata: languageName: node linkType: hard +"is-port-reachable@npm:4.0.0": + version: 4.0.0 + resolution: "is-port-reachable@npm:4.0.0" + checksum: 47b7e10db8edcef27fbf9e50f0de85ad368d35688790ca64a13db67260111ac5f4b98989b11af06199fa93f25d810bd09a5b21b2c2646529668638f7c34d3c04 + languageName: node + linkType: hard + "is-promise@npm:^4.0.0": version: 4.0.0 resolution: "is-promise@npm:4.0.0" @@ -16624,7 +16692,7 @@ __metadata: languageName: node linkType: hard -"rc@npm:1.2.8, rc@npm:^1.2.8": +"rc@npm:1.2.8, rc@npm:^1.0.1, rc@npm:^1.1.6, rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" dependencies: @@ -16946,6 +17014,16 @@ __metadata: languageName: node linkType: hard +"registry-auth-token@npm:3.3.2": + version: 3.3.2 + resolution: "registry-auth-token@npm:3.3.2" + dependencies: + rc: ^1.1.6 + safe-buffer: ^5.0.1 + checksum: c9d7ae160a738f1fa825556e3669e6c771d2c0239ce37679f7e8646157a97d0a76464738be075002a1f754ef9bfb913b689f4bbfd5296d28f136fbf98c8c2217 + languageName: node + linkType: hard + "registry-auth-token@npm:^4.0.0": version: 4.2.2 resolution: "registry-auth-token@npm:4.2.2" @@ -16964,6 +17042,15 @@ __metadata: languageName: node linkType: hard +"registry-url@npm:3.1.0": + version: 3.1.0 + resolution: "registry-url@npm:3.1.0" + dependencies: + rc: ^1.0.1 + checksum: 6d223da41b04e1824f5faa63905c6f2e43b216589d72794111573f017352b790aef42cd1f826463062f89d804abb2027e3d9665d2a9a0426a11eedd04d470af3 + languageName: node + linkType: hard + "registry-url@npm:^5.0.0": version: 5.1.0 resolution: "registry-url@npm:5.1.0" @@ -17759,7 +17846,7 @@ __metadata: languageName: node linkType: hard -"serve-handler@npm:^6.1.3, serve-handler@npm:^6.1.5": +"serve-handler@npm:6.1.5, serve-handler@npm:^6.1.3, serve-handler@npm:^6.1.5": version: 6.1.5 resolution: "serve-handler@npm:6.1.5" dependencies: @@ -17802,6 +17889,27 @@ __metadata: languageName: node linkType: hard +"serve@npm:^14.2.1": + version: 14.2.1 + resolution: "serve@npm:14.2.1" + dependencies: + "@zeit/schemas": 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + bin: + serve: build/main.js + checksum: c39a517b5d795a0a5c2f9fb9ff088b7e4962c579e34ace5b85dd62f93e0eacbc8a90359792c153c444a83258ffda392113dff7bfd10d41ced574a2d1886c2994 + languageName: node + linkType: hard + "set-function-length@npm:^1.1.1": version: 1.1.1 resolution: "set-function-length@npm:1.1.1" @@ -19545,6 +19653,16 @@ __metadata: languageName: node linkType: hard +"update-check@npm:1.5.4": + version: 1.5.4 + resolution: "update-check@npm:1.5.4" + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + checksum: 2c9f7de6f030364c5ea02a341e5ae2dfe76da6559b32d40dd3b047b3ac0927408cf92d322c51cd8e009688210a85ccbf1eba449762a65a0d1b14f3cdf1ea5c48 + languageName: node + linkType: hard + "update-notifier@npm:^5.1.0": version: 5.1.0 resolution: "update-notifier@npm:5.1.0" From c85b06434209989d6013aba2cada611c7df869c2 Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:41:52 +0100 Subject: [PATCH 031/137] chore: disable code lens feature of lsp (#3789) # Description ## Problem\* Resolves: **Disable Code Lens feature of LSP #3788** ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/lsp/src/lib.rs | 5 +- tooling/lsp/src/notifications/mod.rs | 3 - tooling/lsp/src/requests/code_lens_request.rs | 235 ------------------ tooling/lsp/src/requests/mod.rs | 11 +- tooling/lsp/src/types.rs | 18 +- 5 files changed, 10 insertions(+), 262 deletions(-) delete mode 100644 tooling/lsp/src/requests/code_lens_request.rs diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index aa981a735b5..eecd0bda45b 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -27,8 +27,8 @@ use notifications::{ on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized, }; use requests::{ - on_code_lens_request, on_formatting, on_goto_definition_request, on_initialize, - on_profile_run_request, on_shutdown, on_test_run_request, on_tests_request, + on_formatting, on_goto_definition_request, on_initialize, on_profile_run_request, on_shutdown, + on_test_run_request, on_tests_request, }; use serde_json::Value as JsonValue; use tower::Service; @@ -72,7 +72,6 @@ impl NargoLspService { .request::(on_initialize) .request::(on_formatting) .request::(on_shutdown) - .request::(on_code_lens_request) .request::(on_tests_request) .request::(on_test_run_request) .request::(on_profile_run_request) diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 645d05d3d43..a3f2fdde3d6 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -161,9 +161,6 @@ pub(super) fn on_did_save_text_document( }) .collect(); - // We need to refresh lenses when we compile since that's the only time they can be accurately reflected - std::mem::drop(state.client.code_lens_refresh(())); - let _ = state.client.publish_diagnostics(PublishDiagnosticsParams { uri: params.text_document.uri, version: None, diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs deleted file mode 100644 index a47e9f82a63..00000000000 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ /dev/null @@ -1,235 +0,0 @@ -use std::future::{self, Future}; - -use async_lsp::{ErrorCode, LanguageClient, ResponseError}; - -use nargo::{package::Package, prepare_package, workspace::Workspace}; -use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; -use noirc_frontend::hir::FunctionNameMatch; - -use crate::{ - byte_span_to_range, get_non_stdlib_asset, - types::{CodeLens, CodeLensParams, CodeLensResult, Command, LogMessageParams, MessageType}, - LspState, -}; - -const ARROW: &str = "▶\u{fe0e}"; -const TEST_COMMAND: &str = "nargo.test"; -const TEST_CODELENS_TITLE: &str = "Run Test"; -const COMPILE_COMMAND: &str = "nargo.compile"; -const COMPILE_CODELENS_TITLE: &str = "Compile"; -const INFO_COMMAND: &str = "nargo.info"; -const INFO_CODELENS_TITLE: &str = "Info"; -const EXECUTE_COMMAND: &str = "nargo.execute"; -const EXECUTE_CODELENS_TITLE: &str = "Execute"; - -const PROFILE_COMMAND: &str = "nargo.profile"; -const PROFILE_CODELENS_TITLE: &str = "Profile"; - -fn with_arrow(title: &str) -> String { - format!("{ARROW} {title}") -} - -fn package_selection_args(workspace: &Workspace, package: &Package) -> Vec { - vec![ - "--program-dir".into(), - workspace.root_dir.display().to_string().into(), - "--package".into(), - package.name.to_string().into(), - ] -} - -pub(crate) fn on_code_lens_request( - state: &mut LspState, - params: CodeLensParams, -) -> impl Future> { - future::ready(on_code_lens_request_inner(state, params)) -} - -fn on_code_lens_request_inner( - state: &mut LspState, - params: CodeLensParams, -) -> Result { - let file_path = params.text_document.uri.to_file_path().map_err(|_| { - ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") - })?; - - let root_path = state.root_path.as_deref().ok_or_else(|| { - ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") - })?; - - let toml_path = match find_package_manifest(root_path, &file_path) { - Ok(toml_path) => toml_path, - Err(err) => { - // If we cannot find a manifest, we log a warning but return no code lenses - // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps - let _ = state.client.log_message(LogMessageParams { - typ: MessageType::WARNING, - message: err.to_string(), - }); - return Ok(None); - } - }; - let workspace = resolve_workspace_from_toml( - &toml_path, - PackageSelection::All, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - ) - .map_err(|err| { - // If we found a manifest, but the workspace is invalid, we raise an error about it - ResponseError::new(ErrorCode::REQUEST_FAILED, err) - })?; - - let mut lenses: Vec = vec![]; - - for package in &workspace { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); - // We ignore the warnings and errors produced by compilation for producing code lenses - // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false); - - let fm = &context.file_manager; - let files = fm.as_file_map(); - let tests = context - .get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Anything); - - for (func_name, test_function) in tests { - let location = context.function_meta(&test_function.get_id()).name.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let test_command = Command { - title: with_arrow(TEST_CODELENS_TITLE), - command: TEST_COMMAND.into(), - arguments: Some( - [ - package_selection_args(&workspace, package), - vec!["--exact".into(), func_name.into()], - ] - .concat(), - ), - }; - - let test_lens = CodeLens { range, command: Some(test_command), data: None }; - - lenses.push(test_lens); - } - - if package.is_binary() { - if let Some(main_func_id) = context.get_main_function(&crate_id) { - let location = context.function_meta(&main_func_id).name.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let compile_command = Command { - title: with_arrow(COMPILE_CODELENS_TITLE), - command: COMPILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; - - lenses.push(compile_lens); - - let info_command = Command { - title: INFO_CODELENS_TITLE.to_string(), - command: INFO_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let info_lens = CodeLens { range, command: Some(info_command), data: None }; - - lenses.push(info_lens); - - let execute_command = Command { - title: EXECUTE_CODELENS_TITLE.to_string(), - command: EXECUTE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let execute_lens = CodeLens { range, command: Some(execute_command), data: None }; - - lenses.push(execute_lens); - - let profile_command = Command { - title: PROFILE_CODELENS_TITLE.to_string(), - command: PROFILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; - - lenses.push(profile_lens); - } - } - - if package.is_contract() { - // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying - for contract in context.get_all_contracts(&crate_id) { - let location = contract.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let compile_command = Command { - title: with_arrow(COMPILE_CODELENS_TITLE), - command: COMPILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; - - lenses.push(compile_lens); - - let info_command = Command { - title: INFO_CODELENS_TITLE.to_string(), - command: INFO_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let info_lens = CodeLens { range, command: Some(info_command), data: None }; - - lenses.push(info_lens); - - let profile_command = Command { - title: PROFILE_CODELENS_TITLE.to_string(), - command: PROFILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; - - lenses.push(profile_lens); - } - } - } - - if lenses.is_empty() { - Ok(None) - } else { - Ok(Some(lenses)) - } -} diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index 840678ddfc1..309c3dc0a5c 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -1,6 +1,6 @@ use std::future::Future; -use crate::types::{CodeLensOptions, InitializeParams}; +use crate::types::InitializeParams; use async_lsp::ResponseError; use lsp_types::{Position, TextDocumentSyncCapability, TextDocumentSyncKind}; use nargo_fmt::Config; @@ -20,15 +20,14 @@ use crate::{ // They are not attached to the `NargoLspService` struct so they can be unit tested with only `LspState` // and params passed in. -mod code_lens_request; mod goto_definition; mod profile_run; mod test_run; mod tests; pub(crate) use { - code_lens_request::on_code_lens_request, goto_definition::on_goto_definition_request, - profile_run::on_profile_run_request, test_run::on_test_run_request, tests::on_tests_request, + goto_definition::on_goto_definition_request, profile_run::on_profile_run_request, + test_run::on_test_run_request, tests::on_tests_request, }; pub(crate) fn on_initialize( @@ -40,8 +39,6 @@ pub(crate) fn on_initialize( async { let text_document_sync = TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL); - let code_lens = CodeLensOptions { resolve_provider: Some(false) }; - let nargo = NargoCapability { tests: Some(NargoTestsOptions { fetch: Some(true), @@ -53,7 +50,6 @@ pub(crate) fn on_initialize( Ok(InitializeResult { capabilities: ServerCapabilities { text_document_sync: Some(text_document_sync), - code_lens_provider: Some(code_lens), document_formatting_provider: true, nargo: Some(nargo), definition_provider: Some(lsp_types::OneOf::Left(true)), @@ -131,7 +127,6 @@ mod initialization { text_document_sync: Some(TextDocumentSyncCapability::Kind( TextDocumentSyncKind::FULL )), - code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(false) }), document_formatting_provider: true, .. } diff --git a/tooling/lsp/src/types.rs b/tooling/lsp/src/types.rs index 14c0264504d..48c412eb5ad 100644 --- a/tooling/lsp/src/types.rs +++ b/tooling/lsp/src/types.rs @@ -9,11 +9,10 @@ use std::collections::{BTreeMap, HashMap}; // Re-providing lsp_types that we don't need to override pub(crate) use lsp_types::{ - CodeLens, CodeLensOptions, CodeLensParams, Command, Diagnostic, DiagnosticSeverity, - DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, - DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializedParams, - LogMessageParams, MessageType, Position, PublishDiagnosticsParams, Range, ServerInfo, - TextDocumentSyncCapability, Url, + Diagnostic, DiagnosticSeverity, DidChangeConfigurationParams, DidChangeTextDocumentParams, + DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, + InitializeParams, InitializedParams, LogMessageParams, MessageType, Position, + PublishDiagnosticsParams, Range, ServerInfo, TextDocumentSyncCapability, Url, }; pub(crate) mod request { @@ -25,9 +24,7 @@ pub(crate) mod request { }; // Re-providing lsp_types that we don't need to override - pub(crate) use lsp_types::request::{ - CodeLensRequest as CodeLens, Formatting, GotoDefinition, Shutdown, - }; + pub(crate) use lsp_types::request::{Formatting, GotoDefinition, Shutdown}; #[derive(Debug)] pub(crate) struct Initialize; @@ -115,10 +112,6 @@ pub(crate) struct ServerCapabilities { #[serde(skip_serializing_if = "Option::is_none")] pub(crate) definition_provider: Option>, - /// The server provides code lens. - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) code_lens_provider: Option, - /// The server provides document formatting. pub(crate) document_formatting_provider: bool, @@ -221,5 +214,4 @@ pub(crate) struct NargoProfileRunResult { pub(crate) opcodes_counts: HashMap, } -pub(crate) type CodeLensResult = Option>; pub(crate) type GotoDefinitionResult = Option; From a576c5bba6ab92eb4798715a43475808ac954fba Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:16:43 +0100 Subject: [PATCH 032/137] feat(lsp): add goto definition for structs (#3718) # Description ## Problem\* Resolves feat(lsp): add goto definition for structs #3707 ## Summary\* LSP server now understands goto definition command issued by Client (ie. vscode). In case of Struct constructor, member access or method call it will jump to it's definition. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- compiler/noirc_frontend/src/node_interner.rs | 56 ++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index d49e236c68f..2769b5874e9 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1290,9 +1290,65 @@ impl NodeInterner { _ => None, } } + HirExpression::Constructor(expr) => { + let struct_type = &expr.r#type.borrow(); + + eprintln!("\n -> Resolve Constructor {struct_type:?}\n"); + + Some(struct_type.location) + } + HirExpression::MemberAccess(expr_member_access) => { + self.resolve_struct_member_access(expr_member_access) + } + HirExpression::Call(expr_call) => { + let func = expr_call.func; + self.resolve_location(func) + } + _ => None, } } + + /// Resolves the [Location] of the definition for a given [crate::hir_def::expr::HirMemberAccess] + /// This is used to resolve the location of a struct member access. + /// For example, in the expression `foo.bar` we want to resolve the location of `bar` + /// to the location of the definition of `bar` in the struct `foo`. + fn resolve_struct_member_access( + &self, + expr_member_access: &crate::hir_def::expr::HirMemberAccess, + ) -> Option { + let expr_lhs = &expr_member_access.lhs; + let expr_rhs = &expr_member_access.rhs; + + let found_ident = self.nodes.get(expr_lhs.into())?; + + let ident = match found_ident { + Node::Expression(HirExpression::Ident(ident)) => ident, + _ => return None, + }; + + let definition_info = self.definition(ident.id); + + let local_id = match definition_info.kind { + DefinitionKind::Local(Some(local_id)) => local_id, + _ => return None, + }; + + let constructor_expression = match self.nodes.get(local_id.into()) { + Some(Node::Expression(HirExpression::Constructor(constructor_expression))) => { + constructor_expression + } + _ => return None, + }; + + let struct_type = constructor_expression.r#type.borrow(); + let field_names = struct_type.field_names(); + + match field_names.iter().find(|field_name| field_name.0 == expr_rhs.0) { + Some(found) => Some(Location::new(found.span(), struct_type.location.file)), + None => None, + } + } } impl Methods { From ce80f5a2560dcb67b9b46d62a910db9a40695fdd Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:30:33 +0100 Subject: [PATCH 033/137] chore: adds a new option only-acir (#3683) # Description ## Problem\* Resolves #3119 ## Summary\* Adds a new option only-acir which compiles acir bytecode into acir.gz generates witness as .gz instead of .tr use only-acir when generating the artifacts and remove the un-needed steps from rebuild.sh ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [X] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- compiler/noirc_driver/src/lib.rs | 4 ++++ test_programs/rebuild.sh | 12 +----------- tooling/nargo/src/constants.rs | 2 +- tooling/nargo_cli/src/cli/compile_cmd.rs | 19 ++++++++++++++----- tooling/nargo_cli/src/cli/fs/program.rs | 14 ++++++++++++++ 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 298e9838a09..be139846cd7 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -62,6 +62,10 @@ pub struct CompileOptions { #[arg(long, conflicts_with = "deny_warnings")] pub silence_warnings: bool, + /// Output ACIR gzipped bytecode instead of the JSON artefact + #[arg(long, hide = true)] + pub only_acir: bool, + /// Disables the builtin macros being used in the compiler #[arg(long, hide = true)] pub disable_macros: bool, diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh index dfc3dc5c967..d879ca417ee 100755 --- a/test_programs/rebuild.sh +++ b/test_programs/rebuild.sh @@ -14,17 +14,7 @@ process_dir() { if [ -d ./target/ ]; then rm -r ./target/ fi - nargo compile && nargo execute witness - - if [ -f ./target/witness.tr ]; then - mv ./target/witness.tr ./target/witness.gz - fi - - if [ -f ./target/${dir_name}.json ]; then - jq -r '.bytecode' ./target/${dir_name}.json | base64 -d > ./target/acir.gz - fi - - rm ./target/${dir_name}.json + cargo run compile --only-acir && cargo run execute witness if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then rm -r "$current_dir/acir_artifacts/$dir_name/target" diff --git a/tooling/nargo/src/constants.rs b/tooling/nargo/src/constants.rs index 5e448277694..ff8da403c69 100644 --- a/tooling/nargo/src/constants.rs +++ b/tooling/nargo/src/constants.rs @@ -20,4 +20,4 @@ pub const PKG_FILE: &str = "Nargo.toml"; /// The extension for files containing circuit proofs. pub const PROOF_EXT: &str = "proof"; /// The extension for files containing proof witnesses. -pub const WITNESS_EXT: &str = "tr"; +pub const WITNESS_EXT: &str = "gz"; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 7b97cc8afdc..3e4f868aecf 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -23,6 +23,7 @@ use clap::Args; use crate::backends::Backend; use crate::errors::CliError; +use super::fs::program::only_acir; use super::fs::program::{ read_debug_artifact_from_file, read_program_from_file, save_contract_to_file, save_debug_artifact_to_file, save_program_to_file, @@ -215,8 +216,8 @@ fn compile_program( // Apply backend specific optimizations. let optimized_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()); + let only_acir = compile_options.only_acir; + save_program(optimized_program.clone(), package, &workspace.target_directory_path(), only_acir); (context.file_manager, Ok((optimized_program, warnings))) } @@ -244,7 +245,12 @@ fn compile_contract( (context.file_manager, Ok((optimized_contract, warnings))) } -fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) { +fn save_program( + program: CompiledProgram, + package: &Package, + circuit_dir: &Path, + only_acir_opt: bool, +) { let preprocessed_program = PreprocessedProgram { hash: program.hash, backend: String::from(BACKEND_IDENTIFIER), @@ -252,8 +258,11 @@ fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) noir_version: program.noir_version, bytecode: program.circuit, }; - - save_program_to_file(&preprocessed_program, &package.name, circuit_dir); + if only_acir_opt { + only_acir(&preprocessed_program, circuit_dir); + } else { + save_program_to_file(&preprocessed_program, &package.name, circuit_dir); + } let debug_artifact = DebugArtifact { debug_symbols: vec![program.debug], diff --git a/tooling/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs index e82f2d55264..807df25ba48 100644 --- a/tooling/nargo_cli/src/cli/fs/program.rs +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use acvm::acir::circuit::Circuit; use nargo::artifacts::{ contract::PreprocessedContract, debug::DebugArtifact, program::PreprocessedProgram, }; @@ -18,6 +19,19 @@ pub(crate) fn save_program_to_file>( save_build_artifact_to_file(compiled_program, &circuit_name, circuit_dir) } +/// Writes the bytecode as acir.gz +pub(crate) fn only_acir>( + compiled_program: &PreprocessedProgram, + circuit_dir: P, +) -> PathBuf { + create_named_dir(circuit_dir.as_ref(), "target"); + let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); + let bytes = Circuit::serialize_circuit(&compiled_program.bytecode); + write_to_file(&bytes, &circuit_path); + + circuit_path +} + pub(crate) fn save_contract_to_file>( compiled_contract: &PreprocessedContract, circuit_name: &str, From cfa34d4d913dbd35f8329430e0d58830e069d6ff Mon Sep 17 00:00:00 2001 From: jfecher Date: Wed, 13 Dec 2023 08:31:43 -0600 Subject: [PATCH 034/137] fix: Allow trait method references from the trait name (#3774) # Description ## Problem\* Resolves #3773 Part of #2568 ## Summary\* This PR implements the ability to be able to call trait methods such as `Default::default()` where previously we required `StructName::default()`. The specific impl is selected via type inference. Previously, this resulted in a compiler panic. ## Additional Context When a trait method's type isn't constrained enough or is otherwise still ambiguous after type inference, the compiler currently just selects the first trait implementation that matches. E.g. `let _ = Default::default();`. This is a separate issue, so I'll create a new issue for this. ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [x] **[Exceptional Case]** Documentation to be submitted in a separate PR. - I think traits are finally stable enough to start writing documentation for. I'm going to submit another PR to remove some of the experimental warnings the compiler has for traits, and with it add documentation for traits as well. This wouldn't stabilize all trait features (e.g. associated types are still unimplemented), but users will now be able to use basic traits with functions without warnings. Any unimplemented trait items (associated types again) will not be included in the documentation. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../src/hir/def_collector/dc_crate.rs | 1 + .../src/hir/def_collector/dc_mod.rs | 7 +- .../src/hir/resolution/resolver.rs | 99 +++++++++++++++---- .../src/hir/resolution/traits.rs | 54 +++++----- .../noirc_frontend/src/hir/type_check/expr.rs | 21 +++- compiler/noirc_frontend/src/hir_def/traits.rs | 31 ++---- compiler/noirc_frontend/src/node_interner.rs | 48 ++++----- compiler/noirc_frontend/src/tests.rs | 61 +++++------- .../trait_static_methods/src/main.nr | 23 +++++ 9 files changed, 209 insertions(+), 136 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index a008874dc80..ae061792125 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -82,6 +82,7 @@ pub struct UnresolvedTrait { pub module_id: LocalModuleId, pub crate_id: CrateId, pub trait_def: NoirTrait, + pub method_ids: HashMap, pub fns_with_default_impl: UnresolvedFunctions, } diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 39f6c5b9014..aa1c658bade 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,4 +1,4 @@ -use std::vec; +use std::{collections::HashMap, vec}; use acvm::acir::acir_field::FieldOptions; use fm::FileId; @@ -378,6 +378,8 @@ impl<'a> ModCollector<'a> { functions: Vec::new(), trait_id: None, }; + + let mut method_ids = HashMap::new(); for trait_item in &trait_definition.items { match trait_item { TraitItem::Function { @@ -389,6 +391,8 @@ impl<'a> ModCollector<'a> { body, } => { let func_id = context.def_interner.push_empty_fn(); + method_ids.insert(name.to_string(), func_id); + let modifiers = FunctionModifiers { name: name.to_string(), visibility: crate::FunctionVisibility::Public, @@ -473,6 +477,7 @@ impl<'a> ModCollector<'a> { module_id: self.module_id, crate_id: krate, trait_def: trait_definition, + method_ids, fns_with_default_impl: unresolved_functions, }; self.def_collector.collected_traits.insert(trait_id, unresolved); diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index fcd747b65b5..0556698fb58 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -19,7 +19,7 @@ use crate::hir_def::expr::{ }; use crate::hir_def::traits::{Trait, TraitConstraint}; -use crate::token::FunctionAttribute; +use crate::token::{Attributes, FunctionAttribute}; use regex::Regex; use std::collections::{BTreeMap, HashSet}; use std::rc::Rc; @@ -37,11 +37,11 @@ use crate::{ StatementKind, }; use crate::{ - ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionVisibility, Generics, - LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, Shared, StructType, Type, - TypeAliasType, TypeBinding, TypeVariable, UnaryOp, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, - Visibility, ERROR_IDENT, + ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionDefinition, + FunctionReturnType, FunctionVisibility, Generics, LValue, NoirStruct, NoirTypeAlias, Param, + Path, PathKind, Pattern, Shared, StructType, Type, TypeAliasType, TypeBinding, TypeVariable, + UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, Visibility, ERROR_IDENT, }; use fm::FileId; use iter_extended::vecmap; @@ -200,6 +200,52 @@ impl<'a> Resolver<'a> { (hir_func, func_meta, self.errors) } + pub fn resolve_trait_function( + &mut self, + name: &Ident, + parameters: &[(Ident, UnresolvedType)], + return_type: &FunctionReturnType, + where_clause: &[UnresolvedTraitConstraint], + func_id: FuncId, + ) -> (HirFunction, FuncMeta) { + self.scopes.start_function(); + + // Check whether the function has globals in the local module and add them to the scope + self.resolve_local_globals(); + + self.trait_bounds = where_clause.to_vec(); + + let kind = FunctionKind::Normal; + let def = FunctionDefinition { + name: name.clone(), + attributes: Attributes::empty(), + is_open: false, + is_internal: false, + is_unconstrained: false, + visibility: FunctionVisibility::Public, // Trait functions are always public + generics: Vec::new(), // self.generics should already be set + parameters: vecmap(parameters, |(name, typ)| Param { + visibility: Visibility::Private, + pattern: Pattern::Identifier(name.clone()), + typ: typ.clone(), + span: name.span(), + }), + body: BlockExpression(Vec::new()), + span: name.span(), + where_clause: where_clause.to_vec(), + return_type: return_type.clone(), + return_visibility: Visibility::Private, + return_distinctness: Distinctness::DuplicationAllowed, + }; + + let (hir_func, func_meta) = self.intern_function(NoirFunction { kind, def }, func_id); + let func_scope_tree = self.scopes.end_function(); + self.check_for_unused_variables_in_scope_tree(func_scope_tree); + + self.trait_bounds.clear(); + (hir_func, func_meta) + } + fn check_for_unused_variables_in_scope_tree(&mut self, scope_decls: ScopeTree) { let mut unused_vars = Vec::new(); for scope in scope_decls.0.into_iter() { @@ -1584,27 +1630,39 @@ impl<'a> Resolver<'a> { &mut self, path: &Path, ) -> Option<(HirExpression, Type)> { - if let Some(trait_id) = self.trait_id { - if path.kind == PathKind::Plain && path.segments.len() == 2 { - let name = &path.segments[0].0.contents; - let method = &path.segments[1]; + let trait_id = self.trait_id?; - if name == SELF_TYPE_NAME { - let the_trait = self.interner.get_trait(trait_id); + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let name = &path.segments[0].0.contents; + let method = &path.segments[1]; - if let Some(method) = the_trait.find_method(method.0.contents.as_str()) { - let self_type = Type::TypeVariable( - the_trait.self_type_typevar.clone(), - crate::TypeVariableKind::Normal, - ); - return Some((HirExpression::TraitMethodReference(method), self_type)); - } - } + if name == SELF_TYPE_NAME { + let the_trait = self.interner.get_trait(trait_id); + let method = the_trait.find_method(method.0.contents.as_str())?; + let self_type = self.self_type.clone()?; + return Some((HirExpression::TraitMethodReference(method), self_type)); } } None } + // this resolves TraitName::some_static_method + fn resolve_trait_static_method(&mut self, path: &Path) -> Option<(HirExpression, Type)> { + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let method = &path.segments[1]; + + let mut trait_path = path.clone(); + trait_path.pop(); + let trait_id = self.lookup(trait_path).ok()?; + let the_trait = self.interner.get_trait(trait_id); + + let method = the_trait.find_method(method.0.contents.as_str())?; + let self_type = Type::type_variable(the_trait.self_type_typevar_id); + return Some((HirExpression::TraitMethodReference(method), self_type)); + } + None + } + // this resolves a static trait method T::trait_method by iterating over the where clause fn resolve_trait_method_by_named_generic( &mut self, @@ -1641,6 +1699,7 @@ impl<'a> Resolver<'a> { fn resolve_trait_generic_path(&mut self, path: &Path) -> Option<(HirExpression, Type)> { self.resolve_trait_static_method_by_self(path) + .or_else(|| self.resolve_trait_static_method(path)) .or_else(|| self.resolve_trait_method_by_named_generic(path)) } diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index d4969c52c76..54d2630c722 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashSet}; use fm::FileId; use iter_extended::vecmap; -use noirc_errors::{Location, Span}; +use noirc_errors::Location; use crate::{ graph::CrateId, @@ -22,9 +22,7 @@ use crate::{ }; use super::{ - errors::ResolverError, functions, get_module_mut, get_struct_type, - import::PathResolutionError, path_resolver::{PathResolver, StandardPathResolver}, resolver::Resolver, take_errors, @@ -92,13 +90,14 @@ fn resolve_trait_methods( let mut functions = vec![]; let mut resolver_errors = vec![]; + for item in &unresolved_trait.trait_def.items { if let TraitItem::Function { name, generics, parameters, return_type, - where_clause: _, + where_clause, body: _, } = item { @@ -110,6 +109,16 @@ fn resolve_trait_methods( resolver.add_generics(generics); resolver.set_self_type(Some(self_type)); + let func_id = unresolved_trait.method_ids[&name.0.contents]; + let (_, func_meta) = resolver.resolve_trait_function( + name, + parameters, + return_type, + where_clause, + func_id, + ); + resolver.interner.push_fn_meta(func_meta, func_id); + let arguments = vecmap(parameters, |param| resolver.resolve_type(param.1.clone())); let return_type = resolver.resolve_type(return_type.get_type().into_owned()); @@ -124,14 +133,13 @@ fn resolve_trait_methods( let the_trait = resolver.interner.get_trait(trait_id); generics.push((the_trait.self_type_typevar_id, the_trait.self_type_typevar.clone())); - let name = name.clone(); - let span: Span = name.span(); let default_impl_list: Vec<_> = unresolved_trait .fns_with_default_impl .functions .iter() .filter(|(_, _, q)| q.name() == name.0.contents) .collect(); + let default_impl = if default_impl_list.len() == 1 { Some(Box::new(default_impl_list[0].2.clone())) } else { @@ -140,18 +148,18 @@ fn resolve_trait_methods( let no_environment = Box::new(Type::Unit); let function_type = Type::Function(arguments, Box::new(return_type), no_environment); - let typ = Type::Forall(generics, Box::new(function_type)); - let f = TraitFunction { - name, - typ, - span, + functions.push(TraitFunction { + name: name.clone(), + typ: Type::Forall(generics, Box::new(function_type)), + span: name.span(), default_impl, default_impl_file_id: unresolved_trait.file_id, default_impl_module_id: unresolved_trait.module_id, - }; - functions.push(f); - resolver_errors.extend(take_errors_filter_self_not_resolved(file, resolver)); + }); + + let errors = resolver.take_errors().into_iter(); + resolver_errors.extend(errors.map(|resolution_error| (resolution_error.into(), file))); } } (functions, resolver_errors) @@ -451,21 +459,3 @@ pub(crate) fn resolve_trait_impls( methods } - -pub(crate) fn take_errors_filter_self_not_resolved( - file_id: FileId, - resolver: Resolver<'_>, -) -> Vec<(CompilationError, FileId)> { - resolver - .take_errors() - .iter() - .filter(|resolution_error| match resolution_error { - ResolverError::PathResolutionError(PathResolutionError::Unresolved(ident)) => { - &ident.0.contents != "Self" - } - _ => true, - }) - .cloned() - .map(|resolution_error| (resolution_error.into(), file_id)) - .collect() -} diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 720ed8d5b5d..f7154895150 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -10,7 +10,7 @@ use crate::{ }, types::Type, }, - node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitMethodId}, + node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId}, BinaryOpKind, Signedness, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, }; @@ -289,8 +289,23 @@ impl<'interner> TypeChecker<'interner> { } HirExpression::TraitMethodReference(method) => { let the_trait = self.interner.get_trait(method.trait_id); - let typ = &the_trait.methods[method.method_index].typ; - let (typ, bindings) = typ.instantiate(self.interner); + let typ2 = &the_trait.methods[method.method_index].typ; + let (typ, mut bindings) = typ2.instantiate(self.interner); + + // We must also remember to apply these substitutions to the object_type + // referenced by the selected trait impl, if one has yet to be selected. + let impl_kind = self.interner.get_selected_impl_for_ident(*expr_id); + if let Some(TraitImplKind::Assumed { object_type }) = impl_kind { + let the_trait = self.interner.get_trait(method.trait_id); + let object_type = object_type.substitute(&bindings); + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), object_type.clone()), + ); + self.interner + .select_impl_for_ident(*expr_id, TraitImplKind::Assumed { object_type }); + } + self.interner.store_instantiation_bindings(*expr_id, bindings); typ } diff --git a/compiler/noirc_frontend/src/hir_def/traits.rs b/compiler/noirc_frontend/src/hir_def/traits.rs index c1cf5adf4ad..ea9c2e2928c 100644 --- a/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::{ graph::CrateId, node_interner::{FuncId, TraitId, TraitMethodId}, @@ -43,6 +45,12 @@ pub struct Trait { pub methods: Vec, + /// Maps method_name -> method id. + /// This map is separate from methods since TraitFunction ids + /// are created during collection where we don't yet have all + /// the information needed to create the full TraitFunction. + pub method_ids: HashMap, + pub constants: Vec, pub types: Vec, @@ -98,29 +106,6 @@ impl PartialEq for Trait { } impl Trait { - pub fn new( - id: TraitId, - name: Ident, - crate_id: CrateId, - span: Span, - generics: Generics, - self_type_typevar_id: TypeVariableId, - self_type_typevar: TypeVariable, - ) -> Trait { - Trait { - id, - name, - crate_id, - span, - methods: Vec::new(), - constants: Vec::new(), - types: Vec::new(), - generics, - self_type_typevar_id, - self_type_typevar, - } - } - pub fn set_methods(&mut self, methods: Vec) { self.methods = methods; } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 2769b5874e9..236f1e0b513 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -489,28 +489,31 @@ impl NodeInterner { self.id_to_type.insert(expr_id.into(), typ); } - pub fn push_empty_trait(&mut self, type_id: TraitId, typ: &UnresolvedTrait) { + pub fn push_empty_trait(&mut self, type_id: TraitId, unresolved_trait: &UnresolvedTrait) { let self_type_typevar_id = self.next_type_variable_id(); - self.traits.insert( - type_id, - Trait::new( - type_id, - typ.trait_def.name.clone(), - typ.crate_id, - typ.trait_def.span, - vecmap(&typ.trait_def.generics, |_| { - // Temporary type variable ids before the trait is resolved to its actual ids. - // This lets us record how many arguments the type expects so that other types - // can refer to it with generic arguments before the generic parameters themselves - // are resolved. - let id = TypeVariableId(0); - (id, TypeVariable::unbound(id)) - }), - self_type_typevar_id, - TypeVariable::unbound(self_type_typevar_id), - ), - ); + let new_trait = Trait { + id: type_id, + name: unresolved_trait.trait_def.name.clone(), + crate_id: unresolved_trait.crate_id, + span: unresolved_trait.trait_def.span, + generics: vecmap(&unresolved_trait.trait_def.generics, |_| { + // Temporary type variable ids before the trait is resolved to its actual ids. + // This lets us record how many arguments the type expects so that other types + // can refer to it with generic arguments before the generic parameters themselves + // are resolved. + let id = TypeVariableId(0); + (id, TypeVariable::unbound(id)) + }), + self_type_typevar_id, + self_type_typevar: TypeVariable::unbound(self_type_typevar_id), + methods: Vec::new(), + method_ids: unresolved_trait.method_ids.clone(), + constants: Vec::new(), + types: Vec::new(), + }; + + self.traits.insert(type_id, new_trait); } pub fn new_struct( @@ -1255,9 +1258,8 @@ impl NodeInterner { self.selected_trait_implementations.insert(ident_id, trait_impl); } - /// Tags the given identifier with the selected trait_impl so that monomorphization - /// can later recover which impl was selected, or alternatively see if it needs to - /// decide which (because the impl was Assumed). + /// Retrieves the impl selected for a given IdentId during name resolution. + /// From type checking and on, the "ident" referred to is changed to a TraitMethodReference node. pub fn get_selected_impl_for_ident(&self, ident_id: ExprId) -> Option { self.selected_trait_implementations.get(&ident_id).cloned() } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 13ce71c4616..ce3ef87c1a8 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -9,6 +9,7 @@ mod test { use fm::FileId; + use iter_extended::vecmap; use noirc_errors::Location; use crate::hir::def_collector::dc_crate::CompilationError; @@ -18,7 +19,6 @@ mod test { use crate::hir::resolution::import::PathResolutionError; use crate::hir::type_check::TypeCheckError; use crate::hir::Context; - use crate::macros_api::MacroProcessor; use crate::node_interner::{NodeInterner, StmtId}; use crate::graph::CrateGraph; @@ -39,20 +39,23 @@ mod test { errors.iter().any(|(e, _f)| matches!(e, CompilationError::ParseError(_))) } - pub(crate) fn remove_experimental_feature_warnings( - errors: Vec<(CompilationError, FileId)>, - ) -> Vec<(CompilationError, FileId)> { - errors - .iter() - .filter(|(e, _f)| match e.clone() { - CompilationError::ParseError(parser_error) => !matches!( - parser_error.reason(), - Some(ParserErrorReason::ExperimentalFeature(_)) - ), + pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, FileId)>) { + errors.retain(|(error, _)| match error { + CompilationError::ParseError(error) => match error.reason() { + Some(ParserErrorReason::ExperimentalFeature(..)) => false, _ => true, - }) - .cloned() - .collect() + }, + _ => true, + }); + } + + /// Many of the tests in this file have odd unused variable warnings which do not occur + /// when running an identical program using `nargo execute`. They're filtered out of the + /// errors returned by `get_errors` for now. + pub(crate) fn remove_unused_variable_warnings(errors: &mut Vec<(CompilationError, FileId)>) { + errors.retain(|(error, _)| { + !matches!(error, CompilationError::ResolverError(ResolverError::UnusedVariable { .. })) + }); } pub(crate) fn get_program( @@ -66,14 +69,15 @@ mod test { let root_file_id = FileId::dummy(); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); let (program, parser_errors) = parse_program(src); - let mut errors = remove_experimental_feature_warnings( - parser_errors.iter().cloned().map(|e| (e.into(), root_file_id)).collect(), - ); + let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id)); + remove_experimental_warnings(&mut errors); + if !has_parser_error(&errors) { // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); let location = Location::new(Default::default(), root_file_id); let root = modules.insert(ModuleData::new(None, location, false)); + let def_map = CrateDefMap { root: LocalModuleId(root), modules, @@ -81,33 +85,22 @@ mod test { extern_prelude: BTreeMap::new(), }; - let empty_macro_processors: Vec<&dyn MacroProcessor> = Vec::new(); - // Now we want to populate the CrateDefMap using the DefCollector errors.extend(DefCollector::collect( def_map, &mut context, program.clone().into_sorted(), root_file_id, - empty_macro_processors, + Vec::new(), // No macro processors )); } (program, context, errors) } pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { - let (_program, _context, errors) = get_program(src); + let (_program, _context, mut errors) = get_program(src); + remove_unused_variable_warnings(&mut errors); errors - .iter() - .filter(|(e, _f)| match e.clone() { - CompilationError::ParseError(parser_error) => !matches!( - parser_error.reason(), - Some(ParserErrorReason::ExperimentalFeature(_)) - ), - _ => true, - }) - .cloned() - .collect() } #[test] @@ -462,7 +455,7 @@ mod test { }"; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); - assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); + assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); for (err, _file_id) in errors { match &err { @@ -805,7 +798,7 @@ mod test { } "#; - let errors = get_program_errors(src); + let (_, _, errors) = get_program(src); assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); // It should be regarding the unused variable match &errors[0].0 { @@ -882,7 +875,7 @@ mod test { } "#; - let errors = get_program_errors(src); + let (_, _, errors) = get_program(src); assert!(errors.len() == 3, "Expected 3 errors, got: {:?}", errors); // Errors are: diff --git a/test_programs/compile_success_empty/trait_static_methods/src/main.nr b/test_programs/compile_success_empty/trait_static_methods/src/main.nr index 0150da68315..838e47ee82e 100644 --- a/test_programs/compile_success_empty/trait_static_methods/src/main.nr +++ b/test_programs/compile_success_empty/trait_static_methods/src/main.nr @@ -38,4 +38,27 @@ impl ATrait for Bar { fn main() { assert(Foo::static_method() == 100); assert(Bar::static_method() == 200); + + // Regression for #3773 + let zero: Field = MyDefault::my_default(); + assert(zero == 0); +} + +trait MyDefault { + fn my_default() -> Self; +} + +// This impl is first, so if the type directed search picks the first impl +// instead of the correct Field impl below, we'll get a panic in SSA from +// a type mismatch. +impl MyDefault for (Field, Field) { + fn my_default() -> (Field, Field) { + (0, 0) + } +} + +impl MyDefault for Field { + fn my_default() -> Field { + 0 + } } From cb522429592477c2b0544f3b3026a1a946b0e5b1 Mon Sep 17 00:00:00 2001 From: jfecher Date: Wed, 13 Dec 2023 09:17:19 -0600 Subject: [PATCH 035/137] feat: Remove experimental feature warning for traits (#3783) # Description ## Problem\* ## Summary\* After https://github.com/noir-lang/noir/pull/3774 is merged we can merge this PR to remove the experimental warning when using most trait features. This PR also provides documentation for traits. ## Additional Context Since there are still some unimplemented trait features I've added experimental warnings for: - Placing generics on the trait itself - Associated types on traits - Associated constants on traits ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- compiler/noirc_frontend/src/parser/parser.rs | 41 ++- cspell.json | 2 + docs/docs/explanations/noir/traits.md | 348 +++++++++++++++++++ 3 files changed, 377 insertions(+), 14 deletions(-) create mode 100644 docs/docs/explanations/noir/traits.md diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 225e5afaa14..a97637642af 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -414,7 +414,12 @@ fn trait_definition() -> impl NoirParser { .then(trait_body()) .then_ignore(just(Token::RightBrace)) .validate(|(((name, generics), where_clause), items), span, emit| { - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); + if !generics.is_empty() { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Generic traits"), + span, + )); + } TopLevelStatement::Trait(NoirTrait { name, generics, where_clause, span, items }) }) } @@ -437,7 +442,13 @@ fn trait_constant_declaration() -> impl NoirParser { .then(parse_type()) .then(optional_default_value()) .then_ignore(just(Token::Semicolon)) - .map(|((name, typ), default_value)| TraitItem::Constant { name, typ, default_value }) + .validate(|((name, typ), default_value), span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Associated constants"), + span, + )); + TraitItem::Constant { name, typ, default_value } + }) } /// trait_function_declaration: 'fn' ident generics '(' declaration_parameters ')' function_return_type @@ -544,10 +555,15 @@ fn function_declaration_parameters() -> impl NoirParser impl NoirParser { - keyword(Keyword::Type) - .ignore_then(ident()) - .then_ignore(just(Token::Semicolon)) - .map(|name| TraitItem::Type { name }) + keyword(Keyword::Type).ignore_then(ident()).then_ignore(just(Token::Semicolon)).validate( + |name, span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Associated types"), + span, + )); + TraitItem::Type { name } + }, + ) } /// Parses a non-trait implementation, adding a set of methods to a type. @@ -581,11 +597,10 @@ fn trait_implementation() -> impl NoirParser { .then_ignore(just(Token::LeftBrace)) .then(trait_implementation_body()) .then_ignore(just(Token::RightBrace)) - .validate(|args, span, emit| { + .map(|args| { let ((other_args, where_clause), items) = args; let (((impl_generics, trait_name), trait_generics), object_type) = other_args; - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); TopLevelStatement::TraitImpl(NoirTraitImpl { impl_generics, trait_name, @@ -616,12 +631,10 @@ fn where_clause() -> impl NoirParser> { trait_bounds: Vec, } - let constraints = parse_type().then_ignore(just(Token::Colon)).then(trait_bounds()).validate( - |(typ, trait_bounds), span, emit| { - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); - MultiTraitConstraint { typ, trait_bounds } - }, - ); + let constraints = parse_type() + .then_ignore(just(Token::Colon)) + .then(trait_bounds()) + .map(|(typ, trait_bounds)| MultiTraitConstraint { typ, trait_bounds }); keyword(Keyword::Where) .ignore_then(constraints.separated_by(just(Token::Comma))) diff --git a/cspell.json b/cspell.json index fc8d8d7e82c..4d3af064654 100644 --- a/cspell.json +++ b/cspell.json @@ -79,6 +79,7 @@ "monomorphizes", "nand", "nargo", + "newtype", "nixpkgs", "noirc", "noirup", @@ -89,6 +90,7 @@ "pprof", "preprocess", "prettytable", + "println", "printstd", "pseudocode", "quantile", diff --git a/docs/docs/explanations/noir/traits.md b/docs/docs/explanations/noir/traits.md new file mode 100644 index 00000000000..d24deaa84da --- /dev/null +++ b/docs/docs/explanations/noir/traits.md @@ -0,0 +1,348 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: S) where S: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: S) where S: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. From 9c9fbc1d742336d4451944b837e42dac76805193 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:15:18 +0000 Subject: [PATCH 036/137] chore: clippy fix (#3793) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/tests.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index ce3ef87c1a8..2619189ee8d 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -41,10 +41,9 @@ mod test { pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, FileId)>) { errors.retain(|(error, _)| match error { - CompilationError::ParseError(error) => match error.reason() { - Some(ParserErrorReason::ExperimentalFeature(..)) => false, - _ => true, - }, + CompilationError::ParseError(error) => { + !matches!(error.reason(), Some(ParserErrorReason::ExperimentalFeature(..))) + } _ => true, }); } From 14f2fffeb3de5f653c11694ee3c5e5d62aaa34ec Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Wed, 13 Dec 2023 18:33:09 +0100 Subject: [PATCH 037/137] fix(lsp): package resolution on save (#3794) # Description ## Problem\* ## Summary\* While saving file - procedure of compiling package should be applied to single package rather than all packages available in workspace. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/lsp/src/notifications/mod.rs | 22 +++++++--------------- tooling/nargo_toml/src/lib.rs | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index a3f2fdde3d6..876ff157c07 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use nargo::prepare_package; -use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{DiagnosticKind, FileDiagnostic}; @@ -69,29 +69,21 @@ pub(super) fn on_did_save_text_document( } }; - let root_path = match &state.root_path { - Some(root) => root, - None => { - return ControlFlow::Break(Err(ResponseError::new( - ErrorCode::REQUEST_FAILED, - "Could not find project root", - ) - .into())); - } - }; + let package_root = find_file_manifest(file_path.as_path()); - let toml_path = match find_package_manifest(root_path, &file_path) { - Ok(toml_path) => toml_path, - Err(err) => { + let toml_path = match package_root { + Some(toml_path) => toml_path, + None => { // If we cannot find a manifest, we log a warning but return no diagnostics // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps let _ = state.client.log_message(LogMessageParams { typ: MessageType::WARNING, - message: format!("{err}"), + message: format!("Nargo.toml not found for file: {:}", file_path.display()), }); return ControlFlow::Continue(()); } }; + let workspace = match resolve_workspace_from_toml( &toml_path, PackageSelection::All, diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 31426ee4ee4..56024f8ed42 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -24,6 +24,27 @@ mod semver; pub use errors::ManifestError; use git::clone_git_repo; +/// Searches for a `Nargo.toml` file in the current directory and all parent directories. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will search for a `Nargo.toml` file in +/// * `/workspace/package/src`, +/// * `/workspace/package`, +/// * `/workspace`. +/// +/// Returns the [PathBuf] of the `Nargo.toml` file if found, otherwise returns None. +/// +/// It will return innermost `Nargo.toml` file, which is the one closest to the current directory. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will return the `Nargo.toml` file in `/workspace/package/Nargo.toml` +pub fn find_file_manifest(current_path: &Path) -> Option { + for path in current_path.ancestors() { + if let Ok(toml_path) = get_package_manifest(path) { + return Some(toml_path); + } + } + None +} + /// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path]. /// /// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. From 0bb44c3bbc63d385d77d93da6abd07214bcfd700 Mon Sep 17 00:00:00 2001 From: jfecher Date: Wed, 13 Dec 2023 13:13:29 -0600 Subject: [PATCH 038/137] fix: Stop issuing unused variable warnings for variables in trait definitions (#3797) # Description ## Problem\* Previously we'd issue a warning for each trait function parameter that it is unused. This seemed to only trigger when the trait was in another crate. ## Summary\* Stop checking for unused variables in trait function declarations since there is no body to use the variable in anyway. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. Co-authored-by: kevaundray --- .../src/hir/resolution/resolver.rs | 5 ++--- compiler/noirc_frontend/src/tests.rs | 17 +++-------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 0556698fb58..9cd28d80784 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -239,9 +239,8 @@ impl<'a> Resolver<'a> { }; let (hir_func, func_meta) = self.intern_function(NoirFunction { kind, def }, func_id); - let func_scope_tree = self.scopes.end_function(); - self.check_for_unused_variables_in_scope_tree(func_scope_tree); - + let _ = self.scopes.end_function(); + // Don't check the scope tree for unused variables, they can't be used in a declaration anyway. self.trait_bounds.clear(); (hir_func, func_meta) } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 2619189ee8d..7b2a94b4f10 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -48,15 +48,6 @@ mod test { }); } - /// Many of the tests in this file have odd unused variable warnings which do not occur - /// when running an identical program using `nargo execute`. They're filtered out of the - /// errors returned by `get_errors` for now. - pub(crate) fn remove_unused_variable_warnings(errors: &mut Vec<(CompilationError, FileId)>) { - errors.retain(|(error, _)| { - !matches!(error, CompilationError::ResolverError(ResolverError::UnusedVariable { .. })) - }); - } - pub(crate) fn get_program( src: &str, ) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { @@ -97,9 +88,7 @@ mod test { } pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { - let (_program, _context, mut errors) = get_program(src); - remove_unused_variable_warnings(&mut errors); - errors + get_program(src).2 } #[test] @@ -797,7 +786,7 @@ mod test { } "#; - let (_, _, errors) = get_program(src); + let errors = get_program_errors(src); assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); // It should be regarding the unused variable match &errors[0].0 { @@ -874,7 +863,7 @@ mod test { } "#; - let (_, _, errors) = get_program(src); + let errors = get_program_errors(src); assert!(errors.len() == 3, "Expected 3 errors, got: {:?}", errors); // Errors are: From 8e113526a2d78d27ed4e489f16d5604a2aaa18ea Mon Sep 17 00:00:00 2001 From: jfecher Date: Wed, 13 Dec 2023 13:51:04 -0600 Subject: [PATCH 039/137] feat: Add some traits to the stdlib (#3796) # Description ## Problem\* ## Summary\* Adds traits for `Default`, `Add`, `Sub`, `Mul`, `Div`, and `Eq` to the stdlib. Note that this does not implement operator overloading so the operator traits must be called by name. We also have no way currently of implementing a trait for all integer sizes so I've manually implemented only some common ones. Let me know if there are other impls I should add. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../explanations/standard_library/traits.md | 140 ++++++++++++++++++ noir_stdlib/src/default.nr | 48 ++++++ noir_stdlib/src/lib.nr | 2 + noir_stdlib/src/ops.nr | 117 +++++++++++++++ .../no_nested_impl/src/main.nr | 18 +-- 5 files changed, 316 insertions(+), 9 deletions(-) create mode 100644 docs/docs/explanations/standard_library/traits.md create mode 100644 noir_stdlib/src/default.nr create mode 100644 noir_stdlib/src/ops.nr diff --git a/docs/docs/explanations/standard_library/traits.md b/docs/docs/explanations/standard_library/traits.md new file mode 100644 index 00000000000..63b4f3d6f0b --- /dev/null +++ b/docs/docs/explanations/standard_library/traits.md @@ -0,0 +1,140 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust +trait Default { + fn default() -> Self; +} +``` + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + +## `std::ops` + +### `std::ops::Eq` + +```rust +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +Returns `true` if `self` is equal to `other`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Although Noir does not currently have operator overloading, in the future implementing these +traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust +trait Add { + fn add(self, other: Self) -> Self; +} + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +trait Div { + fn div(self, other: Self) -> Self; +} +``` + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr new file mode 100644 index 00000000000..232be74489c --- /dev/null +++ b/noir_stdlib/src/default.nr @@ -0,0 +1,48 @@ +trait Default { + fn default() -> Self; +} + +impl Default for Field { fn default() -> Field { 0 } } + +impl Default for u8 { fn default() -> u8 { 0 } } +impl Default for u16 { fn default() -> u16 { 0 } } +impl Default for u32 { fn default() -> u32 { 0 } } +impl Default for u64 { fn default() -> u64 { 0 } } + +impl Default for i8 { fn default() -> i8 { 0 } } +impl Default for i16 { fn default() -> i16 { 0 } } +impl Default for i32 { fn default() -> i32 { 0 } } +impl Default for i64 { fn default() -> i64 { 0 } } + +impl Default for () { fn default() -> () { () } } +impl Default for bool { fn default() -> bool { false } } + +impl Default for [T; N] where T: Default { + fn default() -> [T; N] { + [T::default(); N] + } +} + +impl Default for (A, B) where A: Default, B: Default { + fn default() -> (A, B) { + (A::default(), B::default()) + } +} + +impl Default for (A, B, C) where A: Default, B: Default, C: Default { + fn default() -> (A, B, C) { + (A::default(), B::default(), C::default()) + } +} + +impl Default for (A, B, C, D) where A: Default, B: Default, C: Default, D: Default { + fn default() -> (A, B, C, D) { + (A::default(), B::default(), C::default(), D::default()) + } +} + +impl Default for (A, B, C, D, E) where A: Default, B: Default, C: Default, D: Default, E: Default { + fn default() -> (A, B, C, D, E) { + (A::default(), B::default(), C::default(), D::default(), E::default()) + } +} diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 3c47de61bab..70b4681b54d 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -19,6 +19,8 @@ mod compat; mod option; mod string; mod test; +mod ops; +mod default; mod prelude; // Oracle calls are required to be wrapped in an unconstrained function diff --git a/noir_stdlib/src/ops.nr b/noir_stdlib/src/ops.nr new file mode 100644 index 00000000000..23acc2f0e5d --- /dev/null +++ b/noir_stdlib/src/ops.nr @@ -0,0 +1,117 @@ + +trait Add { + fn add(self, other: Self) -> Self; +} + +impl Add for Field { fn add(self, other: Field) -> Field { self + other } } + +impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } +impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } +impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } +impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } + +impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } +impl Add for i16 { fn add(self, other: i16) -> i16 { self + other } } +impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } +impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } + +impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } +impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } +impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } +impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } + +impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } +impl Sub for i16 { fn sub(self, other: i16) -> i16 { self - other } } +impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } +impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } + +impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } +impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } +impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } +impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } + +impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } +impl Mul for i16 { fn mul(self, other: i16) -> i16 { self * other } } +impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } +impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } + +trait Div { + fn div(self, other: Self) -> Self; +} + +impl Div for Field { fn div(self, other: Field) -> Field { self / other } } + +impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } +impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } +impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } +impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } + +impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } +impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } +impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } +impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } + +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } + +impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } +impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } +impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } +impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } + +impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } +impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } +impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } +impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } + +impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } +impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } + +impl Eq for [T; N] where T: Eq { + fn eq(self, other: [T; N]) -> bool { + let mut result = true; + for i in 0 .. self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + +impl Eq for (A, B) where A: Eq, B: Eq { + fn eq(self, other: (A, B)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) + } +} + +impl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq { + fn eq(self, other: (A, B, C)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) + } +} + +impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { + fn eq(self, other: (A, B, C, D)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) + } +} + +impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { + fn eq(self, other: (A, B, C, D, E)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) + } +} diff --git a/test_programs/compile_failure/no_nested_impl/src/main.nr b/test_programs/compile_failure/no_nested_impl/src/main.nr index 916567a7c04..1f1056fb6d9 100644 --- a/test_programs/compile_failure/no_nested_impl/src/main.nr +++ b/test_programs/compile_failure/no_nested_impl/src/main.nr @@ -1,21 +1,21 @@ fn main() { let a: [[[[Field; 2]; 2]; 2]; 2] = [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]; - assert(a.eq(a)); + assert(a.my_eq(a)); } -trait Eq { - fn eq(self, other: Self) -> bool; +trait MyEq { + fn my_eq(self, other: Self) -> bool; } -impl Eq for [T; 2] where T: Eq { - fn eq(self, other: Self) -> bool { - self[0].eq(other[0]) - & self[0].eq(other[0]) +impl MyEq for [T; 2] where T: MyEq { + fn my_eq(self, other: Self) -> bool { + self[0].my_eq(other[0]) + & self[0].my_eq(other[0]) } } // Impl for u32 but not Field -impl Eq for u32 { - fn eq(self, other: Self) -> bool { +impl MyEq for u32 { + fn my_eq(self, other: Self) -> bool { self == other } } From e3dcc21cb2c0fef7f28f50b018747c4f09609b11 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Thu, 14 Dec 2023 01:14:15 +0000 Subject: [PATCH 040/137] chore!: Make file manager read-only to the compiler (#3760) # Description This is a PR that moves us towards having the compiler see the FileManager as an immutable object. How it gets populated will now be upto the caller. One issue we have so far is that caller, can be in the wasm context or the native context, so we have file_reader being a component that we conditionally compile depending on the context. Ideally we move to a case where both package source resolution and dependency source resolution is done beforehand, and the compiler assumes that FileManager has both the source for its current crate and all of the crates dependencies. This separation of concerns makes it easier to incrementally compile parts of the compiler in the future. For example, if the FileManager has not changed, then we know that the compilation result should not change,and we do not need to recompile. Further, lets say we add a pass that solely does parsing of the root files in the File Manager, If a particular parsed AST has not changed, then we do not need to parse that file again. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- Cargo.lock | 5 +- compiler/fm/Cargo.toml | 1 - compiler/fm/src/file_reader.rs | 49 ------ compiler/fm/src/lib.rs | 92 +++++++----- .../test/browser/compile_prove_verify.test.ts | 21 ++- .../test/browser/recursion.test.ts | 19 ++- .../onchain_recursive_verification.test.ts | 33 +++-- .../test/node/smart_contract_verifier.test.ts | 8 +- compiler/noirc_driver/Cargo.toml | 1 + compiler/noirc_driver/src/lib.rs | 22 ++- compiler/noirc_driver/src/stdlib.rs | 24 +++ compiler/noirc_frontend/src/tests.rs | 3 +- compiler/wasm/Cargo.toml | 1 - compiler/wasm/src/compile.rs | 139 +++++++++++++----- compiler/wasm/test/browser/index.test.ts | 63 +++----- compiler/wasm/test/node/index.test.ts | 45 +++--- tooling/lsp/Cargo.toml | 1 - tooling/lsp/src/lib.rs | 28 +--- tooling/lsp/src/notifications/mod.rs | 4 +- tooling/lsp/src/requests/goto_definition.rs | 3 +- tooling/lsp/src/requests/test_run.rs | 3 +- tooling/lsp/src/requests/tests.rs | 4 +- tooling/nargo/Cargo.toml | 7 +- tooling/nargo/src/lib.rs | 123 +++++++++++++++- tooling/nargo/src/ops/compile.rs | 6 +- tooling/nargo_cli/src/cli/check_cmd.rs | 3 +- tooling/nargo_cli/src/cli/compile_cmd.rs | 6 +- tooling/nargo_cli/src/cli/fmt_cmd.rs | 7 +- tooling/nargo_cli/src/cli/test_cmd.rs | 3 +- 29 files changed, 430 insertions(+), 294 deletions(-) delete mode 100644 compiler/fm/src/file_reader.rs create mode 100644 compiler/noirc_driver/src/stdlib.rs diff --git a/Cargo.lock b/Cargo.lock index 652271fcaff..cec7b5f0371 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1633,7 +1633,6 @@ version = "0.20.0" dependencies = [ "codespan-reporting", "iter-extended", - "rust-embed", "serde", "tempfile", ] @@ -2443,6 +2442,7 @@ dependencies = [ "rayon", "rustc_version", "serde", + "tempfile", "thiserror", ] @@ -2577,7 +2577,6 @@ version = "0.20.0" dependencies = [ "acvm", "async-lsp", - "cfg-if", "codespan-lsp", "fm", "lsp-types 0.94.1", @@ -2601,7 +2600,6 @@ version = "0.20.0" dependencies = [ "acvm", "build-data", - "cfg-if", "console_error_panic_hook", "fm", "getrandom", @@ -2666,6 +2664,7 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", + "rust-embed", "serde", ] diff --git a/compiler/fm/Cargo.toml b/compiler/fm/Cargo.toml index 9e4309693ed..699f709e9b5 100644 --- a/compiler/fm/Cargo.toml +++ b/compiler/fm/Cargo.toml @@ -9,7 +9,6 @@ license.workspace = true [dependencies] codespan-reporting.workspace = true -rust-embed = "6.6.0" serde.workspace = true [dev-dependencies] diff --git a/compiler/fm/src/file_reader.rs b/compiler/fm/src/file_reader.rs deleted file mode 100644 index d17aefeda7e..00000000000 --- a/compiler/fm/src/file_reader.rs +++ /dev/null @@ -1,49 +0,0 @@ -use rust_embed::RustEmbed; -use std::io::{Error, ErrorKind}; -use std::path::Path; - -// Based on the environment, we either read files using the rust standard library or we -// read files using the javascript host function - -pub type FileReader = dyn Fn(&Path) -> std::io::Result + Send; - -#[derive(RustEmbed)] -#[folder = "../../noir_stdlib/src"] -#[cfg_attr(not(target_os = "windows"), prefix = "std/")] -#[cfg_attr(target_os = "windows", prefix = r"std\")] // Note reversed slash direction -struct StdLibAssets; - -#[cfg(target_os = "windows")] -pub(super) fn is_stdlib_asset(path: &Path) -> bool { - path.starts_with("std\\") -} - -#[cfg(not(target_os = "windows"))] -pub(super) fn is_stdlib_asset(path: &Path) -> bool { - path.starts_with("std/") -} - -fn get_stdlib_asset(path: &Path) -> std::io::Result { - if !is_stdlib_asset(path) { - return Err(Error::new(ErrorKind::InvalidInput, "requested a non-stdlib asset")); - } - - match StdLibAssets::get(path.to_str().unwrap()) { - Some(std_lib_asset) => { - Ok(std::str::from_utf8(std_lib_asset.data.as_ref()).unwrap().to_string()) - } - - None => Err(Error::new(ErrorKind::NotFound, "invalid stdlib path")), - } -} - -pub(crate) fn read_file_to_string( - path_to_file: &Path, - get_non_stdlib_asset: &impl Fn(&Path) -> std::io::Result, -) -> std::io::Result { - if is_stdlib_asset(path_to_file) { - get_stdlib_asset(path_to_file) - } else { - get_non_stdlib_asset(path_to_file) - } -} diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index a251ecc70c5..2a54e58d3b9 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -4,16 +4,12 @@ #![warn(clippy::semicolon_if_nothing_returned)] mod file_map; -mod file_reader; pub use file_map::{File, FileId, FileMap, PathString}; // Re-export for the lsp pub use codespan_reporting::files as codespan_files; -use file_reader::is_stdlib_asset; -pub use file_reader::FileReader; - use std::{ collections::HashMap, path::{Component, Path, PathBuf}, @@ -26,7 +22,6 @@ pub struct FileManager { file_map: FileMap, id_to_path: HashMap, path_to_id: HashMap, - file_reader: Box, } impl std::fmt::Debug for FileManager { @@ -41,13 +36,12 @@ impl std::fmt::Debug for FileManager { } impl FileManager { - pub fn new(root: &Path, file_reader: Box) -> Self { + pub fn new(root: &Path) -> Self { Self { root: root.normalize(), file_map: Default::default(), id_to_path: Default::default(), path_to_id: Default::default(), - file_reader, } } @@ -55,25 +49,32 @@ impl FileManager { &self.file_map } - pub fn add_file(&mut self, file_name: &Path) -> Option { - // Handle both relative file paths and std/lib virtual paths. - let resolved_path: PathBuf = if is_stdlib_asset(file_name) { - // Special case for stdlib where we want to read specifically the `std/` relative path - // TODO: The stdlib path should probably be an absolute path rooted in something people would never create - file_name.to_path_buf() - } else { - self.root.join(file_name).normalize() - }; + /// Adds a source file to the [`FileManager`]. + /// + /// The `file_name` is expected to be relative to the [`FileManager`]'s root directory. + pub fn add_file_with_source(&mut self, file_name: &Path, source: String) -> Option { + let file_name = self.root.join(file_name); + self.add_file_with_source_canonical_path(&file_name, source) + } - // Check that the resolved path already exists in the file map, if it is, we return it. - if let Some(file_id) = self.path_to_id.get(&resolved_path) { + /// Adds a source file to the [`FileManager`] using a path which is not appended to the root path. + /// + /// This should only be used for the stdlib as these files do not exist on the user's filesystem. + pub fn add_file_with_source_canonical_path( + &mut self, + file_name: &Path, + source: String, + ) -> Option { + let file_name = file_name.normalize(); + // Check that the file name already exists in the file map, if it is, we return it. + if let Some(file_id) = self.path_to_id.get(&file_name) { return Some(*file_id); } + let file_name_path_buf = file_name.to_path_buf(); // Otherwise we add the file - let source = file_reader::read_file_to_string(&resolved_path, &self.file_reader).ok()?; - let file_id = self.file_map.add_file(resolved_path.clone().into(), source); - self.register_path(file_id, resolved_path); + let file_id = self.file_map.add_file(file_name_path_buf.clone().into(), source); + self.register_path(file_id, file_name_path_buf); Some(file_id) } @@ -98,7 +99,10 @@ impl FileManager { self.id_to_path.get(&file_id).unwrap().as_path() } - pub fn find_module(&mut self, anchor: FileId, mod_name: &str) -> Result { + // TODO: This should also ideally not be here, so that the file manager + // TODO: does not know about rust modules. + // TODO: Ideally this is moved to def_collector_mod and we make this method accept a FileManager + pub fn find_module(&self, anchor: FileId, mod_name: &str) -> Result { let anchor_path = self.path(anchor).with_extension(""); let anchor_dir = anchor_path.parent().unwrap(); @@ -111,14 +115,19 @@ impl FileManager { anchor_path.join(format!("{mod_name}.{FILE_EXTENSION}")) }; - self.add_file(&candidate).ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) + self.name_to_id(candidate.clone()) + .ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) } + // TODO: This should accept a &Path instead of a PathBuf pub fn name_to_id(&self, file_name: PathBuf) -> Option { self.file_map.get_file_id(&PathString::from_path(file_name)) } } +// TODO: This should not be here because the file manager should not know about the +// TODO: rust modules. See comment on `find_module`` +// TODO: Moreover, the check for main, lib, mod should ideally not be done here /// Returns true if a module's child module's are expected to be in the same directory. /// Returns false if they are expected to be in a subdirectory matching the name of the module. fn should_check_siblings_for_module(module_path: &Path, parent_path: &Path) -> bool { @@ -220,9 +229,11 @@ mod tests { use super::*; use tempfile::{tempdir, TempDir}; - fn create_dummy_file(dir: &TempDir, file_name: &Path) { + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { let file_path = dir.path().join(file_name); - let _file = std::fs::File::create(file_path).unwrap(); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path } #[test] @@ -232,9 +243,9 @@ mod tests { let entry_file_name = Path::new("my_dummy_file.nr"); create_dummy_file(&dir, entry_file_name); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); - let file_id = fm.add_file(entry_file_name).unwrap(); + let file_id = fm.add_file_with_source(entry_file_name, "fn foo() {}".to_string()).unwrap(); let dep_file_name = Path::new("foo.nr"); create_dummy_file(&dir, dep_file_name); @@ -247,9 +258,9 @@ mod tests { let file_name = Path::new("foo.nr"); create_dummy_file(&dir, file_name); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); - let file_id = fm.add_file(file_name).unwrap(); + let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); assert!(fm.path(file_id).ends_with("foo.nr")); } @@ -257,14 +268,14 @@ mod tests { #[test] fn path_resolve_sub_module() { let dir = tempdir().unwrap(); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); // Create a lib.nr file at the root. // we now have dir/lib.nr - let file_name = Path::new("lib.nr"); - create_dummy_file(&dir, file_name); - - let file_id = fm.add_file(file_name).unwrap(); + let lib_nr_path = create_dummy_file(&dir, Path::new("lib.nr")); + let file_id = fm + .add_file_with_source(lib_nr_path.as_path(), "fn foo() {}".to_string()) + .expect("could not add file to file manager and obtain a FileId"); // Create a sub directory // we now have: @@ -277,14 +288,16 @@ mod tests { // we no have: // - dir/lib.nr // - dir/sub_dir/foo.nr - create_dummy_file(&sub_dir, Path::new("foo.nr")); + let foo_nr_path = create_dummy_file(&sub_dir, Path::new("foo.nr")); + fm.add_file_with_source(foo_nr_path.as_path(), "fn foo() {}".to_string()); // Add a parent module for the sub_dir // we no have: // - dir/lib.nr // - dir/sub_dir.nr // - dir/sub_dir/foo.nr - create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); + let sub_dir_nr_path = create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); + fm.add_file_with_source(sub_dir_nr_path.as_path(), "fn foo() {}".to_string()); // First check for the sub_dir.nr file and add it to the FileManager let sub_dir_file_id = fm.find_module(file_id, sub_dir_name).unwrap(); @@ -303,7 +316,7 @@ mod tests { let sub_dir = TempDir::new_in(&dir).unwrap(); let sub_sub_dir = TempDir::new_in(&sub_dir).unwrap(); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); // Create a lib.nr file at the root. let file_name = Path::new("lib.nr"); @@ -313,8 +326,9 @@ mod tests { let second_file_name = PathBuf::from(sub_sub_dir.path()).join("./../../lib.nr"); // Add both files to the file manager - let file_id = fm.add_file(file_name).unwrap(); - let second_file_id = fm.add_file(&second_file_name).unwrap(); + let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); + let second_file_id = + fm.add_file_with_source(&second_file_name, "fn foo() {}".to_string()).unwrap(); assert_eq!(file_id, second_file_id); } diff --git a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts index 2aef56c23f9..29e2fbc55b8 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -1,17 +1,17 @@ import { expect } from '@esm-bundle/chai'; -import { Logger } from 'tslog'; import * as TOML from 'smol-toml'; -import { initializeResolver } from '@noir-lang/source-resolver'; -import newCompiler, { CompiledProgram, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { + CompiledProgram, + PathToFileSourceMap, + compile, + init_log_level as compilerLogLevel, +} from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; import { InputMap } from '@noir-lang/noirc_abi'; import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; import { getFile } from './utils.js'; -import { TEST_LOG_LEVEL } from '../environment.js'; - -const logger = new Logger({ name: 'test', minLevel: TEST_LOG_LEVEL }); await newCompiler(); @@ -33,14 +33,11 @@ const suite = Mocha.Suite.create(mocha.suite, 'Noir end to end test'); suite.timeout(60 * 20e3); //20mins function getCircuit(noirSource: string): CompiledProgram { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - initializeResolver((id: string) => { - logger.debug('source-resolver: resolving:', id); - return noirSource; - }); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', noirSource); // We're ignoring this in the resolver but pass in something sensible. - const result = compile('/main.nr'); + const result = compile('main.nr', undefined, undefined, sourceMap); if (!('program' in result)) { throw new Error('Compilation failed'); } diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index 308be81417f..faa317b2c3c 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -2,8 +2,12 @@ import { expect } from '@esm-bundle/chai'; import { TEST_LOG_LEVEL } from '../environment.js'; import { Logger } from 'tslog'; -import { initializeResolver } from '@noir-lang/source-resolver'; -import newCompiler, { CompiledProgram, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { + CompiledProgram, + PathToFileSourceMap, + compile, + init_log_level as compilerLogLevel, +} from '@noir-lang/noir_wasm'; import { acvm, abi, Noir } from '@noir-lang/noir_js'; import * as TOML from 'smol-toml'; @@ -27,14 +31,9 @@ const circuit_main = 'test_programs/execution_success/assert_statement'; const circuit_recursion = 'compiler/integration-tests/circuits/recursion'; function getCircuit(noirSource: string): CompiledProgram { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - initializeResolver((id: string) => { - logger.debug('source-resolver: resolving:', id); - return noirSource; - }); - - // We're ignoring this in the resolver but pass in something sensible. - const result = compile('/main.nr'); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', noirSource); + const result = compile('main.nr', undefined, undefined, sourceMap); if (!('program' in result)) { throw new Error('Compilation failed'); } diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index 353678b470b..6c20d44882b 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -5,7 +5,12 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'path'; import toml from 'toml'; -import { compile, CompiledProgram, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import { + compile, + CompiledProgram, + init_log_level as compilerLogLevel, + PathToFileSourceMap, +} from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg'; import { Field, InputMap } from '@noir-lang/noirc_abi'; @@ -13,16 +18,24 @@ import { Field, InputMap } from '@noir-lang/noirc_abi'; compilerLogLevel('INFO'); it(`smart contract can verify a recursive proof`, async () => { - const inner_source_path = resolve(`../../test_programs/execution_success/assert_statement/src/main.nr`); - const inner_program = (compile(inner_source_path) as { program: CompiledProgram }).program; - - const recursion_source_path = resolve(`./circuits/recursion/src/main.nr`); - const recursion_program = (compile(recursion_source_path) as { program: CompiledProgram }).program; + const innerSourcePath = resolve(`../../test_programs/execution_success/assert_statement/src/main.nr`); + const sourceMapInnerProgram = new PathToFileSourceMap(); + sourceMapInnerProgram.add_source_code(innerSourcePath, readFileSync(innerSourcePath, 'utf-8')); + const innerProgram = ( + compile(innerSourcePath, undefined, undefined, sourceMapInnerProgram) as { program: CompiledProgram } + ).program; + + const recursionSourcePath = resolve(`./circuits/recursion/src/main.nr`); + const sourceMapRecursionProgram = new PathToFileSourceMap(); + sourceMapRecursionProgram.add_source_code(recursionSourcePath, readFileSync(recursionSourcePath, 'utf-8')); + const recursionProgram = ( + compile(recursionSourcePath, undefined, undefined, sourceMapRecursionProgram) as { program: CompiledProgram } + ).program; // Intermediate proof - const inner_backend = new BarretenbergBackend(inner_program); - const inner = new Noir(inner_program); + const inner_backend = new BarretenbergBackend(innerProgram); + const inner = new Noir(innerProgram); const inner_prover_toml = readFileSync( resolve(`../../test_programs/execution_success/assert_statement/Prover.toml`), @@ -41,8 +54,8 @@ it(`smart contract can verify a recursive proof`, async () => { // Final proof - const recursion_backend = new BarretenbergBackend(recursion_program); - const recursion = new Noir(recursion_program, recursion_backend); + const recursion_backend = new BarretenbergBackend(recursionProgram); + const recursion = new Noir(recursionProgram, recursion_backend); const recursion_inputs: InputMap = { verification_key: vkAsFields, diff --git a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index 7dafada0ffb..5b3d0e2d337 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -5,7 +5,7 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'path'; import toml from 'toml'; -import { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import { PathToFileSourceMap, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg'; @@ -31,9 +31,11 @@ test_cases.forEach((testInfo) => { const base_relative_path = '../..'; const test_case = testInfo.case; - const noir_source_path = resolve(`${base_relative_path}/${test_case}/src/main.nr`); + const noirSourcePath = resolve(`${base_relative_path}/${test_case}/src/main.nr`); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code(noirSourcePath, readFileSync(noirSourcePath, 'utf-8')); - const compileResult = compile(noir_source_path); + const compileResult = compile(noirSourcePath, undefined, undefined, sourceMap); if (!('program' in compileResult)) { throw new Error('Compilation failed'); } diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index 8759e3f65e8..e5a837e6822 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -21,5 +21,6 @@ iter-extended.workspace = true fm.workspace = true serde.workspace = true fxhash.workspace = true +rust-embed = "6.6.0" aztec_macros = { path = "../../aztec_macros" } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index be139846cd7..c326d04c84d 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -23,6 +23,7 @@ mod abi_gen; mod contract; mod debug; mod program; +mod stdlib; use debug::filter_relevant_files; @@ -82,11 +83,23 @@ pub type CompilationResult = Result<(T, Warnings), ErrorsAndWarnings>; /// Adds the file from the file system at `Path` to the crate graph as a root file pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { + // Add the stdlib contents to the file manager, since every package automatically has a dependency + // on the stdlib. For other dependencies, we read the package.Dependencies file to add their file + // contents to the file manager. However since the dependency on the stdlib is implicit, we need + // to manually add it here. + let stdlib_paths_with_source = stdlib::stdlib_paths_with_source(); + for (path, source) in stdlib_paths_with_source { + context.file_manager.add_file_with_source_canonical_path(Path::new(&path), source); + } + let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr"); - let std_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap(); + let std_file_id = context + .file_manager + .name_to_id(path_to_std_lib_file) + .expect("stdlib file id is expected to be present"); let std_crate_id = context.crate_graph.add_stdlib(std_file_id); - let root_file_id = context.file_manager.add_file(file_name).unwrap(); + let root_file_id = context.file_manager.name_to_id(file_name.to_path_buf()).unwrap_or_else(|| panic!("files are expected to be added to the FileManager before reaching the compiler file_path: {file_name:?}")); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); @@ -97,7 +110,10 @@ pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { // Adds the file from the file system at `Path` to the crate graph pub fn prepare_dependency(context: &mut Context, file_name: &Path) -> CrateId { - let root_file_id = context.file_manager.add_file(file_name).unwrap(); + let root_file_id = context + .file_manager + .name_to_id(file_name.to_path_buf()) + .unwrap_or_else(|| panic!("files are expected to be added to the FileManager before reaching the compiler file_path: {file_name:?}")); let crate_id = context.crate_graph.add_crate(root_file_id); diff --git a/compiler/noirc_driver/src/stdlib.rs b/compiler/noirc_driver/src/stdlib.rs new file mode 100644 index 00000000000..5a91e3f45b5 --- /dev/null +++ b/compiler/noirc_driver/src/stdlib.rs @@ -0,0 +1,24 @@ +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "../../noir_stdlib/src"] +#[cfg_attr(not(target_os = "windows"), prefix = "std/")] +#[cfg_attr(target_os = "windows", prefix = r"std\")] // Note reversed slash direction +struct StdLibAssets; + +// Returns a vector of tuples containing the path to a stdlib file in the std lib crate +// along with the source code of that file. +// +// This is needed because when we preload the file manager, it needs to know where +// the source code for the stdlib is. The stdlib is treated special because it comes with +// the compiler and is never included as a dependency like other user defined crates. +pub(crate) fn stdlib_paths_with_source() -> Vec<(String, String)> { + StdLibAssets::iter() + .map(|path| { + let source = std::str::from_utf8(StdLibAssets::get(&path).unwrap().data.as_ref()) + .unwrap() + .to_string(); + (path.to_string(), source) + }) + .collect() +} diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 7b2a94b4f10..3f4755aa0ef 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -52,8 +52,7 @@ mod test { src: &str, ) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { let root = std::path::Path::new("/"); - let fm = FileManager::new(root, Box::new(|path| std::fs::read_to_string(path))); - //let fm = FileManager::new(root, Box::new(get_non_stdlib_asset)); + let fm = FileManager::new(root); let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); let root_file_id = FileId::dummy(); diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index 8e693182db9..58ad7764fdc 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -21,7 +21,6 @@ noirc_errors.workspace = true wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true -cfg-if.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true log.workspace = true diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index e7fd3dd5212..13b366819b0 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -126,6 +126,31 @@ struct DependencyGraph { library_dependencies: HashMap>, } +#[wasm_bindgen] +// This is a map containing the paths of all of the files in the entry-point crate and +// the transitive dependencies of the entry-point crate. +// +// This is for all intents and purposes the file system that the compiler will use to resolve/compile +// files in the crate being compiled and its dependencies. +#[derive(Deserialize, Default)] +pub struct PathToFileSourceMap(HashMap); + +#[wasm_bindgen] +impl PathToFileSourceMap { + #[wasm_bindgen(constructor)] + pub fn new() -> PathToFileSourceMap { + PathToFileSourceMap::default() + } + // Inserts a path and its source code into the map. + // + // Returns true, if there was already source code in the map for the given path + pub fn add_source_code(&mut self, path: String, source_code: String) -> bool { + let path_buf = Path::new(&path).to_path_buf(); + let old_value = self.0.insert(path_buf, source_code); + old_value.is_some() + } +} + pub enum CompileResult { Contract { contract: PreprocessedContract, debug: DebugArtifact }, Program { program: PreprocessedProgram, debug: DebugArtifact }, @@ -136,6 +161,7 @@ pub fn compile( entry_point: String, contracts: Option, dependency_graph: Option, + file_source_map: PathToFileSourceMap, ) -> Result { console_error_panic_hook::set_once(); @@ -146,8 +172,8 @@ pub fn compile( DependencyGraph { root_dependencies: vec![], library_dependencies: HashMap::new() } }; - let root = Path::new("/"); - let fm = FileManager::new(root, Box::new(get_non_stdlib_asset)); + let fm = file_manager_with_source_map(file_source_map); + let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); @@ -200,6 +226,31 @@ pub fn compile( } } +// Create a new FileManager with the given source map +// +// Note: Use this method whenever initializing a new FileManager +// to ensure that the file manager contains all of the files +// that one intends the compiler to use. +// +// For all intents and purposes, the file manager being returned +// should be considered as immutable. +fn file_manager_with_source_map(source_map: PathToFileSourceMap) -> FileManager { + let root = Path::new(""); + let mut fm = FileManager::new(root); + + for (path, source) in source_map.0 { + fm.add_file_with_source(path.as_path(), source); + } + + fm +} + +// Root dependencies are dependencies which the entry-point package relies upon. +// These will be in the Nargo.toml of the package being compiled. +// +// Library dependencies are transitive dependencies; for example, if the entry-point relies +// upon some library `lib1`. Then the packages that `lib1` depend upon will be placed in the +// `library_dependencies` list and the `lib1` will be placed in the `root_dependencies` list. fn process_dependency_graph(context: &mut Context, dependency_graph: DependencyGraph) { let mut crate_names: HashMap<&CrateName, CrateId> = HashMap::new(); @@ -279,51 +330,26 @@ fn preprocess_contract(contract: CompiledContract) -> CompileResult { CompileResult::Contract { contract: preprocessed_contract, debug: debug_artifact } } -cfg_if::cfg_if! { - if #[cfg(target_os = "wasi")] { - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - std::fs::read_to_string(path_to_file) - } - } else { - use std::io::{Error, ErrorKind}; - - #[wasm_bindgen(module = "@noir-lang/source-resolver")] - extern "C" { - #[wasm_bindgen(catch)] - fn read_file(path: &str) -> Result; - } - - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - let path_str = path_to_file.to_str().unwrap(); - match read_file(path_str) { - Ok(buffer) => Ok(buffer), - Err(_) => Err(Error::new(ErrorKind::Other, "could not read file using wasm")), - } - } - } -} - #[cfg(test)] mod test { - use fm::FileManager; use noirc_driver::prepare_crate; use noirc_frontend::{ graph::{CrateGraph, CrateName}, hir::Context, }; - use super::{process_dependency_graph, DependencyGraph}; + use crate::compile::PathToFileSourceMap; + + use super::{file_manager_with_source_map, process_dependency_graph, DependencyGraph}; use std::{collections::HashMap, path::Path}; - fn mock_get_non_stdlib_asset(_path_to_file: &Path) -> std::io::Result { - Ok("".to_string()) - } + fn setup_test_context(source_map: PathToFileSourceMap) -> Context { + let mut fm = file_manager_with_source_map(source_map); + // Add this due to us calling prepare_crate on "/main.nr" below + fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); - fn setup_test_context() -> Context { - let fm = FileManager::new(Path::new("/"), Box::new(mock_get_non_stdlib_asset)); let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); - prepare_crate(&mut context, Path::new("/main.nr")); context @@ -335,10 +361,12 @@ mod test { #[test] fn test_works_with_empty_dependency_graph() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![], library_dependencies: HashMap::new() }; + let source_map = PathToFileSourceMap::default(); + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); // one stdlib + one root crate @@ -347,12 +375,19 @@ mod test { #[test] fn test_works_with_root_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::new(), }; + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 3); @@ -360,12 +395,18 @@ mod test { #[test] fn test_works_with_duplicate_root_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1"), crate_name("lib1")], library_dependencies: HashMap::new(), }; + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 3); @@ -373,7 +414,6 @@ mod test { #[test] fn test_works_with_transitive_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::from([ @@ -382,6 +422,17 @@ mod test { ]), }; + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 5); @@ -389,12 +440,22 @@ mod test { #[test] fn test_works_with_missing_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::from([(crate_name("lib2"), vec![crate_name("lib3")])]), }; + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 5); diff --git a/compiler/wasm/test/browser/index.test.ts b/compiler/wasm/test/browser/index.test.ts index 8a3f82ffff9..346c20c834c 100644 --- a/compiler/wasm/test/browser/index.test.ts +++ b/compiler/wasm/test/browser/index.test.ts @@ -1,6 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import initNoirWasm, { compile } from '@noir-lang/noir_wasm'; -import { initializeResolver } from '@noir-lang/source-resolver'; +import initNoirWasm, { PathToFileSourceMap, compile } from '@noir-lang/noir_wasm'; import { depsScriptExpectedArtifact, depsScriptSourcePath, @@ -28,23 +27,11 @@ async function getPrecompiledSource(path: string): Promise { describe('noir wasm', () => { describe('can compile script without dependencies', () => { - beforeEach(async () => { - const source = await getFileContent(simpleScriptSourcePath); - initializeResolver((id: string) => { - console.log(`Resolving source ${id}`); - - if (typeof source === 'undefined') { - throw Error(`Could not resolve source for '${id}'`); - } else if (id !== '/main.nr') { - throw Error(`Unexpected id: '${id}'`); - } else { - return source; - } - }); - }); - it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/main.nr'); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', await getFileContent(simpleScriptSourcePath)); + + const wasmCircuit = await compile('main.nr', undefined, undefined, sourceMap); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); if (!('program' in wasmCircuit)) { @@ -59,37 +46,29 @@ describe('noir wasm', () => { }); describe('can compile script with dependencies', () => { - beforeEach(async () => { + it('matching nargos compilation', async () => { const [scriptSource, libASource, libBSource] = await Promise.all([ getFileContent(depsScriptSourcePath), getFileContent(libASourcePath), getFileContent(libBSourcePath), ]); - initializeResolver((file: string) => { - switch (file) { - case '/script/main.nr': - return scriptSource; - - case '/lib_a/lib.nr': - return libASource; - - case '/lib_b/lib.nr': - return libBSource; - - default: - return ''; - } - }); - }); - - it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/script/main.nr', false, { - root_dependencies: ['lib_a'], - library_dependencies: { - lib_a: ['lib_b'], + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('script/main.nr', scriptSource); + sourceMap.add_source_code('lib_a/lib.nr', libASource); + sourceMap.add_source_code('lib_b/lib.nr', libBSource); + + const wasmCircuit = await compile( + 'script/main.nr', + false, + { + root_dependencies: ['lib_a'], + library_dependencies: { + lib_a: ['lib_b'], + }, }, - }); + sourceMap, + ); if (!('program' in wasmCircuit)) { throw Error('Expected program to be present'); diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index c0d5f88e407..5cf9e3be2df 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -9,8 +9,7 @@ import { } from '../shared'; import { readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; -import { compile } from '@noir-lang/noir_wasm'; -import { initializeResolver } from '@noir-lang/source-resolver'; +import { compile, PathToFileSourceMap } from '@noir-lang/noir_wasm'; // eslint-disable-next-line @typescript-eslint/no-explicit-any async function getPrecompiledSource(path: string): Promise { @@ -21,7 +20,12 @@ async function getPrecompiledSource(path: string): Promise { describe('noir wasm compilation', () => { describe('can compile simple scripts', () => { it('matching nargos compilation', async () => { - const wasmCircuit = await compile(join(__dirname, simpleScriptSourcePath)); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code( + join(__dirname, simpleScriptSourcePath), + readFileSync(join(__dirname, simpleScriptSourcePath), 'utf-8'), + ); + const wasmCircuit = await compile(join(__dirname, simpleScriptSourcePath), undefined, undefined, sourceMap); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); if (!('program' in wasmCircuit)) { @@ -36,32 +40,25 @@ describe('noir wasm compilation', () => { }); describe('can compile scripts with dependencies', () => { + const sourceMap: PathToFileSourceMap = new PathToFileSourceMap(); beforeEach(() => { - // this test requires a custom resolver in order to correctly resolve dependencies - initializeResolver((file) => { - switch (file) { - case '/script/main.nr': - return readFileSync(join(__dirname, depsScriptSourcePath), 'utf-8'); - - case '/lib_a/lib.nr': - return readFileSync(join(__dirname, libASourcePath), 'utf-8'); - - case '/lib_b/lib.nr': - return readFileSync(join(__dirname, libBSourcePath), 'utf-8'); - - default: - return ''; - } - }); + sourceMap.add_source_code('script/main.nr', readFileSync(join(__dirname, depsScriptSourcePath), 'utf-8')); + sourceMap.add_source_code('lib_a/lib.nr', readFileSync(join(__dirname, libASourcePath), 'utf-8')); + sourceMap.add_source_code('lib_b/lib.nr', readFileSync(join(__dirname, libBSourcePath), 'utf-8')); }); it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/script/main.nr', false, { - root_dependencies: ['lib_a'], - library_dependencies: { - lib_a: ['lib_b'], + const wasmCircuit = await compile( + 'script/main.nr', + false, + { + root_dependencies: ['lib_a'], + library_dependencies: { + lib_a: ['lib_b'], + }, }, - }); + sourceMap, + ); const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 02d6d10ffa8..5f5e701da67 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -21,7 +21,6 @@ noirc_frontend.workspace = true serde.workspace = true serde_json.workspace = true tower.workspace = true -cfg-if.workspace = true async-lsp = { workspace = true, features = ["omni-trait"] } serde_with = "3.2.0" fm.workspace = true diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index eecd0bda45b..2ad8096a13f 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -7,7 +7,7 @@ use std::{ collections::HashMap, future::Future, ops::{self, ControlFlow}, - path::{Path, PathBuf}, + path::PathBuf, pin::Pin, task::{self, Poll}, }; @@ -175,29 +175,3 @@ fn byte_span_to_range<'a, F: files::Files<'a> + ?Sized>( None } } - -cfg_if::cfg_if! { - if #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))] { - use wasm_bindgen::{prelude::*, JsValue}; - - #[wasm_bindgen(module = "@noir-lang/source-resolver")] - extern "C" { - - #[wasm_bindgen(catch)] - fn read_file(path: &str) -> Result; - - } - - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - let path_str = path_to_file.to_str().unwrap(); - match read_file(path_str) { - Ok(buffer) => Ok(buffer), - Err(_) => Err(Error::new(ErrorKind::Other, "could not read file using wasm")), - } - } - } else { - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - std::fs::read_to_string(path_to_file) - } - } -} diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 876ff157c07..61f0d231738 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -13,7 +13,7 @@ use crate::types::{ PublishDiagnosticsParams, }; -use crate::{byte_span_to_range, get_non_stdlib_asset, get_package_tests_in_crate, LspState}; +use crate::{byte_span_to_range, get_package_tests_in_crate, LspState}; pub(super) fn on_initialized( _state: &mut LspState, @@ -103,7 +103,7 @@ pub(super) fn on_did_save_text_document( let diagnostics: Vec<_> = workspace .into_iter() .flat_map(|package| -> Vec { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); + let (mut context, crate_id) = prepare_package(package); let file_diagnostics = match check_crate(&mut context, crate_id, false, false) { Ok(((), warnings)) => warnings, diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 4b5ccddc613..558851d4ecf 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -52,8 +52,7 @@ fn on_goto_definition_inner( let mut definition_position = None; for package in &workspace { - let (mut context, crate_id) = - nargo::prepare_package(package, Box::new(crate::get_non_stdlib_asset)); + let (mut context, crate_id) = nargo::prepare_package(package); // We ignore the warnings and errors produced by compilation while resolving the definition let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 293b101eb85..e5245de426f 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -10,7 +10,6 @@ use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::hir::FunctionNameMatch; use crate::{ - get_non_stdlib_asset, types::{NargoTestRunParams, NargoTestRunResult}, LspState, }; @@ -51,7 +50,7 @@ fn on_test_run_request_inner( // Since we filtered on crate name, this should be the only item in the iterator match workspace.into_iter().next() { Some(package) => { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); + let (mut context, crate_id) = prepare_package(package); if check_crate(&mut context, crate_id, false, false).is_err() { let result = NargoTestRunResult { id: params.id.clone(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index bed29ebe4e6..9a67eaae6db 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -7,7 +7,7 @@ use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSele use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use crate::{ - get_non_stdlib_asset, get_package_tests_in_crate, + get_package_tests_in_crate, types::{NargoPackageTests, NargoTestsParams, NargoTestsResult}, LspState, }; @@ -53,7 +53,7 @@ fn on_tests_request_inner( let package_tests: Vec<_> = workspace .into_iter() .filter_map(|package| { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); + let (mut context, crate_id) = prepare_package(package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails let _ = check_crate(&mut context, crate_id, false, false); diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index f8269459968..48741c367a5 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -24,4 +24,9 @@ iter-extended.workspace = true serde.workspace = true thiserror.workspace = true codespan-reporting.workspace = true -rayon = "1.8.0" \ No newline at end of file +rayon = "1.8.0" + +[dev-dependencies] +# TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` +# TODO: once that method is moved to nargo_cli, we can move this dependency to nargo_cli +tempfile = "3.2.0" \ No newline at end of file diff --git a/tooling/nargo/src/lib.rs b/tooling/nargo/src/lib.rs index ef014fb436b..6f3d36febba 100644 --- a/tooling/nargo/src/lib.rs +++ b/tooling/nargo/src/lib.rs @@ -16,7 +16,7 @@ pub mod workspace; use std::collections::BTreeMap; -use fm::{FileManager, FileReader}; +use fm::FileManager; use noirc_driver::{add_dep, prepare_crate, prepare_dependency}; use noirc_frontend::{ graph::{CrateGraph, CrateId, CrateName}, @@ -42,9 +42,55 @@ pub fn prepare_dependencies( } } -pub fn prepare_package(package: &Package, file_reader: Box) -> (Context, CrateId) { - // TODO: FileManager continues to leak into various crates - let fm = FileManager::new(&package.root_dir, file_reader); +// We will pre-populate the file manager with all the files in the package +// This is so that we can avoid having to read from disk when we are compiling +// +// This does not require parsing because we are interested in the files under the src directory +// it may turn out that we do not need to include some Noir files that we add to the file +// manager +pub fn insert_all_files_for_package_into_file_manager( + package: &Package, + file_manager: &mut FileManager, +) { + // Start off at the entry path and read all files in the parent directory. + let entry_path_parent = package + .entry_path + .parent() + .unwrap_or_else(|| panic!("The entry path is expected to be a single file within a directory and so should have a parent {:?}", package.entry_path)) + .clone(); + + // Get all files in the package and add them to the file manager + let paths = + get_all_paths_in_dir(entry_path_parent).expect("could not get all paths in the package"); + for path in paths { + let source = std::fs::read_to_string(path.as_path()) + .unwrap_or_else(|_| panic!("could not read file {:?} into string", path)); + file_manager.add_file_with_source(path.as_path(), source); + } + + insert_all_files_for_packages_dependencies_into_file_manager(package, file_manager); +} + +// Inserts all files for the dependencies of the package into the file manager +// too +fn insert_all_files_for_packages_dependencies_into_file_manager( + package: &Package, + file_manager: &mut FileManager, +) { + for (_, dep) in package.dependencies.iter() { + match dep { + Dependency::Local { package } | Dependency::Remote { package } => { + insert_all_files_for_package_into_file_manager(package, file_manager); + insert_all_files_for_packages_dependencies_into_file_manager(package, file_manager); + } + } + } +} + +pub fn prepare_package(package: &Package) -> (Context, CrateId) { + let mut fm = FileManager::new(&package.root_dir); + insert_all_files_for_package_into_file_manager(package, &mut fm); + let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); @@ -54,3 +100,72 @@ pub fn prepare_package(package: &Package, file_reader: Box) -> (Cont (context, crate_id) } + +// Get all paths in the directory and subdirectories. +// +// Panics: If the path is not a path to a directory. +// +// TODO: Along with prepare_package, this function is an abstraction leak +// TODO: given that this crate should not know about the file manager. +// TODO: We can clean this up in a future refactor +fn get_all_paths_in_dir(dir: &std::path::Path) -> std::io::Result> { + assert!(dir.is_dir(), "directory {dir:?} is not a path to a directory"); + + let mut paths = Vec::new(); + + if dir.is_dir() { + for entry in std::fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + let mut sub_paths = get_all_paths_in_dir(&path)?; + paths.append(&mut sub_paths); + } else { + paths.push(path); + } + } + } + + Ok(paths) +} + +#[cfg(test)] +mod tests { + use crate::get_all_paths_in_dir; + use std::{ + fs::{self, File}, + path::Path, + }; + use tempfile::tempdir; + + fn create_test_dir_structure(temp_dir: &Path) -> std::io::Result<()> { + fs::create_dir(temp_dir.join("subdir1"))?; + File::create(temp_dir.join("subdir1/file1.txt"))?; + fs::create_dir(temp_dir.join("subdir2"))?; + File::create(temp_dir.join("subdir2/file2.txt"))?; + File::create(temp_dir.join("file3.txt"))?; + Ok(()) + } + + #[test] + fn test_get_all_paths_in_dir() { + let temp_dir = tempdir().expect("could not create a temporary directory"); + create_test_dir_structure(temp_dir.path()) + .expect("could not create test directory structure"); + + let paths = get_all_paths_in_dir(temp_dir.path()) + .expect("could not get all paths in the test directory"); + + // This should be the paths to all of the files in the directory and the subdirectory + let expected_paths = vec![ + temp_dir.path().join("file3.txt"), + temp_dir.path().join("subdir1/file1.txt"), + temp_dir.path().join("subdir2/file2.txt"), + ]; + + assert_eq!(paths.len(), expected_paths.len()); + for path in expected_paths { + assert!(paths.contains(&path)); + } + } +} diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index 02159345086..59ac5672a11 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -70,8 +70,7 @@ pub fn compile_program( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -98,8 +97,7 @@ fn compile_contract( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 20e51fe1b52..0ea8186a237 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -55,8 +55,7 @@ pub(crate) fn run( } fn check_package(package: &Package, compile_options: &CompileOptions) -> Result<(), CompileError> { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); check_crate_and_report_errors( &mut context, crate_id, diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 3e4f868aecf..043c0841958 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -175,8 +175,7 @@ fn compile_program( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -228,8 +227,7 @@ fn compile_contract( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index ec3d373a483..0c2ca71eba3 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -2,6 +2,7 @@ use std::{fs::DirEntry, path::Path}; use clap::Args; use fm::FileManager; +use nargo::insert_all_files_for_package_into_file_manager; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_errors::CustomDiagnostic; @@ -35,11 +36,11 @@ pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliErr let mut check_exit_code_one = false; for package in &workspace { - let mut file_manager = - FileManager::new(&package.root_dir, Box::new(|path| std::fs::read_to_string(path))); + let mut file_manager = FileManager::new(&package.root_dir); + insert_all_files_for_package_into_file_manager(package, &mut file_manager); visit_noir_files(&package.root_dir.join("src"), &mut |entry| { - let file_id = file_manager.add_file(&entry.path()).expect("file exists"); + let file_id = file_manager.name_to_id(entry.path().to_path_buf()).expect("The file should exist since we added all files in the package into the file manager"); let (parsed_module, errors) = parse_file(&file_manager, file_id); let is_all_warnings = errors.iter().all(ParserError::is_warning); diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 7f7ae67d946..43cfecd17e9 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -86,8 +86,7 @@ fn run_tests( show_output: bool, compile_options: &CompileOptions, ) -> Result<(), CliError> { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); check_crate_and_report_errors( &mut context, crate_id, From 57d2505d53e2233becd1e2a7de882c4acb518eff Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:28:48 +0000 Subject: [PATCH 041/137] chore!: remove unused `source-resolver` package (#3791) # Description ## Problem\* Resolves https://github.com/noir-lang/noir/pull/3760#discussion_r1422901174 ## Summary\* This PR removes the source-resolver package now that it's no longer used. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .dockerignore | 6 +- .github/workflows/test-js-packages.yml | 26 +- .gitignore | 5 - Dockerfile.ci | 3 +- compiler/integration-tests/package.json | 1 - compiler/source-resolver/.eslintignore | 1 - compiler/source-resolver/.eslintrc.js | 3 - compiler/source-resolver/package.json | 43 -- compiler/source-resolver/src/index.ts | 31 - compiler/source-resolver/src/index_node.ts | 17 - .../test/cjs_initialization.test.cjs | 51 -- .../test/esm_initialization.test.mjs | 58 -- compiler/source-resolver/tsconfig.cjs.json | 16 - compiler/source-resolver/tsconfig.esm.json | 16 - compiler/source-resolver/types/index.d.ts | 2 - .../source-resolver/types/index_node.d.ts | 2 - compiler/wasm/package.json | 3 - package.json | 4 +- release-please-config.json | 5 - scripts/bootstrap_packages.sh | 3 +- yarn.lock | 561 +----------------- 21 files changed, 24 insertions(+), 833 deletions(-) delete mode 100644 compiler/source-resolver/.eslintignore delete mode 100644 compiler/source-resolver/.eslintrc.js delete mode 100644 compiler/source-resolver/package.json delete mode 100644 compiler/source-resolver/src/index.ts delete mode 100644 compiler/source-resolver/src/index_node.ts delete mode 100644 compiler/source-resolver/test/cjs_initialization.test.cjs delete mode 100644 compiler/source-resolver/test/esm_initialization.test.mjs delete mode 100644 compiler/source-resolver/tsconfig.cjs.json delete mode 100644 compiler/source-resolver/tsconfig.esm.json delete mode 100644 compiler/source-resolver/types/index.d.ts delete mode 100644 compiler/source-resolver/types/index_node.d.ts diff --git a/.dockerignore b/.dockerignore index 25dd24f015c..8bea0aeeb1a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,10 +7,6 @@ packages **/node_modules **/outputs -# Source resolver -compiler/source-resolver/lib -compiler/source-resolver/lib-node - # Noir.js tooling/noir_js/lib @@ -19,4 +15,4 @@ compiler/wasm/nodejs compiler/wasm/web tooling/noirc_abi_wasm/nodejs tooling/noirc_abi_wasm/web -tooling/noir_js/lib \ No newline at end of file +tooling/noir_js/lib diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index 71d6c9a537f..c6762ce3a16 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -265,22 +265,7 @@ jobs: yarn workspace @noir-lang/noir_js build yarn workspace @noir-lang/noir_js test - test-source-resolver: - name: source-resolver - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Build @noir-lang/source-resolver - run: yarn workspace @noir-lang/source-resolver build - - - name: Run tests - run: yarn workspace @noir-lang/source-resolver test + test-noir-wasm: needs: [build-noir-wasm, build-nargo] @@ -319,10 +304,6 @@ jobs: - name: Install Playwright uses: ./.github/actions/install-playwright - - name: Install dependencies - run: | - yarn workspace @noir-lang/source-resolver build - - name: Run node tests run: yarn workspace @noir-lang/noir_wasm test:node @@ -411,8 +392,8 @@ jobs: - name: Setup `integration-tests` run: | # Note the lack of spaces between package names. - PACKAGES_TO_BUILD="@noir-lang/source-resolver,@noir-lang/types,@noir-lang/backend_barretenberg,@noir-lang/noir_js" - yarn workspaces foreach -vp --from "{$PACKAGES_TO_BUILD}" run build + PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/backend_barretenberg,@noir-lang/noir_js" + yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build - name: Run `integration-tests` run: | @@ -431,7 +412,6 @@ jobs: - test-noirc-abi - test-noir-js-backend-barretenberg - test-noir-js - - test-source-resolver - test-noir-wasm - test-noir-codegen - test-integration diff --git a/.gitignore b/.gitignore index 11f0ae3b975..8d02d34d463 100644 --- a/.gitignore +++ b/.gitignore @@ -14,11 +14,6 @@ pkg/ !.yarn/sdks !.yarn/versions -# Source resolver -compiler/source-resolver/node_modules -compiler/source-resolver/lib -compiler/source-resolver/lib-node - # Noir.js tooling/noir_js/lib diff --git a/Dockerfile.ci b/Dockerfile.ci index e85a743e550..9ca995fd94f 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -30,7 +30,6 @@ RUN yarn workspace @noir-lang/backend_barretenberg test RUN ./scripts/nargo_compile_noir_js_assert_lt.sh RUN rm -rf /usr/src/noir/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/debug_assert_lt.json RUN yarn workspace @noir-lang/noir_js test -RUN yarn workspace @noir-lang/source-resolver test RUN ./scripts/nargo_compile_wasm_fixtures.sh RUN yarn workspace @noir-lang/noir_wasm test:node RUN yarn workspace @noir-lang/noir_wasm test:browser @@ -38,4 +37,4 @@ RUN ./scripts/nargo_compile_noir_codegen_assert_lt.sh RUN rm -rf /usr/src/noir/tooling/noir_codegen/test/assert_lt/target/debug_assert_lt.json RUN yarn workspace @noir-lang/noir_codegen test RUN apt-get install -y libc++-dev -RUN yarn test:integration \ No newline at end of file +RUN yarn test:integration diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index 344d1361263..c4e424df480 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -16,7 +16,6 @@ "@noir-lang/backend_barretenberg": "workspace:*", "@noir-lang/noir_js": "workspace:*", "@noir-lang/noir_wasm": "workspace:*", - "@noir-lang/source-resolver": "workspace:*", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@web/dev-server-esbuild": "^0.3.6", diff --git a/compiler/source-resolver/.eslintignore b/compiler/source-resolver/.eslintignore deleted file mode 100644 index 3c3629e647f..00000000000 --- a/compiler/source-resolver/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/compiler/source-resolver/.eslintrc.js b/compiler/source-resolver/.eslintrc.js deleted file mode 100644 index 33335c2a877..00000000000 --- a/compiler/source-resolver/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["../../.eslintrc.js"], -}; diff --git a/compiler/source-resolver/package.json b/compiler/source-resolver/package.json deleted file mode 100644 index 3b20cc7d9b9..00000000000 --- a/compiler/source-resolver/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "@noir-lang/source-resolver", - "version": "0.20.0", - "license": "MIT", - "main": "./lib-node/index_node.js", - "types": "./types/index_node.d.ts", - "module": "./lib/index.js", - "browser": "./lib/index.js", - "exports": { - ".": { - "require": "./lib-node/index_node.js", - "import": "./lib/index.js" - } - }, - "repository": { - "type": "git", - "url": "https://github.com/noir-lang/noir.git" - }, - "scripts": { - "clean-modules": "rm -rf lib", - "build:node": "tsc -p tsconfig.cjs.json", - "build:web": "tsc -p tsconfig.esm.json", - "build": "npm run clean-modules && npm run build:node && npm run build:web && npm run generate-types", - "test": "ava", - "generate-types": "tsc src/*.ts --declaration --emitDeclarationOnly --outDir types", - "clean": "rm -rf ./lib ./lib-node", - "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", - "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", - "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" - }, - "devDependencies": { - "@types/node": "^20.5.7", - "ava": "^5.2.0", - "typescript": "4.9.4" - }, - "files": [ - "lib", - "lib-node", - "src", - "types", - "package.json" - ] -} diff --git a/compiler/source-resolver/src/index.ts b/compiler/source-resolver/src/index.ts deleted file mode 100644 index 3498c195fbd..00000000000 --- a/compiler/source-resolver/src/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -let resolveFunction: ((source_id: string) => string) | null = null; - -export const read_file = function (source_id: string): string { - if (resolveFunction) { - const result = resolveFunction(source_id); - - if (typeof result === 'string') { - return result; - } else { - throw new Error( - '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)'); - } -}; - -function initialize(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', - ); - } -} - -export function initializeResolver(resolver: (source_id: string) => string): void { - resolveFunction = initialize(resolver); -} diff --git a/compiler/source-resolver/src/index_node.ts b/compiler/source-resolver/src/index_node.ts deleted file mode 100644 index 14b7efd30c5..00000000000 --- a/compiler/source-resolver/src/index_node.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -import { initializeResolver, read_file } from './index.js'; - -initializeResolver((source_id: string) => { - let fileContent = ''; - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require('fs'); - fileContent = fs.readFileSync(source_id, { encoding: 'utf8' }) as string; - } catch (e) { - console.log(e); - } - return fileContent; -}); - -export { initializeResolver, read_file }; diff --git a/compiler/source-resolver/test/cjs_initialization.test.cjs b/compiler/source-resolver/test/cjs_initialization.test.cjs deleted file mode 100644 index 1dc7784fa40..00000000000 --- a/compiler/source-resolver/test/cjs_initialization.test.cjs +++ /dev/null @@ -1,51 +0,0 @@ -const test = require('ava'); - -const { initializeResolver, read_file } = require("../lib-node/index_node.js"); - -test('It reads file from file system within read_file using default implementation.', t => { - - const readResult = read_file("./package.json"); - - t.assert(readResult, "return from `read_file` should by truthy"); - -}); - -test('It calls function from initializer within read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return source; - }); - - const readResult = read_file(RESULT_RESPONSE); - - t.is(readResult, RESULT_RESPONSE); - -}); - -test('It communicates error when resolver returns non-String to read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return Promise.resolve(source); - }); - - const error = t.throws(() => { - read_file(RESULT_RESPONSE); - }, { instanceOf: Error }); - - t.is(error.message, 'Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?'); - -}); - -test('It communicates error when resolver is initialized to anything but a function.', t => { - - const error = t.throws(() => { - initializeResolver(null); - }, { instanceOf: Error }); - - t.is(error.message, 'Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter'); - -}); diff --git a/compiler/source-resolver/test/esm_initialization.test.mjs b/compiler/source-resolver/test/esm_initialization.test.mjs deleted file mode 100644 index 197b48e48d0..00000000000 --- a/compiler/source-resolver/test/esm_initialization.test.mjs +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Below tests are commented because they require - * "type": "module", in package.json - * Seems that both CJS and MJS modes are not going to work. -*/ -import test from 'ava'; - -import { initializeResolver, read_file } from "../lib-node/index.js"; - -test('It communicates error when read_file was called before initializeResolver.', t => { - - const error = t.throws(() => { - const readResult = read_file("./package.json"); - }, { instanceOf: Error }); - - t.is(error.message, 'Not yet initialized. Use initializeResolver(() => string)'); - -}); - -test('It calls function from initializer within read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return source; - }); - - const readResult = read_file(RESULT_RESPONSE); - - t.is(readResult, RESULT_RESPONSE); - -}); - -test('It communicates error when resolver returns non-String to read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return Promise.resolve(source); - }); - - const error = t.throws(() => { - read_file(RESULT_RESPONSE); - }, { instanceOf: Error }); - - t.is(error.message, 'Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?'); - -}); - -test('It communicates error when resolver is initialized to anything but a function.', t => { - - const error = t.throws(() => { - initializeResolver(null); - }, { instanceOf: Error }); - - t.is(error.message, 'Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter'); - -}); diff --git a/compiler/source-resolver/tsconfig.cjs.json b/compiler/source-resolver/tsconfig.cjs.json deleted file mode 100644 index 51863a34cec..00000000000 --- a/compiler/source-resolver/tsconfig.cjs.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "es2018", - "moduleResolution": "node", - "outDir": "lib-node", - "module": "commonjs", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": true, - "removeComments": false, - "preserveConstEnums": true, - "sourceMap": true, - "importHelpers": true - }, - "include": ["src"] -} diff --git a/compiler/source-resolver/tsconfig.esm.json b/compiler/source-resolver/tsconfig.esm.json deleted file mode 100644 index dcf4441c4ad..00000000000 --- a/compiler/source-resolver/tsconfig.esm.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "es2018", - "moduleResolution": "node", - "outDir": "lib", - "module": "ES6", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": true, - "removeComments": false, - "preserveConstEnums": true, - "sourceMap": true, - "importHelpers": true - }, - "include": ["src/index.ts"] -} diff --git a/compiler/source-resolver/types/index.d.ts b/compiler/source-resolver/types/index.d.ts deleted file mode 100644 index a17f7bc36bb..00000000000 --- a/compiler/source-resolver/types/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare const read_file: (source_id: string) => string; -export declare function initializeResolver(resolver: (source_id: string) => string): void; diff --git a/compiler/source-resolver/types/index_node.d.ts b/compiler/source-resolver/types/index_node.d.ts deleted file mode 100644 index 3a109e47e73..00000000000 --- a/compiler/source-resolver/types/index_node.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { initializeResolver, read_file } from './index.js'; -export { initializeResolver, read_file }; diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index f1496897baa..b57f700b661 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -30,9 +30,6 @@ "build:nix": "nix build -L .#noir_wasm", "install:from:nix": "yarn clean && yarn build:nix && cp -rL ./result/noir_wasm/nodejs ./ && cp -rL ./result/noir_wasm/web ./" }, - "peerDependencies": { - "@noir-lang/source-resolver": "workspace:*" - }, "devDependencies": { "@esm-bundle/chai": "^4.3.4-fix.0", "@web/dev-server-esbuild": "^0.3.6", diff --git a/package.json b/package.json index bced1fb21e8..20a5b87cfd8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "private": true, "workspaces": [ "compiler/wasm", - "compiler/source-resolver", "compiler/integration-tests", "tooling/noir_js_types", "tooling/noirc_abi_wasm", @@ -27,10 +26,9 @@ "install:noirc_abi_wasm": "yarn workspace @noir-lang/noirc_abi run install:from:nix", "install:from:nix": "yarn install:acvm_js && yarn install:noir_wasm && yarn install:noirc_abi_wasm", "build:types": "yarn workspace @noir-lang/types run build", - "build:source-resolver": "yarn workspace @noir-lang/source-resolver run build", "build:backend_barretenberg": "yarn workspace @noir-lang/backend_barretenberg run build", "build:noir_js": "yarn workspace @noir-lang/noir_js run build", - "build:js:only": "yarn build:types && yarn build:source-resolver && yarn build:backend_barretenberg && yarn build:noir_js", + "build:js:only": "yarn build:types && yarn build:backend_barretenberg && yarn build:noir_js", "prepare:publish": "yarn clean && yarn install:from:nix && yarn build:js:only", "nightly:version": "yarn workspaces foreach run nightly:version", "publish:all": "yarn install && yarn workspaces foreach run publish" diff --git a/release-please-config.json b/release-please-config.json index 1849199b620..562de471f0b 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -14,11 +14,6 @@ "extra-files": [ "Cargo.toml", "flake.nix", - { - "type": "json", - "path": "compiler/source-resolver/package.json", - "jsonpath": "$.version" - }, { "type": "json", "path": "compiler/wasm/package.json", diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh index 233aed7a039..2f293d93faf 100755 --- a/scripts/bootstrap_packages.sh +++ b/scripts/bootstrap_packages.sh @@ -23,10 +23,9 @@ 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/source-resolver/package.tgz -C packages && mv packages/package packages/source-resolver 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 \ No newline at end of file +tar zxfv tooling/noirc_abi_wasm/package.tgz -C packages && mv packages/package packages/noirc_abi diff --git a/yarn.lock b/yarn.lock index bdb9c205d7b..fab2866a228 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4052,8 +4052,6 @@ __metadata: "@web/test-runner": ^0.15.3 "@web/test-runner-playwright": ^0.10.0 mocha: ^10.2.0 - peerDependencies: - "@noir-lang/source-resolver": "workspace:*" languageName: unknown linkType: soft @@ -4100,16 +4098,6 @@ __metadata: languageName: node linkType: hard -"@noir-lang/source-resolver@workspace:*, @noir-lang/source-resolver@workspace:compiler/source-resolver": - version: 0.0.0-use.local - resolution: "@noir-lang/source-resolver@workspace:compiler/source-resolver" - dependencies: - "@types/node": ^20.5.7 - ava: ^5.2.0 - typescript: 4.9.4 - languageName: unknown - linkType: soft - "@noir-lang/types@npm:0.19.4, @noir-lang/types@npm:^0.19.2": version: 0.19.4 resolution: "@noir-lang/types@npm:0.19.4" @@ -5442,7 +5430,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.5.7, @types/node@npm:^20.6.2": +"@types/node@npm:*, @types/node@npm:^20.6.2": version: 20.10.4 resolution: "@types/node@npm:20.10.4" dependencies: @@ -6426,7 +6414,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.2.0": +"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1": version: 8.3.1 resolution: "acorn-walk@npm:8.3.1" checksum: 5c8926ddb5400bc825b6baca782931f9df4ace603ba1a517f5243290fd9cdb089d52877840687b5d5c939591ebc314e2e63721514feaa37c6829c828f2b940ce @@ -6498,16 +6486,6 @@ __metadata: languageName: node linkType: hard -"aggregate-error@npm:^4.0.0": - version: 4.0.1 - resolution: "aggregate-error@npm:4.0.1" - dependencies: - clean-stack: ^4.0.0 - indent-string: ^5.0.0 - checksum: bb3ffdfd13447800fff237c2cba752c59868ee669104bb995dfbbe0b8320e967d679e683dabb640feb32e4882d60258165cde0baafc4cd467cc7d275a13ad6b5 - languageName: node - linkType: hard - "ajv-formats@npm:^2.1.1": version: 2.1.1 resolution: "ajv-formats@npm:2.1.1" @@ -6691,7 +6669,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": +"ansi-styles@npm:^6.1.0": version: 6.2.1 resolution: "ansi-styles@npm:6.2.1" checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 @@ -6766,13 +6744,6 @@ __metadata: languageName: node linkType: hard -"array-find-index@npm:^1.0.1": - version: 1.0.2 - resolution: "array-find-index@npm:1.0.2" - checksum: aac128bf369e1ac6c06ff0bb330788371c0e256f71279fb92d745e26fb4b9db8920e485b4ec25e841c93146bf71a34dcdbcefa115e7e0f96927a214d237b7081 - languageName: node - linkType: hard - "array-flatten@npm:1.1.1": version: 1.1.1 resolution: "array-flatten@npm:1.1.1" @@ -6794,20 +6765,6 @@ __metadata: languageName: node linkType: hard -"arrgv@npm:^1.0.2": - version: 1.0.2 - resolution: "arrgv@npm:1.0.2" - checksum: 470bbb406ea3b34810dd8b03c0b33282617a42d9fce0ab45d58596efefd042fc548eda49161fa8e3f607cbe9df90e7a67003a09043ab9081eff70f97c63dd0e2 - languageName: node - linkType: hard - -"arrify@npm:^3.0.0": - version: 3.0.0 - resolution: "arrify@npm:3.0.0" - checksum: d6c6f3dad9571234f320e130d57fddb2cc283c87f2ac7df6c7005dffc5161b7bb9376f4be655ed257050330336e84afc4f3020d77696ad231ff580a94ae5aba6 - languageName: node - linkType: hard - "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -6872,64 +6829,6 @@ __metadata: languageName: node linkType: hard -"ava@npm:^5.2.0": - version: 5.3.1 - resolution: "ava@npm:5.3.1" - dependencies: - acorn: ^8.8.2 - acorn-walk: ^8.2.0 - ansi-styles: ^6.2.1 - arrgv: ^1.0.2 - arrify: ^3.0.0 - callsites: ^4.0.0 - cbor: ^8.1.0 - chalk: ^5.2.0 - chokidar: ^3.5.3 - chunkd: ^2.0.1 - ci-info: ^3.8.0 - ci-parallel-vars: ^1.0.1 - clean-yaml-object: ^0.1.0 - cli-truncate: ^3.1.0 - code-excerpt: ^4.0.0 - common-path-prefix: ^3.0.0 - concordance: ^5.0.4 - currently-unhandled: ^0.4.1 - debug: ^4.3.4 - emittery: ^1.0.1 - figures: ^5.0.0 - globby: ^13.1.4 - ignore-by-default: ^2.1.0 - indent-string: ^5.0.0 - is-error: ^2.2.2 - is-plain-object: ^5.0.0 - is-promise: ^4.0.0 - matcher: ^5.0.0 - mem: ^9.0.2 - ms: ^2.1.3 - p-event: ^5.0.1 - p-map: ^5.5.0 - picomatch: ^2.3.1 - pkg-conf: ^4.0.0 - plur: ^5.1.0 - pretty-ms: ^8.0.0 - resolve-cwd: ^3.0.0 - stack-utils: ^2.0.6 - strip-ansi: ^7.0.1 - supertap: ^3.0.1 - temp-dir: ^3.0.0 - write-file-atomic: ^5.0.1 - yargs: ^17.7.2 - peerDependencies: - "@ava/typescript": "*" - peerDependenciesMeta: - "@ava/typescript": - optional: true - bin: - ava: entrypoints/cli.mjs - checksum: 126a5932baef74eccd8bec992bd522e25c05b6ee4985dde87c20cece76c2377f0bf9448f242f3f9cd2abbf7a5ac932fe4e4abde2a23792d6271a6088e5a1984e - languageName: node - linkType: hard - "axios@npm:^0.25.0": version: 0.25.0 resolution: "axios@npm:0.25.0" @@ -7141,13 +7040,6 @@ __metadata: languageName: node linkType: hard -"blueimp-md5@npm:^2.10.0": - version: 2.19.0 - resolution: "blueimp-md5@npm:2.19.0" - checksum: 28095dcbd2c67152a2938006e8d7c74c3406ba6556071298f872505432feb2c13241b0476644160ee0a5220383ba94cb8ccdac0053b51f68d168728f9c382530 - languageName: node - linkType: hard - "bn.js@npm:^4.11.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" @@ -7532,13 +7424,6 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^4.0.0": - version: 4.1.0 - resolution: "callsites@npm:4.1.0" - checksum: 4ad31de7b7615fa25bdab9c2373865209d2d5190f895cdf2e2f518bd1dafa7ebcda2e6e9cc9640f2dfde6b3893d82fa4359a78ffc27baad2503227553c6882fa - languageName: node - linkType: hard - "camel-case@npm:^4.1.2": version: 4.1.2 resolution: "camel-case@npm:4.1.2" @@ -7603,15 +7488,6 @@ __metadata: languageName: node linkType: hard -"cbor@npm:^8.1.0": - version: 8.1.0 - resolution: "cbor@npm:8.1.0" - dependencies: - nofilter: ^3.1.0 - checksum: a90338435dc7b45cc01461af979e3bb6ddd4f2a08584c437586039cd5f2235014c06e49d664295debbfb3514d87b2f06728092ab6aa6175e2e85e9cd7dc0c1fd - languageName: node - linkType: hard - "ccount@npm:^1.0.0": version: 1.1.0 resolution: "ccount@npm:1.1.0" @@ -7855,13 +7731,6 @@ __metadata: languageName: node linkType: hard -"chunkd@npm:^2.0.1": - version: 2.0.1 - resolution: "chunkd@npm:2.0.1" - checksum: bab8cc08c752a3648984385dc6f61d751e89dbeef648d22a3b661e1d470eaa0f5182f0b4303710f13ae83d2f85144f8eb2dde7a975861d9021b5c56b881f457b - languageName: node - linkType: hard - "ci-info@npm:^2.0.0": version: 2.0.0 resolution: "ci-info@npm:2.0.0" @@ -7869,20 +7738,13 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^3.2.0, ci-info@npm:^3.8.0": +"ci-info@npm:^3.2.0": version: 3.9.0 resolution: "ci-info@npm:3.9.0" checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 languageName: node linkType: hard -"ci-parallel-vars@npm:^1.0.1": - version: 1.0.1 - resolution: "ci-parallel-vars@npm:1.0.1" - checksum: ae859831f7e8e3585db731b8306c336616e37bd709dad1d7775ea4c0731aefd94741dabb48201edc6827d000008fd7fb72cb977967614ee2d99d6b499f0c35fe - languageName: node - linkType: hard - "cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": version: 1.0.4 resolution: "cipher-base@npm:1.0.4" @@ -7923,22 +7785,6 @@ __metadata: languageName: node linkType: hard -"clean-stack@npm:^4.0.0": - version: 4.2.0 - resolution: "clean-stack@npm:4.2.0" - dependencies: - escape-string-regexp: 5.0.0 - checksum: 373f656a31face5c615c0839213b9b542a0a48057abfb1df66900eab4dc2a5c6097628e4a0b5aa559cdfc4e66f8a14ea47be9681773165a44470ef5fb8ccc172 - languageName: node - linkType: hard - -"clean-yaml-object@npm:^0.1.0": - version: 0.1.0 - resolution: "clean-yaml-object@npm:0.1.0" - checksum: 0374ad2f1fbd4984ecf56ebc62200092f6372b9ccf1b7971bb979c328fb12fe76e759fb1e8adc491c80b7b1861f9f00c7f19813dd2a0f49c88231422c70451f4 - languageName: node - linkType: hard - "cli-boxes@npm:^2.2.1": version: 2.2.1 resolution: "cli-boxes@npm:2.2.1" @@ -7975,16 +7821,6 @@ __metadata: languageName: node linkType: hard -"cli-truncate@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-truncate@npm:3.1.0" - dependencies: - slice-ansi: ^5.0.0 - string-width: ^5.0.0 - checksum: c3243e41974445691c63f8b405df1d5a24049dc33d324fe448dc572e561a7b772ae982692900b1a5960901cc4fc7def25a629b9c69a4208ee89d12ab3332617a - languageName: node - linkType: hard - "clipboardy@npm:3.0.0": version: 3.0.0 resolution: "clipboardy@npm:3.0.0" @@ -8078,15 +7914,6 @@ __metadata: languageName: node linkType: hard -"code-excerpt@npm:^4.0.0": - version: 4.0.0 - resolution: "code-excerpt@npm:4.0.0" - dependencies: - convert-to-spaces: ^2.0.1 - checksum: d57137d8f4825879283a828cc02a1115b56858dc54ed06c625c8f67d6685d1becd2fbaa7f0ab19ecca1f5cca03f8c97bbc1f013cab40261e4d3275032e65efe9 - languageName: node - linkType: hard - "collapse-white-space@npm:^1.0.2": version: 1.0.6 resolution: "collapse-white-space@npm:1.0.6" @@ -8314,22 +8141,6 @@ __metadata: languageName: node linkType: hard -"concordance@npm:^5.0.4": - version: 5.0.4 - resolution: "concordance@npm:5.0.4" - dependencies: - date-time: ^3.1.0 - esutils: ^2.0.3 - fast-diff: ^1.2.0 - js-string-escape: ^1.0.1 - lodash: ^4.17.15 - md5-hex: ^3.0.1 - semver: ^7.3.2 - well-known-symbols: ^2.0.0 - checksum: 749153ba711492feb7c3d2f5bb04c107157440b3e39509bd5dd19ee7b3ac751d1e4cd75796d9f702e0a713312dbc661421c68aa4a2c34d5f6d91f47e3a1c64a6 - languageName: node - linkType: hard - "config-chain@npm:^1.1.11": version: 1.1.13 resolution: "config-chain@npm:1.1.13" @@ -8418,13 +8229,6 @@ __metadata: languageName: node linkType: hard -"convert-to-spaces@npm:^2.0.1": - version: 2.0.1 - resolution: "convert-to-spaces@npm:2.0.1" - checksum: bbb324e5916fe9866f65c0ff5f9c1ea933764d0bdb09fccaf59542e40545ed483db6b2339c6d9eb56a11965a58f1a6038f3174f0e2fb7601343c7107ca5e2751 - languageName: node - linkType: hard - "cookie-signature@npm:1.0.6": version: 1.0.6 resolution: "cookie-signature@npm:1.0.6" @@ -8832,15 +8636,6 @@ __metadata: languageName: node linkType: hard -"currently-unhandled@npm:^0.4.1": - version: 0.4.1 - resolution: "currently-unhandled@npm:0.4.1" - dependencies: - array-find-index: ^1.0.1 - checksum: 1f59fe10b5339b54b1a1eee110022f663f3495cf7cf2f480686e89edc7fa8bfe42dbab4b54f85034bc8b092a76cc7becbc2dad4f9adad332ab5831bec39ad540 - languageName: node - linkType: hard - "data-uri-to-buffer@npm:^4.0.0": version: 4.0.1 resolution: "data-uri-to-buffer@npm:4.0.1" @@ -8848,15 +8643,6 @@ __metadata: languageName: node linkType: hard -"date-time@npm:^3.1.0": - version: 3.1.0 - resolution: "date-time@npm:3.1.0" - dependencies: - time-zone: ^1.0.0 - checksum: f9cfcd1b15dfeabab15c0b9d18eb9e4e2d9d4371713564178d46a8f91ad577a290b5178b80050718d02d9c0cf646f8a875011e12d1ed05871e9f72c72c8a8fe6 - languageName: node - linkType: hard - "debounce@npm:^1.2.0, debounce@npm:^1.2.1": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -9429,13 +9215,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^1.0.1": - version: 1.0.1 - resolution: "emittery@npm:1.0.1" - checksum: d95faee6ffb2e023cadaa6804265fea5298c53d079f170112af8dfae3e141761363ea4510966128259346418e3ec7639310fd75059ecce2423bf8afd07004226 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -9763,13 +9542,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": - version: 5.0.0 - resolution: "escape-string-regexp@npm:5.0.0" - checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e - languageName: node - linkType: hard - "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -9777,10 +9549,10 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 9f8a2d5743677c16e85c810e3024d54f0c8dea6424fad3c79ef6666e81dd0846f7437f5e729dfcdac8981bc9e5294c39b4580814d114076b8d36318f46ae4395 +"escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e languageName: node linkType: hard @@ -10006,7 +9778,7 @@ __metadata: languageName: node linkType: hard -"esutils@npm:^2.0.2, esutils@npm:^2.0.3": +"esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 @@ -10320,7 +10092,7 @@ __metadata: languageName: node linkType: hard -"fast-diff@npm:^1.1.2, fast-diff@npm:^1.2.0": +"fast-diff@npm:^1.1.2": version: 1.3.0 resolution: "fast-diff@npm:1.3.0" checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3 @@ -10432,16 +10204,6 @@ __metadata: languageName: node linkType: hard -"figures@npm:^5.0.0": - version: 5.0.0 - resolution: "figures@npm:5.0.0" - dependencies: - escape-string-regexp: ^5.0.0 - is-unicode-supported: ^1.2.0 - checksum: e6e8b6d1df2f554d4effae4a5ceff5d796f9449f6d4e912d74dab7d5f25916ecda6c305b9084833157d56485a0c78b37164430ddc5675bcee1330e346710669e - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -10562,7 +10324,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^6.0.0, find-up@npm:^6.3.0": +"find-up@npm:^6.3.0": version: 6.3.0 resolution: "find-up@npm:6.3.0" dependencies: @@ -11090,7 +10852,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.1, globby@npm:^13.1.2, globby@npm:^13.1.4": +"globby@npm:^13.1.1, globby@npm:^13.1.2": version: 13.2.2 resolution: "globby@npm:13.2.2" dependencies: @@ -11979,13 +11741,6 @@ __metadata: languageName: node linkType: hard -"ignore-by-default@npm:^2.1.0": - version: 2.1.0 - resolution: "ignore-by-default@npm:2.1.0" - checksum: 2b2df4622b6a07a3e91893987be8f060dc553f7736b67e72aa2312041c450a6fa8371733d03c42f45a02e47ec824e961c2fba63a3d94fc59cbd669220a5b0d7a - languageName: node - linkType: hard - "ignore@npm:^5.2.0, ignore@npm:^5.2.4": version: 5.3.0 resolution: "ignore@npm:5.3.0" @@ -12063,13 +11818,6 @@ __metadata: languageName: node linkType: hard -"indent-string@npm:^5.0.0": - version: 5.0.0 - resolution: "indent-string@npm:5.0.0" - checksum: e466c27b6373440e6d84fbc19e750219ce25865cb82d578e41a6053d727e5520dc5725217d6eb1cc76005a1bb1696a0f106d84ce7ebda3033b963a38583fb3b3 - languageName: node - linkType: hard - "infima@npm:0.2.0-alpha.43": version: 0.2.0-alpha.43 resolution: "infima@npm:0.2.0-alpha.43" @@ -12143,7 +11891,6 @@ __metadata: "@noir-lang/backend_barretenberg": "workspace:*" "@noir-lang/noir_js": "workspace:*" "@noir-lang/noir_wasm": "workspace:*" - "@noir-lang/source-resolver": "workspace:*" "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 "@nomicfoundation/hardhat-ethers": ^3.0.0 "@web/dev-server-esbuild": ^0.3.6 @@ -12213,13 +11960,6 @@ __metadata: languageName: node linkType: hard -"irregular-plurals@npm:^3.3.0": - version: 3.5.0 - resolution: "irregular-plurals@npm:3.5.0" - checksum: 5b663091dc89155df7b2e9d053e8fb11941a0c4be95c4b6549ed3ea020489fdf4f75ea586c915b5b543704252679a5a6e8c6c3587da5ac3fc57b12da90a9aee7 - languageName: node - linkType: hard - "is-alphabetical@npm:1.0.4, is-alphabetical@npm:^1.0.0": version: 1.0.4 resolution: "is-alphabetical@npm:1.0.4" @@ -12349,13 +12089,6 @@ __metadata: languageName: node linkType: hard -"is-error@npm:^2.2.2": - version: 2.2.2 - resolution: "is-error@npm:2.2.2" - checksum: a97b39587150f0d38f9f93f64699807fe3020fe5edbd63548f234dc2ba96fd7c776d66c062bf031dfeb93c7f48db563ff6bde588418ca041da37c659a416f055 - languageName: node - linkType: hard - "is-extendable@npm:^0.1.0": version: 0.1.1 resolution: "is-extendable@npm:0.1.1" @@ -12377,13 +12110,6 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^4.0.0": - version: 4.0.0 - resolution: "is-fullwidth-code-point@npm:4.0.0" - checksum: 8ae89bf5057bdf4f57b346fb6c55e9c3dd2549983d54191d722d5c739397a903012cc41a04ee3403fd872e811243ef91a7c5196da7b5841dc6b6aae31a264a8d - languageName: node - linkType: hard - "is-generator-function@npm:^1.0.7": version: 1.0.10 resolution: "is-generator-function@npm:1.0.10" @@ -12551,13 +12277,6 @@ __metadata: languageName: node linkType: hard -"is-promise@npm:^4.0.0": - version: 4.0.0 - resolution: "is-promise@npm:4.0.0" - checksum: 0b46517ad47b00b6358fd6553c83ec1f6ba9acd7ffb3d30a0bf519c5c69e7147c132430452351b8a9fc198f8dd6c4f76f8e6f5a7f100f8c77d57d9e0f4261a8a - languageName: node - linkType: hard - "is-reference@npm:^3.0.0": version: 3.0.2 resolution: "is-reference@npm:3.0.2" @@ -12609,13 +12328,6 @@ __metadata: languageName: node linkType: hard -"is-unicode-supported@npm:^1.2.0": - version: 1.3.0 - resolution: "is-unicode-supported@npm:1.3.0" - checksum: 20a1fc161afafaf49243551a5ac33b6c4cf0bbcce369fcd8f2951fbdd000c30698ce320de3ee6830497310a8f41880f8066d440aa3eb0a853e2aa4836dd89abc - languageName: node - linkType: hard - "is-whitespace-character@npm:^1.0.0": version: 1.0.4 resolution: "is-whitespace-character@npm:1.0.4" @@ -12816,13 +12528,6 @@ __metadata: languageName: node linkType: hard -"js-string-escape@npm:^1.0.1": - version: 1.0.1 - resolution: "js-string-escape@npm:1.0.1" - checksum: f11e0991bf57e0c183b55c547acec85bd2445f043efc9ea5aa68b41bd2a3e7d3ce94636cb233ae0d84064ba4c1a505d32e969813c5b13f81e7d4be12c59256fe - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -12841,7 +12546,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": +"js-yaml@npm:^3.13.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" dependencies: @@ -13232,13 +12937,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^7.0.0": - version: 7.0.1 - resolution: "load-json-file@npm:7.0.1" - checksum: a560288da6891778321ef993e4bdbdf05374a4f3a3aeedd5ba6b64672798c830d748cfc59a2ec9891a3db30e78b3d04172e0dcb0d4828168289a393147ca0e74 - languageName: node - linkType: hard - "loader-runner@npm:^4.2.0": version: 4.3.0 resolution: "loader-runner@npm:4.3.0" @@ -13360,7 +13058,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -13543,15 +13241,6 @@ __metadata: languageName: node linkType: hard -"map-age-cleaner@npm:^0.1.3": - version: 0.1.3 - resolution: "map-age-cleaner@npm:0.1.3" - dependencies: - p-defer: ^1.0.0 - checksum: cb2804a5bcb3cbdfe4b59066ea6d19f5e7c8c196cd55795ea4c28f792b192e4c442426ae52524e5e1acbccf393d3bddacefc3d41f803e66453f6c4eda3650bc1 - languageName: node - linkType: hard - "map-stream@npm:~0.1.0": version: 0.1.0 resolution: "map-stream@npm:0.1.0" @@ -13603,15 +13292,6 @@ __metadata: languageName: node linkType: hard -"matcher@npm:^5.0.0": - version: 5.0.0 - resolution: "matcher@npm:5.0.0" - dependencies: - escape-string-regexp: ^5.0.0 - checksum: 28f191c2d23fee0f6f32fd0181d9fe173b0ab815a919edba55605438a2f9fa40372e002574a1b17add981b0a8669c75bc6194318d065ed2dceffd8b160c38118 - languageName: node - linkType: hard - "mcl-wasm@npm:^0.7.1": version: 0.7.9 resolution: "mcl-wasm@npm:0.7.9" @@ -13619,15 +13299,6 @@ __metadata: languageName: node linkType: hard -"md5-hex@npm:^3.0.1": - version: 3.0.1 - resolution: "md5-hex@npm:3.0.1" - dependencies: - blueimp-md5: ^2.10.0 - checksum: 6799a19e8bdd3e0c2861b94c1d4d858a89220488d7885c1fa236797e367d0c2e5f2b789e05309307083503f85be3603a9686a5915568a473137d6b4117419cc2 - languageName: node - linkType: hard - "md5.js@npm:^1.3.4": version: 1.3.5 resolution: "md5.js@npm:1.3.5" @@ -13968,16 +13639,6 @@ __metadata: languageName: node linkType: hard -"mem@npm:^9.0.2": - version: 9.0.2 - resolution: "mem@npm:9.0.2" - dependencies: - map-age-cleaner: ^0.1.3 - mimic-fn: ^4.0.0 - checksum: 07829bb182af0e3ecf748dc2edb1c3b10a256ef10458f7e24d06561a2adc2b3ef34d14abe81678bbcedb46faa477e7370223f118b1a5e1252da5fe43496f3967 - languageName: node - linkType: hard - "memfs@npm:^3.1.2, memfs@npm:^3.4.3": version: 3.5.3 resolution: "memfs@npm:3.5.3" @@ -14913,7 +14574,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.1": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -15102,13 +14763,6 @@ __metadata: languageName: node linkType: hard -"nofilter@npm:^3.1.0": - version: 3.1.0 - resolution: "nofilter@npm:3.1.0" - checksum: 58aa85a5b4b35cbb6e42de8a8591c5e338061edc9f3e7286f2c335e9e9b9b8fa7c335ae45daa8a1f3433164dc0b9a3d187fa96f9516e04a17a1f9ce722becc4f - languageName: node - linkType: hard - "nopt@npm:^7.0.0": version: 7.2.0 resolution: "nopt@npm:7.2.0" @@ -15378,22 +15032,6 @@ __metadata: languageName: node linkType: hard -"p-defer@npm:^1.0.0": - version: 1.0.0 - resolution: "p-defer@npm:1.0.0" - checksum: 4271b935c27987e7b6f229e5de4cdd335d808465604644cb7b4c4c95bef266735859a93b16415af8a41fd663ee9e3b97a1a2023ca9def613dba1bad2a0da0c7b - languageName: node - linkType: hard - -"p-event@npm:^5.0.1": - version: 5.0.1 - resolution: "p-event@npm:5.0.1" - dependencies: - p-timeout: ^5.0.2 - checksum: 3bdd8df6092e6b149f25e9c2eb1c0843b3b4279b07be2a2c72c02b65b267a8908c2040fefd606f2497b0f2bcefcd214f8ca5a74f0c883515d400ccf1d88d5683 - languageName: node - linkType: hard - "p-limit@npm:^1.1.0": version: 1.3.0 resolution: "p-limit@npm:1.3.0" @@ -15484,15 +15122,6 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^5.5.0": - version: 5.5.0 - resolution: "p-map@npm:5.5.0" - dependencies: - aggregate-error: ^4.0.0 - checksum: 065cb6fca6b78afbd070dd9224ff160dc23eea96e57863c09a0c8ea7ce921043f76854be7ee0abc295cff1ac9adcf700e79a1fbe3b80b625081087be58e7effb - languageName: node - linkType: hard - "p-retry@npm:^4.5.0": version: 4.6.2 resolution: "p-retry@npm:4.6.2" @@ -15503,13 +15132,6 @@ __metadata: languageName: node linkType: hard -"p-timeout@npm:^5.0.2": - version: 5.1.0 - resolution: "p-timeout@npm:5.1.0" - checksum: f5cd4e17301ff1ff1d8dbf2817df0ad88c6bba99349fc24d8d181827176ad4f8aca649190b8a5b1a428dfd6ddc091af4606835d3e0cb0656e04045da5c9e270c - languageName: node - linkType: hard - "p-try@npm:^1.0.0": version: 1.0.0 resolution: "p-try@npm:1.0.0" @@ -15609,13 +15231,6 @@ __metadata: languageName: node linkType: hard -"parse-ms@npm:^3.0.0": - version: 3.0.0 - resolution: "parse-ms@npm:3.0.0" - checksum: fc602bba093835562321a67a9d6c8c9687ca4f26a09459a77e07ebd7efddd1a5766725ec60eb0c83a2abe67f7a23808f7deb1c1226727776eaf7f9607ae09db2 - languageName: node - linkType: hard - "parse-numeric-range@npm:^1.3.0": version: 1.3.0 resolution: "parse-numeric-range@npm:1.3.0" @@ -15823,16 +15438,6 @@ __metadata: languageName: node linkType: hard -"pkg-conf@npm:^4.0.0": - version: 4.0.0 - resolution: "pkg-conf@npm:4.0.0" - dependencies: - find-up: ^6.0.0 - load-json-file: ^7.0.0 - checksum: 6da0c064a74f6c7ae80d7d68c5853e14f7e762a2a80c6ca9e0aa827002b90b69c86fefe3bac830b10a6f1739e7f96a1f728637f2a141e50b0fdafe92a2c3eab6 - languageName: node - linkType: hard - "pkg-dir@npm:^4.1.0": version: 4.2.0 resolution: "pkg-dir@npm:4.2.0" @@ -15884,15 +15489,6 @@ __metadata: languageName: node linkType: hard -"plur@npm:^5.1.0": - version: 5.1.0 - resolution: "plur@npm:5.1.0" - dependencies: - irregular-plurals: ^3.3.0 - checksum: 57e400dc4b926768fb0abab7f8688fe17e85673712134546e7beaaee188bae7e0504976e847d7e41d0d6103ff2fd61204095f03c2a45de19a8bad15aecb45cc1 - languageName: node - linkType: hard - "portfinder@npm:^1.0.32": version: 1.0.32 resolution: "portfinder@npm:1.0.32" @@ -16400,15 +15996,6 @@ __metadata: languageName: node linkType: hard -"pretty-ms@npm:^8.0.0": - version: 8.0.0 - resolution: "pretty-ms@npm:8.0.0" - dependencies: - parse-ms: ^3.0.0 - checksum: b7d2a8182887af0e5ab93f9df331f10db9b8eda86855e2de115eb01a6c501bde5631a8813b1b0abdd7d045e79b08ae875369a8fd279a3dacd6d9e572bdd3bfa6 - languageName: node - linkType: hard - "pretty-time@npm:^1.1.0": version: 1.1.0 resolution: "pretty-time@npm:1.1.0" @@ -17353,15 +16940,6 @@ __metadata: languageName: node linkType: hard -"resolve-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "resolve-cwd@npm:3.0.0" - dependencies: - resolve-from: ^5.0.0 - checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 - languageName: node - linkType: hard - "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -17369,13 +16947,6 @@ __metadata: languageName: node linkType: hard -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf - languageName: node - linkType: hard - "resolve-path@npm:^1.4.0": version: 1.4.0 resolution: "resolve-path@npm:1.4.0" @@ -17819,15 +17390,6 @@ __metadata: languageName: node linkType: hard -"serialize-error@npm:^7.0.1": - version: 7.0.1 - resolution: "serialize-error@npm:7.0.1" - dependencies: - type-fest: ^0.13.1 - checksum: e0aba4dca2fc9fe74ae1baf38dbd99190e1945445a241ba646290f2176cdb2032281a76443b02ccf0caf30da5657d510746506368889a593b9835a497fc0732e - languageName: node - linkType: hard - "serialize-javascript@npm:6.0.0": version: 6.0.0 resolution: "serialize-javascript@npm:6.0.0" @@ -18110,16 +17672,6 @@ __metadata: languageName: node linkType: hard -"slice-ansi@npm:^5.0.0": - version: 5.0.0 - resolution: "slice-ansi@npm:5.0.0" - dependencies: - ansi-styles: ^6.0.0 - is-fullwidth-code-point: ^4.0.0 - checksum: 7e600a2a55e333a21ef5214b987c8358fe28bfb03c2867ff2cbf919d62143d1812ac27b4297a077fdaf27a03da3678e49551c93e35f9498a3d90221908a1180e - languageName: node - linkType: hard - "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -18310,15 +17862,6 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: ^2.0.0 - checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 - languageName: node - linkType: hard - "stacktrace-parser@npm:^0.1.10": version: 0.1.10 resolution: "stacktrace-parser@npm:0.1.10" @@ -18406,7 +17949,7 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": version: 5.1.2 resolution: "string-width@npm:5.1.2" dependencies: @@ -18564,18 +18107,6 @@ __metadata: languageName: node linkType: hard -"supertap@npm:^3.0.1": - version: 3.0.1 - resolution: "supertap@npm:3.0.1" - dependencies: - indent-string: ^5.0.0 - js-yaml: ^3.14.1 - serialize-error: ^7.0.1 - strip-ansi: ^7.0.1 - checksum: ee3d71c1d25f7f15d4a849e72b0c5f430df7cd8f702cf082fdbec5642a9546be6557766745655fa3a3e9c88f7c7eed849f2d74457b5b72cb9d94a779c0c8a948 - languageName: node - linkType: hard - "supports-color@npm:8.1.1, supports-color@npm:^8.0.0": version: 8.1.1 resolution: "supports-color@npm:8.1.1" @@ -18726,13 +18257,6 @@ __metadata: languageName: node linkType: hard -"temp-dir@npm:^3.0.0": - version: 3.0.0 - resolution: "temp-dir@npm:3.0.0" - checksum: 577211e995d1d584dd60f1469351d45e8a5b4524e4a9e42d3bdd12cfde1d0bb8f5898311bef24e02aaafb69514c1feb58c7b4c33dcec7129da3b0861a4ca935b - languageName: node - linkType: hard - "terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7, terser-webpack-plugin@npm:^5.3.9": version: 5.3.9 resolution: "terser-webpack-plugin@npm:5.3.9" @@ -18790,13 +18314,6 @@ __metadata: languageName: node linkType: hard -"time-zone@npm:^1.0.0": - version: 1.0.0 - resolution: "time-zone@npm:1.0.0" - checksum: e46f5a69b8c236dcd8e91e29d40d4e7a3495ed4f59888c3f84ce1d9678e20461421a6ba41233509d47dd94bc18f1a4377764838b21b584663f942b3426dcbce8 - languageName: node - linkType: hard - "tiny-invariant@npm:^1.0.2": version: 1.3.1 resolution: "tiny-invariant@npm:1.3.1" @@ -19093,13 +18610,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.13.1": - version: 0.13.1 - resolution: "type-fest@npm:0.13.1" - checksum: e6bf2e3c449f27d4ef5d56faf8b86feafbc3aec3025fc9a5fbe2db0a2587c44714521f9c30d8516a833c8c506d6263f5cc11267522b10c6ccdb6cc55b0a9d1c4 - languageName: node - linkType: hard - "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -19197,16 +18707,6 @@ __metadata: languageName: node linkType: hard -"typescript@npm:4.9.4": - version: 4.9.4 - resolution: "typescript@npm:4.9.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 - languageName: node - linkType: hard - "typescript@npm:5.1.5": version: 5.1.5 resolution: "typescript@npm:5.1.5" @@ -19237,16 +18737,6 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@4.9.4#~builtin": - version: 4.9.4 - resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=289587" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 2160f7ad975c59b2f5816817d3916be1d156c5688a7517602b3b640c5015e740f4ba933996ac85371d68f7bbdd41602150fb8b68334122ac637fdb5418085e7a - languageName: node - linkType: hard - "typescript@patch:typescript@5.1.5#~builtin": version: 5.1.5 resolution: "typescript@patch:typescript@npm%3A5.1.5#~builtin::version=5.1.5&hash=5da071" @@ -20140,13 +19630,6 @@ __metadata: languageName: node linkType: hard -"well-known-symbols@npm:^2.0.0": - version: 2.0.0 - resolution: "well-known-symbols@npm:2.0.0" - checksum: 4f54bbc3012371cb4d228f436891b8e7536d34ac61a57541890257e96788608e096231e0121ac24d08ef2f908b3eb2dc0adba35023eaeb2a7df655da91415402 - languageName: node - linkType: hard - "whatwg-url@npm:^11.0.0": version: 11.0.0 resolution: "whatwg-url@npm:11.0.0" @@ -20301,16 +19784,6 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: ^0.1.4 - signal-exit: ^4.0.1 - checksum: 8dbb0e2512c2f72ccc20ccedab9986c7d02d04039ed6e8780c987dc4940b793339c50172a1008eed7747001bfacc0ca47562668a069a7506c46c77d7ba3926a9 - languageName: node - linkType: hard - "ws@npm:7.4.6": version: 7.4.6 resolution: "ws@npm:7.4.6" @@ -20516,7 +19989,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.7.1, yargs@npm:^17.7.2": +"yargs@npm:^17.7.1": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From f1aa92824fce322fae76615793a1d5335a97159e Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 14 Dec 2023 13:30:20 +0000 Subject: [PATCH 042/137] chore(ci): enforce timeouts on build and test workflows (#3804) # Description ## Problem\* Resolves ## Summary\* This PR adds a timeout to all of the jobs which are likely to spin out for a long time. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/publish-nargo.yml | 2 ++ .github/workflows/test-js-packages.yml | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml index 59d4fe4cc48..3bcc9a13570 100644 --- a/.github/workflows/publish-nargo.yml +++ b/.github/workflows/publish-nargo.yml @@ -30,6 +30,7 @@ jobs: strategy: matrix: target: [x86_64-apple-darwin, aarch64-apple-darwin] + timeout-minutes: 30 steps: - name: Checkout @@ -120,6 +121,7 @@ jobs: fail-fast: false matrix: target: [x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl] + timeout-minutes: 30 steps: - name: Checkout diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index c6762ce3a16..a298d67a485 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -15,6 +15,7 @@ concurrency: jobs: build-nargo: runs-on: ubuntu-22.04 + timeout-minutes: 30 steps: - name: Checkout Noir repo @@ -47,6 +48,7 @@ jobs: build-noir-wasm: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout sources @@ -76,6 +78,8 @@ jobs: build-acvm-js: runs-on: ubuntu-latest + timeout-minutes: 30 + steps: - name: Checkout sources uses: actions/checkout@v4 @@ -103,6 +107,7 @@ jobs: build-noirc-abi: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout sources @@ -133,6 +138,7 @@ jobs: needs: [build-acvm-js] name: ACVM JS (Node.js) runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout sources @@ -154,6 +160,7 @@ jobs: needs: [build-acvm-js] name: ACVM JS (Browser) runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout sources @@ -180,6 +187,7 @@ jobs: needs: [build-noirc-abi] name: noirc_abi runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout sources @@ -265,12 +273,12 @@ jobs: yarn workspace @noir-lang/noir_js build yarn workspace @noir-lang/noir_js test - - test-noir-wasm: needs: [build-noir-wasm, build-nargo] name: noir_wasm runs-on: ubuntu-latest + timeout-minutes: 30 + steps: - name: Checkout sources uses: actions/checkout@v4 @@ -314,6 +322,8 @@ jobs: needs: [build-acvm-js, build-noirc-abi] name: noir_codegen runs-on: ubuntu-latest + timeout-minutes: 30 + steps: - name: Checkout uses: actions/checkout@v4 @@ -346,7 +356,8 @@ jobs: name: Integration Tests runs-on: ubuntu-latest needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] - + timeout-minutes: 30 + steps: - name: Checkout uses: actions/checkout@v4 From 97373e8cb2b37e0dc4ee6c3702008b0d0491835d Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 14 Dec 2023 13:35:29 +0000 Subject: [PATCH 043/137] chore: clippy fix (#3803) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/lsp/src/requests/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index 309c3dc0a5c..e2fdcdf08da 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -105,9 +105,7 @@ pub(crate) fn on_shutdown( #[cfg(test)] mod initialization { use async_lsp::ClientSocket; - use lsp_types::{ - CodeLensOptions, InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind, - }; + use lsp_types::{InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind}; use tokio::test; use crate::{ From 98a500436a68652a367ccbf77e32f8544aff73bc Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:32:21 +0100 Subject: [PATCH 044/137] feat: add support for writing tracing debug info to file (#3790) # Description ## Problem\* Turning rtacing on/off by adding code each time is cumbersome. ## Summary\* Allows to turn tracing on by defining `env` `NARGO_LOG_DIR` = `/path/to/directory/with/logs/` Our own tracing would be aded gradually on as needed basis. By enabling this we still benefit from other crates using tracing. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- Cargo.lock | 72 ++++++++++++++++++++++++++++++----- Cargo.toml | 2 + cspell.json | 1 + tooling/nargo_cli/Cargo.toml | 5 +++ tooling/nargo_cli/src/main.rs | 13 +++++++ 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cec7b5f0371..0ee4fdf1016 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1135,6 +1135,16 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -2494,6 +2504,9 @@ dependencies = [ "tokio-util", "toml", "tower", + "tracing", + "tracing-appender", + "tracing-subscriber", ] [[package]] @@ -2736,6 +2749,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -2808,6 +2831,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -4407,22 +4436,33 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -4431,9 +4471,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -4449,15 +4489,29 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "nu-ansi-term", "sharded-slab", + "smallvec", "thread_local", "tracing-core", + "tracing-log", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c42eeb9c002..7cd00ee0a60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -122,6 +122,8 @@ num-traits = "0.2" similar-asserts = "1.5.0" log = "0.4.17" +tracing = "0.1.40" + [profile.dev] # This is required to be able to run `cargo test` in acvm_js due to the `locals exceeds maximum` error. # See https://ritik-mishra.medium.com/resolving-the-wasm-pack-error-locals-exceed-maximum-ec3a9d96685b diff --git a/cspell.json b/cspell.json index 4d3af064654..e02e68871bb 100644 --- a/cspell.json +++ b/cspell.json @@ -5,6 +5,7 @@ "acir", "acvm", "aeiou", + "appender", "arithmetization", "arity", "arkworks", diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 7d6be099d46..008b1233cd8 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -53,6 +53,11 @@ tokio = { version = "1.0", features = ["io-std"] } backend-interface = { path = "../backend_interface" } bb_abstraction_leaks.workspace = true +# Logs +tracing.workspace = true +tracing-subscriber = "0.3.18" +tracing-appender = "0.2.3" + [target.'cfg(not(unix))'.dependencies] tokio-util = { version = "0.7.8", features = ["compat"] } diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs index aefff697707..7eeca2ab2b0 100644 --- a/tooling/nargo_cli/src/main.rs +++ b/tooling/nargo_cli/src/main.rs @@ -11,8 +11,11 @@ mod backends; mod cli; mod errors; +use std::env; + use color_eyre::config::HookBuilder; use env_logger::{Builder, Env}; +use tracing_appender::rolling; const PANIC_MESSAGE: &str = "This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.\nIf there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml"; @@ -20,6 +23,16 @@ fn main() { let env = Env::default().filter_or("NOIR_LOG", "error"); // Default to 'error' if NOIR_LOG is not set Builder::from_env(env).init(); + // Setup tracing + if let Ok(log_dir) = env::var("NARGO_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "nargo-log"); + tracing_subscriber::fmt() + .with_writer(debug_file) + .with_ansi(false) + .with_max_level(tracing::Level::TRACE) + .init(); + } + // Register a panic hook to display more readable panic messages to end-users let (panic_hook, _) = HookBuilder::default().display_env_section(false).panic_section(PANIC_MESSAGE).into_hooks(); From 151dbf0e9db07920457a41fc712e21e2c41751c3 Mon Sep 17 00:00:00 2001 From: jfecher Date: Thu, 14 Dec 2023 11:49:59 -0600 Subject: [PATCH 045/137] chore: Remove signed integer warning (#3808) # Description ## Problem\* Resolves ## Summary\* Removes the experimental feature warning for signed integers. Bit shifting is the only task that remains for signed integers and this already has a separate error message. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/parser/parser.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index a97637642af..660c85759b9 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -1119,14 +1119,7 @@ fn int_type() -> impl NoirParser { Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) } })) - .validate(|(_, token), span, emit| { - let typ = UnresolvedTypeData::from_int_token(token).with_span(span); - if let UnresolvedTypeData::Integer(crate::Signedness::Signed, _) = &typ.typ { - let reason = ParserErrorReason::ExperimentalFeature("Signed integer types"); - emit(ParserError::with_reason(reason, span)); - } - typ - }) + .map_with_span(|(_, token), span| UnresolvedTypeData::from_int_token(token).with_span(span)) } fn named_type(type_parser: impl NoirParser) -> impl NoirParser { From 8a8d8a4aa8946d7844787ed3a88c9230930622d5 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 14 Dec 2023 18:03:58 +0000 Subject: [PATCH 046/137] chore: add tracing to program compilation + execution (#3811) # Description ## Problem\* Resolves ## Summary\* This PR adds tracing logs to various operations so we can track what gets called and how long it takes easily. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 6 ++++++ acvm-repo/acvm/Cargo.toml | 1 + acvm-repo/acvm/src/compiler/optimizers/mod.rs | 4 ++++ acvm-repo/acvm/src/compiler/transformers/mod.rs | 4 ++++ compiler/noirc_driver/Cargo.toml | 1 + compiler/noirc_driver/src/lib.rs | 5 +++++ compiler/noirc_errors/Cargo.toml | 1 + compiler/noirc_errors/src/debug_info.rs | 2 ++ compiler/noirc_evaluator/Cargo.toml | 1 + compiler/noirc_evaluator/src/ssa.rs | 13 ++++++++++++- compiler/noirc_frontend/Cargo.toml | 1 + compiler/noirc_frontend/src/monomorphization/mod.rs | 3 +++ tooling/nargo/Cargo.toml | 3 ++- tooling/nargo/src/ops/execute.rs | 3 +++ 14 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ee4fdf1016..d2606d211ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,7 @@ dependencies = [ "acvm_stdlib", "brillig_vm", "indexmap 1.9.3", + "log", "num-bigint", "num-traits", "paste", @@ -2443,6 +2444,7 @@ dependencies = [ "codespan-reporting", "fm", "iter-extended", + "log", "noirc_abi", "noirc_driver", "noirc_errors", @@ -2673,6 +2675,7 @@ dependencies = [ "fm", "fxhash", "iter-extended", + "log", "noirc_abi", "noirc_errors", "noirc_evaluator", @@ -2690,6 +2693,7 @@ dependencies = [ "codespan", "codespan-reporting", "fm", + "log", "serde", "serde_with", ] @@ -2702,6 +2706,7 @@ dependencies = [ "fxhash", "im", "iter-extended", + "log", "noirc_errors", "noirc_frontend", "num-bigint", @@ -2718,6 +2723,7 @@ dependencies = [ "chumsky", "fm", "iter-extended", + "log", "noirc_errors", "noirc_printable_type", "regex", diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 6e4c2d322bb..2515f9012e4 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -16,6 +16,7 @@ repository.workspace = true num-bigint.workspace = true num-traits.workspace = true thiserror.workspace = true +log.workspace = true acir.workspace = true stdlib.workspace = true diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index 627ddbb4117..6e2af4f58a1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -22,6 +22,8 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, AcirTransformationMap) { + log::trace!("Start circuit optimization"); + // General optimizer pass let opcodes: Vec = acir .opcodes @@ -52,5 +54,7 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, AcirTransformationMa let transformation_map = AcirTransformationMap { acir_opcode_positions }; + log::trace!("Finish circuit optimization"); + (acir, transformation_map) } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index d827b759666..00ee9dc7ce5 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -44,6 +44,8 @@ pub(super) fn transform_internal( is_opcode_supported: impl Fn(&Opcode) -> bool, acir_opcode_positions: Vec, ) -> Result<(Circuit, AcirTransformationMap), CompileError> { + log::trace!("Start circuit transformation"); + // Fallback transformer pass let (acir, acir_opcode_positions) = FallbackTransformer::transform(acir, is_opcode_supported, acir_opcode_positions)?; @@ -217,5 +219,7 @@ pub(super) fn transform_internal( let transformation_map = AcirTransformationMap { acir_opcode_positions: new_acir_opcode_positions }; + log::trace!("Finish circuit transformation"); + Ok((acir, transformation_map)) } diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index e5a837e6822..7f431db4398 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -22,5 +22,6 @@ fm.workspace = true serde.workspace = true fxhash.workspace = true rust-embed = "6.6.0" +log.workspace = true aztec_macros = { path = "../../aztec_macros" } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index c326d04c84d..24b159568f2 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -147,6 +147,8 @@ pub fn check_crate( deny_warnings: bool, disable_macros: bool, ) -> CompilationResult<()> { + log::trace!("Start checking crate"); + let macros: Vec<&dyn MacroProcessor> = if disable_macros { vec![] } else { @@ -160,6 +162,8 @@ pub fn check_crate( diagnostic.in_file(file_id) })); + log::trace!("Finish checking crate"); + if has_errors(&errors, deny_warnings) { Err(errors) } else { @@ -372,6 +376,7 @@ pub fn compile_no_check( force_compile || options.print_acir || options.show_brillig || options.show_ssa; if !force_compile && hashes_match { + log::info!("Program matches existing artifact, returning early"); return Ok(cached_program.expect("cache must exist for hashes to match")); } let visibility = program.return_visibility; diff --git a/compiler/noirc_errors/Cargo.toml b/compiler/noirc_errors/Cargo.toml index 0cb6afc73bd..812a507550c 100644 --- a/compiler/noirc_errors/Cargo.toml +++ b/compiler/noirc_errors/Cargo.toml @@ -15,3 +15,4 @@ fm.workspace = true chumsky.workspace = true serde.workspace = true serde_with = "3.2.0" +log.workspace = true diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 888c24adc1a..3ae5c193e39 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -39,6 +39,7 @@ impl DebugInfo { /// renders the old `OpcodeLocation`s invalid. The AcirTransformationMap is able to map the old `OpcodeLocation` to the new ones. /// Note: One old `OpcodeLocation` might have transformed into more than one new `OpcodeLocation`. pub fn update_acir(&mut self, update_map: AcirTransformationMap) { + log::trace!("Start debug info update"); let old_locations = mem::take(&mut self.locations); for (old_opcode_location, source_locations) in old_locations { @@ -46,6 +47,7 @@ impl DebugInfo { self.locations.insert(new_opcode_location, source_locations.clone()); }); } + log::trace!("Finish debug info update"); } pub fn opcode_location(&self, loc: &OpcodeLocation) -> Option> { diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index 933ec2b300c..6e7152c6d71 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -17,3 +17,4 @@ thiserror.workspace = true num-bigint = "0.4" im = { version = "15.1", features = ["serde"] } serde.workspace = true +log.workspace = true diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 8e1c62edc69..6a02a5f6edc 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -42,6 +42,7 @@ pub(crate) fn optimize_into_acir( ) -> Result { let abi_distinctness = program.return_distinctness; + log::trace!("Start SSA generation"); let ssa_builder = SsaBuilder::new(program, print_ssa_passes)? .run_pass(Ssa::defunctionalize, "After Defunctionalization:") .run_pass(Ssa::inline_functions, "After Inlining:") @@ -69,9 +70,15 @@ pub(crate) fn optimize_into_acir( let ssa = ssa_builder .run_pass(Ssa::fill_internal_slices, "After Fill Internal Slice Dummy Data:") .finish(); + log::trace!("Finish SSA generation"); let last_array_uses = ssa.find_last_array_uses(); - ssa.into_acir(brillig, abi_distinctness, &last_array_uses) + + log::trace!("Start ACIR generation"); + let acir = ssa.into_acir(brillig, abi_distinctness, &last_array_uses); + log::trace!("Finish ACIR generation"); + + acir } /// Compiles the [`Program`] into [`ACIR`][acvm::acir::circuit::Circuit]. @@ -83,6 +90,8 @@ pub fn create_circuit( enable_ssa_logging: bool, enable_brillig_logging: bool, ) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { + log::trace!("Start circuit generation"); + let func_sig = program.main_function_signature.clone(); let mut generated_acir = optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?; @@ -124,6 +133,8 @@ pub fn create_circuit( let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); debug_info.update_acir(transformation_map); + log::trace!("Finish circuit generation"); + Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) } diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index 6f3c35a814a..1565a105522 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -22,6 +22,7 @@ serde.workspace = true rustc-hash = "1.1.0" small-ord-set = "0.1.3" regex = "1.9.1" +log.workspace = true [dev-dependencies] strum = "0.24" diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 78cde11593b..52b8d5bfd79 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -92,6 +92,7 @@ type HirType = crate::Type; /// this function. Typically, this is the function named "main" in the source project, /// but it can also be, for example, an arbitrary test function for running `nargo test`. pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Program { + log::trace!("Start monomorphization"); let mut monomorphizer = Monomorphizer::new(interner); let function_sig = monomorphizer.compile_main(main); @@ -106,6 +107,8 @@ pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Pro let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); let FuncMeta { return_distinctness, return_visibility, .. } = interner.function_meta(&main); + + log::trace!("Finish monomorphization"); Program::new( functions, function_sig, diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index 48741c367a5..ec4e1488809 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -24,9 +24,10 @@ iter-extended.workspace = true serde.workspace = true thiserror.workspace = true codespan-reporting.workspace = true +log.workspace = true rayon = "1.8.0" [dev-dependencies] # TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` # TODO: once that method is moved to nargo_cli, we can move this dependency to nargo_cli -tempfile = "3.2.0" \ No newline at end of file +tempfile = "3.2.0" diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs index d7cb44188c4..2ac85781410 100644 --- a/tooling/nargo/src/ops/execute.rs +++ b/tooling/nargo/src/ops/execute.rs @@ -13,6 +13,7 @@ pub fn execute_circuit( blackbox_solver: &B, foreign_call_executor: &mut F, ) -> Result { + log::trace!("Start circuit execution"); let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); loop { @@ -55,5 +56,7 @@ pub fn execute_circuit( } let solved_witness = acvm.finalize(); + + log::trace!("Finish circuit execution"); Ok(solved_witness) } From 49da769452d0e9a9c3b8cddd8c7c520a4efcd595 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:37:31 +0000 Subject: [PATCH 047/137] chore: move module related code from `fm` to `noirc-frontend` (#3806) # Description ## Problem\* Resolves #3799 ## Summary\* This is a relatively quick and dirty resolution to #3799. We may want to integrate these functions into `ModCollector` as methods but I think they also work standalone plus it means that we can transfer the tests across without needing to create a `ModCollector` instance. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 1 + Cargo.toml | 1 + compiler/fm/Cargo.toml | 2 +- compiler/fm/src/lib.rs | 99 --------------- compiler/noirc_frontend/Cargo.toml | 1 + .../src/hir/def_collector/dc_mod.rs | 119 +++++++++++++++++- tooling/backend_interface/Cargo.toml | 2 +- tooling/nargo/Cargo.toml | 2 +- tooling/nargo_cli/Cargo.toml | 2 +- 9 files changed, 123 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2606d211ab..442d9750be0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2734,6 +2734,7 @@ dependencies = [ "smol_str", "strum", "strum_macros", + "tempfile", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 7cd00ee0a60..bcc98debdc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,6 +121,7 @@ num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" log = "0.4.17" +tempfile = "3.6.0" tracing = "0.1.40" diff --git a/compiler/fm/Cargo.toml b/compiler/fm/Cargo.toml index 699f709e9b5..42e4b0c25d7 100644 --- a/compiler/fm/Cargo.toml +++ b/compiler/fm/Cargo.toml @@ -12,5 +12,5 @@ codespan-reporting.workspace = true serde.workspace = true [dev-dependencies] -tempfile = "3.2.0" +tempfile.workspace = true iter-extended.workspace = true diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 2a54e58d3b9..47b245eea2e 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -99,54 +99,12 @@ impl FileManager { self.id_to_path.get(&file_id).unwrap().as_path() } - // TODO: This should also ideally not be here, so that the file manager - // TODO: does not know about rust modules. - // TODO: Ideally this is moved to def_collector_mod and we make this method accept a FileManager - pub fn find_module(&self, anchor: FileId, mod_name: &str) -> Result { - let anchor_path = self.path(anchor).with_extension(""); - let anchor_dir = anchor_path.parent().unwrap(); - - // if `anchor` is a `main.nr`, `lib.nr`, `mod.nr` or `{mod_name}.nr`, we check siblings of - // the anchor at `base/mod_name.nr`. - let candidate = if should_check_siblings_for_module(&anchor_path, anchor_dir) { - anchor_dir.join(format!("{mod_name}.{FILE_EXTENSION}")) - } else { - // Otherwise, we check for children of the anchor at `base/anchor/mod_name.nr` - anchor_path.join(format!("{mod_name}.{FILE_EXTENSION}")) - }; - - self.name_to_id(candidate.clone()) - .ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) - } - // TODO: This should accept a &Path instead of a PathBuf pub fn name_to_id(&self, file_name: PathBuf) -> Option { self.file_map.get_file_id(&PathString::from_path(file_name)) } } -// TODO: This should not be here because the file manager should not know about the -// TODO: rust modules. See comment on `find_module`` -// TODO: Moreover, the check for main, lib, mod should ideally not be done here -/// Returns true if a module's child module's are expected to be in the same directory. -/// Returns false if they are expected to be in a subdirectory matching the name of the module. -fn should_check_siblings_for_module(module_path: &Path, parent_path: &Path) -> bool { - if let Some(filename) = module_path.file_stem() { - // This check also means a `main.nr` or `lib.nr` file outside of the crate root would - // check its same directory for child modules instead of a subdirectory. Should we prohibit - // `main.nr` and `lib.nr` files outside of the crate root? - filename == "main" - || filename == "lib" - || filename == "mod" - || Some(filename) == parent_path.file_stem() - } else { - // If there's no filename, we arbitrarily return true. - // Alternatively, we could panic, but this is left to a different step where we - // ideally have some source location to issue an error. - true - } -} - pub trait NormalizePath { /// Replacement for `std::fs::canonicalize` that doesn't verify the path exists. /// @@ -236,22 +194,6 @@ mod tests { file_path } - #[test] - fn path_resolve_file_module() { - let dir = tempdir().unwrap(); - - let entry_file_name = Path::new("my_dummy_file.nr"); - create_dummy_file(&dir, entry_file_name); - - let mut fm = FileManager::new(dir.path()); - - let file_id = fm.add_file_with_source(entry_file_name, "fn foo() {}".to_string()).unwrap(); - - let dep_file_name = Path::new("foo.nr"); - create_dummy_file(&dir, dep_file_name); - fm.find_module(file_id, "foo").unwrap_err(); - } - #[test] fn path_resolve_file_module_other_ext() { let dir = tempdir().unwrap(); @@ -265,47 +207,6 @@ mod tests { assert!(fm.path(file_id).ends_with("foo.nr")); } - #[test] - fn path_resolve_sub_module() { - let dir = tempdir().unwrap(); - let mut fm = FileManager::new(dir.path()); - - // Create a lib.nr file at the root. - // we now have dir/lib.nr - let lib_nr_path = create_dummy_file(&dir, Path::new("lib.nr")); - let file_id = fm - .add_file_with_source(lib_nr_path.as_path(), "fn foo() {}".to_string()) - .expect("could not add file to file manager and obtain a FileId"); - - // Create a sub directory - // we now have: - // - dir/lib.nr - // - dir/sub_dir - let sub_dir = TempDir::new_in(&dir).unwrap(); - let sub_dir_name = sub_dir.path().file_name().unwrap().to_str().unwrap(); - - // Add foo.nr to the subdirectory - // we no have: - // - dir/lib.nr - // - dir/sub_dir/foo.nr - let foo_nr_path = create_dummy_file(&sub_dir, Path::new("foo.nr")); - fm.add_file_with_source(foo_nr_path.as_path(), "fn foo() {}".to_string()); - - // Add a parent module for the sub_dir - // we no have: - // - dir/lib.nr - // - dir/sub_dir.nr - // - dir/sub_dir/foo.nr - let sub_dir_nr_path = create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); - fm.add_file_with_source(sub_dir_nr_path.as_path(), "fn foo() {}".to_string()); - - // First check for the sub_dir.nr file and add it to the FileManager - let sub_dir_file_id = fm.find_module(file_id, sub_dir_name).unwrap(); - - // Now check for files in it's subdirectory - fm.find_module(sub_dir_file_id, "foo").unwrap(); - } - /// Tests that two identical files that have different paths are treated as the same file /// e.g. if we start in the dir ./src and have a file ../../foo.nr /// that should be treated as the same file as ../ starting in ./ diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index 1565a105522..aa3a8e9f6b8 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -27,3 +27,4 @@ log.workspace = true [dev-dependencies] strum = "0.24" strum_macros = "0.24" +tempfile.workspace = true diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index aa1c658bade..04791b11b2a 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,7 +1,7 @@ -use std::{collections::HashMap, vec}; +use std::{collections::HashMap, path::Path, vec}; use acvm::acir::acir_field::FieldOptions; -use fm::FileId; +use fm::{FileId, FileManager, FILE_EXTENSION}; use noirc_errors::Location; use crate::{ @@ -524,7 +524,7 @@ impl<'a> ModCollector<'a> { ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let child_file_id = - match context.file_manager.find_module(self.file_id, &mod_name.0.contents) { + match find_module(&context.file_manager, self.file_id, &mod_name.0.contents) { Ok(child_file_id) => child_file_id, Err(expected_path) => { let mod_name = mod_name.clone(); @@ -628,3 +628,116 @@ impl<'a> ModCollector<'a> { Ok(LocalModuleId(module_id)) } } + +fn find_module( + file_manager: &FileManager, + anchor: FileId, + mod_name: &str, +) -> Result { + let anchor_path = file_manager.path(anchor).with_extension(""); + let anchor_dir = anchor_path.parent().unwrap(); + + // if `anchor` is a `main.nr`, `lib.nr`, `mod.nr` or `{mod_name}.nr`, we check siblings of + // the anchor at `base/mod_name.nr`. + let candidate = if should_check_siblings_for_module(&anchor_path, anchor_dir) { + anchor_dir.join(format!("{mod_name}.{FILE_EXTENSION}")) + } else { + // Otherwise, we check for children of the anchor at `base/anchor/mod_name.nr` + anchor_path.join(format!("{mod_name}.{FILE_EXTENSION}")) + }; + + file_manager + .name_to_id(candidate.clone()) + .ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) +} + +/// Returns true if a module's child modules are expected to be in the same directory. +/// Returns false if they are expected to be in a subdirectory matching the name of the module. +fn should_check_siblings_for_module(module_path: &Path, parent_path: &Path) -> bool { + if let Some(filename) = module_path.file_stem() { + // This check also means a `main.nr` or `lib.nr` file outside of the crate root would + // check its same directory for child modules instead of a subdirectory. Should we prohibit + // `main.nr` and `lib.nr` files outside of the crate root? + filename == "main" + || filename == "lib" + || filename == "mod" + || Some(filename) == parent_path.file_stem() + } else { + // If there's no filename, we arbitrarily return true. + // Alternatively, we could panic, but this is left to a different step where we + // ideally have some source location to issue an error. + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { + let file_path = dir.path().join(file_name); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path + } + + #[test] + fn path_resolve_file_module() { + let dir = tempdir().unwrap(); + + let entry_file_name = Path::new("my_dummy_file.nr"); + create_dummy_file(&dir, entry_file_name); + + let mut fm = FileManager::new(dir.path()); + + let file_id = fm.add_file_with_source(entry_file_name, "fn foo() {}".to_string()).unwrap(); + + let dep_file_name = Path::new("foo.nr"); + create_dummy_file(&dir, dep_file_name); + find_module(&fm, file_id, "foo").unwrap_err(); + } + + #[test] + fn path_resolve_sub_module() { + let dir = tempdir().unwrap(); + let mut fm = FileManager::new(dir.path()); + + // Create a lib.nr file at the root. + // we now have dir/lib.nr + let lib_nr_path = create_dummy_file(&dir, Path::new("lib.nr")); + let file_id = fm + .add_file_with_source(lib_nr_path.as_path(), "fn foo() {}".to_string()) + .expect("could not add file to file manager and obtain a FileId"); + + // Create a sub directory + // we now have: + // - dir/lib.nr + // - dir/sub_dir + let sub_dir = TempDir::new_in(&dir).unwrap(); + let sub_dir_name = sub_dir.path().file_name().unwrap().to_str().unwrap(); + + // Add foo.nr to the subdirectory + // we no have: + // - dir/lib.nr + // - dir/sub_dir/foo.nr + let foo_nr_path = create_dummy_file(&sub_dir, Path::new("foo.nr")); + fm.add_file_with_source(foo_nr_path.as_path(), "fn foo() {}".to_string()); + + // Add a parent module for the sub_dir + // we no have: + // - dir/lib.nr + // - dir/sub_dir.nr + // - dir/sub_dir/foo.nr + let sub_dir_nr_path = create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); + fm.add_file_with_source(sub_dir_nr_path.as_path(), "fn foo() {}".to_string()); + + // First check for the sub_dir.nr file and add it to the FileManager + let sub_dir_file_id = find_module(&fm, file_id, sub_dir_name).unwrap(); + + // Now check for files in it's subdirectory + find_module(&fm, sub_dir_file_id, "foo").unwrap(); + } +} diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml index a9217af65d2..32c5d28e3b0 100644 --- a/tooling/backend_interface/Cargo.toml +++ b/tooling/backend_interface/Cargo.toml @@ -18,7 +18,7 @@ serde_json.workspace = true bb_abstraction_leaks.workspace = true log.workspace = true -tempfile = "3.6.0" +tempfile.workspace = true ## bb binary downloading tar = "~0.4.15" diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index ec4e1488809..f0733d7ad44 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -30,4 +30,4 @@ rayon = "1.8.0" [dev-dependencies] # TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` # TODO: once that method is moved to nargo_cli, we can move this dependency to nargo_cli -tempfile = "3.2.0" +tempfile.workspace = true \ No newline at end of file diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 008b1233cd8..2f99fefb778 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -62,7 +62,7 @@ tracing-appender = "0.2.3" tokio-util = { version = "0.7.8", features = ["compat"] } [dev-dependencies] -tempfile = "3.6.0" +tempfile.workspace = true dirs.workspace = true assert_cmd = "2.0.8" assert_fs = "1.0.10" From ea4d89d34a839f4e501a56282994054a6464fef2 Mon Sep 17 00:00:00 2001 From: jfecher Date: Thu, 14 Dec 2023 16:15:33 -0600 Subject: [PATCH 048/137] chore: Add missing generics to trait docs (#3810) # Description ## Problem\* Resolves ## Summary\* Fixes an issue with the trait documentation where two methods were missing the brackets to introduce their generic parameters. I also renamed the generic `S` to `T` to match the paragraph above it talking about "all types `T` that implement `Area`" ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/explanations/noir/traits.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/explanations/noir/traits.md b/docs/docs/explanations/noir/traits.md index d24deaa84da..7ba07e74f40 100644 --- a/docs/docs/explanations/noir/traits.md +++ b/docs/docs/explanations/noir/traits.md @@ -53,7 +53,7 @@ trait Area { fn area(self) -> Field; } -fn log_area(shape: S) where S: Area { +fn log_area(shape: T) where T: Area { println(shape.area()); } ``` @@ -85,7 +85,7 @@ As seen in `log_area` above, when we want to create a function or method that is a trait, we can add a where clause to the generic function. ```rust -fn log_area(shape: S) where S: Area { +fn log_area(shape: T) where T: Area { println(shape.area()); } ``` @@ -94,7 +94,7 @@ It is also possible to apply multiple trait constraints on the same variable at operator. Similarly, we can have multiple trait constraints by separating each with a comma: ```rust -fn foo(elements: [T], thing: U) where +fn foo(elements: [T], thing: U) where T: Default + Add + Eq, U: Bar, { From d617ea4266f188328af33dac17913115e16b52cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Fri, 15 Dec 2023 00:07:51 +0000 Subject: [PATCH 049/137] chore: filtering patches from docs deployment script (#3779) # Description This change makes the script that runs before `yarn build` filter down the patches to the latest patch of every major. ## Problem\* This script used to remove: - Prereleases - Nightlies (which are prereleases) - "Aztec" versions However, this would mean that every patch, as long as it was stable, would have its own docs deployed. This would lead to docs having three patch versions, which shouldn't even differ (they're patches, no breaking changes), like 0.19.1, 0.19.2, etc ## Summary\* This change simplifies the script by removing some computation that was there just for debugging reasons. It also stops assuming all "aztec" versions are prereleases. And finally, it filters down only for the latest patch version. ## Additional Context Another way of doing it (which is how we're doing it now) is to just make all non-latest patch as prereleases, which is kinda annoying. With this change, it shouldn't matter. --- docs/.gitignore | 1 + docs/package.json | 4 +-- docs/scripts/setStable.ts | 59 +++++++++++++++++++++++++-------------- docs/tsconfig.json | 3 +- docs/versions.json | 4 --- versions.json | 4 --- 6 files changed, 43 insertions(+), 32 deletions(-) delete mode 100644 docs/versions.json delete mode 100644 versions.json diff --git a/docs/.gitignore b/docs/.gitignore index e4abc8785c7..4f6eee8284e 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -22,3 +22,4 @@ yarn-debug.log* yarn-error.log* package-lock.json +versions.json diff --git a/docs/package.json b/docs/package.json index 86f15b0a311..1fa4ab79b85 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,9 +3,9 @@ "version": "0.0.0", "private": true, "scripts": { - "start": "docusaurus start", + "start": "yarn version::stables && docusaurus start", "build": "yarn version::stables && docusaurus build", - "version::stables": "node --loader ts-node/esm ./scripts/setStable.ts", + "version::stables": "ts-node ./scripts/setStable.ts", "serve": "serve build" }, "dependencies": { diff --git a/docs/scripts/setStable.ts b/docs/scripts/setStable.ts index e23d990763a..0f86c4afd59 100644 --- a/docs/scripts/setStable.ts +++ b/docs/scripts/setStable.ts @@ -1,13 +1,13 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ const fs = require('fs'); const path = require('path'); const axios = require('axios'); +const GITHUB_PAGES = 3; const IGNORE_VERSIONS = ['0.16.0']; -const NUMBER_OF_VERSIONS_TO_SHOW = 4; +const NUMBER_OF_VERSIONS_TO_SHOW = 2; async function main() { - const versionsFile = path.resolve('../versions.json'); - const axiosOpts = { params: { per_page: 100 }, headers: {}, @@ -15,24 +15,41 @@ async function main() { if (process.env.GITHUB_TOKEN) axiosOpts.headers = { Authorization: `token ${process.env.GITHUB_TOKEN}` }; - const { data } = await axios.get('https://api.github.com/repos/noir-lang/noir/releases', axiosOpts); - - const all = data.map((release) => release.tag_name); - console.log('All versions: ', all); - const aztecs = data.filter((release) => release.tag_name.includes('aztec')).map((release) => release.tag_name); - console.log('Removing aztecs: ', aztecs); - const prereleases = data.filter((release) => !release.prerelease).map((release) => release.tag_name); - console.log('Removing prereleases: ', prereleases); - - const stables = data - .filter((release) => !release.prerelease && !release.tag_name.includes('aztec')) - .filter((release) => !IGNORE_VERSIONS.includes(release.tag_name.replace('v', ''))) - .map((release) => release.tag_name) - .slice(0, NUMBER_OF_VERSIONS_TO_SHOW); - - console.log('Stables: ', stables); - - fs.writeFileSync(versionsFile, JSON.stringify(stables, null, 2)); + let stables = []; + console.log('Retrieved versions:'); + + for (let i = 0; i < GITHUB_PAGES; i++) { + const { data } = await axios.get(`https://api.github.com/repos/noir-lang/noir/releases?page=${i + 1}`, axiosOpts); + + console.log(data.map((release) => release.tag_name)); + stables.push( + ...data + .filter( + (release) => + !release.prerelease && !release.tag_name.includes('aztec') && !release.tag_name.includes('aztec'), + ) + .filter((release) => !IGNORE_VERSIONS.includes(release.tag_name.replace('v', ''))) + .map((release) => release.tag_name), + ); + } + + stables = stables.slice(0, NUMBER_OF_VERSIONS_TO_SHOW); + + console.log('Filtered down to stables: ', stables); + + const onlyLatestPatches = []; + const minorsSet = new Set(stables.map((el) => el.split('.')[1])); + for (const minor of minorsSet) { + const minorVersions = stables.filter((el) => el.split('.')[1] === minor); + const max = minorVersions.reduce((prev, current) => { + return prev > current ? prev : current; + }); + onlyLatestPatches.push(max); + } + + console.log('Only latest patches: ', onlyLatestPatches); + + fs.writeFileSync(path.resolve(__dirname, '../versions.json'), JSON.stringify(onlyLatestPatches, null, 2)); } main(); diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 01b56ec5988..241fcf4b5e3 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "@docusaurus/tsconfig", "compilerOptions": { - "baseUrl": "." + "baseUrl": ".", + "downlevelIteration": true }, } diff --git a/docs/versions.json b/docs/versions.json deleted file mode 100644 index 7e140c94b73..00000000000 --- a/docs/versions.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "v0.19.4", - "v0.17.0" -] diff --git a/versions.json b/versions.json deleted file mode 100644 index a1c826264f4..00000000000 --- a/versions.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "v0.19.4", - "v0.17.0" -] \ No newline at end of file From 2a8af1e4141ffff61547ee1c2837a6392bd5db48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Fri, 15 Dec 2023 10:28:20 +0000 Subject: [PATCH 050/137] feat: speed up transformation of debug messages (#3815) # Description Same as https://github.com/noir-lang/noir/pull/3814 but with a different approach, by building the map of old to new inside AcirTransformationMap ## Problem\* Resolves https://github.com/noir-lang/noir/issues/3809 ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acvm/src/compiler/mod.rs | 44 ++++++++++++------- acvm-repo/acvm/src/compiler/optimizers/mod.rs | 10 ++--- .../acvm/src/compiler/transformers/mod.rs | 14 +++--- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/acvm-repo/acvm/src/compiler/mod.rs b/acvm-repo/acvm/src/compiler/mod.rs index 4abf94a2e78..0ed5b591675 100644 --- a/acvm-repo/acvm/src/compiler/mod.rs +++ b/acvm-repo/acvm/src/compiler/mod.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use acir::{ circuit::{opcodes::UnsupportedMemoryOpcode, Circuit, Opcode, OpcodeLocation}, BlackBoxFunc, @@ -27,12 +29,22 @@ pub enum CompileError { /// metadata they had about the opcodes to the new opcode structure generated after the transformation. #[derive(Debug)] pub struct AcirTransformationMap { - /// This is a vector of pointers to the old acir opcodes. The index of the vector is the new opcode index. - /// The value of the vector is the old opcode index pointed. - acir_opcode_positions: Vec, + /// Maps the old acir indices to the new acir indices + old_indices_to_new_indices: HashMap>, } impl AcirTransformationMap { + /// Builds a map from a vector of pointers to the old acir opcodes. + /// The index of the vector is the new opcode index. + /// The value of the vector is the old opcode index pointed. + fn new(acir_opcode_positions: Vec) -> Self { + let mut old_indices_to_new_indices = HashMap::with_capacity(acir_opcode_positions.len()); + for (new_index, old_index) in acir_opcode_positions.into_iter().enumerate() { + old_indices_to_new_indices.entry(old_index).or_insert_with(Vec::new).push(new_index); + } + AcirTransformationMap { old_indices_to_new_indices } + } + pub fn new_locations( &self, old_location: OpcodeLocation, @@ -42,16 +54,16 @@ impl AcirTransformationMap { OpcodeLocation::Brillig { acir_index, .. } => acir_index, }; - self.acir_opcode_positions - .iter() - .enumerate() - .filter(move |(_, &old_index)| old_index == old_acir_index) - .map(move |(new_index, _)| match old_location { - OpcodeLocation::Acir(_) => OpcodeLocation::Acir(new_index), - OpcodeLocation::Brillig { brillig_index, .. } => { - OpcodeLocation::Brillig { acir_index: new_index, brillig_index } - } - }) + self.old_indices_to_new_indices.get(&old_acir_index).into_iter().flat_map( + move |new_indices| { + new_indices.iter().map(move |new_index| match old_location { + OpcodeLocation::Acir(_) => OpcodeLocation::Acir(*new_index), + OpcodeLocation::Brillig { brillig_index, .. } => { + OpcodeLocation::Brillig { acir_index: *new_index, brillig_index } + } + }) + }, + ) } } @@ -74,11 +86,13 @@ pub fn compile( np_language: Language, is_opcode_supported: impl Fn(&Opcode) -> bool, ) -> Result<(Circuit, AcirTransformationMap), CompileError> { - let (acir, AcirTransformationMap { acir_opcode_positions }) = optimize_internal(acir); + let (acir, acir_opcode_positions) = optimize_internal(acir); - let (mut acir, transformation_map) = + let (mut acir, acir_opcode_positions) = transform_internal(acir, np_language, is_opcode_supported, acir_opcode_positions)?; + let transformation_map = AcirTransformationMap::new(acir_opcode_positions); + acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); Ok((acir, transformation_map)) diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index 6e2af4f58a1..85a97c2c7dc 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -13,7 +13,9 @@ use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { - let (mut acir, transformation_map) = optimize_internal(acir); + let (mut acir, new_opcode_positions) = optimize_internal(acir); + + let transformation_map = AcirTransformationMap::new(new_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); @@ -21,7 +23,7 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. -pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, AcirTransformationMap) { +pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { log::trace!("Start circuit optimization"); // General optimizer pass @@ -52,9 +54,7 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, AcirTransformationMa let (acir, acir_opcode_positions) = range_optimizer.replace_redundant_ranges(acir_opcode_positions); - let transformation_map = AcirTransformationMap { acir_opcode_positions }; - log::trace!("Finish circuit optimization"); - (acir, transformation_map) + (acir, acir_opcode_positions) } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index 00ee9dc7ce5..c4c94e371b8 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -27,9 +27,11 @@ pub fn transform( // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) let acir_opcode_positions = acir.opcodes.iter().enumerate().map(|(i, _)| i).collect(); - let (mut acir, transformation_map) = + let (mut acir, acir_opcode_positions) = transform_internal(acir, np_language, is_opcode_supported, acir_opcode_positions)?; + let transformation_map = AcirTransformationMap::new(acir_opcode_positions); + acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); Ok((acir, transformation_map)) @@ -43,7 +45,7 @@ pub(super) fn transform_internal( np_language: Language, is_opcode_supported: impl Fn(&Opcode) -> bool, acir_opcode_positions: Vec, -) -> Result<(Circuit, AcirTransformationMap), CompileError> { +) -> Result<(Circuit, Vec), CompileError> { log::trace!("Start circuit transformation"); // Fallback transformer pass @@ -52,9 +54,8 @@ pub(super) fn transform_internal( let mut transformer = match &np_language { crate::Language::R1CS => { - let transformation_map = AcirTransformationMap { acir_opcode_positions }; let transformer = R1CSTransformer::new(acir); - return Ok((transformer.transform(), transformation_map)); + return Ok((transformer.transform(), acir_opcode_positions)); } crate::Language::PLONKCSat { width } => { let mut csat = CSatTransformer::new(*width); @@ -216,10 +217,7 @@ pub(super) fn transform_internal( ..acir }; - let transformation_map = - AcirTransformationMap { acir_opcode_positions: new_acir_opcode_positions }; - log::trace!("Finish circuit transformation"); - Ok((acir, transformation_map)) + Ok((acir, new_acir_opcode_positions)) } From 45ea515dc9d761e01cb2456786eaf34f25e047d9 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:05:14 +0000 Subject: [PATCH 051/137] chore: move empty programs to correct test directory (#3818) # Description ## Problem\* Resolves ## Summary\* This pulls across the housekeeping changes from #3814 which weren't included in #3815 ## Additional Context ## Documentation\* Check one: - x ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../brillig_set_slice_of_slice/Nargo.toml | 0 .../brillig_set_slice_of_slice/src/main.nr | 0 .../regression_3635/Nargo.toml | 0 .../regression_3635/src/main.nr | 0 test_programs/execution_success/regression_3635/Prover.toml | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename test_programs/{execution_success => compile_success_empty}/brillig_set_slice_of_slice/Nargo.toml (100%) rename test_programs/{execution_success => compile_success_empty}/brillig_set_slice_of_slice/src/main.nr (100%) rename test_programs/{execution_success => compile_success_empty}/regression_3635/Nargo.toml (100%) rename test_programs/{execution_success => compile_success_empty}/regression_3635/src/main.nr (100%) delete mode 100644 test_programs/execution_success/regression_3635/Prover.toml diff --git a/test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml b/test_programs/compile_success_empty/brillig_set_slice_of_slice/Nargo.toml similarity index 100% rename from test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml rename to test_programs/compile_success_empty/brillig_set_slice_of_slice/Nargo.toml diff --git a/test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr b/test_programs/compile_success_empty/brillig_set_slice_of_slice/src/main.nr similarity index 100% rename from test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr rename to test_programs/compile_success_empty/brillig_set_slice_of_slice/src/main.nr diff --git a/test_programs/execution_success/regression_3635/Nargo.toml b/test_programs/compile_success_empty/regression_3635/Nargo.toml similarity index 100% rename from test_programs/execution_success/regression_3635/Nargo.toml rename to test_programs/compile_success_empty/regression_3635/Nargo.toml diff --git a/test_programs/execution_success/regression_3635/src/main.nr b/test_programs/compile_success_empty/regression_3635/src/main.nr similarity index 100% rename from test_programs/execution_success/regression_3635/src/main.nr rename to test_programs/compile_success_empty/regression_3635/src/main.nr diff --git a/test_programs/execution_success/regression_3635/Prover.toml b/test_programs/execution_success/regression_3635/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 From ddfb6a84ad3cde038612d06dbb2ec26329cd862c Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:11:16 +0000 Subject: [PATCH 052/137] chore: add bootstrap sha for release-please (#3823) # Description ## Problem\* Resolves ## Summary\* This PR adds a bootstrap sha which corresponds to the failed 0.19.5 release. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- release-please-config.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index 562de471f0b..3c5397c6784 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -81,5 +81,6 @@ }, "plugins": [ "sentence-case" - ] -} + ], + "bootstrap-sha": "690cfc0468de0b9aee53ccfe832c71c16e61e5fc" +} \ No newline at end of file From e7fb36bfe2f9971eef7129d26680cccf5fbffff4 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 15 Dec 2023 16:17:16 +0000 Subject: [PATCH 053/137] chore: Release Noir(0.21.0) (#3824) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :robot: I have created a release *beep* *boop* ---
0.21.0 ## [0.21.0](https://github.com/noir-lang/noir/compare/v0.20.0...v0.21.0) (2023-12-15) ### ⚠ BREAKING CHANGES * remove unused `source-resolver` package ([#3791](https://github.com/noir-lang/noir/issues/3791)) * Make file manager read-only to the compiler ([#3760](https://github.com/noir-lang/noir/issues/3760)) ### Features * Add `prelude.nr` ([#3693](https://github.com/noir-lang/noir/issues/3693)) ([5f0f81f](https://github.com/noir-lang/noir/commit/5f0f81f7f49b021880e0bff648aa6c6d0fede46c)) * Add some traits to the stdlib ([#3796](https://github.com/noir-lang/noir/issues/3796)) ([8e11352](https://github.com/noir-lang/noir/commit/8e113526a2d78d27ed4e489f16d5604a2aaa18ea)) * Add support for writing tracing debug info to file ([#3790](https://github.com/noir-lang/noir/issues/3790)) ([98a5004](https://github.com/noir-lang/noir/commit/98a500436a68652a367ccbf77e32f8544aff73bc)) * Allow passing custom foreign call handlers when creating proofs in NoirJS ([#3764](https://github.com/noir-lang/noir/issues/3764)) ([6076e08](https://github.com/noir-lang/noir/commit/6076e08a0814bb6f3836af3c65a7b40c066b9494)) * Allow underscores in integer literals ([#3746](https://github.com/noir-lang/noir/issues/3746)) ([2c06a64](https://github.com/noir-lang/noir/commit/2c06a64e502bac6839375c5636d39a172a609a5f)) * Avoid overflow checks on boolean multiplication ([#3745](https://github.com/noir-lang/noir/issues/3745)) ([9b5b686](https://github.com/noir-lang/noir/commit/9b5b6861c3aa0e154e17598ac9994d3970f0e752)) * Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) * Dockerfile to test cargo and JS packages ([#3684](https://github.com/noir-lang/noir/issues/3684)) ([513d619](https://github.com/noir-lang/noir/commit/513d6196a0766082a3c88a4050498bae2cfa7e13)) * Docs landing page with a playground ([#3667](https://github.com/noir-lang/noir/issues/3667)) ([9a95fbe](https://github.com/noir-lang/noir/commit/9a95fbeefb2ecd5a898006530a1e054cd345bfe8)) * Enhance test information output ([#3696](https://github.com/noir-lang/noir/issues/3696)) ([468fbbc](https://github.com/noir-lang/noir/commit/468fbbca43e33b23bc662bf1d36dcb79830a291c)) * Implement print without newline ([#3650](https://github.com/noir-lang/noir/issues/3650)) ([9827dfe](https://github.com/noir-lang/noir/commit/9827dfe51118ba55da6da51ab8bf45cffd2ca756)) * **lsp:** Add goto definition for locals ([#3705](https://github.com/noir-lang/noir/issues/3705)) ([9dd465c](https://github.com/noir-lang/noir/commit/9dd465c23e286481fa9a35632d133901f86d5883)) * **lsp:** Add goto definition for structs ([#3718](https://github.com/noir-lang/noir/issues/3718)) ([a576c5b](https://github.com/noir-lang/noir/commit/a576c5bba6ab92eb4798715a43475808ac954fba)) * Optimize out unnecessary truncation instructions ([#3717](https://github.com/noir-lang/noir/issues/3717)) ([c9c72ae](https://github.com/noir-lang/noir/commit/c9c72ae7b80aa9504a082dd083b19d4b80d954c5)) * Remove experimental feature warning for traits ([#3783](https://github.com/noir-lang/noir/issues/3783)) ([cb52242](https://github.com/noir-lang/noir/commit/cb522429592477c2b0544f3b3026a1a946b0e5b1)) * Reorganizing docs to fit diataxis framework ([#3711](https://github.com/noir-lang/noir/issues/3711)) ([54a1ed5](https://github.com/noir-lang/noir/commit/54a1ed58c991eefa7ac9304b894c7046c294487b)) * Simplify explicit equality assertions to assert equality directly ([#3708](https://github.com/noir-lang/noir/issues/3708)) ([2fc46e2](https://github.com/noir-lang/noir/commit/2fc46e2269bba8d9ad6ae5fcea10e64dce9b3745)) * Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) ### Bug Fixes * `try_unify` no longer binds types on failure ([#3697](https://github.com/noir-lang/noir/issues/3697)) ([f03e581](https://github.com/noir-lang/noir/commit/f03e5812439bdf9d1aedc69debdc50ba5dba2049)) * Add missing assertion to test ([#3765](https://github.com/noir-lang/noir/issues/3765)) ([bcbe116](https://github.com/noir-lang/noir/commit/bcbe11613b7205476a49ad0d588b868b4fc43ba1)) * Add negative integer literals ([#3690](https://github.com/noir-lang/noir/issues/3690)) ([8b3a68f](https://github.com/noir-lang/noir/commit/8b3a68f5286c09e1f612dbcfff3fe41023ab7109)) * Allow trait method references from the trait name ([#3774](https://github.com/noir-lang/noir/issues/3774)) ([cfa34d4](https://github.com/noir-lang/noir/commit/cfa34d4d913dbd35f8329430e0d58830e069d6ff)) * Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) * **docs:** Trigger `update-docs` workflow when the `release-please` PR gets merged and not on every merge to master ([#3677](https://github.com/noir-lang/noir/issues/3677)) ([9a3d1d2](https://github.com/noir-lang/noir/commit/9a3d1d2cf647cd583344f8da122fed1acbca9397)) * Initialise strings as u8 array ([#3682](https://github.com/noir-lang/noir/issues/3682)) ([8da40b7](https://github.com/noir-lang/noir/commit/8da40b75a36ebac51d5377311db3c55fa339dcac)) * **lsp:** Package resolution on save ([#3794](https://github.com/noir-lang/noir/issues/3794)) ([14f2fff](https://github.com/noir-lang/noir/commit/14f2fffeb3de5f653c11694ee3c5e5d62aaa34ec)) * Parse negative integer literals ([#3698](https://github.com/noir-lang/noir/issues/3698)) ([463ab06](https://github.com/noir-lang/noir/commit/463ab060075db1915127c3f6cef11bfed9d40109)) * Pub is required on return for entry points ([#3616](https://github.com/noir-lang/noir/issues/3616)) ([7f1d796](https://github.com/noir-lang/noir/commit/7f1d7968368734e02b152e2e907dc7af9e1604c8)) * Remove `noirc_driver/aztec` feature flag in docker ([#3784](https://github.com/noir-lang/noir/issues/3784)) ([a48d562](https://github.com/noir-lang/noir/commit/a48d562b59aa2009a9c9b65dd71e11cdd8d06cf0)) * Remove include-keys option ([#3692](https://github.com/noir-lang/noir/issues/3692)) ([95d7ce2](https://github.com/noir-lang/noir/commit/95d7ce21016e3603bf279efb970536ad32d89a3a)) * Revert chnage to modify version in workspace file for acvm dependencies ([#3673](https://github.com/noir-lang/noir/issues/3673)) ([0696f75](https://github.com/noir-lang/noir/commit/0696f755364293bcc7ebc7a0def0dcafede2e543)) * Sequence update-lockfile workflow so it gets modified after the ACVM version in the root has been changed ([#3676](https://github.com/noir-lang/noir/issues/3676)) ([c00cd85](https://github.com/noir-lang/noir/commit/c00cd8537836f8e4d8559b01d16dfdd1b5cad519)) * **ssa:** Handle array arguments to side effectual constrain statements ([#3740](https://github.com/noir-lang/noir/issues/3740)) ([028d65e](https://github.com/noir-lang/noir/commit/028d65ea71f9c11e69784d06e0f9768668455f83)) * Stop cloning Traits! ([#3736](https://github.com/noir-lang/noir/issues/3736)) ([fcff412](https://github.com/noir-lang/noir/commit/fcff412bb39a04a5c88506ae5a5ee2fbdefd93ef)) * Stop issuing unused variable warnings for variables in trait definitions ([#3797](https://github.com/noir-lang/noir/issues/3797)) ([0bb44c3](https://github.com/noir-lang/noir/commit/0bb44c3bbc63d385d77d93da6abd07214bcfd700)) * Unsigned integers cannot be negated ([#3688](https://github.com/noir-lang/noir/issues/3688)) ([f904ae1](https://github.com/noir-lang/noir/commit/f904ae1065af74652b2111ea17b72f994de37472)) ### Miscellaneous Chores * Make file manager read-only to the compiler ([#3760](https://github.com/noir-lang/noir/issues/3760)) ([e3dcc21](https://github.com/noir-lang/noir/commit/e3dcc21cb2c0fef7f28f50b018747c4f09609b11)) * Remove unused `source-resolver` package ([#3791](https://github.com/noir-lang/noir/issues/3791)) ([57d2505](https://github.com/noir-lang/noir/commit/57d2505d53e2233becd1e2a7de882c4acb518eff))
0.37.1 ## [0.37.1](https://github.com/noir-lang/noir/compare/v0.37.0...v0.37.1) (2023-12-15) ### Features * Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) * Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) ### Bug Fixes * Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2))
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 4 +- CHANGELOG.md | 57 +++++++++++++++++++ Cargo.toml | 18 +++--- acvm-repo/CHANGELOG.md | 13 +++++ acvm-repo/acir/Cargo.toml | 2 +- acvm-repo/acir_field/Cargo.toml | 2 +- acvm-repo/acvm/Cargo.toml | 2 +- acvm-repo/acvm_js/Cargo.toml | 2 +- acvm-repo/acvm_js/package.json | 2 +- .../barretenberg_blackbox_solver/Cargo.toml | 2 +- acvm-repo/blackbox_solver/Cargo.toml | 2 +- acvm-repo/brillig/Cargo.toml | 2 +- acvm-repo/brillig_vm/Cargo.toml | 2 +- acvm-repo/stdlib/Cargo.toml | 2 +- compiler/wasm/package.json | 2 +- flake.nix | 2 +- tooling/noir_codegen/package.json | 2 +- tooling/noir_js/package.json | 2 +- .../noir_js_backend_barretenberg/package.json | 2 +- tooling/noir_js_types/package.json | 2 +- tooling/noirc_abi_wasm/package.json | 2 +- 21 files changed, 98 insertions(+), 28 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9e3193c22fb..d722662cd12 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.20.0", - "acvm-repo": "0.37.0" + ".": "0.21.0", + "acvm-repo": "0.37.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9abb97f6860..6a6fdcef0fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,62 @@ # Changelog +## [0.21.0](https://github.com/noir-lang/noir/compare/v0.20.0...v0.21.0) (2023-12-15) + + +### ⚠ BREAKING CHANGES + +* remove unused `source-resolver` package ([#3791](https://github.com/noir-lang/noir/issues/3791)) +* Make file manager read-only to the compiler ([#3760](https://github.com/noir-lang/noir/issues/3760)) + +### Features + +* Add `prelude.nr` ([#3693](https://github.com/noir-lang/noir/issues/3693)) ([5f0f81f](https://github.com/noir-lang/noir/commit/5f0f81f7f49b021880e0bff648aa6c6d0fede46c)) +* Add some traits to the stdlib ([#3796](https://github.com/noir-lang/noir/issues/3796)) ([8e11352](https://github.com/noir-lang/noir/commit/8e113526a2d78d27ed4e489f16d5604a2aaa18ea)) +* Add support for writing tracing debug info to file ([#3790](https://github.com/noir-lang/noir/issues/3790)) ([98a5004](https://github.com/noir-lang/noir/commit/98a500436a68652a367ccbf77e32f8544aff73bc)) +* Allow passing custom foreign call handlers when creating proofs in NoirJS ([#3764](https://github.com/noir-lang/noir/issues/3764)) ([6076e08](https://github.com/noir-lang/noir/commit/6076e08a0814bb6f3836af3c65a7b40c066b9494)) +* Allow underscores in integer literals ([#3746](https://github.com/noir-lang/noir/issues/3746)) ([2c06a64](https://github.com/noir-lang/noir/commit/2c06a64e502bac6839375c5636d39a172a609a5f)) +* Avoid overflow checks on boolean multiplication ([#3745](https://github.com/noir-lang/noir/issues/3745)) ([9b5b686](https://github.com/noir-lang/noir/commit/9b5b6861c3aa0e154e17598ac9994d3970f0e752)) +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Dockerfile to test cargo and JS packages ([#3684](https://github.com/noir-lang/noir/issues/3684)) ([513d619](https://github.com/noir-lang/noir/commit/513d6196a0766082a3c88a4050498bae2cfa7e13)) +* Docs landing page with a playground ([#3667](https://github.com/noir-lang/noir/issues/3667)) ([9a95fbe](https://github.com/noir-lang/noir/commit/9a95fbeefb2ecd5a898006530a1e054cd345bfe8)) +* Enhance test information output ([#3696](https://github.com/noir-lang/noir/issues/3696)) ([468fbbc](https://github.com/noir-lang/noir/commit/468fbbca43e33b23bc662bf1d36dcb79830a291c)) +* Implement print without newline ([#3650](https://github.com/noir-lang/noir/issues/3650)) ([9827dfe](https://github.com/noir-lang/noir/commit/9827dfe51118ba55da6da51ab8bf45cffd2ca756)) +* **lsp:** Add goto definition for locals ([#3705](https://github.com/noir-lang/noir/issues/3705)) ([9dd465c](https://github.com/noir-lang/noir/commit/9dd465c23e286481fa9a35632d133901f86d5883)) +* **lsp:** Add goto definition for structs ([#3718](https://github.com/noir-lang/noir/issues/3718)) ([a576c5b](https://github.com/noir-lang/noir/commit/a576c5bba6ab92eb4798715a43475808ac954fba)) +* Optimize out unnecessary truncation instructions ([#3717](https://github.com/noir-lang/noir/issues/3717)) ([c9c72ae](https://github.com/noir-lang/noir/commit/c9c72ae7b80aa9504a082dd083b19d4b80d954c5)) +* Remove experimental feature warning for traits ([#3783](https://github.com/noir-lang/noir/issues/3783)) ([cb52242](https://github.com/noir-lang/noir/commit/cb522429592477c2b0544f3b3026a1a946b0e5b1)) +* Reorganizing docs to fit diataxis framework ([#3711](https://github.com/noir-lang/noir/issues/3711)) ([54a1ed5](https://github.com/noir-lang/noir/commit/54a1ed58c991eefa7ac9304b894c7046c294487b)) +* Simplify explicit equality assertions to assert equality directly ([#3708](https://github.com/noir-lang/noir/issues/3708)) ([2fc46e2](https://github.com/noir-lang/noir/commit/2fc46e2269bba8d9ad6ae5fcea10e64dce9b3745)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) + + +### Bug Fixes + +* `try_unify` no longer binds types on failure ([#3697](https://github.com/noir-lang/noir/issues/3697)) ([f03e581](https://github.com/noir-lang/noir/commit/f03e5812439bdf9d1aedc69debdc50ba5dba2049)) +* Add missing assertion to test ([#3765](https://github.com/noir-lang/noir/issues/3765)) ([bcbe116](https://github.com/noir-lang/noir/commit/bcbe11613b7205476a49ad0d588b868b4fc43ba1)) +* Add negative integer literals ([#3690](https://github.com/noir-lang/noir/issues/3690)) ([8b3a68f](https://github.com/noir-lang/noir/commit/8b3a68f5286c09e1f612dbcfff3fe41023ab7109)) +* Allow trait method references from the trait name ([#3774](https://github.com/noir-lang/noir/issues/3774)) ([cfa34d4](https://github.com/noir-lang/noir/commit/cfa34d4d913dbd35f8329430e0d58830e069d6ff)) +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) +* **docs:** Trigger `update-docs` workflow when the `release-please` PR gets merged and not on every merge to master ([#3677](https://github.com/noir-lang/noir/issues/3677)) ([9a3d1d2](https://github.com/noir-lang/noir/commit/9a3d1d2cf647cd583344f8da122fed1acbca9397)) +* Initialise strings as u8 array ([#3682](https://github.com/noir-lang/noir/issues/3682)) ([8da40b7](https://github.com/noir-lang/noir/commit/8da40b75a36ebac51d5377311db3c55fa339dcac)) +* **lsp:** Package resolution on save ([#3794](https://github.com/noir-lang/noir/issues/3794)) ([14f2fff](https://github.com/noir-lang/noir/commit/14f2fffeb3de5f653c11694ee3c5e5d62aaa34ec)) +* Parse negative integer literals ([#3698](https://github.com/noir-lang/noir/issues/3698)) ([463ab06](https://github.com/noir-lang/noir/commit/463ab060075db1915127c3f6cef11bfed9d40109)) +* Pub is required on return for entry points ([#3616](https://github.com/noir-lang/noir/issues/3616)) ([7f1d796](https://github.com/noir-lang/noir/commit/7f1d7968368734e02b152e2e907dc7af9e1604c8)) +* Remove `noirc_driver/aztec` feature flag in docker ([#3784](https://github.com/noir-lang/noir/issues/3784)) ([a48d562](https://github.com/noir-lang/noir/commit/a48d562b59aa2009a9c9b65dd71e11cdd8d06cf0)) +* Remove include-keys option ([#3692](https://github.com/noir-lang/noir/issues/3692)) ([95d7ce2](https://github.com/noir-lang/noir/commit/95d7ce21016e3603bf279efb970536ad32d89a3a)) +* Revert chnage to modify version in workspace file for acvm dependencies ([#3673](https://github.com/noir-lang/noir/issues/3673)) ([0696f75](https://github.com/noir-lang/noir/commit/0696f755364293bcc7ebc7a0def0dcafede2e543)) +* Sequence update-lockfile workflow so it gets modified after the ACVM version in the root has been changed ([#3676](https://github.com/noir-lang/noir/issues/3676)) ([c00cd85](https://github.com/noir-lang/noir/commit/c00cd8537836f8e4d8559b01d16dfdd1b5cad519)) +* **ssa:** Handle array arguments to side effectual constrain statements ([#3740](https://github.com/noir-lang/noir/issues/3740)) ([028d65e](https://github.com/noir-lang/noir/commit/028d65ea71f9c11e69784d06e0f9768668455f83)) +* Stop cloning Traits! ([#3736](https://github.com/noir-lang/noir/issues/3736)) ([fcff412](https://github.com/noir-lang/noir/commit/fcff412bb39a04a5c88506ae5a5ee2fbdefd93ef)) +* Stop issuing unused variable warnings for variables in trait definitions ([#3797](https://github.com/noir-lang/noir/issues/3797)) ([0bb44c3](https://github.com/noir-lang/noir/commit/0bb44c3bbc63d385d77d93da6abd07214bcfd700)) +* Unsigned integers cannot be negated ([#3688](https://github.com/noir-lang/noir/issues/3688)) ([f904ae1](https://github.com/noir-lang/noir/commit/f904ae1065af74652b2111ea17b72f994de37472)) + + +### Miscellaneous Chores + +* Make file manager read-only to the compiler ([#3760](https://github.com/noir-lang/noir/issues/3760)) ([e3dcc21](https://github.com/noir-lang/noir/commit/e3dcc21cb2c0fef7f28f50b018747c4f09609b11)) +* Remove unused `source-resolver` package ([#3791](https://github.com/noir-lang/noir/issues/3791)) ([57d2505](https://github.com/noir-lang/noir/commit/57d2505d53e2233becd1e2a7de882c4acb518eff)) + ## [0.20.0](https://github.com/noir-lang/noir/compare/v0.19.5...v0.20.0) (2023-12-01) diff --git a/Cargo.toml b/Cargo.toml index bcc98debdc8..a49b7c97f1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.20.0" +version = "0.21.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -50,14 +50,14 @@ repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.37.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.37.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.37.0", path = "acvm-repo/acvm" } -stdlib = { version = "0.37.0", package = "acvm_stdlib", path = "acvm-repo/stdlib", default-features = false } -brillig = { version = "0.37.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.37.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.37.0", path = "acvm-repo/blackbox_solver", default-features = false } -barretenberg_blackbox_solver = { version = "0.37.0", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } +acir_field = { version = "0.37.1", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.37.1", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.37.1", path = "acvm-repo/acvm" } +stdlib = { version = "0.37.1", package = "acvm_stdlib", path = "acvm-repo/stdlib", default-features = false } +brillig = { version = "0.37.1", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.37.1", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.37.1", path = "acvm-repo/blackbox_solver", default-features = false } +barretenberg_blackbox_solver = { version = "0.37.1", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } # Noir compiler workspace dependencies arena = { path = "compiler/utils/arena" } diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index fea0029744b..d65863989dd 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.37.1](https://github.com/noir-lang/noir/compare/v0.37.0...v0.37.1) (2023-12-15) + + +### Features + +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) + + +### Bug Fixes + +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) + ## [0.37.0](https://github.com/noir-lang/noir/compare/v0.36.0...v0.37.0) (2023-12-01) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index 100ab06aff0..6c9b76561e4 100644 --- a/acvm-repo/acir/Cargo.toml +++ b/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 76030bc8863..0f17d7b4959 100644 --- a/acvm-repo/acir_field/Cargo.toml +++ b/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 2515f9012e4..6a1ac372ed8 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index f6054b49de1..c788919666f 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index a890ca40080..fbc76a1ee62 100644 --- a/acvm-repo/acvm_js/package.json +++ b/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.37.0", + "version": "0.37.1", "repository": { "type": "git", "url": "https://github.com/noir-lang/acvm.git" diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index bcf02eeab09..09b8286a1f1 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "barretenberg_blackbox_solver" description = "A wrapper around a barretenberg WASM binary to execute black box functions for which there is no rust implementation" # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index aaff52c3c04..39dd35637a9 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index 47f9b3f429e..d57f4ed26fa 100644 --- a/acvm-repo/brillig/Cargo.toml +++ b/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig_vm/Cargo.toml b/acvm-repo/brillig_vm/Cargo.toml index 8c533352dd5..b28e472636f 100644 --- a/acvm-repo/brillig_vm/Cargo.toml +++ b/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/stdlib/Cargo.toml b/acvm-repo/stdlib/Cargo.toml index de50d112df6..689411d3357 100644 --- a/acvm-repo/stdlib/Cargo.toml +++ b/acvm-repo/stdlib/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_stdlib" description = "The ACVM standard library." # x-release-please-start-version -version = "0.37.0" +version = "0.37.1" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index b57f700b661..40774c3449b 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.20.0", + "version": "0.21.0", "license": "(MIT OR Apache-2.0)", "main": "./nodejs/noir_wasm.js", "types": "./web/noir_wasm.d.ts", diff --git a/flake.nix b/flake.nix index 0ec712aa082..6688ef6ea85 100644 --- a/flake.nix +++ b/flake.nix @@ -73,7 +73,7 @@ # Configuration shared between builds config = { # x-release-please-start-version - version = "0.20.0"; + version = "0.21.0"; # x-release-please-end src = pkgs.lib.cleanSourceWith { diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json index 52ad0321b85..45ec7f71c6b 100644 --- a/tooling/noir_codegen/package.json +++ b/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.20.0", + "version": "0.21.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index e42cbb1d162..ddbbc1a0de2 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.20.0", + "version": "0.21.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index 623a290410c..db67d1b9715 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.20.0", + "version": "0.21.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index b322b9b6207..8359a459963 100644 --- a/tooling/noir_js_types/package.json +++ b/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.20.0", + "version": "0.21.0", "license": "(MIT OR Apache-2.0)", "files": [ "lib", diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index fe801a40d5e..b59a077bd75 100644 --- a/tooling/noirc_abi_wasm/package.json +++ b/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.20.0", + "version": "0.21.0", "license": "(MIT OR Apache-2.0)", "files": [ "nodejs", From 7e868f387b544fdf226c9f834fe3dbbd2610c993 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:39:14 +0000 Subject: [PATCH 054/137] chore: fix lockfile (#3826) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 442d9750be0..b8478357f96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir_field", "base64", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.37.0" +version = "0.37.1" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir", "acvm_blackbox_solver", @@ -55,7 +55,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir", "blake2", @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acvm", "barretenberg_blackbox_solver", @@ -89,7 +89,7 @@ dependencies = [ [[package]] name = "acvm_stdlib" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir", ] @@ -218,7 +218,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arena" -version = "0.20.0" +version = "0.21.0" dependencies = [ "generational-arena", ] @@ -427,7 +427,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.20.0" +version = "0.21.0" dependencies = [ "iter-extended", "noirc_frontend", @@ -470,7 +470,7 @@ dependencies = [ [[package]] name = "barretenberg_blackbox_solver" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir", "acvm_blackbox_solver", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir_field", "serde", @@ -602,7 +602,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.37.0" +version = "0.37.1" dependencies = [ "acir", "acvm_blackbox_solver", @@ -1640,7 +1640,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.20.0" +version = "0.21.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -2216,7 +2216,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.20.0" +version = "0.21.0" [[package]] name = "itertools" @@ -2438,7 +2438,7 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nargo" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "codespan-reporting", @@ -2460,7 +2460,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "assert_cmd", @@ -2513,7 +2513,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.20.0" +version = "0.21.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2525,7 +2525,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.20.0" +version = "0.21.0" dependencies = [ "dirs", "fm", @@ -2574,7 +2574,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "codespan-reporting", @@ -2588,7 +2588,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "async-lsp", @@ -2611,7 +2611,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "build-data", @@ -2632,7 +2632,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "iter-extended", @@ -2649,7 +2649,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "build-data", @@ -2666,7 +2666,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "aztec_macros", @@ -2686,7 +2686,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "chumsky", @@ -2700,7 +2700,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "fxhash", @@ -2716,7 +2716,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "arena", @@ -2740,7 +2740,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.20.0" +version = "0.21.0" dependencies = [ "acvm", "iter-extended", From c388dae0e230b6e6aedd535a9f5f0428d3bf2eda Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:59:09 +0000 Subject: [PATCH 055/137] chore(ci): correct how docs are build for releases (#3828) # Description ## Problem\* Resolves ## Summary\* This PR moves the cutting of a new docs version to happen within the release-please PR. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/release.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fcf630345ac..d95ec10be23 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,8 +83,11 @@ jobs: update-docs: name: Update docs needs: [release-please, update-lockfile] - if: ${{ needs.release-please.outputs.tag-name }} + if: ${{ needs.release-please.outputs.release-pr }} runs-on: ubuntu-latest + env: + PENDING_RELEASE_SEMVER: v${{ needs.release-please.outputs.major }}.${{needs.release-please.outputs.minor}}.${{needs.release-please.outputs.patch}} + steps: - name: Checkout release branch uses: actions/checkout@v4 @@ -102,7 +105,7 @@ jobs: - name: Cut a new version working-directory: ./docs - run: yarn docusaurus docs:version ${{ needs.release-please.outputs.tag-name }} + run: yarn docusaurus docs:version ${{ env.PENDING_RELEASE_SEMVER }} - name: Configure git run: | @@ -112,7 +115,7 @@ jobs: - name: Commit new documentation version run: | git add . - git commit -m "chore(docs): cut new docs version for tag ${{ needs.release-please.outputs.tag-name }}" + git commit -m "chore(docs): cut new docs version for tag ${{ env.PENDING_RELEASE_SEMVER }}" git push build-binaries: From eaf13bc03f74d0c09ea47cc0e99bcb4d2ba1d783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Fri, 15 Dec 2023 16:40:30 +0000 Subject: [PATCH 056/137] chore: recursion howto explainers (#3792) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR also moves things around to accomodate one new `how-to` and its correspondent `explainer` ## Problem\* An explainer and a guide on recursion was long overdue, but very much needed. ## Summary\* It may seem like a lot of files but most of them are just things moving around: - Created a new top-level category "Noir" to avoid mixing syntax stuff with high-level explanations. That's most of the file moves - Added a divider on the sidebar - In the new "explanation" category, I wrote an explainer. **This is one of the two files that needs to be reviewed** - In the `how to` category, I wrote a guide. **This also needs to be reviewed** - I found out the links to `@site` were valid... But they route to the assets, thus rendering the page in markdown format 😱 The docusaurus documentation is not entirely clear about that, and I clearly missed the tiny reference to that fact in the advanced pages. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: Maxim Vezenov Co-authored-by: josh crites --- compiler/source-resolver/lib-node/index.js | 32 +++ .../source-resolver/lib-node/index.js.map | 1 + .../source-resolver/lib-node/index_node.js | 20 ++ .../lib-node/index_node.js.map | 1 + compiler/source-resolver/lib/index.js | 27 +++ compiler/source-resolver/lib/index.js.map | 1 + docs/docs/explainers/explainer-recursion.md | 175 +++++++++++++++++ docs/docs/explanations/_category_.json | 5 - docs/docs/getting_started/create_a_project.md | 6 +- .../installation/other_install_methods.md | 4 +- .../docs/getting_started/project_breakdown.md | 4 +- docs/docs/how_to/how-to-recursion.md | 184 ++++++++++++++++++ ...idity_verifier.md => solidity_verifier.md} | 3 +- docs/docs/index.md | 4 +- docs/docs/migration_notes.md | 2 +- .../modules_packages_crates/_category_.json | 0 .../crates_and_packages.md | 0 .../modules_packages_crates/dependencies.md | 0 .../modules_packages_crates/modules.md | 0 .../modules_packages_crates/workspaces.md | 0 .../standard_library/_category_.json | 0 .../standard_library/black_box_fns.md | 0 .../cryptographic_primitives}/_category_.json | 0 .../cryptographic_primitives/ec_primitives.md | 0 .../ecdsa_sig_verification.mdx | 0 .../cryptographic_primitives/eddsa.mdx | 0 .../cryptographic_primitives/hashes.mdx | 0 .../cryptographic_primitives/index.md | 0 .../cryptographic_primitives/scalar.mdx | 0 .../cryptographic_primitives/schnorr.mdx | 0 .../standard_library/logging.md | 0 .../standard_library/merkle_trees.md | 2 +- .../standard_library/options.md | 0 .../standard_library/recursion.md | 20 +- .../standard_library/zeroed.md | 0 .../noir => noir/syntax}/_category_.json | 2 +- .../noir => noir/syntax}/assert.md | 0 .../noir => noir/syntax}/comments.md | 0 .../noir => noir/syntax}/control_flow.md | 0 .../noir => noir/syntax}/data_bus.md | 0 .../syntax/data_types}/_category_.json | 0 .../noir => noir/syntax}/data_types/arrays.md | 0 .../syntax}/data_types/booleans.md | 0 .../noir => noir/syntax}/data_types/fields.md | 0 .../syntax}/data_types/function_types.md | 2 +- .../noir => noir/syntax}/data_types/index.md | 2 +- .../syntax}/data_types/integers.md | 0 .../syntax}/data_types/references.md | 0 .../syntax}/data_types/slices.mdx | 0 .../syntax}/data_types/strings.md | 0 .../syntax}/data_types/structs.md | 0 .../noir => noir/syntax}/data_types/tuples.md | 0 .../syntax}/data_types/vectors.mdx | 0 .../noir => noir/syntax}/distinct.md | 0 .../noir => noir/syntax}/functions.md | 8 +- .../noir => noir/syntax}/generics.md | 0 .../noir => noir/syntax}/lambdas.md | 0 .../noir => noir/syntax}/mutability.md | 0 .../{explanations/noir => noir/syntax}/ops.md | 0 .../noir => noir/syntax}/shadowing.md | 0 .../noir => noir/syntax}/unconstrained.md | 0 docs/docs/reference/nargo_commands.md | 2 +- docs/docs/tutorials/noirjs_app.md | 2 +- docs/docusaurus.config.ts | 2 +- docs/sidebars.js | 22 ++- docs/src/css/sidebar.css | 4 + 66 files changed, 496 insertions(+), 41 deletions(-) create mode 100644 compiler/source-resolver/lib-node/index.js create mode 100644 compiler/source-resolver/lib-node/index.js.map create mode 100644 compiler/source-resolver/lib-node/index_node.js create mode 100644 compiler/source-resolver/lib-node/index_node.js.map create mode 100644 compiler/source-resolver/lib/index.js create mode 100644 compiler/source-resolver/lib/index.js.map create mode 100644 docs/docs/explainers/explainer-recursion.md delete mode 100644 docs/docs/explanations/_category_.json create mode 100644 docs/docs/how_to/how-to-recursion.md rename docs/docs/how_to/{03_solidity_verifier.md => solidity_verifier.md} (98%) rename docs/docs/{explanations => noir}/modules_packages_crates/_category_.json (100%) rename docs/docs/{explanations => noir}/modules_packages_crates/crates_and_packages.md (100%) rename docs/docs/{explanations => noir}/modules_packages_crates/dependencies.md (100%) rename docs/docs/{explanations => noir}/modules_packages_crates/modules.md (100%) rename docs/docs/{explanations => noir}/modules_packages_crates/workspaces.md (100%) rename docs/docs/{explanations => noir}/standard_library/_category_.json (100%) rename docs/docs/{explanations => noir}/standard_library/black_box_fns.md (100%) rename docs/docs/{explanations/noir/data_types => noir/standard_library/cryptographic_primitives}/_category_.json (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/ec_primitives.md (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/eddsa.mdx (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/hashes.mdx (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/index.md (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/scalar.mdx (100%) rename docs/docs/{explanations => noir}/standard_library/cryptographic_primitives/schnorr.mdx (100%) rename docs/docs/{explanations => noir}/standard_library/logging.md (100%) rename docs/docs/{explanations => noir}/standard_library/merkle_trees.md (93%) rename docs/docs/{explanations => noir}/standard_library/options.md (100%) rename docs/docs/{explanations => noir}/standard_library/recursion.md (65%) rename docs/docs/{explanations => noir}/standard_library/zeroed.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/_category_.json (75%) rename docs/docs/{explanations/noir => noir/syntax}/assert.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/comments.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/control_flow.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_bus.md (100%) rename docs/docs/{explanations/standard_library/cryptographic_primitives => noir/syntax/data_types}/_category_.json (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/arrays.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/booleans.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/fields.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/function_types.md (88%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/index.md (97%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/integers.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/references.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/slices.mdx (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/strings.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/structs.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/tuples.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/data_types/vectors.mdx (100%) rename docs/docs/{explanations/noir => noir/syntax}/distinct.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/functions.md (92%) rename docs/docs/{explanations/noir => noir/syntax}/generics.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/lambdas.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/mutability.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/ops.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/shadowing.md (100%) rename docs/docs/{explanations/noir => noir/syntax}/unconstrained.md (100%) create mode 100644 docs/src/css/sidebar.css diff --git a/compiler/source-resolver/lib-node/index.js b/compiler/source-resolver/lib-node/index.js new file mode 100644 index 00000000000..7de637b6853 --- /dev/null +++ b/compiler/source-resolver/lib-node/index.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.initializeResolver = exports.read_file = void 0; +let resolveFunction = null; +const read_file = function (source_id) { + if (resolveFunction) { + const result = resolveFunction(source_id); + if (typeof result === 'string') { + return result; + } + else { + throw new Error('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)'); + } +}; +exports.read_file = read_file; +function initialize(noir_resolver) { + 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'); + } +} +function initializeResolver(resolver) { + resolveFunction = initialize(resolver); +} +exports.initializeResolver = initializeResolver; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index.js.map b/compiler/source-resolver/lib-node/index.js.map new file mode 100644 index 00000000000..4ac7301ddc9 --- /dev/null +++ b/compiler/source-resolver/lib-node/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,IAAI,eAAe,GAA2C,IAAI,CAAC;AAE5D,MAAM,SAAS,GAAG,UAAU,SAAiB;IAClD,IAAI,eAAe,EAAE;QACnB,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;YAC9B,OAAO,MAAM,CAAC;SACf;aAAM;YACL,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;SACH;KACF;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAC9E;AACH,CAAC,CAAC;AAdW,QAAA,SAAS,aAcpB;AAEF,SAAS,UAAU,CAAC,aAA4C;IAC9D,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;QACvC,OAAO,aAAa,CAAC;KACtB;SAAM;QACL,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;KACH;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,QAAuC;IACxE,eAAe,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC;AAFD,gDAEC"} \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index_node.js b/compiler/source-resolver/lib-node/index_node.js new file mode 100644 index 00000000000..7d54737ce49 --- /dev/null +++ b/compiler/source-resolver/lib-node/index_node.js @@ -0,0 +1,20 @@ +"use strict"; +/// +Object.defineProperty(exports, "__esModule", { value: true }); +exports.read_file = exports.initializeResolver = void 0; +const index_js_1 = require("./index.js"); +Object.defineProperty(exports, "initializeResolver", { enumerable: true, get: function () { return index_js_1.initializeResolver; } }); +Object.defineProperty(exports, "read_file", { enumerable: true, get: function () { return index_js_1.read_file; } }); +(0, index_js_1.initializeResolver)((source_id) => { + let fileContent = ''; + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fs = require('fs'); + fileContent = fs.readFileSync(source_id, { encoding: 'utf8' }); + } + catch (e) { + console.log(e); + } + return fileContent; +}); +//# sourceMappingURL=index_node.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index_node.js.map b/compiler/source-resolver/lib-node/index_node.js.map new file mode 100644 index 00000000000..920818232c3 --- /dev/null +++ b/compiler/source-resolver/lib-node/index_node.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index_node.js","sourceRoot":"","sources":["../src/index_node.ts"],"names":[],"mappings":";AAAA,8BAA8B;;;AAE9B,yCAA2D;AAclD,mGAdA,6BAAkB,OAcA;AAAE,0FAdA,oBAAS,OAcA;AAZtC,IAAA,6BAAkB,EAAC,CAAC,SAAiB,EAAE,EAAE;IACvC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI;QACF,8DAA8D;QAC9D,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAW,CAAC;KAC1E;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAChB;IACD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/compiler/source-resolver/lib/index.js b/compiler/source-resolver/lib/index.js new file mode 100644 index 00000000000..079b4460592 --- /dev/null +++ b/compiler/source-resolver/lib/index.js @@ -0,0 +1,27 @@ +let resolveFunction = null; +export const read_file = function (source_id) { + if (resolveFunction) { + const result = resolveFunction(source_id); + if (typeof result === 'string') { + return result; + } + else { + throw new Error('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)'); + } +}; +function initialize(noir_resolver) { + 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'); + } +} +export function initializeResolver(resolver) { + resolveFunction = initialize(resolver); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib/index.js.map b/compiler/source-resolver/lib/index.js.map new file mode 100644 index 00000000000..e62ae1e4c8a --- /dev/null +++ b/compiler/source-resolver/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,IAAI,eAAe,GAA2C,IAAI,CAAC;AAEnE,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,SAAiB;IAClD,IAAI,eAAe,EAAE;QACnB,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;YAC9B,OAAO,MAAM,CAAC;SACf;aAAM;YACL,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;SACH;KACF;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAC9E;AACH,CAAC,CAAC;AAEF,SAAS,UAAU,CAAC,aAA4C;IAC9D,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;QACvC,OAAO,aAAa,CAAC;KACtB;SAAM;QACL,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;KACH;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAuC;IACxE,eAAe,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC"} \ No newline at end of file diff --git a/docs/docs/explainers/explainer-recursion.md b/docs/docs/explainers/explainer-recursion.md new file mode 100644 index 00000000000..cc431a878dc --- /dev/null +++ b/docs/docs/explainers/explainer-recursion.md @@ -0,0 +1,175 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation Objects", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +So, Alice started thinking: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +So, the tallier puts all the votes in a merkle tree, and everyone can also prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He could find it more efficient to generate a proof for that setup phase separately, and verifying it in his actual business logic section of the circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof +- The input aggregation object + +It also returns the `output aggregation object`. These aggregation objects can be confusing at times, so let's dive in a little bit. + +### Aggregation objects + +Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. + +In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he is verifying a proof, so it needs to output an `aggregation object`: he is generating a recursive proof! +- Alice verifies Bob's *recursive proof*, and uses Bob's `output aggregation object` as the `input aggregation object` in her proof... Which in turn, generates another `output aggregation object`. + +One should notice that when Bob generates his first proof, he has no input aggregation object. Because he is not verifying an recursive proof, he has no `input aggregation object`. In this case, he may use zeros instead. + +We can imagine the `aggregation object` as the baton in a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursiveness would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. diff --git a/docs/docs/explanations/_category_.json b/docs/docs/explanations/_category_.json deleted file mode 100644 index 151ee204894..00000000000 --- a/docs/docs/explanations/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 3, - "collapsible": true, - "collapsed": true -} diff --git a/docs/docs/getting_started/create_a_project.md b/docs/docs/getting_started/create_a_project.md index 76bed5be9b8..f10916c39c5 100644 --- a/docs/docs/getting_started/create_a_project.md +++ b/docs/docs/getting_started/create_a_project.md @@ -69,7 +69,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](@site/docs/explanations/noir/data_types/index.md) section. +[Data Types](../noir/syntax/data_types/index.md) section. The next line of the program specifies its body: @@ -79,7 +79,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](@site/docs/explanations/noir/comments.md) chapter. +For more Noir syntax, check the [Language Concepts](../noir/syntax/comments.md) chapter. ## Build In/Output Files @@ -139,4 +139,4 @@ corresponding error instead. Congratulations, you have now created and verified a proof for your very first Noir program! -In the [next section](@site/docs/getting_started/project_breakdown.md), we will go into more detail on each step performed. +In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/docs/getting_started/installation/other_install_methods.md b/docs/docs/getting_started/installation/other_install_methods.md index d90a10103d9..36f05657277 100644 --- a/docs/docs/getting_started/installation/other_install_methods.md +++ b/docs/docs/getting_started/installation/other_install_methods.md @@ -24,7 +24,7 @@ sidebar_position: 1 ## Installation -The most common method of installing Nargo is through [Noirup](@site/docs/getting_started/installation/index.md) +The most common method of installing Nargo is through [Noirup](./index.md) However, there are other methods for installing Nargo: @@ -167,7 +167,7 @@ The default backend for Noir (Barretenberg) doesn't provide Windows binaries at Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. -step 2: Follow the [Noirup instructions](@site/docs/getting_started/installation/index.md). +step 2: Follow the [Noirup instructions](./index.md). ## Uninstalling Nargo diff --git a/docs/docs/getting_started/project_breakdown.md b/docs/docs/getting_started/project_breakdown.md index 026127b9ed0..5a214804f7b 100644 --- a/docs/docs/getting_started/project_breakdown.md +++ b/docs/docs/getting_started/project_breakdown.md @@ -52,7 +52,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](@site/docs/explanations/modules_packages_crates/workspaces.md) will look a bit different. For example: +Nargo.toml for a [workspace](../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -75,7 +75,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](@site/docs/explanations/modules_packages_crates/dependencies.md) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../noir/modules_packages_crates/dependencies.md) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/docs/how_to/how-to-recursion.md b/docs/docs/how_to/how-to-recursion.md new file mode 100644 index 00000000000..226f7e6e73d --- /dev/null +++ b/docs/docs/how_to/how-to-recursion.md @@ -0,0 +1,184 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. Meaning it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. Which means these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume these two: + +- `main`: a circuit of type `assert(x != y)` +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursiveness, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateIntermediateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit are we actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*. So it is Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyIntermediateProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate the intermediate artifacts: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateIntermediateProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]`. However, currently the backend doesn't remove the public inputs from the proof when converting it. + +This means that if your `main` circuit has two public inputs, then you should also modify the recursive circuit to accept a proof with the public inputs appended. This means that in our example, since `y` is a public input, our `proofAsFields` is of type `[Field; 94]`. + +Verification keys in Barretenberg are always of size 114. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, + input_aggregation_object: Array(16).fill(0) // this circuit is verifying a non-recursive proof, so there's no input aggregation object: just use zero +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateFinalProof(witness) +const verified = backend.verifyFinalProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! In that case, you should keep in mind the `returnValue`, as it will contain the `input_aggregation_object` for the next proof. + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { +main: mainJSON, +recursive: recursiveJSON +} +const backends = { +main: new BarretenbergBackend(circuits.main), +recursive: new BarretenbergBackend(circuits.recursive) +} +const noirs = { +main: new Noir(circuits.main, backends.main), +recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noirs.main.execute(input) +const proof = await backends.main.generateIntermediateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyIntermediateProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateIntermediateProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noirs.recursive.generateFinalProof(recursiveInputs) +``` + +::: diff --git a/docs/docs/how_to/03_solidity_verifier.md b/docs/docs/how_to/solidity_verifier.md similarity index 98% rename from docs/docs/how_to/03_solidity_verifier.md rename to docs/docs/how_to/solidity_verifier.md index 1a89fe492f4..8022b0e5f20 100644 --- a/docs/docs/how_to/03_solidity_verifier.md +++ b/docs/docs/how_to/solidity_verifier.md @@ -3,7 +3,7 @@ title: Generate a Solidity Verifier description: Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! + contract. Read more to find out keywords: [ solidity verifier, @@ -16,6 +16,7 @@ keywords: proving backend, Barretenberg, ] +sidebar_position: 0 --- For certain applications, it may be desirable to run the verifier as a smart contract instead of on diff --git a/docs/docs/index.md b/docs/docs/index.md index 754f9f6e31d..016832f9f5e 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -38,7 +38,7 @@ programming. ### Solidity Developers Noir streamlines the creation of Solidity contracts that interface with SNARK systems. -[`Utilize the nargo codegen-verifier`](@site/docs/reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier +[`Utilize the nargo codegen-verifier`](./reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim to modularize this process for even greater ease of use. @@ -82,4 +82,4 @@ Some libraries that are available today include: - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](@site/docs/explanations/modules_packages_crates/dependencies.md) for more information. +See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index a5fd10769f7..d5d0682cf0c 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -16,7 +16,7 @@ To update, please make sure this field in `Nargo.toml` matches the output of `na ## ≥0.14 -The index of the [for loops](@site/docs/explanations/noir/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: +The index of the [for loops](noir/syntax/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: ```rust for i in 0..10 { diff --git a/docs/docs/explanations/modules_packages_crates/_category_.json b/docs/docs/noir/modules_packages_crates/_category_.json similarity index 100% rename from docs/docs/explanations/modules_packages_crates/_category_.json rename to docs/docs/noir/modules_packages_crates/_category_.json diff --git a/docs/docs/explanations/modules_packages_crates/crates_and_packages.md b/docs/docs/noir/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/docs/explanations/modules_packages_crates/crates_and_packages.md rename to docs/docs/noir/modules_packages_crates/crates_and_packages.md diff --git a/docs/docs/explanations/modules_packages_crates/dependencies.md b/docs/docs/noir/modules_packages_crates/dependencies.md similarity index 100% rename from docs/docs/explanations/modules_packages_crates/dependencies.md rename to docs/docs/noir/modules_packages_crates/dependencies.md diff --git a/docs/docs/explanations/modules_packages_crates/modules.md b/docs/docs/noir/modules_packages_crates/modules.md similarity index 100% rename from docs/docs/explanations/modules_packages_crates/modules.md rename to docs/docs/noir/modules_packages_crates/modules.md diff --git a/docs/docs/explanations/modules_packages_crates/workspaces.md b/docs/docs/noir/modules_packages_crates/workspaces.md similarity index 100% rename from docs/docs/explanations/modules_packages_crates/workspaces.md rename to docs/docs/noir/modules_packages_crates/workspaces.md diff --git a/docs/docs/explanations/standard_library/_category_.json b/docs/docs/noir/standard_library/_category_.json similarity index 100% rename from docs/docs/explanations/standard_library/_category_.json rename to docs/docs/noir/standard_library/_category_.json diff --git a/docs/docs/explanations/standard_library/black_box_fns.md b/docs/docs/noir/standard_library/black_box_fns.md similarity index 100% rename from docs/docs/explanations/standard_library/black_box_fns.md rename to docs/docs/noir/standard_library/black_box_fns.md diff --git a/docs/docs/explanations/noir/data_types/_category_.json b/docs/docs/noir/standard_library/cryptographic_primitives/_category_.json similarity index 100% rename from docs/docs/explanations/noir/data_types/_category_.json rename to docs/docs/noir/standard_library/cryptographic_primitives/_category_.json diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md b/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md rename to docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx rename to docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx rename to docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx rename to docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/index.md b/docs/docs/noir/standard_library/cryptographic_primitives/index.md similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/index.md rename to docs/docs/noir/standard_library/cryptographic_primitives/index.md diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx rename to docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx rename to docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx diff --git a/docs/docs/explanations/standard_library/logging.md b/docs/docs/noir/standard_library/logging.md similarity index 100% rename from docs/docs/explanations/standard_library/logging.md rename to docs/docs/noir/standard_library/logging.md diff --git a/docs/docs/explanations/standard_library/merkle_trees.md b/docs/docs/noir/standard_library/merkle_trees.md similarity index 93% rename from docs/docs/explanations/standard_library/merkle_trees.md rename to docs/docs/noir/standard_library/merkle_trees.md index 07fa2ccda79..5b45617812a 100644 --- a/docs/docs/explanations/standard_library/merkle_trees.md +++ b/docs/docs/noir/standard_library/merkle_trees.md @@ -17,7 +17,7 @@ keywords: ## compute_merkle_root -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](@site/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx#pedersen_hash). +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). ```rust fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field diff --git a/docs/docs/explanations/standard_library/options.md b/docs/docs/noir/standard_library/options.md similarity index 100% rename from docs/docs/explanations/standard_library/options.md rename to docs/docs/noir/standard_library/options.md diff --git a/docs/docs/explanations/standard_library/recursion.md b/docs/docs/noir/standard_library/recursion.md similarity index 65% rename from docs/docs/explanations/standard_library/recursion.md rename to docs/docs/noir/standard_library/recursion.md index ff4c63acaa7..67962082a8f 100644 --- a/docs/docs/explanations/standard_library/recursion.md +++ b/docs/docs/noir/standard_library/recursion.md @@ -19,11 +19,7 @@ This is a black box function. Read [this section](./black_box_fns) to learn more ::: -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: +## Example usage ```rust use dep::std; @@ -37,17 +33,17 @@ fn main( proof_b : [Field; 94], ) -> pub [Field; 16] { let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), key_hash, input_aggregation_object ); let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), key_hash, output_aggregation_object_a ); @@ -60,8 +56,6 @@ fn main( } ``` -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - ## Parameters ### `verification_key` diff --git a/docs/docs/explanations/standard_library/zeroed.md b/docs/docs/noir/standard_library/zeroed.md similarity index 100% rename from docs/docs/explanations/standard_library/zeroed.md rename to docs/docs/noir/standard_library/zeroed.md diff --git a/docs/docs/explanations/noir/_category_.json b/docs/docs/noir/syntax/_category_.json similarity index 75% rename from docs/docs/explanations/noir/_category_.json rename to docs/docs/noir/syntax/_category_.json index 448d8987d1a..666b691ae91 100644 --- a/docs/docs/explanations/noir/_category_.json +++ b/docs/docs/noir/syntax/_category_.json @@ -1,5 +1,5 @@ { - "label": "Noir", + "label": "Syntax", "position": 0, "collapsible": true, "collapsed": true diff --git a/docs/docs/explanations/noir/assert.md b/docs/docs/noir/syntax/assert.md similarity index 100% rename from docs/docs/explanations/noir/assert.md rename to docs/docs/noir/syntax/assert.md diff --git a/docs/docs/explanations/noir/comments.md b/docs/docs/noir/syntax/comments.md similarity index 100% rename from docs/docs/explanations/noir/comments.md rename to docs/docs/noir/syntax/comments.md diff --git a/docs/docs/explanations/noir/control_flow.md b/docs/docs/noir/syntax/control_flow.md similarity index 100% rename from docs/docs/explanations/noir/control_flow.md rename to docs/docs/noir/syntax/control_flow.md diff --git a/docs/docs/explanations/noir/data_bus.md b/docs/docs/noir/syntax/data_bus.md similarity index 100% rename from docs/docs/explanations/noir/data_bus.md rename to docs/docs/noir/syntax/data_bus.md diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json b/docs/docs/noir/syntax/data_types/_category_.json similarity index 100% rename from docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json rename to docs/docs/noir/syntax/data_types/_category_.json diff --git a/docs/docs/explanations/noir/data_types/arrays.md b/docs/docs/noir/syntax/data_types/arrays.md similarity index 100% rename from docs/docs/explanations/noir/data_types/arrays.md rename to docs/docs/noir/syntax/data_types/arrays.md diff --git a/docs/docs/explanations/noir/data_types/booleans.md b/docs/docs/noir/syntax/data_types/booleans.md similarity index 100% rename from docs/docs/explanations/noir/data_types/booleans.md rename to docs/docs/noir/syntax/data_types/booleans.md diff --git a/docs/docs/explanations/noir/data_types/fields.md b/docs/docs/noir/syntax/data_types/fields.md similarity index 100% rename from docs/docs/explanations/noir/data_types/fields.md rename to docs/docs/noir/syntax/data_types/fields.md diff --git a/docs/docs/explanations/noir/data_types/function_types.md b/docs/docs/noir/syntax/data_types/function_types.md similarity index 88% rename from docs/docs/explanations/noir/data_types/function_types.md rename to docs/docs/noir/syntax/data_types/function_types.md index f6121af17e2..61e4076adaf 100644 --- a/docs/docs/explanations/noir/data_types/function_types.md +++ b/docs/docs/noir/syntax/data_types/function_types.md @@ -23,4 +23,4 @@ fn main() { ``` A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](../lambdas.md) for more details. +See [Lambdas](@site/docs/noir/syntax/lambdas.md) for more details. diff --git a/docs/docs/explanations/noir/data_types/index.md b/docs/docs/noir/syntax/data_types/index.md similarity index 97% rename from docs/docs/explanations/noir/data_types/index.md rename to docs/docs/noir/syntax/data_types/index.md index 56ed55c444b..52e568e9b7e 100644 --- a/docs/docs/explanations/noir/data_types/index.md +++ b/docs/docs/noir/syntax/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/explanations/noir/generics.md): +Type aliases can also be used with [generics](@site/docs/noir/syntax/generics.md): ```rust type Id = Size; diff --git a/docs/docs/explanations/noir/data_types/integers.md b/docs/docs/noir/syntax/data_types/integers.md similarity index 100% rename from docs/docs/explanations/noir/data_types/integers.md rename to docs/docs/noir/syntax/data_types/integers.md diff --git a/docs/docs/explanations/noir/data_types/references.md b/docs/docs/noir/syntax/data_types/references.md similarity index 100% rename from docs/docs/explanations/noir/data_types/references.md rename to docs/docs/noir/syntax/data_types/references.md diff --git a/docs/docs/explanations/noir/data_types/slices.mdx b/docs/docs/noir/syntax/data_types/slices.mdx similarity index 100% rename from docs/docs/explanations/noir/data_types/slices.mdx rename to docs/docs/noir/syntax/data_types/slices.mdx diff --git a/docs/docs/explanations/noir/data_types/strings.md b/docs/docs/noir/syntax/data_types/strings.md similarity index 100% rename from docs/docs/explanations/noir/data_types/strings.md rename to docs/docs/noir/syntax/data_types/strings.md diff --git a/docs/docs/explanations/noir/data_types/structs.md b/docs/docs/noir/syntax/data_types/structs.md similarity index 100% rename from docs/docs/explanations/noir/data_types/structs.md rename to docs/docs/noir/syntax/data_types/structs.md diff --git a/docs/docs/explanations/noir/data_types/tuples.md b/docs/docs/noir/syntax/data_types/tuples.md similarity index 100% rename from docs/docs/explanations/noir/data_types/tuples.md rename to docs/docs/noir/syntax/data_types/tuples.md diff --git a/docs/docs/explanations/noir/data_types/vectors.mdx b/docs/docs/noir/syntax/data_types/vectors.mdx similarity index 100% rename from docs/docs/explanations/noir/data_types/vectors.mdx rename to docs/docs/noir/syntax/data_types/vectors.mdx diff --git a/docs/docs/explanations/noir/distinct.md b/docs/docs/noir/syntax/distinct.md similarity index 100% rename from docs/docs/explanations/noir/distinct.md rename to docs/docs/noir/syntax/distinct.md diff --git a/docs/docs/explanations/noir/functions.md b/docs/docs/noir/syntax/functions.md similarity index 92% rename from docs/docs/explanations/noir/functions.md rename to docs/docs/noir/syntax/functions.md index 94f929038ee..48aba9cd058 100644 --- a/docs/docs/explanations/noir/functions.md +++ b/docs/docs/noir/syntax/functions.md @@ -15,7 +15,7 @@ To declare a function the `fn` keyword is used. fn foo() {} ``` -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](@site/docs/explanations/modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: ```rust pub fn foo() {} @@ -62,7 +62,7 @@ fn main(x : [Field]) // can't compile, has variable size fn main(....// i think you got it by now ``` -Keep in mind [tests](@site/docs/getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: ```rust fn main(x : [Field]) { @@ -189,8 +189,8 @@ Supported attributes include: - **builtin**: the function is implemented by the compiler, for efficiency purposes. - **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` - **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](@site/docs/reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](@site/docs/getting_started/tooling/testing.md) for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details ### Field Attribute diff --git a/docs/docs/explanations/noir/generics.md b/docs/docs/noir/syntax/generics.md similarity index 100% rename from docs/docs/explanations/noir/generics.md rename to docs/docs/noir/syntax/generics.md diff --git a/docs/docs/explanations/noir/lambdas.md b/docs/docs/noir/syntax/lambdas.md similarity index 100% rename from docs/docs/explanations/noir/lambdas.md rename to docs/docs/noir/syntax/lambdas.md diff --git a/docs/docs/explanations/noir/mutability.md b/docs/docs/noir/syntax/mutability.md similarity index 100% rename from docs/docs/explanations/noir/mutability.md rename to docs/docs/noir/syntax/mutability.md diff --git a/docs/docs/explanations/noir/ops.md b/docs/docs/noir/syntax/ops.md similarity index 100% rename from docs/docs/explanations/noir/ops.md rename to docs/docs/noir/syntax/ops.md diff --git a/docs/docs/explanations/noir/shadowing.md b/docs/docs/noir/syntax/shadowing.md similarity index 100% rename from docs/docs/explanations/noir/shadowing.md rename to docs/docs/noir/syntax/shadowing.md diff --git a/docs/docs/explanations/noir/unconstrained.md b/docs/docs/noir/syntax/unconstrained.md similarity index 100% rename from docs/docs/explanations/noir/unconstrained.md rename to docs/docs/noir/syntax/unconstrained.md diff --git a/docs/docs/reference/nargo_commands.md b/docs/docs/reference/nargo_commands.md index 239e88d9691..ff3dee8973f 100644 --- a/docs/docs/reference/nargo_commands.md +++ b/docs/docs/reference/nargo_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](@site/docs/getting_started/tooling/testing.md). +See an example on the [testing page](../getting_started/tooling/testing.md). ### Options diff --git a/docs/docs/tutorials/noirjs_app.md b/docs/docs/tutorials/noirjs_app.md index e0f674fa09c..302ee4aeade 100644 --- a/docs/docs/tutorials/noirjs_app.md +++ b/docs/docs/tutorials/noirjs_app.md @@ -21,7 +21,7 @@ In this guide, we will be pinned to 0.17.0. Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). -First of all, follow the the [Nargo guide](@site/docs/getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: +First of all, follow the the [Nargo guide](../getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: ```bash nargo compile diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 98ef1fd680c..7516d35c6d9 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -40,7 +40,7 @@ export default { }, blog: false, theme: { - customCss: './src/css/custom.css', + customCss: ['./src/css/custom.css', './src/css/sidebar.css'], }, }, ], diff --git a/docs/sidebars.js b/docs/sidebars.js index 016ead14a8f..f1e79ba9ebc 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -21,10 +21,15 @@ export default { items: [ { type: 'autogenerated', - dirName: 'explanations', + dirName: 'noir', }, ], }, + { + type: 'html', + value: '
', + defaultStyle: true, + }, { type: 'category', label: 'How To Guides', @@ -35,6 +40,16 @@ export default { }, ], }, + { + type: 'category', + label: 'Explainers', + items: [ + { + type: 'autogenerated', + dirName: 'explainers', + }, + ], + }, { type: 'category', label: 'Tutorials', @@ -50,6 +65,11 @@ export default { label: 'Reference', items: [{ type: 'autogenerated', dirName: 'reference' }], }, + { + type: 'html', + value: '
', + defaultStyle: true, + }, { type: 'doc', id: 'migration_notes', diff --git a/docs/src/css/sidebar.css b/docs/src/css/sidebar.css new file mode 100644 index 00000000000..3c03c374058 --- /dev/null +++ b/docs/src/css/sidebar.css @@ -0,0 +1,4 @@ +.divider { + border-top: 2px solid #eee; + margin: 0.5em 0; +} From 0383100853a80a5b28b797cdfeae0d271f1b7805 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 15 Dec 2023 17:25:03 +0000 Subject: [PATCH 057/137] chore!: Remove partial backend feature (#3805) # Description Related to #3772 ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: TomAFrench --- .github/workflows/publish-acvm.yml | 6 - Cargo.lock | 8 - Cargo.toml | 1 - .../acir/src/circuit/black_box_functions.rs | 3 - acvm-repo/acir/src/circuit/opcodes.rs | 26 - acvm-repo/acvm/Cargo.toml | 7 +- acvm-repo/acvm/src/compiler/mod.rs | 24 +- .../src/compiler/transformers/fallback.rs | 158 ----- .../acvm/src/compiler/transformers/mod.rs | 25 +- acvm-repo/acvm/src/pwg/mod.rs | 34 +- acvm-repo/acvm/tests/stdlib.rs | 354 ---------- acvm-repo/blackbox_solver/src/lib.rs | 2 - acvm-repo/stdlib/CHANGELOG.md | 350 ---------- acvm-repo/stdlib/Cargo.toml | 22 - .../stdlib/src/blackbox_fallbacks/blake2s.rs | 468 ------------- .../src/blackbox_fallbacks/hash_to_field.rs | 168 ----- .../src/blackbox_fallbacks/keccak256.rs | 269 -------- .../src/blackbox_fallbacks/logic_fallbacks.rs | 127 ---- .../stdlib/src/blackbox_fallbacks/mod.rs | 19 - .../stdlib/src/blackbox_fallbacks/sha256.rs | 377 ---------- .../stdlib/src/blackbox_fallbacks/uint.rs | 648 ------------------ .../stdlib/src/blackbox_fallbacks/uint32.rs | 30 - .../stdlib/src/blackbox_fallbacks/uint64.rs | 30 - .../stdlib/src/blackbox_fallbacks/uint8.rs | 2 - .../stdlib/src/blackbox_fallbacks/utils.rs | 175 ----- acvm-repo/stdlib/src/helpers.rs | 23 - acvm-repo/stdlib/src/lib.rs | 7 - .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 8 +- compiler/wasm/src/compile.rs | 10 +- release-please-config.json | 1 - tooling/backend_interface/src/cli/info.rs | 30 +- tooling/backend_interface/src/lib.rs | 51 +- tooling/backend_interface/src/proof_system.rs | 17 +- tooling/lsp/src/requests/profile_run.rs | 5 +- tooling/nargo/src/errors.rs | 7 - tooling/nargo/src/ops/compile.rs | 20 +- tooling/nargo/src/ops/optimize.rs | 33 +- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 8 +- tooling/nargo_cli/src/cli/compile_cmd.rs | 30 +- tooling/nargo_cli/src/cli/debug_cmd.rs | 11 +- tooling/nargo_cli/src/cli/execute_cmd.rs | 11 +- tooling/nargo_cli/src/cli/info_cmd.rs | 3 +- tooling/nargo_cli/src/cli/prove_cmd.rs | 10 +- tooling/nargo_cli/src/cli/verify_cmd.rs | 10 +- 44 files changed, 72 insertions(+), 3556 deletions(-) delete mode 100644 acvm-repo/acvm/src/compiler/transformers/fallback.rs delete mode 100644 acvm-repo/acvm/tests/stdlib.rs delete mode 100644 acvm-repo/stdlib/CHANGELOG.md delete mode 100644 acvm-repo/stdlib/Cargo.toml delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/blake2s.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/hash_to_field.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/keccak256.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/logic_fallbacks.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/mod.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/sha256.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/uint.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/uint32.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/uint64.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/uint8.rs delete mode 100644 acvm-repo/stdlib/src/blackbox_fallbacks/utils.rs delete mode 100644 acvm-repo/stdlib/src/helpers.rs delete mode 100644 acvm-repo/stdlib/src/lib.rs diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index 06876f27c8d..59a104e3f75 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -51,12 +51,6 @@ jobs: env: CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} - - name: Publish acvm_stdlib - run: | - cargo publish --package acvm_stdlib - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} - - name: Publish brillig_vm run: | cargo publish --package brillig_vm diff --git a/Cargo.lock b/Cargo.lock index b8478357f96..129840f67f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,6 @@ version = "0.37.1" dependencies = [ "acir", "acvm_blackbox_solver", - "acvm_stdlib", "brillig_vm", "indexmap 1.9.3", "log", @@ -87,13 +86,6 @@ dependencies = [ "wasm-logger", ] -[[package]] -name = "acvm_stdlib" -version = "0.37.1" -dependencies = [ - "acir", -] - [[package]] name = "addr2line" version = "0.20.0" diff --git a/Cargo.toml b/Cargo.toml index a49b7c97f1e..5a7499f21a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,6 @@ members = [ "acvm-repo/acir", "acvm-repo/acvm", "acvm-repo/acvm_js", - "acvm-repo/stdlib", "acvm-repo/brillig", "acvm-repo/brillig_vm", "acvm-repo/blackbox_solver", diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 9129f44008c..d00cd6d28df 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -1,8 +1,5 @@ //! Black box functions are ACIR opcodes which rely on backends implementing support for specialized constraints. //! This makes certain zk-snark unfriendly computations cheaper than if they were implemented in more basic constraints. -//! -//! It is possible to fallback to less efficient implementations written in ACIR in some cases. -//! These are implemented inside the ACVM stdlib. use serde::{Deserialize, Serialize}; #[cfg(test)] diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index dc7f73b47e5..62566fee7fe 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -33,21 +33,6 @@ pub enum Opcode { }, } -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum UnsupportedMemoryOpcode { - MemoryOp, - MemoryInit, -} - -impl std::fmt::Display for UnsupportedMemoryOpcode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - UnsupportedMemoryOpcode::MemoryOp => write!(f, "MemoryOp"), - UnsupportedMemoryOpcode::MemoryInit => write!(f, "MemoryInit"), - } - } -} - impl Opcode { // TODO We can add a domain separator by doing something like: // TODO concat!("directive:", directive.name) @@ -62,17 +47,6 @@ impl Opcode { } } - pub fn unsupported_opcode(&self) -> UnsupportedMemoryOpcode { - match self { - Opcode::MemoryOp { .. } => UnsupportedMemoryOpcode::MemoryOp, - Opcode::MemoryInit { .. } => UnsupportedMemoryOpcode::MemoryInit, - Opcode::BlackBoxFuncCall(_) => { - unreachable!("Unsupported Blackbox function should not be reported here") - } - _ => unreachable!("Opcode is supported"), - } - } - pub fn is_arithmetic(&self) -> bool { matches!(self, Opcode::Arithmetic(_)) } diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 6a1ac372ed8..498d1a80fe1 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -19,28 +19,23 @@ thiserror.workspace = true log.workspace = true acir.workspace = true -stdlib.workspace = true brillig_vm.workspace = true acvm_blackbox_solver.workspace = true indexmap = "1.7.0" [features] -default = ["bn254", "testing"] +default = ["bn254"] bn254 = [ "acir/bn254", - "stdlib/bn254", "brillig_vm/bn254", "acvm_blackbox_solver/bn254", ] bls12_381 = [ "acir/bls12_381", - "stdlib/bls12_381", "brillig_vm/bls12_381", "acvm_blackbox_solver/bls12_381", ] -testing = ["stdlib/testing", "unstable-fallbacks"] -unstable-fallbacks = [] [dev-dependencies] rand = "0.8.5" diff --git a/acvm-repo/acvm/src/compiler/mod.rs b/acvm-repo/acvm/src/compiler/mod.rs index 0ed5b591675..1a73f841f3d 100644 --- a/acvm-repo/acvm/src/compiler/mod.rs +++ b/acvm-repo/acvm/src/compiler/mod.rs @@ -1,10 +1,6 @@ use std::collections::HashMap; -use acir::{ - circuit::{opcodes::UnsupportedMemoryOpcode, Circuit, Opcode, OpcodeLocation}, - BlackBoxFunc, -}; -use thiserror::Error; +use acir::circuit::{Circuit, OpcodeLocation}; use crate::Language; @@ -17,14 +13,6 @@ use optimizers::optimize_internal; pub use transformers::transform; use transformers::transform_internal; -#[derive(PartialEq, Eq, Debug, Error)] -pub enum CompileError { - #[error("The blackbox function {0} is not supported by the backend and acvm does not have a fallback implementation")] - UnsupportedBlackBox(BlackBoxFunc), - #[error("The opcode {0} is not supported by the backend and acvm does not have a fallback implementation")] - UnsupportedMemoryOpcode(UnsupportedMemoryOpcode), -} - /// This module moves and decomposes acir opcodes. The transformation map allows consumers of this module to map /// metadata they had about the opcodes to the new opcode structure generated after the transformation. #[derive(Debug)] @@ -81,19 +69,15 @@ fn transform_assert_messages( } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn compile( - acir: Circuit, - np_language: Language, - is_opcode_supported: impl Fn(&Opcode) -> bool, -) -> Result<(Circuit, AcirTransformationMap), CompileError> { +pub fn compile(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) { let (acir, acir_opcode_positions) = optimize_internal(acir); let (mut acir, acir_opcode_positions) = - transform_internal(acir, np_language, is_opcode_supported, acir_opcode_positions)?; + transform_internal(acir, np_language, acir_opcode_positions); let transformation_map = AcirTransformationMap::new(acir_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); - Ok((acir, transformation_map)) + (acir, transformation_map) } diff --git a/acvm-repo/acvm/src/compiler/transformers/fallback.rs b/acvm-repo/acvm/src/compiler/transformers/fallback.rs deleted file mode 100644 index 06dfc84a798..00000000000 --- a/acvm-repo/acvm/src/compiler/transformers/fallback.rs +++ /dev/null @@ -1,158 +0,0 @@ -use super::super::CompileError; -use acir::{ - circuit::{opcodes::BlackBoxFuncCall, Circuit, Opcode}, - native_types::Expression, -}; - -/// The initial transformer to act on a [`Circuit`]. This replaces any unsupported opcodes with -/// fallback implementations consisting of well supported opcodes. -pub(crate) struct FallbackTransformer; - -impl FallbackTransformer { - //ACIR pass which replace unsupported opcodes using arithmetic fallback - pub(crate) fn transform( - acir: Circuit, - is_supported: impl Fn(&Opcode) -> bool, - opcode_positions: Vec, - ) -> Result<(Circuit, Vec), CompileError> { - let mut acir_supported_opcodes = Vec::with_capacity(acir.opcodes.len()); - let mut new_opcode_positions = Vec::with_capacity(opcode_positions.len()); - let mut witness_idx = acir.current_witness_index + 1; - - for (idx, opcode) in acir.opcodes.into_iter().enumerate() { - match &opcode { - Opcode::Arithmetic(_) | Opcode::Directive(_) | Opcode::Brillig(_) => { - // directive, arithmetic expression or blocks are handled by acvm - new_opcode_positions.push(opcode_positions[idx]); - acir_supported_opcodes.push(opcode); - continue; - } - Opcode::MemoryInit { .. } | Opcode::MemoryOp { .. } => { - if !is_supported(&opcode) { - return Err(CompileError::UnsupportedMemoryOpcode( - opcode.unsupported_opcode(), - )); - } - new_opcode_positions.push(opcode_positions[idx]); - acir_supported_opcodes.push(opcode); - } - Opcode::BlackBoxFuncCall(bb_func_call) => { - // We know it is an black box function. Now check if it is - // supported by the backend. If it is supported, then we can simply - // collect the opcode - if is_supported(&opcode) { - new_opcode_positions.push(opcode_positions[idx]); - acir_supported_opcodes.push(opcode); - continue; - } else { - // If we get here then we know that this black box function is not supported - // so we need to replace it with a version of the opcode which only uses arithmetic - // expressions - let (updated_witness_index, opcodes_fallback) = - Self::opcode_fallback(bb_func_call, witness_idx)?; - witness_idx = updated_witness_index; - new_opcode_positions - .extend(vec![opcode_positions[idx]; opcodes_fallback.len()]); - acir_supported_opcodes.extend(opcodes_fallback); - } - } - } - } - - Ok(( - Circuit { - current_witness_index: witness_idx - 1, - opcodes: acir_supported_opcodes, - ..acir - }, - new_opcode_positions, - )) - } - - fn opcode_fallback( - gc: &BlackBoxFuncCall, - current_witness_idx: u32, - ) -> Result<(u32, Vec), CompileError> { - let (updated_witness_index, opcodes_fallback) = match gc { - BlackBoxFuncCall::AND { lhs, rhs, output } => { - assert_eq!( - lhs.num_bits, rhs.num_bits, - "number of bits specified for each input must be the same" - ); - stdlib::blackbox_fallbacks::and( - Expression::from(lhs.witness), - Expression::from(rhs.witness), - *output, - lhs.num_bits, - current_witness_idx, - ) - } - BlackBoxFuncCall::XOR { lhs, rhs, output } => { - assert_eq!( - lhs.num_bits, rhs.num_bits, - "number of bits specified for each input must be the same" - ); - stdlib::blackbox_fallbacks::xor( - Expression::from(lhs.witness), - Expression::from(rhs.witness), - *output, - lhs.num_bits, - current_witness_idx, - ) - } - BlackBoxFuncCall::RANGE { input } => { - // Note there are no outputs because range produces no outputs - stdlib::blackbox_fallbacks::range( - Expression::from(input.witness), - input.num_bits, - current_witness_idx, - ) - } - #[cfg(feature = "unstable-fallbacks")] - BlackBoxFuncCall::SHA256 { inputs, outputs } => { - let sha256_inputs = - inputs.iter().map(|input| (input.witness.into(), input.num_bits)).collect(); - stdlib::blackbox_fallbacks::sha256( - sha256_inputs, - outputs.to_vec(), - current_witness_idx, - ) - } - #[cfg(feature = "unstable-fallbacks")] - BlackBoxFuncCall::Blake2s { inputs, outputs } => { - let blake2s_inputs = - inputs.iter().map(|input| (input.witness.into(), input.num_bits)).collect(); - stdlib::blackbox_fallbacks::blake2s( - blake2s_inputs, - outputs.to_vec(), - current_witness_idx, - ) - } - #[cfg(feature = "unstable-fallbacks")] - BlackBoxFuncCall::HashToField128Security { inputs, output } => { - let hash_to_field_inputs = - inputs.iter().map(|input| (input.witness.into(), input.num_bits)).collect(); - stdlib::blackbox_fallbacks::hash_to_field( - hash_to_field_inputs, - *output, - current_witness_idx, - ) - } - #[cfg(feature = "unstable-fallbacks")] - BlackBoxFuncCall::Keccak256 { inputs, outputs } => { - let keccak_inputs = - inputs.iter().map(|input| (input.witness.into(), input.num_bits)).collect(); - stdlib::blackbox_fallbacks::keccak256( - keccak_inputs, - outputs.to_vec(), - current_witness_idx, - ) - } - _ => { - return Err(CompileError::UnsupportedBlackBox(gc.get_black_box_func())); - } - }; - - Ok((updated_witness_index, opcodes_fallback)) - } -} diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index c4c94e371b8..fc406ba2b54 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -8,33 +8,27 @@ use indexmap::IndexMap; use crate::Language; mod csat; -mod fallback; mod r1cs; pub(crate) use csat::CSatTransformer; -pub(crate) use fallback::FallbackTransformer; pub(crate) use r1cs::R1CSTransformer; -use super::{transform_assert_messages, AcirTransformationMap, CompileError}; +use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn transform( - acir: Circuit, - np_language: Language, - is_opcode_supported: impl Fn(&Opcode) -> bool, -) -> Result<(Circuit, AcirTransformationMap), CompileError> { +pub fn transform(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) { // Track original acir opcode positions throughout the transformation passes of the compilation // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) let acir_opcode_positions = acir.opcodes.iter().enumerate().map(|(i, _)| i).collect(); let (mut acir, acir_opcode_positions) = - transform_internal(acir, np_language, is_opcode_supported, acir_opcode_positions)?; + transform_internal(acir, np_language, acir_opcode_positions); let transformation_map = AcirTransformationMap::new(acir_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); - Ok((acir, transformation_map)) + (acir, transformation_map) } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. @@ -43,19 +37,14 @@ pub fn transform( pub(super) fn transform_internal( acir: Circuit, np_language: Language, - is_opcode_supported: impl Fn(&Opcode) -> bool, acir_opcode_positions: Vec, -) -> Result<(Circuit, Vec), CompileError> { +) -> (Circuit, Vec) { log::trace!("Start circuit transformation"); - // Fallback transformer pass - let (acir, acir_opcode_positions) = - FallbackTransformer::transform(acir, is_opcode_supported, acir_opcode_positions)?; - let mut transformer = match &np_language { crate::Language::R1CS => { let transformer = R1CSTransformer::new(acir); - return Ok((transformer.transform(), acir_opcode_positions)); + return (transformer.transform(), acir_opcode_positions); } crate::Language::PLONKCSat { width } => { let mut csat = CSatTransformer::new(*width); @@ -219,5 +208,5 @@ pub(super) fn transform_internal( log::trace!("Finish circuit transformation"); - Ok((acir, new_acir_opcode_positions)) + (acir, new_acir_opcode_positions) } diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index c1edf60161a..859ad010dcd 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -11,7 +11,7 @@ use acir::{ use acvm_blackbox_solver::BlackBoxResolutionError; use self::{arithmetic::ArithmeticSolver, directives::solve_directives, memory_op::MemoryOpSolver}; -use crate::{BlackBoxFunctionSolver, Language}; +use crate::BlackBoxFunctionSolver; use thiserror::Error; @@ -104,8 +104,6 @@ impl std::fmt::Display for ErrorLocation { pub enum OpcodeResolutionError { #[error("Cannot solve opcode: {0}")] OpcodeNotSolvable(#[from] OpcodeNotSolvable), - #[error("Backend does not currently support the {0} opcode. ACVM does not currently have a fallback for this opcode.")] - UnsupportedBlackBoxFunc(BlackBoxFunc), #[error("Cannot satisfy constraint")] UnsatisfiedConstrain { opcode_location: ErrorLocation }, #[error("Index out of bounds, array has size {array_size:?}, but index was {index:?}")] @@ -122,9 +120,6 @@ impl From for OpcodeResolutionError { BlackBoxResolutionError::Failed(func, reason) => { OpcodeResolutionError::BlackBoxFunctionFailed(func, reason) } - BlackBoxResolutionError::Unsupported(func) => { - OpcodeResolutionError::UnsupportedBlackBoxFunc(func) - } } } } @@ -450,30 +445,3 @@ fn any_witness_from_expression(expr: &Expression) -> Option { Some(expr.linear_combinations[0].1) } } - -#[deprecated( - note = "For backwards compatibility, this method allows you to derive _sensible_ defaults for opcode support based on the np language. \n Backends should simply specify what they support." -)] -// This is set to match the previous functionality that we had -// Where we could deduce what opcodes were supported -// by knowing the np complete language -pub fn default_is_opcode_supported(language: Language) -> fn(&Opcode) -> bool { - // R1CS does not support any of the opcode except Arithmetic by default. - // The compiler will replace those that it can -- ie range, xor, and - fn r1cs_is_supported(opcode: &Opcode) -> bool { - matches!(opcode, Opcode::Arithmetic(_)) - } - - // PLONK supports most of the opcodes by default - // The ones which are not supported, the acvm compiler will - // attempt to transform into supported opcodes. If these are also not available - // then a compiler error will be emitted. - fn plonk_is_supported(_opcode: &Opcode) -> bool { - true - } - - match language { - Language::R1CS => r1cs_is_supported, - Language::PLONKCSat { .. } => plonk_is_supported, - } -} diff --git a/acvm-repo/acvm/tests/stdlib.rs b/acvm-repo/acvm/tests/stdlib.rs deleted file mode 100644 index c96c55f9401..00000000000 --- a/acvm-repo/acvm/tests/stdlib.rs +++ /dev/null @@ -1,354 +0,0 @@ -#![cfg(feature = "testing")] -mod solver; -use crate::solver::StubbedBackend; -use acir::{ - circuit::{ - opcodes::{BlackBoxFuncCall, FunctionInput}, - Circuit, Opcode, - }, - native_types::{Expression, Witness}, - FieldElement, -}; -use acvm::{ - compiler::compile, - pwg::{ACVMStatus, ACVM}, - Language, -}; -use acvm_blackbox_solver::{blake2s, hash_to_field_128_security, keccak256, sha256}; -use paste::paste; -use proptest::prelude::*; -use std::collections::{BTreeMap, BTreeSet}; -use stdlib::blackbox_fallbacks::{UInt32, UInt64, UInt8}; - -test_uint!(test_uint8, UInt8, u8, 8); -test_uint!(test_uint32, UInt32, u32, 32); -test_uint!(test_uint64, UInt64, u64, 64); - -#[macro_export] -macro_rules! test_uint { - ( - $name:tt, - $uint:ident, - $u:ident, - $size:expr - ) => { - paste! { - test_uint_inner!( - [<$name _rol>], - [<$name _ror>], - [<$name _euclidean_division>], - [<$name _add>], - [<$name _sub>], - [<$name _left_shift>], - [<$name _right_shift>], - [<$name _less_than>], - $uint, - $u, - $size - ); - } - }; -} - -#[macro_export] -macro_rules! test_uint_inner { - ( - $rol:tt, - $ror:tt, - $euclidean_division:tt, - $add:tt, - $sub:tt, - $left_shift:tt, - $right_shift:tt, - $less_than:tt, - $uint: ident, - $u: ident, - $size: expr - ) => { - proptest! { - #[test] - fn $rol(x in 0..$u::MAX, y in 0..32_u32) { - let fe = FieldElement::from(x as u128); - let w = Witness(1); - let result = x.rotate_left(y); - let uint = $uint::new(w); - let (w, extra_opcodes, _) = uint.rol(y, 2); - let witness_assignments = BTreeMap::from([(Witness(1), fe)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $ror(x in 0..$u::MAX, y in 0..32_u32) { - let fe = FieldElement::from(x as u128); - let w = Witness(1); - let result = x.rotate_right(y); - let uint = $uint::new(w); - let (w, extra_opcodes, _) = uint.ror(y, 2); - let witness_assignments = BTreeMap::from([(Witness(1), fe)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $euclidean_division(x in 0..$u::MAX, y in 1 - ..$u::MAX) { - let lhs = FieldElement::from(x as u128); - let rhs = FieldElement::from(y as u128); - let w1 = Witness(1); - let w2 = Witness(2); - let q = x.div_euclid(y); - let r = x.rem_euclid(y); - let u32_1 = $uint::new(w1); - let u32_2 = $uint::new(w2); - let (q_w, r_w, extra_opcodes, _) = $uint::euclidean_division(&u32_1, &u32_2, 3); - let witness_assignments = BTreeMap::from([(Witness(1), lhs),(Witness(2), rhs)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&q_w.get_inner()).unwrap(), &FieldElement::from(q as u128)); - prop_assert_eq!(acvm.witness_map().get(&r_w.get_inner()).unwrap(), &FieldElement::from(r as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $add(x in 0..$u::MAX, y in 0..$u::MAX, z in 0..$u::MAX) { - let lhs = FieldElement::from(x as u128); - let rhs = FieldElement::from(y as u128); - let rhs_z = FieldElement::from(z as u128); - let result = FieldElement::from(((x as u128).wrapping_add(y as u128) % (1_u128 << $size)).wrapping_add(z as u128) % (1_u128 << $size)); - let w1 = Witness(1); - let w2 = Witness(2); - let w3 = Witness(3); - let u32_1 = $uint::new(w1); - let u32_2 = $uint::new(w2); - let u32_3 = $uint::new(w3); - let mut opcodes = Vec::new(); - let (w, extra_opcodes, num_witness) = u32_1.add(&u32_2, 4); - opcodes.extend(extra_opcodes); - let (w2, extra_opcodes, _) = w.add(&u32_3, num_witness); - opcodes.extend(extra_opcodes); - let witness_assignments = BTreeMap::from([(Witness(1), lhs), (Witness(2), rhs), (Witness(3), rhs_z)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w2.get_inner()).unwrap(), &result); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $sub(x in 0..$u::MAX, y in 0..$u::MAX, z in 0..$u::MAX) { - let lhs = FieldElement::from(x as u128); - let rhs = FieldElement::from(y as u128); - let rhs_z = FieldElement::from(z as u128); - let result = FieldElement::from(((x as u128).wrapping_sub(y as u128) % (1_u128 << $size)).wrapping_sub(z as u128) % (1_u128 << $size)); - let w1 = Witness(1); - let w2 = Witness(2); - let w3 = Witness(3); - let u32_1 = $uint::new(w1); - let u32_2 = $uint::new(w2); - let u32_3 = $uint::new(w3); - let mut opcodes = Vec::new(); - let (w, extra_opcodes, num_witness) = u32_1.sub(&u32_2, 4); - opcodes.extend(extra_opcodes); - let (w2, extra_opcodes, _) = w.sub(&u32_3, num_witness); - opcodes.extend(extra_opcodes); - let witness_assignments = BTreeMap::from([(Witness(1), lhs), (Witness(2), rhs), (Witness(3), rhs_z)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w2.get_inner()).unwrap(), &result); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $left_shift(x in 0..$u::MAX, y in 0..32_u32) { - let lhs = FieldElement::from(x as u128); - let w1 = Witness(1); - let result = x.overflowing_shl(y).0; - let u32_1 = $uint::new(w1); - let (w, extra_opcodes, _) = u32_1.leftshift(y, 2); - let witness_assignments = BTreeMap::from([(Witness(1), lhs)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $right_shift(x in 0..$u::MAX, y in 0..32_u32) { - let lhs = FieldElement::from(x as u128); - let w1 = Witness(1); - let result = x.overflowing_shr(y).0; - let u32_1 = $uint::new(w1); - let (w, extra_opcodes, _) = u32_1.rightshift(y, 2); - let witness_assignments = BTreeMap::from([(Witness(1), lhs)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - - #[test] - fn $less_than(x in 0..$u::MAX, y in 0..$u::MAX) { - let lhs = FieldElement::from(x as u128); - let rhs = FieldElement::from(y as u128); - let w1 = Witness(1); - let w2 = Witness(2); - let result = x < y; - let u32_1 = $uint::new(w1); - let u32_2 = $uint::new(w2); - let (w, extra_opcodes, _) = u32_1.less_than_comparison(&u32_2, 3); - let witness_assignments = BTreeMap::from([(Witness(1), lhs), (Witness(2), rhs)]).into(); - let mut acvm = ACVM::new(&StubbedBackend, &extra_opcodes, witness_assignments); - let solver_status = acvm.solve(); - - prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - } - }; -} - -test_hashes!(test_sha256, sha256, SHA256, does_not_support_sha256); -test_hashes!(test_blake2s, blake2s, Blake2s, does_not_support_blake2s); -test_hashes!(test_keccak, keccak256, Keccak256, does_not_support_keccak); - -fn does_not_support_sha256(opcode: &Opcode) -> bool { - !matches!(opcode, Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SHA256 { .. })) -} -fn does_not_support_blake2s(opcode: &Opcode) -> bool { - !matches!(opcode, Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Blake2s { .. })) -} -fn does_not_support_keccak(opcode: &Opcode) -> bool { - !matches!(opcode, Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccak256 { .. })) -} - -#[macro_export] -macro_rules! test_hashes { - ( - $name:ident, - $hasher:ident, - $opcode:ident, - $opcode_support: ident - ) => { - proptest! { - #![proptest_config(ProptestConfig::with_cases(3))] - #[test] - fn $name(input_values in proptest::collection::vec(0..u8::MAX, 1..50)) { - let mut opcodes = Vec::new(); - let mut witness_assignments = BTreeMap::new(); - let mut input_witnesses: Vec = Vec::new(); - let mut correct_result_witnesses: Vec = Vec::new(); - let mut output_witnesses: Vec = Vec::new(); - - // prepare test data - let mut counter = 0; - let output = $hasher(&input_values).unwrap(); - for inp_v in input_values { - counter += 1; - let function_input = FunctionInput { witness: Witness(counter), num_bits: 8 }; - input_witnesses.push(function_input); - witness_assignments.insert(Witness(counter), FieldElement::from(inp_v as u128)); - } - - for o_v in output { - counter += 1; - correct_result_witnesses.push(Witness(counter)); - witness_assignments.insert(Witness(counter), FieldElement::from(o_v as u128)); - } - - for _ in 0..32 { - counter += 1; - output_witnesses.push(Witness(counter)); - } - let blackbox = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::$opcode { inputs: input_witnesses, outputs: output_witnesses.clone() }); - opcodes.push(blackbox); - - // constrain the output to be the same as the hasher - for i in 0..correct_result_witnesses.len() { - let mut output_constraint = Expression::from(correct_result_witnesses[i]); - output_constraint.push_addition_term(-FieldElement::one(), output_witnesses[i]); - opcodes.push(Opcode::Arithmetic(output_constraint)); - } - - // compile circuit - let circuit = Circuit { - current_witness_index: witness_assignments.len() as u32 + 32, - opcodes, - private_parameters: BTreeSet::new(), // This is not correct but is unused in this test. - ..Circuit::default() - }; - let circuit = compile(circuit, Language::PLONKCSat{ width: 3 }, $opcode_support).unwrap().0; - - // solve witnesses - let mut acvm = ACVM::new(&StubbedBackend, &circuit.opcodes, witness_assignments.into()); - let solver_status = acvm.solve(); - - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } - } - }; -} - -fn does_not_support_hash_to_field(opcode: &Opcode) -> bool { - !matches!(opcode, Opcode::BlackBoxFuncCall(BlackBoxFuncCall::HashToField128Security { .. })) -} - -proptest! { - #![proptest_config(ProptestConfig::with_cases(3))] - #[test] - fn test_hash_to_field(input_values in proptest::collection::vec(0..u8::MAX, 1..50)) { - let mut opcodes = Vec::new(); - let mut witness_assignments = BTreeMap::new(); - let mut input_witnesses: Vec = Vec::new(); - - // prepare test data - let mut counter = 0; - let output = hash_to_field_128_security(&input_values).unwrap(); - for inp_v in input_values { - counter += 1; - let function_input = FunctionInput { witness: Witness(counter), num_bits: 8 }; - input_witnesses.push(function_input); - witness_assignments.insert(Witness(counter), FieldElement::from(inp_v as u128)); - } - - counter += 1; - let correct_result_witnesses: Witness = Witness(counter); - witness_assignments.insert(Witness(counter), output); - - counter += 1; - let output_witness: Witness = Witness(counter); - - let blackbox = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::HashToField128Security { inputs: input_witnesses, output: output_witness }); - opcodes.push(blackbox); - - // constrain the output to be the same as the hasher - let mut output_constraint = Expression::from(correct_result_witnesses); - output_constraint.push_addition_term(-FieldElement::one(), output_witness); - opcodes.push(Opcode::Arithmetic(output_constraint)); - - // compile circuit - let circuit = Circuit { - current_witness_index: witness_assignments.len() as u32 + 1, - opcodes, - private_parameters: BTreeSet::new(), // This is not correct but is unused in this test. - ..Circuit::default() - }; - let circuit = compile(circuit, Language::PLONKCSat{ width: 3 }, does_not_support_hash_to_field).unwrap().0; - - // solve witnesses - let mut acvm = ACVM::new(&StubbedBackend, &circuit.opcodes, witness_assignments.into()); - let solver_status = acvm.solve(); - - prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); - } -} diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index 13d0f562415..8b7c6343962 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -16,8 +16,6 @@ use thiserror::Error; #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum BlackBoxResolutionError { - #[error("unsupported blackbox function: {0}")] - Unsupported(BlackBoxFunc), #[error("failed to solve blackbox function: {0}, reason: {1}")] Failed(BlackBoxFunc, String), } diff --git a/acvm-repo/stdlib/CHANGELOG.md b/acvm-repo/stdlib/CHANGELOG.md deleted file mode 100644 index bea80c95d1e..00000000000 --- a/acvm-repo/stdlib/CHANGELOG.md +++ /dev/null @@ -1,350 +0,0 @@ -# Changelog - -## [0.27.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.26.1...acvm_stdlib-v0.27.0) (2023-09-19) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.26.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.26.0...acvm_stdlib-v0.26.1) (2023-09-12) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.26.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.25.0...acvm_stdlib-v0.26.0) (2023-09-07) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.25.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.24.1...acvm_stdlib-v0.25.0) (2023-09-04) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.24.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.24.0...acvm_stdlib-v0.24.1) (2023-09-03) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.24.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.23.0...acvm_stdlib-v0.24.0) (2023-08-31) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.23.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.22.0...acvm_stdlib-v0.23.0) (2023-08-30) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.22.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.21.0...acvm_stdlib-v0.22.0) (2023-08-18) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.21.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.20.1...acvm_stdlib-v0.21.0) (2023-07-26) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.20.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.20.0...acvm_stdlib-v0.20.1) (2023-07-26) - - -### Features - -* add optimisations to fallback black box functions on booleans ([#446](https://github.com/noir-lang/acvm/issues/446)) ([2cfb2a8](https://github.com/noir-lang/acvm/commit/2cfb2a8cf911a81eedbd9da13ab2c616abd67f83)) -* **stdlib:** Add fallback implementation of `Keccak256` black box function ([#445](https://github.com/noir-lang/acvm/issues/445)) ([f7ebb03](https://github.com/noir-lang/acvm/commit/f7ebb03653c971f119700ff8126d9eb5ff01be0f)) - -## [0.20.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.19.1...acvm_stdlib-v0.20.0) (2023-07-20) - - -### Features - -* **stdlib:** Add fallback implementation of `HashToField128Security` black box function ([#435](https://github.com/noir-lang/acvm/issues/435)) ([ed40f22](https://github.com/noir-lang/acvm/commit/ed40f228529e888d1960bfa70cb92b277e24b37f)) - -## [0.19.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.19.0...acvm_stdlib-v0.19.1) (2023-07-17) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.19.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.18.2...acvm_stdlib-v0.19.0) (2023-07-15) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.18.2](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.18.1...acvm_stdlib-v0.18.2) (2023-07-12) - - -### Features - -* **stdlib:** Add fallback implementation of `Blake2s` black box function ([#424](https://github.com/noir-lang/acvm/issues/424)) ([982d940](https://github.com/noir-lang/acvm/commit/982d94087d46092ce7a5e94dbd7e732195f58e42)) - -## [0.18.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.18.0...acvm_stdlib-v0.18.1) (2023-07-12) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.18.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.17.0...acvm_stdlib-v0.18.0) (2023-07-12) - - -### Features - -* **stdlib:** Add fallback implementation of `SHA256` black box function ([#407](https://github.com/noir-lang/acvm/issues/407)) ([040369a](https://github.com/noir-lang/acvm/commit/040369adc8749fa5ec2edd255ff54c105c3140f5)) - -## [0.17.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.16.0...acvm_stdlib-v0.17.0) (2023-07-07) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.16.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.15.1...acvm_stdlib-v0.16.0) (2023-07-06) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.15.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.15.0...acvm_stdlib-v0.15.1) (2023-06-20) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.15.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.14.2...acvm_stdlib-v0.15.0) (2023-06-15) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.14.2](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.14.1...acvm_stdlib-v0.14.2) (2023-06-08) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.14.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.14.0...acvm_stdlib-v0.14.1) (2023-06-07) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.14.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.13.3...acvm_stdlib-v0.14.0) (2023-06-06) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.13.3](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.13.2...acvm_stdlib-v0.13.3) (2023-06-05) - - -### Bug Fixes - -* Empty commit to trigger release-please ([e8f0748](https://github.com/noir-lang/acvm/commit/e8f0748042ef505d59ab63266d3c36c5358ee30d)) - -## [0.13.2](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.13.1...acvm_stdlib-v0.13.2) (2023-06-02) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.13.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.13.0...acvm_stdlib-v0.13.1) (2023-06-01) - - -### Bug Fixes - -* **ci:** Correct typo to avoid `undefined` in changelogs ([#333](https://github.com/noir-lang/acvm/issues/333)) ([d3424c0](https://github.com/noir-lang/acvm/commit/d3424c04fd303c9cbe25d03118d8b358cbb84b83)) - -## [0.13.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.12.0...acvm_stdlib-v0.13.0) (2023-06-01) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.12.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.11.0...acvm_stdlib-v0.12.0) (2023-05-17) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.11.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.10.3...acvm_stdlib-v0.11.0) (2023-05-04) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.10.3](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.10.2...acvm_stdlib-v0.10.3) (2023-04-28) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.10.2](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.10.1...acvm_stdlib-v0.10.2) (2023-04-28) - - -### Bug Fixes - -* add default flag to `acvm_stdlib` ([#242](https://github.com/noir-lang/acvm/issues/242)) ([83b6fa8](https://github.com/noir-lang/acvm/commit/83b6fa8302569add7e3ac8481b2fd2a6a1ff3576)) - -## [0.10.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.10.0...acvm_stdlib-v0.10.1) (2023-04-28) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - -## [0.10.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.9.0...acvm_stdlib-v0.10.0) (2023-04-26) - - -### ⚠ BREAKING CHANGES - -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) - -### Bug Fixes - -* prevent `bn254` feature flag always being enabled ([#225](https://github.com/noir-lang/acvm/issues/225)) ([82eee6a](https://github.com/noir-lang/acvm/commit/82eee6ab08ae480f04904ca8571fd88f4466c000)) - - -### Miscellaneous Chores - -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) - -## [0.9.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.8.1...acvm_stdlib-v0.9.0) (2023-04-07) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.8.1 to 0.9.0 - -## [0.8.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.8.0...acvm_stdlib-v0.8.1) (2023-03-30) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.8.0 to 0.8.1 - -## [0.8.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.7.1...acvm_stdlib-v0.8.0) (2023-03-28) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.7.1 to 0.8.0 - -## [0.7.1](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.7.0...acvm_stdlib-v0.7.1) (2023-03-27) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.7.0 to 0.7.1 - -## [0.7.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.6.0...acvm_stdlib-v0.7.0) (2023-03-23) - - -### Miscellaneous Chores - -* **acvm_stdlib:** Synchronize acvm versions - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.6.0 to 0.7.0 - -## [0.6.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.5.0...acvm_stdlib-v0.6.0) (2023-03-03) - - -### ⚠ BREAKING CHANGES - -* **acir:** rename `term_addition` to `push_addition_term` -* **acir:** rename `term_multiplication` to `push_multiplication_term` ([#122](https://github.com/noir-lang/acvm/issues/122)) - -### Miscellaneous Chores - -* **acir:** rename `term_addition` to `push_addition_term` ([d389385](https://github.com/noir-lang/acvm/commit/d38938542851a97dc01727438391e6a65e44c689)) -* **acir:** rename `term_multiplication` to `push_multiplication_term` ([#122](https://github.com/noir-lang/acvm/issues/122)) ([d389385](https://github.com/noir-lang/acvm/commit/d38938542851a97dc01727438391e6a65e44c689)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.5.0 to 0.6.0 - -## [0.5.0](https://github.com/noir-lang/acvm/compare/acvm_stdlib-v0.4.1...acvm_stdlib-v0.5.0) (2023-02-22) - - -### ⚠ BREAKING CHANGES - -* refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) - -### Miscellaneous Chores - -* refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) ([2427a27](https://github.com/noir-lang/acvm/commit/2427a275048e598c6d651cce8348a4c55148f235)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * acir bumped from 0.4.1 to 0.5.0 diff --git a/acvm-repo/stdlib/Cargo.toml b/acvm-repo/stdlib/Cargo.toml deleted file mode 100644 index 689411d3357..00000000000 --- a/acvm-repo/stdlib/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "acvm_stdlib" -description = "The ACVM standard library." -# x-release-please-start-version -version = "0.37.1" -# x-release-please-end -authors.workspace = true -edition.workspace = true -license.workspace = true -rust-version.workspace = true -repository.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -acir.workspace = true - -[features] -default = ["bn254"] -bn254 = ["acir/bn254"] -bls12_381 = ["acir/bls12_381"] -testing = ["bn254"] diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/blake2s.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/blake2s.rs deleted file mode 100644 index 92bf93d2d56..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/blake2s.rs +++ /dev/null @@ -1,468 +0,0 @@ -//! Blake2s fallback function. -use super::{ - utils::{byte_decomposition, round_to_nearest_byte}, - UInt32, -}; -use acir::{ - circuit::Opcode, - native_types::{Expression, Witness}, - FieldElement, -}; -use std::vec; - -const BLAKE2S_BLOCKBYTES_USIZE: usize = 64; -const MSG_SCHEDULE_BLAKE2: [[usize; 16]; 10] = [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], -]; -const INITIAL_H: [u32; 8] = [ - 0x6b08e647, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -]; -const IV_VALUE: [u32; 8] = [ - 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, -]; - -pub fn blake2s( - inputs: Vec<(Expression, u32)>, - outputs: Vec, - mut num_witness: u32, -) -> (u32, Vec) { - let mut new_opcodes = Vec::new(); - let mut new_inputs = Vec::new(); - - // Decompose the input field elements into bytes and collect the resulting witnesses. - for (witness, num_bits) in inputs { - let num_bytes = round_to_nearest_byte(num_bits); - let (extra_opcodes, extra_inputs, updated_witness_counter) = - byte_decomposition(witness, num_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - new_inputs.extend(extra_inputs); - num_witness = updated_witness_counter; - } - - let (result, num_witness, extra_opcodes) = create_blake2s_constraint(new_inputs, num_witness); - new_opcodes.extend(extra_opcodes); - - // constrain the outputs to be the same as the result of the circuit - for i in 0..outputs.len() { - let mut expr = Expression::from(outputs[i]); - expr.push_addition_term(-FieldElement::one(), result[i]); - new_opcodes.push(Opcode::Arithmetic(expr)); - } - (num_witness, new_opcodes) -} - -pub(crate) fn create_blake2s_constraint( - input: Vec, - num_witness: u32, -) -> (Vec, u32, Vec) { - let mut new_opcodes = Vec::new(); - - // prepare constants - let (mut blake2s_state, extra_opcodes, num_witness) = Blake2sState::init(num_witness); - new_opcodes.extend(extra_opcodes); - let (blake2s_constants, extra_opcodes, num_witness) = - Blake2sConstantsInCircuit::init(num_witness); - new_opcodes.extend(extra_opcodes); - let (blake2s_iv, extra_opcodes, mut num_witness) = Blake2sIV::init(num_witness); - new_opcodes.extend(extra_opcodes); - - let mut offset = 0; - let mut size = input.len(); - - while size > BLAKE2S_BLOCKBYTES_USIZE { - let (extra_opcodes, updated_witness_counter) = blake2s_increment_counter( - &mut blake2s_state, - &blake2s_constants.blake2s_blockbytes_uint32, - num_witness, - ); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, updated_witness_counter) = blake2s_compress( - &mut blake2s_state, - &blake2s_iv, - input.get(offset..offset + BLAKE2S_BLOCKBYTES_USIZE).unwrap(), - updated_witness_counter, - ); - new_opcodes.extend(extra_opcodes); - offset += BLAKE2S_BLOCKBYTES_USIZE; - size -= BLAKE2S_BLOCKBYTES_USIZE; - num_witness = updated_witness_counter; - } - - let (u32_max, extra_opcodes, mut num_witness) = UInt32::load_constant(u32::MAX, num_witness); - new_opcodes.extend(extra_opcodes); - blake2s_state.f[0] = u32_max; - - // pad final block - let mut final_block = input.get(offset..).unwrap().to_vec(); - for _ in 0..BLAKE2S_BLOCKBYTES_USIZE - final_block.len() { - let (pad, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(0_u32, num_witness); - new_opcodes.extend(extra_opcodes); - final_block.push(pad.inner); - num_witness = updated_witness_counter; - } - - let (size_w, extra_opcodes, num_witness) = UInt32::load_constant(size as u32, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - blake2s_increment_counter(&mut blake2s_state, &size_w, num_witness); - new_opcodes.extend(extra_opcodes); - - let (extra_opcodes, num_witness) = - blake2s_compress(&mut blake2s_state, &blake2s_iv, &final_block, num_witness); - new_opcodes.extend(extra_opcodes); - - // decompose the result bytes in u32 to u8 - let (extra_opcodes, mut byte1, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[0].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte2, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[1].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte3, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[2].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte4, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[3].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte5, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[4].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte6, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[5].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte7, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[6].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut byte8, num_witness) = - byte_decomposition(Expression::from(blake2s_state.h[7].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - - byte1.reverse(); - byte2.reverse(); - byte3.reverse(); - byte4.reverse(); - byte5.reverse(); - byte6.reverse(); - byte7.reverse(); - byte8.reverse(); - - let result = vec![byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8] - .into_iter() - .flatten() - .collect(); - - (result, num_witness, new_opcodes) -} - -fn blake2s_increment_counter( - state: &mut Blake2sState, - inc: &UInt32, - num_witness: u32, -) -> (Vec, u32) { - let mut new_opcodes = Vec::new(); - - // t0 + inc - let (state_t0, extra_opcodes, num_witness) = state.t[0].add(inc, num_witness); - new_opcodes.extend(extra_opcodes); - state.t[0] = state_t0; - - // t1 + (t0 < inc) - let (to_inc, extra_opcodes, num_witness) = state.t[0].less_than_comparison(inc, num_witness); - new_opcodes.extend(extra_opcodes); - let (state_t1, extra_opcodes, num_witness) = state.t[1].add(&to_inc, num_witness); - new_opcodes.extend(extra_opcodes); - state.t[1] = state_t1; - - (new_opcodes, num_witness) -} - -fn blake2s_compress( - state: &mut Blake2sState, - blake2s_iv: &Blake2sIV, - input: &[Witness], - mut num_witness: u32, -) -> (Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut m = Vec::new(); - let mut v = Vec::new(); - - for i in 0..16 { - let mut mi_bytes = input.get(i * 4..i * 4 + 4).unwrap().to_vec(); - mi_bytes.reverse(); - let (mi, extra_opcodes, updated_witness_counter) = - UInt32::from_witnesses(&mi_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - m.push(mi[0]); - num_witness = updated_witness_counter; - } - - for i in 0..8 { - v.push(state.h[i]); - } - - v.push(blake2s_iv.iv[0]); - v.push(blake2s_iv.iv[1]); - v.push(blake2s_iv.iv[2]); - v.push(blake2s_iv.iv[3]); - let (v12, extra_opcodes, num_witness) = state.t[0].xor(&blake2s_iv.iv[4], num_witness); - new_opcodes.extend(extra_opcodes); - v.push(v12); - let (v13, extra_opcodes, num_witness) = state.t[1].xor(&blake2s_iv.iv[5], num_witness); - new_opcodes.extend(extra_opcodes); - v.push(v13); - let (v14, extra_opcodes, num_witness) = state.f[0].xor(&blake2s_iv.iv[6], num_witness); - new_opcodes.extend(extra_opcodes); - v.push(v14); - let (v15, extra_opcodes, num_witness) = state.f[1].xor(&blake2s_iv.iv[7], num_witness); - new_opcodes.extend(extra_opcodes); - v.push(v15); - - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 0, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 1, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 2, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 3, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 5, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 6, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 7, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = blake2s_round(&mut v, &m, 8, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, mut num_witness) = blake2s_round(&mut v, &m, 9, num_witness); - new_opcodes.extend(extra_opcodes); - - for i in 0..8 { - let (a, extra_opcodes, updated_witness_counter) = state.h[i].xor(&v[i], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_hi, extra_opcodes, updated_witness_counter) = - a.xor(&v[i + 8], updated_witness_counter); - new_opcodes.extend(extra_opcodes); - state.h[i] = state_hi; - num_witness = updated_witness_counter; - } - - (new_opcodes, num_witness) -} - -fn blake2s_round( - state: &mut [UInt32], - msg: &[UInt32], - round: usize, - num_witness: u32, -) -> (Vec, u32) { - let mut new_opcodes = Vec::new(); - let schedule = &MSG_SCHEDULE_BLAKE2[round]; - - // Mix the columns. - let (extra_opcodes, num_witness) = - g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]], num_witness); - new_opcodes.extend(extra_opcodes); - - // Mix the rows. - let (extra_opcodes, num_witness) = - g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]], num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, num_witness) = - g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]], num_witness); - new_opcodes.extend(extra_opcodes); - - (new_opcodes, num_witness) -} - -#[allow(clippy::too_many_arguments)] -fn g( - state: &mut [UInt32], - a: usize, - b: usize, - c: usize, - d: usize, - x: UInt32, - y: UInt32, - num_witness: u32, -) -> (Vec, u32) { - let mut new_opcodes = Vec::new(); - - // calculate state[a] as `state[a] + state[b] + x` - let (state_a_1, extra_opcodes, num_witness) = state[a].add(&state[b], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_a, extra_opcodes, num_witness) = state_a_1.add(&x, num_witness); - new_opcodes.extend(extra_opcodes); - state[a] = state_a; - - // calculate state[d] as `(state[d] ^ state[a]).ror(16)` - let (state_d_1, extra_opcodes, num_witness) = state[d].xor(&state[a], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_d, extra_opcodes, num_witness) = state_d_1.ror(16, num_witness); - new_opcodes.extend(extra_opcodes); - state[d] = state_d; - - // calculate state[c] as `state[c] + state[d]` - let (state_c, extra_opcodes, num_witness) = state[c].add(&state[d], num_witness); - new_opcodes.extend(extra_opcodes); - state[c] = state_c; - - // caclulate state[b] as `(state[b] ^ state[c]).ror(12)` - let (state_b_1, extra_opcodes, num_witness) = state[b].xor(&state[c], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_b, extra_opcodes, num_witness) = state_b_1.ror(12, num_witness); - new_opcodes.extend(extra_opcodes); - state[b] = state_b; - - // calculate state[a] as `state[a] + state[b] + y` - let (state_a_1, extra_opcodes, num_witness) = state[a].add(&state[b], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_a, extra_opcodes, num_witness) = state_a_1.add(&y, num_witness); - new_opcodes.extend(extra_opcodes); - state[a] = state_a; - - // calculate state[d] as `(state[d] ^ state[a]).ror(8)` - let (state_d_1, extra_opcodes, num_witness) = state[d].xor(&state[a], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_d, extra_opcodes, num_witness) = state_d_1.ror(8, num_witness); - new_opcodes.extend(extra_opcodes); - state[d] = state_d; - - // calculate state[c] as `state[c] + state[d]` - let (state_c, extra_opcodes, num_witness) = state[c].add(&state[d], num_witness); - new_opcodes.extend(extra_opcodes); - state[c] = state_c; - - // caclulate state[b] as `(state[b] ^ state[c]).ror(7)` - let (state_b_1, extra_opcodes, num_witness) = state[b].xor(&state[c], num_witness); - new_opcodes.extend(extra_opcodes); - let (state_b, extra_opcodes, num_witness) = state_b_1.ror(7, num_witness); - new_opcodes.extend(extra_opcodes); - state[b] = state_b; - - (new_opcodes, num_witness) -} - -/// Blake2s state `h` `t` and `f` -#[derive(Debug)] -struct Blake2sState { - h: Vec, - t: Vec, - f: Vec, -} - -impl Blake2sState { - fn new(h: Vec, t: Vec, f: Vec) -> Self { - Blake2sState { h, t, f } - } - - /// Initialize internal state of Blake2s - fn init(mut num_witness: u32) -> (Blake2sState, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut h = Vec::new(); - let mut t = Vec::new(); - let mut f = Vec::new(); - - for init_h in INITIAL_H { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(init_h, num_witness); - new_opcodes.extend(extra_opcodes); - h.push(new_witness); - num_witness = updated_witness_counter; - } - - for _ in 0..2 { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(0_u32, num_witness); - new_opcodes.extend(extra_opcodes); - t.push(new_witness); - num_witness = updated_witness_counter; - } - - for _ in 0..2 { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(0_u32, num_witness); - new_opcodes.extend(extra_opcodes); - f.push(new_witness); - num_witness = updated_witness_counter; - } - - let blake2s_state = Blake2sState::new(h, t, f); - - (blake2s_state, new_opcodes, num_witness) - } -} - -/// Blake2s IV (Initialization Vector) -struct Blake2sIV { - iv: Vec, -} - -impl Blake2sIV { - fn new(iv: Vec) -> Self { - Blake2sIV { iv } - } - - /// Initialize IV of Blake2s - fn init(mut num_witness: u32) -> (Blake2sIV, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut iv = Vec::new(); - - for iv_v in IV_VALUE { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(iv_v, num_witness); - new_opcodes.extend(extra_opcodes); - iv.push(new_witness); - num_witness = updated_witness_counter; - } - - let blake2s_iv = Blake2sIV::new(iv); - - (blake2s_iv, new_opcodes, num_witness) - } -} - -struct Blake2sConstantsInCircuit { - blake2s_blockbytes_uint32: UInt32, -} - -impl Blake2sConstantsInCircuit { - fn new(blake2s_blockbytes_uint32: UInt32) -> Self { - Blake2sConstantsInCircuit { blake2s_blockbytes_uint32 } - } - - fn init(num_witness: u32) -> (Blake2sConstantsInCircuit, Vec, u32) { - let mut new_opcodes = Vec::new(); - let (blake2s_blockbytes_uint32, extra_opcodes, num_witness) = - UInt32::load_constant(64_u32, num_witness); - new_opcodes.extend(extra_opcodes); - - (Blake2sConstantsInCircuit::new(blake2s_blockbytes_uint32), new_opcodes, num_witness) - } -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/hash_to_field.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/hash_to_field.rs deleted file mode 100644 index 91a7cdd09e4..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/hash_to_field.rs +++ /dev/null @@ -1,168 +0,0 @@ -//! HashToField128Security fallback function. -use super::{ - blake2s::create_blake2s_constraint, - utils::{byte_decomposition, round_to_nearest_byte}, - UInt32, -}; -use crate::helpers::VariableStore; -use acir::{ - brillig::{self, RegisterIndex}, - circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, - Opcode, - }, - native_types::{Expression, Witness}, - FieldElement, -}; - -pub fn hash_to_field( - inputs: Vec<(Expression, u32)>, - outputs: Witness, - mut num_witness: u32, -) -> (u32, Vec) { - let mut new_opcodes = Vec::new(); - let mut new_inputs = Vec::new(); - - // Decompose the input field elements into bytes and collect the resulting witnesses. - for (witness, num_bits) in inputs { - let num_bytes = round_to_nearest_byte(num_bits); - let (extra_opcodes, extra_inputs, updated_witness_counter) = - byte_decomposition(witness, num_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - new_inputs.extend(extra_inputs); - num_witness = updated_witness_counter; - } - - let (result, num_witness, extra_opcodes) = create_blake2s_constraint(new_inputs, num_witness); - new_opcodes.extend(extra_opcodes); - - // transform bytes to a single field - let (result, extra_opcodes, num_witness) = field_from_be_bytes(&result, num_witness); - new_opcodes.extend(extra_opcodes); - - // constrain the outputs to be the same as the result of the circuit - let mut expr = Expression::from(outputs); - expr.push_addition_term(-FieldElement::one(), result); - new_opcodes.push(Opcode::Arithmetic(expr)); - (num_witness, new_opcodes) -} - -/// Convert bytes represented by [Witness]es to a single [FieldElement] -fn field_from_be_bytes(result: &[Witness], num_witness: u32) -> (Witness, Vec, u32) { - let mut new_opcodes = Vec::new(); - - // Load `0` and `256` using the load constant function from UInt32 - let (new_witness, extra_opcodes, num_witness) = UInt32::load_constant(0, num_witness); - let mut new_witness = new_witness.inner; - new_opcodes.extend(extra_opcodes); - let (const_256, extra_opcodes, mut num_witness) = UInt32::load_constant(256, num_witness); - let const_256 = const_256.inner; - new_opcodes.extend(extra_opcodes); - - // add byte and multiply 256 each round - for r in result.iter().take(result.len() - 1) { - let (updated_witness, extra_opcodes, updated_witness_counter) = - field_addition(&new_witness, r, num_witness); - new_opcodes.extend(extra_opcodes); - let (updated_witness, extra_opcodes, updated_witness_counter) = - field_mul(&updated_witness, &const_256, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - new_witness = updated_witness; - num_witness = updated_witness_counter; - } - - let (new_witness, extra_opcodes, num_witness) = - field_addition(&new_witness, &result[result.len() - 1], num_witness); - new_opcodes.extend(extra_opcodes); - - (new_witness, new_opcodes, num_witness) -} - -/// Caculate and constrain `self` + `rhs` as field -fn field_addition( - lhs: &Witness, - rhs: &Witness, - mut num_witness: u32, -) -> (Witness, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calculate `self` + `rhs` as field - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), *lhs)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), *rhs)], - q_c: FieldElement::zero(), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::BinaryFieldOp { - op: brillig::BinaryFieldOp::Add, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain addition - let mut add_expr = Expression::from(new_witness); - add_expr.push_addition_term(-FieldElement::one(), *lhs); - add_expr.push_addition_term(-FieldElement::one(), *rhs); - new_opcodes.push(Opcode::Arithmetic(add_expr)); - - (new_witness, new_opcodes, num_witness) -} - -/// Calculate and constrain `self` * `rhs` as field -pub(crate) fn field_mul( - lhs: &Witness, - rhs: &Witness, - mut num_witness: u32, -) -> (Witness, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calulate `self` * `rhs` with overflow - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), *lhs)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), *rhs)], - q_c: FieldElement::zero(), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::BinaryFieldOp { - op: brillig::BinaryFieldOp::Mul, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain mul - let mut mul_constraint = Expression::from(new_witness); - mul_constraint.push_multiplication_term(-FieldElement::one(), *lhs, *rhs); - new_opcodes.push(Opcode::Arithmetic(mul_constraint)); - - (new_witness, new_opcodes, num_witness) -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/keccak256.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/keccak256.rs deleted file mode 100644 index d91db3dc2c6..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/keccak256.rs +++ /dev/null @@ -1,269 +0,0 @@ -//! Keccak256 fallback function. -use super::{ - sha256::pad, - uint8::UInt8, - utils::{byte_decomposition, round_to_nearest_byte}, - UInt64, -}; -use acir::{ - circuit::Opcode, - native_types::{Expression, Witness}, - FieldElement, -}; - -const STATE_NUM_BYTES: usize = 200; -const BITS: usize = 256; -const WORD_SIZE: usize = 8; -const BLOCK_SIZE: usize = (1600 - BITS * 2) / WORD_SIZE; -const ROUND_CONSTANTS: [u64; 24] = [ - 1, - 0x8082, - 0x800000000000808a, - 0x8000000080008000, - 0x808b, - 0x80000001, - 0x8000000080008081, - 0x8000000000008009, - 0x8a, - 0x88, - 0x80008009, - 0x8000000a, - 0x8000808b, - 0x800000000000008b, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x800a, - 0x800000008000000a, - 0x8000000080008081, - 0x8000000000008080, - 0x80000001, - 0x8000000080008008, -]; -const RHO: [u32; 24] = - [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44]; -const PI: [usize; 24] = - [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1]; - -pub fn keccak256( - inputs: Vec<(Expression, u32)>, - outputs: Vec, - mut num_witness: u32, -) -> (u32, Vec) { - let mut new_opcodes = Vec::new(); - let mut new_inputs = Vec::new(); - - // Decompose the input field elements into bytes and collect the resulting witnesses. - for (witness, num_bits) in inputs { - let num_bytes = round_to_nearest_byte(num_bits); - let (extra_opcodes, extra_inputs, updated_witness_counter) = - byte_decomposition(witness, num_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - new_inputs.extend(extra_inputs); - num_witness = updated_witness_counter; - } - - let (result, num_witness, extra_opcodes) = create_keccak_constraint(new_inputs, num_witness); - new_opcodes.extend(extra_opcodes); - - // constrain the outputs to be the same as the result of the circuit - for i in 0..outputs.len() { - let mut expr = Expression::from(outputs[i]); - expr.push_addition_term(-FieldElement::one(), result[i]); - new_opcodes.push(Opcode::Arithmetic(expr)); - } - (num_witness, new_opcodes) -} - -fn create_keccak_constraint( - input: Vec, - num_witness: u32, -) -> (Vec, u32, Vec) { - let mut new_opcodes = Vec::new(); - let num_blocks = input.len() / BLOCK_SIZE + 1; - - // pad keccak - let (input, extra_opcodes, mut num_witness) = pad_keccak(input, num_blocks, num_witness); - new_opcodes.extend(extra_opcodes); - - // prepare state - let mut state = Vec::with_capacity(200); - for _ in 0..STATE_NUM_BYTES { - let (zero, extra_opcodes, updated_witness_counter) = UInt8::load_constant(0, num_witness); - new_opcodes.extend(extra_opcodes); - state.push(zero); - num_witness = updated_witness_counter; - } - - // process block - for i in 0..num_blocks { - for j in 0..BLOCK_SIZE { - let (new_state, extra_opcodes, updated_witness_counter) = - state[j].xor(&UInt8::new(input[i * BLOCK_SIZE + j]), num_witness); - new_opcodes.extend(extra_opcodes); - state[j] = new_state; - num_witness = updated_witness_counter; - } - let (new_state, extra_opcodes, updated_witness_counter) = keccakf(state, num_witness); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - state = new_state; - } - - let result: Vec = state[..32].iter().map(|x| x.inner).collect(); - (result, num_witness, new_opcodes) -} - -fn keccakf(state: Vec, num_witness: u32) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - - // turn state into UInt64 - let mut state_witnesses: Vec = Vec::new(); - for i in 0..state.len() / 8 { - for j in 0..8 { - state_witnesses.push(state[i * 8 + (7 - j)].inner); - } - } - let (mut state_u64, extra_opcodes, mut num_witness) = - UInt64::from_witnesses(&state_witnesses, num_witness); - new_opcodes.extend(extra_opcodes); - - // process round - for round_constant in ROUND_CONSTANTS { - let (new_state_u64, extra_opcodes, updated_witness_counter) = - keccak_round(state_u64, round_constant, num_witness); - state_u64 = new_state_u64; - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - } - - // turn state back to UInt8 - let state_u64_witnesses: Vec = state_u64.into_iter().map(|x| x.inner).collect(); - let mut state_u8 = Vec::with_capacity(state_u64_witnesses.len()); - for state_u64_witness in state_u64_witnesses { - let (extra_opcodes, mut u8s, updated_witness_counter) = - byte_decomposition(Expression::from(state_u64_witness), 8, num_witness); - new_opcodes.extend(extra_opcodes); - u8s.reverse(); - state_u8.push(u8s); - num_witness = updated_witness_counter; - } - - let state_u8: Vec = state_u8.into_iter().flatten().map(UInt8::new).collect(); - (state_u8, new_opcodes, num_witness) -} - -fn keccak_round( - mut a: Vec, - round_const: u64, - mut num_witness: u32, -) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - - // theta - let mut array = Vec::with_capacity(5); - for _ in 0..5 { - let (zero, extra_opcodes, updated_witness_counter) = UInt64::load_constant(0, num_witness); - array.push(zero); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - } - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - let (new_array_ele, extra_opcodes, updated_witness_counter) = - array[x].xor(&a[x + y], num_witness); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - array[x] = new_array_ele; - } - } - for x in 0..5 { - for y_count in 0..5 { - let y = y_count * 5; - let (a_ele, extra_opcodes, updated_witness_counter) = - array[(x + 1) % 5].rol(1, num_witness); - new_opcodes.extend(extra_opcodes); - let (b_ele, extra_opcodes, updated_witness_counter) = - array[(x + 4) % 5].xor(&a_ele, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (new_array_ele, extra_opcodes, updated_witness_counter) = - a[x + y].xor(&b_ele, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - a[x + y] = new_array_ele; - } - } - - // rho and pi - let mut last = a[1]; - for x in 0..24 { - array[0] = a[PI[x]]; - let (a_ele, extra_opcodes, updated_witness_counter) = last.rol(RHO[x], num_witness); - new_opcodes.extend(extra_opcodes); - a[PI[x]] = a_ele; - num_witness = updated_witness_counter; - last = array[0]; - } - - // chi - for y_step in 0..5 { - let y = y_step * 5; - - array[..5].copy_from_slice(&a[y..(5 + y)]); - - for x in 0..5 { - let (a_ele, extra_opcodes, updated_witness_counter) = - array[(x + 1) % 5].not(num_witness); - new_opcodes.extend(extra_opcodes); - let (b_ele, extra_opcodes, updated_witness_counter) = - a_ele.and(&array[(x + 2) % 5], updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (c_ele, extra_opcodes, updated_witness_counter) = - array[x].xor(&b_ele, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - a[y + x] = c_ele; - num_witness = updated_witness_counter; - } - } - - // iota - let (rc, extra_opcodes, num_witness) = UInt64::load_constant(round_const, num_witness); - new_opcodes.extend(extra_opcodes); - let (a_ele, extra_opcodes, num_witness) = a[0].xor(&rc, num_witness); - new_opcodes.extend(extra_opcodes); - a[0] = a_ele; - - (a, new_opcodes, num_witness) -} - -fn pad_keccak( - mut input: Vec, - num_blocks: usize, - num_witness: u32, -) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let total_len = BLOCK_SIZE * num_blocks; - - let (mut num_witness, pad_witness, extra_opcodes) = pad(0x01, 8, num_witness); - - new_opcodes.extend(extra_opcodes); - input.push(pad_witness); - for _ in 0..total_len - input.len() { - let (updated_witness_counter, pad_witness, extra_opcodes) = pad(0x00, 8, num_witness); - new_opcodes.extend(extra_opcodes); - input.push(pad_witness); - num_witness = updated_witness_counter; - } - - let (zero_x_80, extra_opcodes, num_witness) = UInt8::load_constant(0x80, num_witness); - new_opcodes.extend(extra_opcodes); - let (final_pad, extra_opcodes, num_witness) = - UInt8::new(input[total_len - 1]).xor(&zero_x_80, num_witness); - new_opcodes.extend(extra_opcodes); - input[total_len - 1] = final_pad.inner; - - (input, new_opcodes, num_witness) -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/logic_fallbacks.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/logic_fallbacks.rs deleted file mode 100644 index fa8c1060a26..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/logic_fallbacks.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::{blackbox_fallbacks::utils::mul_with_witness, helpers::VariableStore}; - -use super::utils::{bit_decomposition, boolean_expr}; -use acir::{ - acir_field::FieldElement, - circuit::Opcode, - native_types::{Expression, Witness}, -}; - -// Range constraint -pub fn range(opcode: Expression, bit_size: u32, mut num_witness: u32) -> (u32, Vec) { - if bit_size == 1 { - let mut variables = VariableStore::new(&mut num_witness); - let bit_constraint = Opcode::Arithmetic(boolean_expr(&opcode, &mut variables)); - return (variables.finalize(), vec![bit_constraint]); - } - - let (new_opcodes, _, updated_witness_counter) = - bit_decomposition(opcode, bit_size, num_witness); - (updated_witness_counter, new_opcodes) -} - -/// Returns a set of opcodes which constrain `a & b == result` -/// -/// `a` and `b` are assumed to be constrained to fit within `bit_size` externally. -pub fn and( - a: Expression, - b: Expression, - result: Witness, - bit_size: u32, - mut num_witness: u32, -) -> (u32, Vec) { - if bit_size == 1 { - let mut variables = VariableStore::new(&mut num_witness); - - let mut and_expr = mul_with_witness(&a, &b, &mut variables); - and_expr.push_addition_term(-FieldElement::one(), result); - - return (variables.finalize(), vec![Opcode::Arithmetic(and_expr)]); - } - // Decompose the operands into bits - // - let (extra_opcodes_a, a_bits, updated_witness_counter) = - bit_decomposition(a, bit_size, num_witness); - - let (extra_opcodes_b, b_bits, updated_witness_counter) = - bit_decomposition(b, bit_size, updated_witness_counter); - - assert_eq!(a_bits.len(), b_bits.len()); - assert_eq!(a_bits.len(), bit_size as usize); - - let mut two_pow = FieldElement::one(); - let two = FieldElement::from(2_i128); - - // Build an expression that Multiplies each bit element-wise - // This gives the same truth table as the AND operation - // Additionally, we multiply by a power of 2 to build up the - // expected output; ie result = \sum 2^i x_i * y_i - let mut and_expr = Expression::default(); - for (a_bit, b_bit) in a_bits.into_iter().zip(b_bits) { - and_expr.push_multiplication_term(two_pow, a_bit, b_bit); - two_pow = two * two_pow; - } - and_expr.push_addition_term(-FieldElement::one(), result); - - and_expr.sort(); - - let mut new_opcodes = Vec::new(); - new_opcodes.extend(extra_opcodes_a); - new_opcodes.extend(extra_opcodes_b); - new_opcodes.push(Opcode::Arithmetic(and_expr)); - - (updated_witness_counter, new_opcodes) -} - -/// Returns a set of opcodes which constrain `a ^ b == result` -/// -/// `a` and `b` are assumed to be constrained to fit within `bit_size` externally. -pub fn xor( - a: Expression, - b: Expression, - result: Witness, - bit_size: u32, - mut num_witness: u32, -) -> (u32, Vec) { - if bit_size == 1 { - let mut variables = VariableStore::new(&mut num_witness); - - let product = mul_with_witness(&a, &b, &mut variables); - let mut xor_expr = &(&a + &b) - &product; - xor_expr.push_addition_term(-FieldElement::one(), result); - - return (variables.finalize(), vec![Opcode::Arithmetic(xor_expr)]); - } - - // Decompose the operands into bits - // - let (extra_opcodes_a, a_bits, updated_witness_counter) = - bit_decomposition(a, bit_size, num_witness); - let (extra_opcodes_b, b_bits, updated_witness_counter) = - bit_decomposition(b, bit_size, updated_witness_counter); - - assert_eq!(a_bits.len(), b_bits.len()); - assert_eq!(a_bits.len(), bit_size as usize); - - let mut two_pow = FieldElement::one(); - let two = FieldElement::from(2_i128); - - // Build an xor expression - // TODO: check this is the correct arithmetization - let mut xor_expr = Expression::default(); - for (a_bit, b_bit) in a_bits.into_iter().zip(b_bits) { - xor_expr.push_addition_term(two_pow, a_bit); - xor_expr.push_addition_term(two_pow, b_bit); - two_pow = two * two_pow; - xor_expr.push_multiplication_term(-two_pow, a_bit, b_bit); - } - xor_expr.push_addition_term(-FieldElement::one(), result); - - xor_expr.sort(); - let mut new_opcodes = Vec::new(); - new_opcodes.extend(extra_opcodes_a); - new_opcodes.extend(extra_opcodes_b); - new_opcodes.push(Opcode::Arithmetic(xor_expr)); - - (updated_witness_counter, new_opcodes) -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/mod.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/mod.rs deleted file mode 100644 index d2ca3c50fa7..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod blake2s; -mod hash_to_field; -mod keccak256; -mod logic_fallbacks; -mod sha256; -#[macro_use] -mod uint; -mod uint32; -mod uint64; -mod uint8; -mod utils; -pub use blake2s::blake2s; -pub use hash_to_field::hash_to_field; -pub use keccak256::keccak256; -pub use logic_fallbacks::{and, range, xor}; -pub use sha256::sha256; -pub use uint32::UInt32; -pub use uint64::UInt64; -pub use uint8::UInt8; diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/sha256.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/sha256.rs deleted file mode 100644 index 1661b030bcc..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/sha256.rs +++ /dev/null @@ -1,377 +0,0 @@ -//! Sha256 fallback function. -use super::uint32::UInt32; -use super::utils::{byte_decomposition, round_to_nearest_byte}; -use crate::helpers::VariableStore; -use acir::{ - brillig, - circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, - opcodes::{BlackBoxFuncCall, FunctionInput}, - Opcode, - }, - native_types::{Expression, Witness}, - FieldElement, -}; - -const INIT_CONSTANTS: [u32; 8] = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -]; - -const ROUND_CONSTANTS: [u32; 64] = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -]; - -pub fn sha256( - inputs: Vec<(Expression, u32)>, - outputs: Vec, - mut num_witness: u32, -) -> (u32, Vec) { - let mut new_opcodes = Vec::new(); - let mut new_inputs = Vec::new(); - let mut total_num_bytes = 0; - - // Decompose the input field elements into bytes and collect the resulting witnesses. - for (witness, num_bits) in inputs { - let num_bytes = round_to_nearest_byte(num_bits); - total_num_bytes += num_bytes; - let (extra_opcodes, extra_inputs, updated_witness_counter) = - byte_decomposition(witness, num_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - new_inputs.extend(extra_inputs); - num_witness = updated_witness_counter; - } - - let (result, num_witness, extra_opcodes) = - create_sha256_constraint(new_inputs, total_num_bytes, num_witness); - new_opcodes.extend(extra_opcodes); - - // constrain the outputs to be the same as the result of the circuit - for i in 0..outputs.len() { - let mut expr = Expression::from(outputs[i]); - expr.push_addition_term(-FieldElement::one(), result[i]); - new_opcodes.push(Opcode::Arithmetic(expr)); - } - (num_witness, new_opcodes) -} - -fn create_sha256_constraint( - mut input: Vec, - total_num_bytes: u32, - num_witness: u32, -) -> (Vec, u32, Vec) { - let mut new_opcodes = Vec::new(); - - // pad the bytes according to sha256 padding rules - let message_bits = total_num_bytes * 8; - let (mut num_witness, pad_witness, extra_opcodes) = pad(128, 8, num_witness); - new_opcodes.extend(extra_opcodes); - input.push(pad_witness); - let bytes_per_block = 64; - let num_bytes = (input.len() + 8) as u32; - let num_blocks = num_bytes / bytes_per_block + ((num_bytes % bytes_per_block != 0) as u32); - let num_total_bytes = num_blocks * bytes_per_block; - for _ in num_bytes..num_total_bytes { - let (updated_witness_counter, pad_witness, extra_opcodes) = pad(0, 8, num_witness); - num_witness = updated_witness_counter; - new_opcodes.extend(extra_opcodes); - input.push(pad_witness); - } - let (num_witness, pad_witness, extra_opcodes) = pad(message_bits, 64, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, pad_witness, num_witness) = - byte_decomposition(pad_witness.into(), 8, num_witness); - new_opcodes.extend(extra_opcodes); - input.extend(pad_witness); - - // turn witness into u32 and load sha256 state - let (input, extra_opcodes, num_witness) = UInt32::from_witnesses(&input, num_witness); - new_opcodes.extend(extra_opcodes); - let (mut rolling_hash, extra_opcodes, num_witness) = prepare_state_constants(num_witness); - new_opcodes.extend(extra_opcodes); - let (round_constants, extra_opcodes, mut num_witness) = prepare_round_constants(num_witness); - new_opcodes.extend(extra_opcodes); - // split the input into blocks of size 16 - let input: Vec> = input.chunks(16).map(|block| block.to_vec()).collect(); - - // process sha256 blocks - for i in &input { - let (new_rolling_hash, extra_opcodes, updated_witness_counter) = - sha256_block(i, rolling_hash.clone(), round_constants.clone(), num_witness); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - rolling_hash = new_rolling_hash; - } - - // decompose the result bytes in u32 to u8 - let (extra_opcodes, byte1, num_witness) = - byte_decomposition(Expression::from(rolling_hash[0].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte2, num_witness) = - byte_decomposition(Expression::from(rolling_hash[1].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte3, num_witness) = - byte_decomposition(Expression::from(rolling_hash[2].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte4, num_witness) = - byte_decomposition(Expression::from(rolling_hash[3].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte5, num_witness) = - byte_decomposition(Expression::from(rolling_hash[4].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte6, num_witness) = - byte_decomposition(Expression::from(rolling_hash[5].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte7, num_witness) = - byte_decomposition(Expression::from(rolling_hash[6].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - let (extra_opcodes, byte8, num_witness) = - byte_decomposition(Expression::from(rolling_hash[7].inner), 4, num_witness); - new_opcodes.extend(extra_opcodes); - - let result = vec![byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8] - .into_iter() - .flatten() - .collect(); - - (result, num_witness, new_opcodes) -} - -pub(crate) fn pad(number: u32, bit_size: u32, mut num_witness: u32) -> (u32, Witness, Vec) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let pad = variables.new_variable(); - - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from(number as u128), - })], - outputs: vec![BrilligOutputs::Simple(pad)], - bytecode: vec![brillig::Opcode::Stop], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - - let range = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: pad, num_bits: bit_size }, - }); - new_opcodes.push(range); - - (num_witness, pad, new_opcodes) -} - -fn sha256_block( - input: &[UInt32], - rolling_hash: Vec, - round_constants: Vec, - mut num_witness: u32, -) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut w = Vec::new(); - w.extend(input.to_owned()); - - for i in 16..64 { - // calculate s0 `w[i - 15].ror(7) ^ w[i - 15].ror(18) ^ (w[i - 15] >> 3)` - let (a1, extra_opcodes, updated_witness_counter) = w[i - 15].ror(7, num_witness); - new_opcodes.extend(extra_opcodes); - let (a2, extra_opcodes, updated_witness_counter) = - w[i - 15].ror(18, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (a3, extra_opcodes, updated_witness_counter) = - w[i - 15].rightshift(3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (a4, extra_opcodes, updated_witness_counter) = a1.xor(&a2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (s0, extra_opcodes, updated_witness_counter) = a4.xor(&a3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate s1 `w[i - 2].ror(17) ^ w[i - 2].ror(19) ^ (w[i - 2] >> 10)` - let (b1, extra_opcodes, updated_witness_counter) = - w[i - 2].ror(17, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (b2, extra_opcodes, updated_witness_counter) = - w[i - 2].ror(19, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (b3, extra_opcodes, updated_witness_counter) = - w[i - 2].rightshift(10, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (b4, extra_opcodes, updated_witness_counter) = b1.xor(&b2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (s1, extra_opcodes, updated_witness_counter) = b4.xor(&b3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate w[i] `w[i - 16] + w[i - 7] + s0 + s1` - let (c1, extra_opcodes, updated_witness_counter) = - w[i - 16].add(&w[i - 7], updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (c2, extra_opcodes, updated_witness_counter) = c1.add(&s0, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (c3, extra_opcodes, updated_witness_counter) = c2.add(&s1, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - w.push(c3); - num_witness = updated_witness_counter; - } - - let mut a = rolling_hash[0]; - let mut b = rolling_hash[1]; - let mut c = rolling_hash[2]; - let mut d = rolling_hash[3]; - let mut e = rolling_hash[4]; - let mut f = rolling_hash[5]; - let mut g = rolling_hash[6]; - let mut h = rolling_hash[7]; - - #[allow(non_snake_case)] - for i in 0..64 { - // calculate S1 `e.ror(6) ^ e.ror(11) ^ e.ror(25)` - let (a1, extra_opcodes, updated_witness_counter) = e.ror(6, num_witness); - new_opcodes.extend(extra_opcodes); - let (a2, extra_opcodes, updated_witness_counter) = e.ror(11, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (a3, extra_opcodes, updated_witness_counter) = e.ror(25, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (a4, extra_opcodes, updated_witness_counter) = a1.xor(&a2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (S1, extra_opcodes, updated_witness_counter) = a4.xor(&a3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate ch `(e & f) + (~e & g)` - let (b1, extra_opcodes, updated_witness_counter) = e.and(&f, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (b2, extra_opcodes, updated_witness_counter) = e.not(updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (b3, extra_opcodes, updated_witness_counter) = b2.and(&g, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (ch, extra_opcodes, updated_witness_counter) = b1.add(&b3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // caculate temp1 `h + S1 + ch + round_constants[i] + w[i]` - let (c1, extra_opcodes, updated_witness_counter) = h.add(&S1, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (c2, extra_opcodes, updated_witness_counter) = c1.add(&ch, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (c3, extra_opcodes, updated_witness_counter) = - c2.add(&round_constants[i], updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (temp1, extra_opcodes, updated_witness_counter) = - c3.add(&w[i], updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate S0 `a.ror(2) ^ a.ror(13) ^ a.ror(22)` - let (d1, extra_opcodes, updated_witness_counter) = a.ror(2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (d2, extra_opcodes, updated_witness_counter) = a.ror(13, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (d3, extra_opcodes, updated_witness_counter) = a.ror(22, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (d4, extra_opcodes, updated_witness_counter) = d1.xor(&d2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (S0, extra_opcodes, updated_witness_counter) = d4.xor(&d3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate T0 `b & c` - let (T0, extra_opcodes, updated_witness_counter) = b.and(&c, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate maj `(a & (b + c - (T0 + T0))) + T0` which is the same as `(a & b) ^ (a & c) ^ (b & c)` - let (e1, extra_opcodes, updated_witness_counter) = T0.add(&T0, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (e2, extra_opcodes, updated_witness_counter) = c.sub(&e1, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (e3, extra_opcodes, updated_witness_counter) = b.add(&e2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (e4, extra_opcodes, updated_witness_counter) = a.and(&e3, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - let (maj, extra_opcodes, updated_witness_counter) = e4.add(&T0, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - // calculate temp2 `S0 + maj` - let (temp2, extra_opcodes, updated_witness_counter) = S0.add(&maj, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - - h = g; - g = f; - f = e; - let (new_e, extra_opcodes, updated_witness_counter) = - d.add(&temp1, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - d = c; - c = b; - b = a; - let (new_a, extra_opcodes, updated_witness_counter) = - temp1.add(&temp2, updated_witness_counter); - new_opcodes.extend(extra_opcodes); - num_witness = updated_witness_counter; - a = new_a; - e = new_e; - } - - let mut output = Vec::new(); - let (output0, extra_opcodes, num_witness) = a.add(&rolling_hash[0], num_witness); - new_opcodes.extend(extra_opcodes); - let (output1, extra_opcodes, num_witness) = b.add(&rolling_hash[1], num_witness); - new_opcodes.extend(extra_opcodes); - let (output2, extra_opcodes, num_witness) = c.add(&rolling_hash[2], num_witness); - new_opcodes.extend(extra_opcodes); - let (output3, extra_opcodes, num_witness) = d.add(&rolling_hash[3], num_witness); - new_opcodes.extend(extra_opcodes); - let (output4, extra_opcodes, num_witness) = e.add(&rolling_hash[4], num_witness); - new_opcodes.extend(extra_opcodes); - let (output5, extra_opcodes, num_witness) = f.add(&rolling_hash[5], num_witness); - new_opcodes.extend(extra_opcodes); - let (output6, extra_opcodes, num_witness) = g.add(&rolling_hash[6], num_witness); - new_opcodes.extend(extra_opcodes); - let (output7, extra_opcodes, num_witness) = h.add(&rolling_hash[7], num_witness); - new_opcodes.extend(extra_opcodes); - - output.push(output0); - output.push(output1); - output.push(output2); - output.push(output3); - output.push(output4); - output.push(output5); - output.push(output6); - output.push(output7); - - (output, new_opcodes, num_witness) -} - -/// Load initial state constants of Sha256 -pub(crate) fn prepare_state_constants(mut num_witness: u32) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut new_witnesses = Vec::new(); - - for i in INIT_CONSTANTS { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(i, num_witness); - new_opcodes.extend(extra_opcodes); - new_witnesses.push(new_witness); - num_witness = updated_witness_counter; - } - - (new_witnesses, new_opcodes, num_witness) -} - -/// Load round constants of Sha256 -pub(crate) fn prepare_round_constants(mut num_witness: u32) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut new_witnesses = Vec::new(); - - for i in ROUND_CONSTANTS { - let (new_witness, extra_opcodes, updated_witness_counter) = - UInt32::load_constant(i, num_witness); - new_opcodes.extend(extra_opcodes); - new_witnesses.push(new_witness); - num_witness = updated_witness_counter; - } - - (new_witnesses, new_opcodes, num_witness) -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/uint.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/uint.rs deleted file mode 100644 index 6f4039835f7..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/uint.rs +++ /dev/null @@ -1,648 +0,0 @@ -#[macro_export] -macro_rules! impl_uint { - ( - $name:ident, - $type:ty, - $size:expr - ) => { - use acir::{ - brillig::{self, RegisterIndex}, - circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, - directives::QuotientDirective, - opcodes::{BlackBoxFuncCall, FunctionInput}, - Opcode, - }, - native_types::{Expression, Witness}, - FieldElement, - }; - use $crate::helpers::VariableStore; - - /// UInt contains a witness that points to a field element that represents a u32 integer - /// It has a inner field of type [Witness] that points to the field element and width = 32 - #[derive(Copy, Clone, Debug)] - pub struct $name { - pub(crate) inner: Witness, - width: u32, - } - - impl $name { - #[cfg(any(test, feature = "testing"))] - pub fn get_inner(&self) -> Witness { - self.inner - } - } - - impl $name { - /// Initialize A new [UInt] type with a [Witness] - pub fn new(witness: Witness) -> Self { - $name { inner: witness, width: $size } - } - - /// Get u(n) + 1 - pub(crate) fn get_max_plus_one( - &self, - mut num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from(2_u128.pow(self.width)), - })], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::Stop], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Load a constant into the circuit - pub(crate) fn load_constant( - constant: $type, - mut num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from(constant as u128), - })], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::Stop], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Returns the quotient and remainder such that lhs = rhs * quotient + remainder - // This should be the same as its equivalent in the Noir repo - pub fn euclidean_division( - lhs: &$name, - rhs: &$name, - mut num_witness: u32, - ) -> ($name, $name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let q_witness = variables.new_variable(); - let r_witness = variables.new_variable(); - - // compute quotient using directive function - let quotient_opcode = Opcode::Directive( - acir::circuit::directives::Directive::Quotient(QuotientDirective { - a: lhs.inner.into(), - b: rhs.inner.into(), - q: q_witness, - r: r_witness, - predicate: None, - }), - ); - new_opcodes.push(quotient_opcode); - - // make sure r and q are in 32 bit range - let r_range_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: r_witness, num_bits: lhs.width }, - }); - let q_range_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: q_witness, num_bits: lhs.width }, - }); - new_opcodes.push(r_range_opcode); - new_opcodes.push(q_range_opcode); - let num_witness = variables.finalize(); - - // constrain r < rhs - let (rhs_sub_r, extra_opcodes, num_witness) = - rhs.sub_no_overflow(&$name::new(r_witness), num_witness); - new_opcodes.extend(extra_opcodes); - let rhs_sub_r_range_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: rhs_sub_r.inner, num_bits: lhs.width }, - }); - new_opcodes.push(rhs_sub_r_range_opcode); - - // constrain lhs = rhs * quotient + remainder - let rhs_expr = Expression::from(rhs.inner); - let lhs_constraint = Expression::from(lhs.inner); - let rhs_constraint = &rhs_expr * &Expression::from(q_witness); - let rhs_constraint = &rhs_constraint.unwrap() + &Expression::from(r_witness); - let div_euclidean = &lhs_constraint - &rhs_constraint; - new_opcodes.push(Opcode::Arithmetic(div_euclidean)); - - ($name::new(q_witness), $name::new(r_witness), new_opcodes, num_witness) - } - - /// Rotate left `rotation` bits. `(x << rotation) | (x >> (width - rotation))` - // This should be the same as `u32.rotate_left(rotation)` in rust stdlib - pub fn rol(&self, rotation: u32, num_witness: u32) -> ($name, Vec, u32) { - let rotation = rotation % self.width; - let mut new_opcodes = Vec::new(); - let (right_shift, extra_opcodes, num_witness) = - self.rightshift(self.width - rotation, num_witness); - new_opcodes.extend(extra_opcodes); - let (left_shift, extra_opcodes, num_witness) = - self.leftshift(rotation, num_witness); - new_opcodes.extend(extra_opcodes); - let (result, extra_opcodes, num_witness) = left_shift.or(&right_shift, num_witness); - new_opcodes.extend(extra_opcodes); - - (result, new_opcodes, num_witness) - } - - /// Rotate right `rotation` bits. `(x >> rotation) | (x << (width - rotation))` - // This should be the same as `u32.rotate_right(rotation)` in rust stdlib - pub fn ror(&self, rotation: u32, num_witness: u32) -> ($name, Vec, u32) { - let rotation = rotation % self.width; - let mut new_opcodes = Vec::new(); - let (left_shift, extra_opcodes, num_witness) = - self.leftshift(self.width - rotation, num_witness); - new_opcodes.extend(extra_opcodes); - let (right_shift, extra_opcodes, num_witness) = - self.rightshift(rotation, num_witness); - new_opcodes.extend(extra_opcodes); - let (result, extra_opcodes, num_witness) = left_shift.or(&right_shift, num_witness); - new_opcodes.extend(extra_opcodes); - - (result, new_opcodes, num_witness) - } - - /// left shift by `bits` - pub fn leftshift(&self, bits: u32, num_witness: u32) -> ($name, Vec, u32) { - let bits = bits % self.width; - let mut new_opcodes = Vec::new(); - let two: $type = 2; - let (two_pow_rhs, extra_opcodes, num_witness) = - $name::load_constant(two.pow(bits), num_witness); - new_opcodes.extend(extra_opcodes); - let (left_shift, extra_opcodes, num_witness) = self.mul(&two_pow_rhs, num_witness); - new_opcodes.extend(extra_opcodes); - - (left_shift, new_opcodes, num_witness) - } - - /// right shift by `bits` - pub fn rightshift(&self, bits: u32, num_witness: u32) -> ($name, Vec, u32) { - let bits = bits % self.width; - let mut new_opcodes = Vec::new(); - let two: $type = 2; - let (two_pow_rhs, extra_opcodes, num_witness) = - $name::load_constant(two.pow(bits), num_witness); - new_opcodes.extend(extra_opcodes); - let (right_shift, _, extra_opcodes, num_witness) = - $name::euclidean_division(self, &two_pow_rhs, num_witness); - new_opcodes.extend(extra_opcodes); - - (right_shift, new_opcodes, num_witness) - } - - /// Caculate and constrain `self` + `rhs` - pub fn add(&self, rhs: &$name, mut num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calculate `self` + `rhs` with overflow - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), rhs.inner)], - q_c: FieldElement::zero(), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Add, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain addition - let mut add_expr = Expression::from(new_witness); - add_expr.push_addition_term(-FieldElement::one(), self.inner); - add_expr.push_addition_term(-FieldElement::one(), rhs.inner); - new_opcodes.push(Opcode::Arithmetic(add_expr)); - - // mod 2^width to get final result as the remainder - let (two_pow_width, extra_opcodes, num_witness) = - self.get_max_plus_one(num_witness); - new_opcodes.extend(extra_opcodes); - let (_, add_mod, extra_opcodes, num_witness) = $name::euclidean_division( - &$name::new(new_witness), - &two_pow_width, - num_witness, - ); - new_opcodes.extend(extra_opcodes); - - (add_mod, new_opcodes, num_witness) - } - - /// Caculate and constrain `self` - `rhs` - pub fn sub(&self, rhs: &$name, mut num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calculate 2^32 + self - rhs to avoid overflow - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), rhs.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from(1_u128 << self.width), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![ - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Add, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(2), - destination: RegisterIndex::from(0), - }, - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Sub, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }, - ], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain subtraction - let mut sub_constraint = Expression::from(self.inner); - sub_constraint.push_addition_term(-FieldElement::one(), new_witness); - sub_constraint.push_addition_term(-FieldElement::one(), rhs.inner); - sub_constraint.q_c = FieldElement::from(1_u128 << self.width); - new_opcodes.push(Opcode::Arithmetic(sub_constraint)); - - // mod 2^width to get final result as the remainder - let (two_pow_width, extra_opcodes, num_witness) = - self.get_max_plus_one(num_witness); - new_opcodes.extend(extra_opcodes); - let (_, sub_mod, extra_opcodes, num_witness) = $name::euclidean_division( - &$name::new(new_witness), - &two_pow_width, - num_witness, - ); - new_opcodes.extend(extra_opcodes); - - (sub_mod, new_opcodes, num_witness) - } - - /// Calculate and constrain `self` - `rhs` - 1 without allowing overflow - /// This is a helper function to `euclidean_division` - // There is a `-1` because theres a case where rhs = 2^32 and remainder = 0 - pub(crate) fn sub_no_overflow( - &self, - rhs: &$name, - mut num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calculate self - rhs - 1 - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), rhs.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::one(), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![ - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Sub, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }, - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Sub, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(2), - destination: RegisterIndex::from(0), - }, - ], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain subtraction - let mut sub_constraint = Expression::from(self.inner); - sub_constraint.push_addition_term(-FieldElement::one(), new_witness); - sub_constraint.push_addition_term(-FieldElement::one(), rhs.inner); - sub_constraint.q_c = -FieldElement::one(); - new_opcodes.push(Opcode::Arithmetic(sub_constraint)); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Calculate and constrain `self` * `rhs` - pub(crate) fn mul( - &self, - rhs: &$name, - mut num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - // calulate `self` * `rhs` with overflow - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), rhs.inner)], - q_c: FieldElement::zero(), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::BinaryFieldOp { - op: brillig::BinaryFieldOp::Mul, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain mul - let mut mul_constraint = Expression::from(new_witness); - mul_constraint.push_multiplication_term( - -FieldElement::one(), - self.inner, - rhs.inner, - ); - new_opcodes.push(Opcode::Arithmetic(mul_constraint)); - - // mod 2^width to get final result as the remainder - let (two_pow_rhs, extra_opcodes, num_witness) = self.get_max_plus_one(num_witness); - new_opcodes.extend(extra_opcodes); - let (_, mul_mod, extra_opcodes, num_witness) = - $name::euclidean_division(&$name::new(new_witness), &two_pow_rhs, num_witness); - new_opcodes.extend(extra_opcodes); - - (mul_mod, new_opcodes, num_witness) - } - - /// Calculate and constrain `self` and `rhs` - pub fn and(&self, rhs: &$name, mut num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - let num_witness = variables.finalize(); - let and_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND { - lhs: FunctionInput { witness: self.inner, num_bits: self.width }, - rhs: FunctionInput { witness: rhs.inner, num_bits: self.width }, - output: new_witness, - }); - new_opcodes.push(and_opcode); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Calculate and constrain `self` xor `rhs` - pub fn xor(&self, rhs: &$name, mut num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - let num_witness = variables.finalize(); - let xor_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::XOR { - lhs: FunctionInput { witness: self.inner, num_bits: self.width }, - rhs: FunctionInput { witness: rhs.inner, num_bits: self.width }, - output: new_witness, - }); - new_opcodes.push(xor_opcode); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Calculate and constrain `self` or `rhs` - pub fn or(&self, rhs: &$name, num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - - // a | b = (a & b) + (a ^ b) - let (a_and_b, extra_opcodes, num_witness) = self.and(rhs, num_witness); - new_opcodes.extend(extra_opcodes); - let (a_xor_b, extra_opcodes, num_witness) = self.xor(rhs, num_witness); - new_opcodes.extend(extra_opcodes); - let (or, extra_opcodes, num_witness) = a_and_b.add(&a_xor_b, num_witness); - new_opcodes.extend(extra_opcodes); - - (or, new_opcodes, num_witness) - } - - /// Calculate and constrain not `self` - pub(crate) fn not(&self, mut num_witness: u32) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from((1_u128 << self.width) - 1), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Sub, - bit_size: self.width, - lhs: RegisterIndex::from(1), - rhs: RegisterIndex::from(0), - destination: RegisterIndex::from(0), - }], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - let mut not_constraint = Expression::from(new_witness); - not_constraint.push_addition_term(FieldElement::one(), self.inner); - not_constraint.q_c = -FieldElement::from((1_u128 << self.width) - 1); - new_opcodes.push(Opcode::Arithmetic(not_constraint)); - - ($name::new(new_witness), new_opcodes, num_witness) - } - - /// Calculate and constrain `self` >= `rhs` - // This should be similar to its equivalent in the Noir repo - pub(crate) fn more_than_eq_comparison( - &self, - rhs: &$name, - mut num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let new_witness = variables.new_variable(); - let q_witness = variables.new_variable(); - let r_witness = variables.new_variable(); - - // calculate 2^32 + self - rhs - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), self.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::one(), rhs.inner)], - q_c: FieldElement::zero(), - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![], - q_c: FieldElement::from(1_u128 << self.width), - }), - ], - outputs: vec![BrilligOutputs::Simple(new_witness)], - bytecode: vec![ - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Add, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(2), - destination: RegisterIndex::from(0), - }, - brillig::Opcode::BinaryIntOp { - op: brillig::BinaryIntOp::Sub, - bit_size: 127, - lhs: RegisterIndex::from(0), - rhs: RegisterIndex::from(1), - destination: RegisterIndex::from(0), - }, - ], - predicate: None, - }); - new_opcodes.push(brillig_opcode); - let num_witness = variables.finalize(); - - // constrain subtraction - let mut sub_constraint = Expression::from(self.inner); - sub_constraint.push_addition_term(-FieldElement::one(), new_witness); - sub_constraint.push_addition_term(-FieldElement::one(), rhs.inner); - sub_constraint.q_c = FieldElement::from(1_u128 << self.width); - new_opcodes.push(Opcode::Arithmetic(sub_constraint)); - - let (two_pow_rhs, extra_opcodes, num_witness) = self.get_max_plus_one(num_witness); - new_opcodes.extend(extra_opcodes); - - // constraint 2^{max_bits} + a - b = q * 2^{max_bits} + r - // q = 1 if a == b - // q = 1 if a > b - // q = 0 if a < b - let quotient_opcode = Opcode::Directive( - acir::circuit::directives::Directive::Quotient(QuotientDirective { - a: new_witness.into(), - b: two_pow_rhs.inner.into(), - q: q_witness, - r: r_witness, - predicate: None, - }), - ); - new_opcodes.push(quotient_opcode); - - // make sure r in 32 bit range and q is 1 bit - let r_range_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: r_witness, num_bits: self.width }, - }); - let q_range_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: q_witness, num_bits: 1 }, - }); - new_opcodes.push(r_range_opcode); - new_opcodes.push(q_range_opcode); - - ($name::new(q_witness), new_opcodes, num_witness) - } - - /// Calculate and constrain `self` < `rhs` - pub fn less_than_comparison( - &self, - rhs: &$name, - num_witness: u32, - ) -> ($name, Vec, u32) { - let mut new_opcodes = Vec::new(); - let (mut comparison, extra_opcodes, num_witness) = - self.more_than_eq_comparison(rhs, num_witness); - new_opcodes.extend(extra_opcodes); - comparison.width = 1; - - // `self` < `rhs` == not `self` >= `rhs` - let (less_than, extra_opcodes, num_witness) = comparison.not(num_witness); - new_opcodes.extend(extra_opcodes); - - (less_than, new_opcodes, num_witness) - } - } - }; -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/uint32.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/uint32.rs deleted file mode 100644 index 58314d6ba4c..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/uint32.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::impl_uint; - -impl_uint!(UInt32, u32, 32); -impl UInt32 { - /// Load a [UInt32] from four [Witness]es each representing a [u8] - pub(crate) fn from_witnesses( - witnesses: &[Witness], - mut num_witness: u32, - ) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let mut uint = Vec::new(); - - for i in 0..witnesses.len() / 4 { - let new_witness = variables.new_variable(); - uint.push(UInt32::new(new_witness)); - let mut expr = Expression::from(new_witness); - for j in 0..4 { - let scaling_factor_value = 1 << (8 * (3 - j) as u32); - let scaling_factor = FieldElement::from(scaling_factor_value as u128); - expr.push_addition_term(-scaling_factor, witnesses[i * 4 + j]); - } - - new_opcodes.push(Opcode::Arithmetic(expr)); - } - let num_witness = variables.finalize(); - - (uint, new_opcodes, num_witness) - } -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/uint64.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/uint64.rs deleted file mode 100644 index cddb23275cb..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/uint64.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::impl_uint; - -impl_uint!(UInt64, u64, 64); -impl UInt64 { - /// Load a [UInt64] from eight [Witness]es each representing a [u8] - pub(crate) fn from_witnesses( - witnesses: &[Witness], - mut num_witness: u32, - ) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - let mut uint = Vec::new(); - - for i in 0..witnesses.len() / 8 { - let new_witness = variables.new_variable(); - uint.push(UInt64::new(new_witness)); - let mut expr = Expression::from(new_witness); - for j in 0..8 { - let scaling_factor_value: u128 = 1 << (8 * (7 - j) as u32); - let scaling_factor = FieldElement::from(scaling_factor_value); - expr.push_addition_term(-scaling_factor, witnesses[i * 8 + j]); - } - - new_opcodes.push(Opcode::Arithmetic(expr)); - } - let num_witness = variables.finalize(); - - (uint, new_opcodes, num_witness) - } -} diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/uint8.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/uint8.rs deleted file mode 100644 index 2ffc2cae1be..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/uint8.rs +++ /dev/null @@ -1,2 +0,0 @@ -use crate::impl_uint; -impl_uint!(UInt8, u8, 8); diff --git a/acvm-repo/stdlib/src/blackbox_fallbacks/utils.rs b/acvm-repo/stdlib/src/blackbox_fallbacks/utils.rs deleted file mode 100644 index 4921c71c9fe..00000000000 --- a/acvm-repo/stdlib/src/blackbox_fallbacks/utils.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::helpers::VariableStore; -use acir::{ - circuit::{ - directives::Directive, - opcodes::{BlackBoxFuncCall, FunctionInput}, - Opcode, - }, - native_types::{Expression, Witness}, - FieldElement, -}; - -fn round_to_nearest_mul_8(num_bits: u32) -> u32 { - let remainder = num_bits % 8; - - if remainder == 0 { - return num_bits; - } - - num_bits + 8 - remainder -} - -pub(crate) fn round_to_nearest_byte(num_bits: u32) -> u32 { - round_to_nearest_mul_8(num_bits) / 8 -} - -pub(crate) fn boolean_expr(expr: &Expression, variables: &mut VariableStore) -> Expression { - &mul_with_witness(expr, expr, variables) - expr -} - -/// Returns an expression which represents `lhs * rhs` -/// -/// If one has multiplicative term and the other is of degree one or more, -/// the function creates [intermediate variables][`Witness`] accordingly. -/// There are two cases where we can optimize the multiplication between two expressions: -/// 1. If both expressions have at most a total degree of 1 in each term, then we can just multiply them -/// as each term in the result will be degree-2. -/// 2. If one expression is a constant, then we can just multiply the constant with the other expression -/// -/// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial -/// which is what you get when you multiply two degree-1 univariate polynomials. -pub(crate) fn mul_with_witness( - lhs: &Expression, - rhs: &Expression, - variables: &mut VariableStore, -) -> Expression { - use std::borrow::Cow; - let lhs_is_linear = lhs.is_linear(); - let rhs_is_linear = rhs.is_linear(); - - // Case 1: Both expressions have at most a total degree of 1 in each term - if lhs_is_linear && rhs_is_linear { - return (lhs * rhs) - .expect("one of the expressions is a constant and so this should not fail"); - } - - // Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial - let lhs_reduced = if lhs_is_linear { - Cow::Borrowed(lhs) - } else { - Cow::Owned(variables.new_variable().into()) - }; - - // If the lhs and rhs are the same, then we do not need to reduce - // rhs, we only need to square the lhs. - if lhs == rhs { - return (&*lhs_reduced * &*lhs_reduced) - .expect("Both expressions are reduced to be degree<=1"); - }; - - let rhs_reduced = if rhs_is_linear { - Cow::Borrowed(rhs) - } else { - Cow::Owned(variables.new_variable().into()) - }; - - (&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree<=1") -} - -// Generates opcodes and directives to bit decompose the input `opcode` -// Returns the bits and the updated witness counter -// TODO:Ideally, we return the updated witness counter, or we require the input -// TODO to be a VariableStore. We are not doing this because we want migration to -// TODO be less painful -pub(crate) fn bit_decomposition( - opcode: Expression, - bit_size: u32, - mut num_witness: u32, -) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - - // First create a witness for each bit - let mut bit_vector = Vec::with_capacity(bit_size as usize); - for _ in 0..bit_size { - bit_vector.push(variables.new_variable()); - } - - // Next create a directive which computes those bits. - new_opcodes.push(Opcode::Directive(Directive::ToLeRadix { - a: opcode.clone(), - b: bit_vector.clone(), - radix: 2, - })); - - // Now apply constraints to the bits such that they are the bit decomposition - // of the input and each bit is actually a bit - let mut binary_exprs = Vec::new(); - let mut bit_decomp_constraint = opcode; - let mut two_pow: FieldElement = FieldElement::one(); - let two = FieldElement::from(2_i128); - for &bit in &bit_vector { - // Bit constraint to ensure each bit is a zero or one; bit^2 - bit = 0 - let expr = boolean_expr(&bit.into(), &mut variables); - binary_exprs.push(Opcode::Arithmetic(expr)); - - // Constraint to ensure that the bits are constrained to be a bit decomposition - // of the input - // ie \sum 2^i * x_i = input - bit_decomp_constraint.push_addition_term(-two_pow, bit); - two_pow = two * two_pow; - } - - new_opcodes.extend(binary_exprs); - bit_decomp_constraint.sort(); // TODO: we have an issue open to check if this is needed. Ideally, we remove it. - new_opcodes.push(Opcode::Arithmetic(bit_decomp_constraint)); - - (new_opcodes, bit_vector, variables.finalize()) -} - -// TODO: Maybe this can be merged with `bit_decomposition` -pub(crate) fn byte_decomposition( - opcode: Expression, - num_bytes: u32, - mut num_witness: u32, -) -> (Vec, Vec, u32) { - let mut new_opcodes = Vec::new(); - let mut variables = VariableStore::new(&mut num_witness); - - // First create a witness for each byte - let mut vector = Vec::with_capacity(num_bytes as usize); - for _ in 0..num_bytes { - vector.push(variables.new_variable()); - } - - // Next create a directive which computes those byte. - new_opcodes.push(Opcode::Directive(Directive::ToLeRadix { - a: opcode.clone(), - b: vector.clone(), - radix: 256, - })); - vector.reverse(); - - // Now apply constraints to the bytes such that they are the byte decomposition - // of the input and each byte is actually a byte - let mut byte_exprs = Vec::new(); - let mut decomp_constraint = opcode; - let byte_shift: u128 = 256; - for (i, v) in vector.iter().enumerate() { - let range = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { witness: *v, num_bits: 8 }, - }); - let scaling_factor_value = byte_shift.pow(num_bytes - 1 - i as u32); - let scaling_factor = FieldElement::from(scaling_factor_value); - - decomp_constraint.push_addition_term(-scaling_factor, *v); - - byte_exprs.push(range); - } - - new_opcodes.extend(byte_exprs); - decomp_constraint.sort(); - new_opcodes.push(Opcode::Arithmetic(decomp_constraint)); - - (new_opcodes, vector, variables.finalize()) -} diff --git a/acvm-repo/stdlib/src/helpers.rs b/acvm-repo/stdlib/src/helpers.rs deleted file mode 100644 index 5ab258368f4..00000000000 --- a/acvm-repo/stdlib/src/helpers.rs +++ /dev/null @@ -1,23 +0,0 @@ -use acir::native_types::Witness; - -// Simple helper struct to keep track of the current witness index -// and create variables -pub struct VariableStore<'a> { - witness_index: &'a mut u32, -} - -impl<'a> VariableStore<'a> { - pub fn new(witness_index: &'a mut u32) -> Self { - Self { witness_index } - } - - pub fn new_variable(&mut self) -> Witness { - let witness = Witness(*self.witness_index); - *self.witness_index += 1; - witness - } - - pub fn finalize(self) -> u32 { - *self.witness_index - } -} diff --git a/acvm-repo/stdlib/src/lib.rs b/acvm-repo/stdlib/src/lib.rs deleted file mode 100644 index 9aecde631fb..00000000000 --- a/acvm-repo/stdlib/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![forbid(unsafe_code)] -#![warn(unreachable_pub)] -#![warn(clippy::semicolon_if_nothing_returned)] -#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] - -pub mod blackbox_fallbacks; -pub mod helpers; diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 712913841f3..1f85145260d 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1605,28 +1605,28 @@ fn execute_brillig( _signature: &[u8], _message: &[u8], ) -> Result { - Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::SchnorrVerify)) + unimplemented!("SchnorrVerify is not supported") } fn pedersen_commitment( &self, _inputs: &[FieldElement], _domain_separator: u32, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::PedersenCommitment)) + unimplemented!("PedersenCommitment is not supported") } fn pedersen_hash( &self, _inputs: &[FieldElement], _domain_separator: u32, ) -> Result { - Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::PedersenHash)) + unimplemented!("PedersenHash is not supported") } fn fixed_base_scalar_mul( &self, _low: &FieldElement, _high: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::FixedBaseScalarMul)) + unimplemented!("FixedBaseScalarMul is not supported") } } diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 13b366819b0..2d99963ea1d 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -186,8 +186,6 @@ pub fn compile( // For now we default to plonk width = 3, though we can add it as a parameter let np_language = acvm::Language::PLONKCSat { width: 3 }; - #[allow(deprecated)] - let is_opcode_supported = acvm::pwg::default_is_opcode_supported(np_language); if contracts.unwrap_or_default() { let compiled_contract = compile_contract(&mut context, crate_id, &compile_options) @@ -200,9 +198,7 @@ pub fn compile( })? .0; - let optimized_contract = - nargo::ops::optimize_contract(compiled_contract, np_language, &is_opcode_supported) - .expect("Contract optimization failed"); + let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language); let compile_output = preprocess_contract(optimized_contract); Ok(JsCompileResult::new(compile_output)) @@ -217,9 +213,7 @@ pub fn compile( })? .0; - let optimized_program = - nargo::ops::optimize_program(compiled_program, np_language, &is_opcode_supported) - .expect("Program optimization failed"); + let optimized_program = nargo::ops::optimize_program(compiled_program, np_language); let compile_output = preprocess_program(optimized_program); Ok(JsCompileResult::new(compile_output)) diff --git a/release-please-config.json b/release-please-config.json index 3c5397c6784..e73993ca974 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -65,7 +65,6 @@ "blackbox_solver/Cargo.toml", "brillig/Cargo.toml", "brillig_vm/Cargo.toml", - "stdlib/Cargo.toml", { "type": "json", "path": "acvm_js/package.json", diff --git a/tooling/backend_interface/src/cli/info.rs b/tooling/backend_interface/src/cli/info.rs index d3fd89bd2bc..1aa2e640b15 100644 --- a/tooling/backend_interface/src/cli/info.rs +++ b/tooling/backend_interface/src/cli/info.rs @@ -1,9 +1,8 @@ use acvm::Language; use serde::Deserialize; -use std::collections::HashSet; use std::path::{Path, PathBuf}; -use crate::{BackendError, BackendOpcodeSupport}; +use crate::BackendError; use super::string_from_stderr; @@ -14,7 +13,11 @@ pub(crate) struct InfoCommand { #[derive(Deserialize)] struct InfoResponse { language: LanguageResponse, + #[allow(dead_code)] + #[deprecated(note = "This field is deprecated and will be removed in the future")] opcodes_supported: Vec, + #[allow(dead_code)] + #[deprecated(note = "This field is deprecated and will be removed in the future")] black_box_functions_supported: Vec, } @@ -24,20 +27,8 @@ struct LanguageResponse { width: Option, } -impl BackendOpcodeSupport { - fn new(info: InfoResponse) -> Self { - let opcodes: HashSet = info.opcodes_supported.into_iter().collect(); - let black_box_functions: HashSet = - info.black_box_functions_supported.into_iter().collect(); - Self { opcodes, black_box_functions } - } -} - impl InfoCommand { - pub(crate) fn run( - self, - binary_path: &Path, - ) -> Result<(Language, BackendOpcodeSupport), BackendError> { + pub(crate) fn run(self, binary_path: &Path) -> Result { let mut command = std::process::Command::new(binary_path); command.arg("info").arg("-c").arg(self.crs_path).arg("-o").arg("-"); @@ -59,23 +50,18 @@ impl InfoCommand { _ => panic!("Unknown langauge"), }; - Ok((language, BackendOpcodeSupport::new(backend_info))) + Ok(language) } } #[test] fn info_command() -> Result<(), BackendError> { - use acvm::acir::circuit::opcodes::Opcode; - - use acvm::acir::native_types::Expression; - let backend = crate::get_mock_backend()?; let crs_path = backend.backend_directory(); - let (language, opcode_support) = InfoCommand { crs_path }.run(backend.binary_path())?; + let language = InfoCommand { crs_path }.run(backend.binary_path())?; assert!(matches!(language, Language::PLONKCSat { width: 3 })); - assert!(opcode_support.is_opcode_supported(&Opcode::Arithmetic(Expression::default()))); Ok(()) } diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index d25319e11d5..c5232c3473a 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -1,14 +1,13 @@ #![warn(unused_crate_dependencies, unused_extern_crates)] #![warn(unreachable_pub)] -use std::{collections::HashSet, path::PathBuf}; +use std::path::PathBuf; mod cli; mod download; mod proof_system; mod smart_contract; -use acvm::acir::circuit::Opcode; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use bb_abstraction_leaks::BB_VERSION; use cli::VersionCommand; @@ -135,54 +134,6 @@ impl Backend { } } -pub struct BackendOpcodeSupport { - opcodes: HashSet, - black_box_functions: HashSet, -} - -impl BackendOpcodeSupport { - pub fn is_opcode_supported(&self, opcode: &Opcode) -> bool { - match opcode { - Opcode::Arithmetic(_) => self.opcodes.contains("arithmetic"), - Opcode::Directive(_) => self.opcodes.contains("directive"), - Opcode::Brillig(_) => self.opcodes.contains("brillig"), - Opcode::MemoryInit { .. } => self.opcodes.contains("memory_init"), - Opcode::MemoryOp { .. } => self.opcodes.contains("memory_op"), - Opcode::BlackBoxFuncCall(func) => { - self.black_box_functions.contains(func.get_black_box_func().name()) - } - } - } - - pub fn all() -> BackendOpcodeSupport { - BackendOpcodeSupport { - opcodes: HashSet::from([ - "arithmetic".to_string(), - "directive".to_string(), - "brillig".to_string(), - "memory_init".to_string(), - "memory_op".to_string(), - ]), - black_box_functions: HashSet::from([ - "sha256".to_string(), - "schnorr_verify".to_string(), - "blake2s".to_string(), - "pedersen".to_string(), - "pedersen_hash".to_string(), - "hash_to_field_128_security".to_string(), - "ecdsa_secp256k1".to_string(), - "fixed_base_scalar_mul".to_string(), - "and".to_string(), - "xor".to_string(), - "range".to_string(), - "keccak256".to_string(), - "recursive_aggregation".to_string(), - "ecdsa_secp256r1".to_string(), - ]), - } - } -} - #[cfg(test)] mod backend { use crate::{Backend, BackendError}; diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index bb47603bbf7..1de4b352bf7 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -11,7 +11,7 @@ use crate::cli::{ GatesCommand, InfoCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand, VkAsFieldsCommand, WriteVkCommand, }; -use crate::{Backend, BackendError, BackendOpcodeSupport}; +use crate::{Backend, BackendError}; impl Backend { pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { @@ -30,21 +30,20 @@ impl Backend { .run(binary_path) } - pub fn get_backend_info(&self) -> Result<(Language, BackendOpcodeSupport), BackendError> { + pub fn get_backend_info(&self) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; InfoCommand { crs_path: self.crs_directory() }.run(binary_path) } - /// If we cannot get a valid backend, returns the default backend which supports all the opcodes - /// and uses Plonk with width 3 + /// If we cannot get a valid backend, returns Plonk with width 3 /// The function also prints a message saying we could not find a backend - pub fn get_backend_info_or_default(&self) -> (Language, BackendOpcodeSupport) { - if let Ok(backend_info) = self.get_backend_info() { - (backend_info.0, backend_info.1) + pub fn get_backend_info_or_default(&self) -> Language { + if let Ok(language) = self.get_backend_info() { + language } else { - log::warn!("No valid backend found, defaulting to Plonk with width 3 and all opcodes supported"); - (Language::PLONKCSat { width: 3 }, BackendOpcodeSupport::all()) + log::warn!("No valid backend found, defaulting to Plonk with width 3"); + Language::PLONKCSat { width: 3 } } } diff --git a/tooling/lsp/src/requests/profile_run.rs b/tooling/lsp/src/requests/profile_run.rs index 84888d30ba5..231003e1e83 100644 --- a/tooling/lsp/src/requests/profile_run.rs +++ b/tooling/lsp/src/requests/profile_run.rs @@ -3,7 +3,7 @@ use std::{ future::{self, Future}, }; -use acvm::{acir::circuit::Opcode, Language}; +use acvm::Language; use async_lsp::{ErrorCode, ResponseError}; use nargo::artifacts::debug::DebugArtifact; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -57,8 +57,6 @@ fn on_profile_run_request_inner( .cloned() .partition(|package| package.is_binary()); - // # TODO(#3504): Consider how to incorporate Backend relevant information in wider context. - let is_opcode_supported = |_opcode: &Opcode| true; let np_language = Language::PLONKCSat { width: 3 }; let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace( @@ -66,7 +64,6 @@ fn on_profile_run_request_inner( &binary_packages, &contract_packages, np_language, - is_opcode_supported, &CompileOptions::default(), ) .map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?; diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index bca8ca24767..c743768bee2 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -47,12 +47,6 @@ pub enum NargoError { ForeignCallError(#[from] ForeignCallError), } -impl From for NargoError { - fn from(_: acvm::compiler::CompileError) -> Self { - NargoError::CompilationError - } -} - impl NargoError { /// Extracts the user defined failure message from the ExecutionError /// If one exists. @@ -69,7 +63,6 @@ impl NargoError { ExecutionError::AssertionFailed(message, _) => Some(message), ExecutionError::SolvingError(error) => match error { OpcodeResolutionError::IndexOutOfBounds { .. } - | OpcodeResolutionError::UnsupportedBlackBoxFunc(_) | OpcodeResolutionError::OpcodeNotSolvable(_) | OpcodeResolutionError::UnsatisfiedConstrain { .. } => None, OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message), diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index 59ac5672a11..c23ab242ae4 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -1,4 +1,4 @@ -use acvm::{acir::circuit::Opcode, Language}; +use acvm::Language; use fm::FileManager; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; @@ -18,22 +18,17 @@ pub fn compile_workspace( binary_packages: &[Package], contract_packages: &[Package], np_language: Language, - is_opcode_supported: impl Fn(&Opcode) -> bool + std::marker::Sync, compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CompileError> { // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() - .map(|package| { - compile_program(workspace, package, compile_options, np_language, &is_opcode_supported) - }) + .map(|package| compile_program(workspace, package, compile_options, np_language)) .collect(); let contract_results: Vec<(FileManager, CompilationResult)> = contract_packages .par_iter() - .map(|package| { - compile_contract(package, compile_options, np_language, &is_opcode_supported) - }) + .map(|package| compile_contract(package, compile_options, np_language)) .collect(); // Report any warnings/errors which were encountered during compilation. @@ -68,7 +63,6 @@ pub fn compile_program( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); @@ -85,8 +79,7 @@ pub fn compile_program( }; // Apply backend specific optimizations. - let optimized_program = crate::ops::optimize_program(program, np_language, is_opcode_supported) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_program = crate::ops::optimize_program(program, np_language); (context.file_manager, Ok((optimized_program, warnings))) } @@ -95,7 +88,6 @@ fn compile_contract( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = @@ -106,9 +98,7 @@ fn compile_contract( } }; - let optimized_contract = - crate::ops::optimize_contract(contract, np_language, &is_opcode_supported) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_contract = crate::ops::optimize_contract(contract, np_language); (context.file_manager, Ok((optimized_contract, warnings))) } diff --git a/tooling/nargo/src/ops/optimize.rs b/tooling/nargo/src/ops/optimize.rs index 54e2432aa40..6f96a49d04f 100644 --- a/tooling/nargo/src/ops/optimize.rs +++ b/tooling/nargo/src/ops/optimize.rs @@ -1,34 +1,23 @@ -use acvm::{acir::circuit::Opcode, Language}; -use iter_extended::try_vecmap; +use acvm::Language; +use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -use crate::NargoError; - -pub fn optimize_program( - mut program: CompiledProgram, - np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, -) -> Result { - let (optimized_circuit, location_map) = - acvm::compiler::compile(program.circuit, np_language, is_opcode_supported)?; +pub fn optimize_program(mut program: CompiledProgram, np_language: Language) -> CompiledProgram { + let (optimized_circuit, location_map) = acvm::compiler::compile(program.circuit, np_language); program.circuit = optimized_circuit; program.debug.update_acir(location_map); - Ok(program) + program } -pub fn optimize_contract( - contract: CompiledContract, - np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, -) -> Result { - let functions = try_vecmap(contract.functions, |mut func| { +pub fn optimize_contract(contract: CompiledContract, np_language: Language) -> CompiledContract { + let functions = vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode, np_language, is_opcode_supported)?; + acvm::compiler::compile(func.bytecode, np_language); func.bytecode = optimized_bytecode; func.debug.update_acir(location_map); - Ok::<_, NargoError>(func) - })?; + func + }); - Ok(CompiledContract { functions, ..contract }) + CompiledContract { functions, ..contract } } diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 02c83adb59a..dfda25043f3 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -7,7 +7,6 @@ use crate::backends::Backend; use crate::errors::CliError; use acvm::Language; -use backend_interface::BackendOpcodeSupport; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use clap::Args; use nargo::package::Package; @@ -46,7 +45,7 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let (np_language, opcode_support) = backend.get_backend_info()?; + let np_language = backend.get_backend_info()?; for package in &workspace { let smart_contract_string = smart_contract_for_package( &workspace, @@ -54,7 +53,6 @@ pub(crate) fn run( package, &args.compile_options, np_language, - &opcode_support, )?; let contract_dir = workspace.contracts_directory_path(package); @@ -74,10 +72,8 @@ fn smart_contract_for_package( package: &Package, compile_options: &CompileOptions, np_language: Language, - opcode_support: &BackendOpcodeSupport, ) -> Result { - let program = - compile_bin_package(workspace, package, compile_options, np_language, opcode_support)?; + let program = compile_bin_package(workspace, package, compile_options, np_language)?; let mut smart_contract_string = backend.eth_contract(&program.circuit)?; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 043c0841958..f0fb0cc1ec7 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,8 +1,6 @@ use std::path::Path; -use acvm::acir::circuit::Opcode; use acvm::Language; -use backend_interface::BackendOpcodeSupport; use fm::FileManager; use iter_extended::vecmap; use nargo::artifacts::contract::PreprocessedContract; @@ -72,13 +70,12 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let (np_language, opcode_support) = backend.get_backend_info_or_default(); + let np_language = backend.get_backend_info_or_default(); let (_, compiled_contracts) = compile_workspace( &workspace, &binary_packages, &contract_packages, np_language, - &opcode_support, &args.compile_options, )?; @@ -95,24 +92,17 @@ pub(super) fn compile_workspace( binary_packages: &[Package], contract_packages: &[Package], np_language: Language, - opcode_support: &BackendOpcodeSupport, compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CliError> { // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() - .map(|package| { - let is_opcode_supported = |opcode: &_| opcode_support.is_opcode_supported(opcode); - compile_program(workspace, package, compile_options, np_language, &is_opcode_supported) - }) + .map(|package| compile_program(workspace, package, compile_options, np_language)) .collect(); let contract_results: Vec<(FileManager, CompilationResult)> = contract_packages .par_iter() - .map(|package| { - let is_opcode_supported = |opcode: &_| opcode_support.is_opcode_supported(opcode); - compile_contract(package, compile_options, np_language, &is_opcode_supported) - }) + .map(|package| compile_contract(package, compile_options, np_language)) .collect(); // Report any warnings/errors which were encountered during compilation. @@ -147,16 +137,13 @@ pub(crate) fn compile_bin_package( package: &Package, compile_options: &CompileOptions, np_language: Language, - opcode_support: &BackendOpcodeSupport, ) -> Result { if package.is_library() { return Err(CompileError::LibraryCrate(package.name.clone()).into()); } let (file_manager, compilation_result) = - compile_program(workspace, package, compile_options, np_language, &|opcode| { - opcode_support.is_opcode_supported(opcode) - }); + compile_program(workspace, package, compile_options, np_language); let program = report_errors( compilation_result, @@ -173,7 +160,6 @@ fn compile_program( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); @@ -213,8 +199,7 @@ fn compile_program( }; // Apply backend specific optimizations. - let optimized_program = nargo::ops::optimize_program(program, np_language, is_opcode_supported) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_program = nargo::ops::optimize_program(program, np_language); let only_acir = compile_options.only_acir; save_program(optimized_program.clone(), package, &workspace.target_directory_path(), only_acir); @@ -225,7 +210,6 @@ fn compile_contract( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = @@ -236,9 +220,7 @@ fn compile_contract( } }; - let optimized_contract = - nargo::ops::optimize_contract(contract, np_language, &is_opcode_supported) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_contract = nargo::ops::optimize_contract(contract, np_language); (context.file_manager, Ok((optimized_contract, warnings))) } diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 5204e0f122c..ba07b3b096c 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -49,7 +49,7 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; let target_dir = &workspace.target_directory_path(); - let (np_language, opcode_support) = backend.get_backend_info()?; + let np_language = backend.get_backend_info()?; let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { println!( @@ -58,13 +58,8 @@ pub(crate) fn run( return Ok(()); }; - let compiled_program = compile_bin_package( - &workspace, - package, - &args.compile_options, - np_language, - &opcode_support, - )?; + let compiled_program = + compile_bin_package(&workspace, package, &args.compile_options, np_language)?; run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir) } diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index 2f69b4c7df7..ac3d80fe1fe 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -56,15 +56,10 @@ pub(crate) fn run( )?; let target_dir = &workspace.target_directory_path(); - let (np_language, opcode_support) = backend.get_backend_info_or_default(); + let np_language = backend.get_backend_info_or_default(); for package in &workspace { - let compiled_program = compile_bin_package( - &workspace, - package, - &args.compile_options, - np_language, - &opcode_support, - )?; + let compiled_program = + compile_bin_package(&workspace, package, &args.compile_options, np_language)?; let (return_value, solved_witness) = execute_program_and_decode(compiled_program, package, &args.prover_name)?; diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index b0f771bfc1c..9c2f10aab80 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -67,13 +67,12 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let (np_language, opcode_support) = backend.get_backend_info_or_default(); + let np_language = backend.get_backend_info_or_default(); let (compiled_programs, compiled_contracts) = compile_workspace( &workspace, &binary_packages, &contract_packages, np_language, - &opcode_support, &args.compile_options, )?; diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index 54b148ec3a2..da8812fc93b 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -57,15 +57,9 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let (np_language, opcode_support) = backend.get_backend_info()?; + let np_language = backend.get_backend_info()?; for package in &workspace { - let program = compile_bin_package( - &workspace, - package, - &args.compile_options, - np_language, - &opcode_support, - )?; + let program = compile_bin_package(&workspace, package, &args.compile_options, np_language)?; prove_package( backend, diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 2f8a6efbba4..53b046a5b76 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -48,15 +48,9 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let (np_language, opcode_support) = backend.get_backend_info()?; + let np_language = backend.get_backend_info()?; for package in &workspace { - let program = compile_bin_package( - &workspace, - package, - &args.compile_options, - np_language, - &opcode_support, - )?; + let program = compile_bin_package(&workspace, package, &args.compile_options, np_language)?; verify_package(backend, &workspace, package, program, &args.verifier_name)?; } From 456cefdb76b890a426a261e0803cc47b7a85cc4e Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 02:52:30 +0000 Subject: [PATCH 058/137] chore: Update acvm version along with the lockfile (#3830) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/release.yml | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d95ec10be23..3dbd1b2f210 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,35 +39,9 @@ jobs: run: | ./scripts/update-acvm-workspace-versions.sh - - name: Configure git - run: | - git config user.name kevaundray - git config user.email kevtheappdev@gmail.com - - - name: Commit updates - run: | - git add Cargo.toml - git commit -m 'chore: Update root workspace acvm versions' - git push - - update-lockfile: - name: Update lockfile - needs: [release-please,update-acvm-workspace-package-versions] - if: ${{ needs.release-please.outputs.release-pr }} - runs-on: ubuntu-latest - steps: - - name: Checkout release branch - uses: actions/checkout@v4 - with: - ref: ${{ fromJSON(needs.release-please.outputs.release-pr).headBranchName }} - token: ${{ secrets.NOIR_RELEASES_TOKEN }} - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.65.0 - - name: Update lockfile run: | - cargo update --workspace + cargo update --workspace - name: Configure git run: | @@ -76,13 +50,13 @@ jobs: - name: Commit updates run: | - git add Cargo.lock - git commit -m 'chore: Update lockfile' + git add . + git commit -m 'chore: Update root workspace acvm versions and lockfile' git push update-docs: name: Update docs - needs: [release-please, update-lockfile] + needs: [release-please, update-acvm-workspace-package-versions] if: ${{ needs.release-please.outputs.release-pr }} runs-on: ubuntu-latest env: From c8a886fce6edbc1f26e4712409101a2ec5941944 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 02:53:05 +0000 Subject: [PATCH 059/137] chore: Remove rebuild.sh workflow (#3822) # Description This is currently broken, however it works on the aztec-packages side. Since this is now being ran on the aztec-packages side we no longer need it ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/acir-artifacts.yml | 107 --------------------------- 1 file changed, 107 deletions(-) delete mode 100644 .github/workflows/acir-artifacts.yml diff --git a/.github/workflows/acir-artifacts.yml b/.github/workflows/acir-artifacts.yml deleted file mode 100644 index 43d9acfdedb..00000000000 --- a/.github/workflows/acir-artifacts.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Build ACIR artifacts - -on: - pull_request: - push: - branches: - - master - -jobs: - check-artifacts-requested: - name: Check if artifacts should be published - runs-on: ubuntu-22.04 - outputs: - publish: ${{ steps.check.outputs.result }} - - steps: - - name: Check if artifacts should be published - id: check - uses: actions/github-script@v6 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { REF_NAME } = process.env; - if (REF_NAME == "master") { - console.log(`publish = true`) - return true; - } - - const labels = context.payload.pull_request.labels.map(label => label.name); - const publish = labels.includes('publish-acir'); - - console.log(`publish = ${publish}`) - return publish; - result-encoding: string - env: - REF_NAME: ${{ github.ref_name }} - - build-nargo: - name: Build nargo binary - if: ${{ needs.check-artifacts-requested.outputs.publish == 'true' }} - runs-on: ubuntu-22.04 - needs: [check-artifacts-requested] - strategy: - matrix: - target: [x86_64-unknown-linux-gnu] - - steps: - - name: Checkout Noir repo - uses: actions/checkout@v4 - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.71.1 - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.target }} - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Build Nargo - run: cargo build --package nargo_cli --release - - - name: Package artifacts - run: | - mkdir dist - cp ./target/release/nargo ./dist/nargo - 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - auto-pr-rebuild-script: - name: Rebuild ACIR artifacts - needs: [build-nargo] - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Download nargo binary - uses: actions/download-artifact@v3 - with: - name: nargo - path: ./nargo - - - name: Add Nargo to $PATH - run: | - chmod +x ${{ github.workspace }}/nargo/nargo - echo "${{ github.workspace }}/nargo" >> $GITHUB_PATH - - - name: Run rebuild script - working-directory: test_programs - run: | - chmod +x ./rebuild.sh - ./rebuild.sh - - - name: Upload ACIR artifacts - uses: actions/upload-artifact@v3 - with: - name: acir-artifacts - path: ./test_programs/acir_artifacts - retention-days: 10 From 56885a94cdc369d65598a8582d46b6ca3bb9fcea Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 15:13:24 +0000 Subject: [PATCH 060/137] chore: Remove javascript docker workflow (#3832) # Description Related to #3831 This removes the docker workflow and we can add it back when the issue is fixed. We have not transitioned over to the docker workflow, so this is fine to do and won't affect testing coverage ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/test-js.yml | 52 ----------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 .github/workflows/test-js.yml diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml deleted file mode 100644 index 2f29e027156..00000000000 --- a/.github/workflows/test-js.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Test JS packages - -on: - pull_request: - merge_group: - push: - branches: - - master - -# This will cancel previous runs when a branch or PR is updated -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - - -jobs: - build: - name: Test JS packages - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Get current date - id: date - run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE - - name: prepare docker images tags - id: prep - run: | - REGISTRY="ghcr.io" - IMG="${REGISTRY}/${{ github.repository }}" - IMAGE=$(echo "$IMG" | tr '[:upper:]' '[:lower:]') - TAGS="${IMAGE}:${{ github.sha }}" - TAGS="${TAGS},${IMAGE}:latest,${IMAGE}:v${{ steps.date.outputs.date }}" - echo ::set-output name=tags::${TAGS} - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Test JS packages - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile.ci - tags: ${{ steps.prep.outputs.tags }} - target: test-js - cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file From 19155d02a1248c85e94f14a2a0bb383a4edeb16f Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 18:11:07 +0000 Subject: [PATCH 061/137] feat: Add context-centric based API for noir_wasm (#3798) # Description Currently this PR is not breaking This adds an API that maps closer to the API we'd have in the CLI or atleast one that differs less with the native version. One can imagine a shared Context object and in nargo_cli the main difference is the PathToSourceMap struct that gets passed in for example. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French --- compiler/wasm/src/compile.rs | 18 +- compiler/wasm/src/compile_new.rs | 336 ++++++++++++++++++++++++++ compiler/wasm/src/lib.rs | 4 + compiler/wasm/test/node/index.test.ts | 78 +++++- 4 files changed, 426 insertions(+), 10 deletions(-) create mode 100644 compiler/wasm/src/compile_new.rs diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 2d99963ea1d..6171267cb03 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -120,12 +120,11 @@ impl JsCompileResult { } } -#[derive(Deserialize)] -struct DependencyGraph { - root_dependencies: Vec, - library_dependencies: HashMap>, +#[derive(Deserialize, Default)] +pub(crate) struct DependencyGraph { + pub(crate) root_dependencies: Vec, + pub(crate) library_dependencies: HashMap>, } - #[wasm_bindgen] // This is a map containing the paths of all of the files in the entry-point crate and // the transitive dependencies of the entry-point crate. @@ -133,7 +132,7 @@ struct DependencyGraph { // This is for all intents and purposes the file system that the compiler will use to resolve/compile // files in the crate being compiled and its dependencies. #[derive(Deserialize, Default)] -pub struct PathToFileSourceMap(HashMap); +pub struct PathToFileSourceMap(pub(crate) HashMap); #[wasm_bindgen] impl PathToFileSourceMap { @@ -228,7 +227,7 @@ pub fn compile( // // For all intents and purposes, the file manager being returned // should be considered as immutable. -fn file_manager_with_source_map(source_map: PathToFileSourceMap) -> FileManager { +pub(crate) fn file_manager_with_source_map(source_map: PathToFileSourceMap) -> FileManager { let root = Path::new(""); let mut fm = FileManager::new(root); @@ -277,7 +276,7 @@ fn add_noir_lib(context: &mut Context, library_name: &CrateName) -> CrateId { prepare_dependency(context, &path_to_lib) } -fn preprocess_program(program: CompiledProgram) -> CompileResult { +pub(crate) fn preprocess_program(program: CompiledProgram) -> CompileResult { let debug_artifact = DebugArtifact { debug_symbols: vec![program.debug], file_map: program.file_map, @@ -295,7 +294,8 @@ fn preprocess_program(program: CompiledProgram) -> CompileResult { CompileResult::Program { program: preprocessed_program, debug: debug_artifact } } -fn preprocess_contract(contract: CompiledContract) -> CompileResult { +// TODO: This method should not be doing so much, most of this should be done in nargo or the driver +pub(crate) fn preprocess_contract(contract: CompiledContract) -> CompileResult { let debug_artifact = DebugArtifact { debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), file_map: contract.file_map, diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs new file mode 100644 index 00000000000..5c0a06b18f0 --- /dev/null +++ b/compiler/wasm/src/compile_new.rs @@ -0,0 +1,336 @@ +use crate::compile::{ + file_manager_with_source_map, preprocess_contract, preprocess_program, JsCompileResult, + PathToFileSourceMap, +}; +use crate::errors::{CompileError, JsCompileError}; +use noirc_driver::{ + add_dep, compile_contract, compile_main, prepare_crate, prepare_dependency, CompileOptions, +}; +use noirc_frontend::{ + graph::{CrateGraph, CrateId, CrateName}, + hir::Context, +}; +use std::path::Path; +use wasm_bindgen::prelude::wasm_bindgen; + +/// This is a wrapper class that is wasm-bindgen compatible +/// We do not use js_name and rename it like CrateId because +/// then the impl block is not picked up in javascript. +#[wasm_bindgen] +pub struct CompilerContext { + context: Context, +} + +#[wasm_bindgen(js_name = "CrateId")] +#[derive(Debug, Copy, Clone)] +pub struct CrateIDWrapper(CrateId); + +#[wasm_bindgen] +impl CompilerContext { + #[wasm_bindgen(constructor)] + pub fn new(source_map: PathToFileSourceMap) -> CompilerContext { + console_error_panic_hook::set_once(); + + let fm = file_manager_with_source_map(source_map); + let graph = CrateGraph::default(); + CompilerContext { context: Context::new(fm, graph) } + } + + #[cfg(test)] + pub(crate) fn crate_graph(&self) -> &CrateGraph { + &self.context.crate_graph + } + #[cfg(test)] + pub(crate) fn root_crate_id(&self) -> CrateIDWrapper { + CrateIDWrapper(*self.context.root_crate_id()) + } + + // Processes the root crate by adding it to the package graph and automatically + // importing the stdlib as a dependency for it. + // + // Its ID in the package graph is returned + pub fn process_root_crate(&mut self, path_to_crate: String) -> CrateIDWrapper { + let path_to_crate = Path::new(&path_to_crate); + + // Adds the root crate to the crate graph and returns its crate id + CrateIDWrapper(prepare_crate(&mut self.context, path_to_crate)) + } + + pub fn process_dependency_crate(&mut self, path_to_crate: String) -> CrateIDWrapper { + let path_to_crate = Path::new(&path_to_crate); + + // Adds the root crate to the crate graph and returns its crate id + CrateIDWrapper(prepare_dependency(&mut self.context, path_to_crate)) + } + + // Adds a named edge from one crate to the other. + // + // For example, lets say we have two crates CrateId1 and CrateId2 + // This function will add an edge from CrateId1 to CrateId2 and the edge will be named `crate_name` + // + // This essentially says that CrateId1 depends on CrateId2 and the dependency is named `crate_name` + // + // We pass references to &CrateIdWrapper even though it is a copy because Rust's move semantics are + // not respected once we use javascript. ie it will actually allocated a new object in javascript + // then deallocate that object if we do not pass as a reference. + pub fn add_dependency_edge( + &mut self, + crate_name: String, + from: &CrateIDWrapper, + to: &CrateIDWrapper, + ) { + let parsed_crate_name: CrateName = crate_name + .parse() + .unwrap_or_else(|_| panic!("Failed to parse crate name {}", crate_name)); + add_dep(&mut self.context, from.0, to.0, parsed_crate_name); + } + + pub fn compile_program( + mut self, + program_width: usize, + ) -> Result { + let compile_options = CompileOptions::default(); + let np_language = acvm::Language::PLONKCSat { width: program_width }; + + let root_crate_id = *self.context.root_crate_id(); + + let compiled_program = + compile_main(&mut self.context, root_crate_id, &compile_options, None, true) + .map_err(|errs| { + CompileError::with_file_diagnostics( + "Failed to compile program", + errs, + &self.context.file_manager, + ) + })? + .0; + + let optimized_program = nargo::ops::optimize_program(compiled_program, np_language); + + let compile_output = preprocess_program(optimized_program); + Ok(JsCompileResult::new(compile_output)) + } + + pub fn compile_contract( + mut self, + program_width: usize, + ) -> Result { + let compile_options = CompileOptions::default(); + let np_language = acvm::Language::PLONKCSat { width: program_width }; + let root_crate_id = *self.context.root_crate_id(); + + let compiled_contract = + compile_contract(&mut self.context, root_crate_id, &compile_options) + .map_err(|errs| { + CompileError::with_file_diagnostics( + "Failed to compile contract", + errs, + &self.context.file_manager, + ) + })? + .0; + + let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language); + + let compile_output = preprocess_contract(optimized_contract); + Ok(JsCompileResult::new(compile_output)) + } +} + +/// This is a method that exposes the same API as `compile` +/// But uses the Context based APi internally +#[wasm_bindgen] +pub fn compile_( + entry_point: String, + contracts: Option, + dependency_graph: Option, + file_source_map: PathToFileSourceMap, +) -> Result { + use std::collections::HashMap; + + console_error_panic_hook::set_once(); + + let dependency_graph: crate::compile::DependencyGraph = + if let Some(dependency_graph) = dependency_graph { + ::into_serde( + &wasm_bindgen::JsValue::from(dependency_graph), + ) + .map_err(|err| err.to_string())? + } else { + crate::compile::DependencyGraph::default() + }; + + let mut compiler_context = CompilerContext::new(file_source_map); + + // Set the root crate + let root_id = compiler_context.process_root_crate(entry_point.clone()); + + let add_noir_lib = |context: &mut CompilerContext, lib_name: &CrateName| -> CrateIDWrapper { + let lib_name_string = lib_name.to_string(); + let path_to_lib = Path::new(&lib_name_string) + .join("lib.nr") + .to_str() + .expect("paths are expected to be valid utf-8") + .to_string(); + context.process_dependency_crate(path_to_lib) + }; + + // Add the dependency graph + let mut crate_names: HashMap = HashMap::new(); + // + // Process the direct dependencies of the root + for lib_name in dependency_graph.root_dependencies { + let lib_name_string = lib_name.to_string(); + + let crate_id = add_noir_lib(&mut compiler_context, &lib_name); + + crate_names.insert(lib_name.clone(), crate_id); + + // Add the dependency edges + compiler_context.add_dependency_edge(lib_name_string, &root_id, &crate_id); + } + + // Process the transitive dependencies of the root + for (lib_name, dependencies) in &dependency_graph.library_dependencies { + // first create the library crate if needed + // this crate might not have been registered yet because of the order of the HashMap + // e.g. {root: [lib1], libs: { lib2 -> [lib3], lib1 -> [lib2] }} + let crate_id = *crate_names + .entry(lib_name.clone()) + .or_insert_with(|| add_noir_lib(&mut compiler_context, lib_name)); + + for dependency_name in dependencies { + let dependency_name_string = dependency_name.to_string(); + + let dep_crate_id = crate_names + .entry(dependency_name.clone()) + .or_insert_with(|| add_noir_lib(&mut compiler_context, dependency_name)); + + compiler_context.add_dependency_edge(dependency_name_string, &crate_id, dep_crate_id); + } + } + + let is_contract = contracts.unwrap_or(false); + let program_width = 3; + + if is_contract { + compiler_context.compile_contract(program_width) + } else { + compiler_context.compile_program(program_width) + } +} + +#[cfg(test)] +mod test { + use noirc_driver::prepare_crate; + use noirc_frontend::{graph::CrateGraph, hir::Context}; + + use crate::compile::{file_manager_with_source_map, PathToFileSourceMap}; + + use std::path::Path; + + use super::CompilerContext; + + fn setup_test_context(source_map: PathToFileSourceMap) -> CompilerContext { + let mut fm = file_manager_with_source_map(source_map); + // Add this due to us calling prepare_crate on "/main.nr" below + fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); + + let graph = CrateGraph::default(); + let mut context = Context::new(fm, graph); + prepare_crate(&mut context, Path::new("/main.nr")); + + CompilerContext { context } + } + + #[test] + fn test_works_with_empty_dependency_graph() { + let source_map = PathToFileSourceMap::default(); + let context = setup_test_context(source_map); + + // one stdlib + one root crate + assert_eq!(context.crate_graph().number_of_crates(), 2); + } + + #[test] + fn test_works_with_root_dependencies() { + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); + context.process_dependency_crate("lib1/lib.nr".to_string()); + + assert_eq!(context.crate_graph().number_of_crates(), 3); + } + + #[test] + fn test_works_with_duplicate_root_dependencies() { + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + let mut context = setup_test_context(source_map); + + let lib1_crate_id = context.process_dependency_crate("lib1/lib.nr".to_string()); + let root_crate_id = context.root_crate_id(); + + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id); + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id); + + assert_eq!(context.crate_graph().number_of_crates(), 3); + } + + #[test] + fn test_works_with_transitive_dependencies() { + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); + + let lib1_crate_id = context.process_dependency_crate("lib1/lib.nr".to_string()); + let lib2_crate_id = context.process_dependency_crate("lib2/lib.nr".to_string()); + let lib3_crate_id = context.process_dependency_crate("lib3/lib.nr".to_string()); + let root_crate_id = context.root_crate_id(); + + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id); + context.add_dependency_edge("lib2".to_string(), &lib1_crate_id, &lib2_crate_id); + context.add_dependency_edge("lib3".to_string(), &lib2_crate_id, &lib3_crate_id); + + assert_eq!(context.crate_graph().number_of_crates(), 5); + } + + #[test] + fn test_works_with_missing_dependencies() { + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + let mut context = setup_test_context(source_map); + + let lib1_crate_id = context.process_dependency_crate("lib1/lib.nr".to_string()); + let lib2_crate_id = context.process_dependency_crate("lib2/lib.nr".to_string()); + let lib3_crate_id = context.process_dependency_crate("lib3/lib.nr".to_string()); + let root_crate_id = context.root_crate_id(); + + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id); + context.add_dependency_edge("lib3".to_string(), &lib2_crate_id, &lib3_crate_id); + + assert_eq!(context.crate_graph().number_of_crates(), 5); + } +} diff --git a/compiler/wasm/src/lib.rs b/compiler/wasm/src/lib.rs index 9f2f558f85c..43095fee4d4 100644 --- a/compiler/wasm/src/lib.rs +++ b/compiler/wasm/src/lib.rs @@ -14,11 +14,15 @@ use wasm_bindgen::prelude::*; mod circuit; mod compile; +mod compile_new; mod errors; pub use circuit::{acir_read_bytes, acir_write_bytes}; pub use compile::compile; +// Expose the new Context-Centric API +pub use compile_new::{compile_, CompilerContext, CrateIDWrapper}; + #[derive(Serialize, Deserialize)] pub struct BuildInfo { git_hash: &'static str, diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index 5cf9e3be2df..390cc940361 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -9,7 +9,7 @@ import { } from '../shared'; import { readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; -import { compile, PathToFileSourceMap } from '@noir-lang/noir_wasm'; +import { compile, compile_, CompilerContext, PathToFileSourceMap } from '@noir-lang/noir_wasm'; // eslint-disable-next-line @typescript-eslint/no-explicit-any async function getPrecompiledSource(path: string): Promise { @@ -72,4 +72,80 @@ describe('noir wasm compilation', () => { expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); + + describe('can compile scripts with dependencies -- context-api', () => { + let sourceMap: PathToFileSourceMap; + beforeEach(() => { + sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('script/main.nr', readFileSync(join(__dirname, depsScriptSourcePath), 'utf-8')); + sourceMap.add_source_code('lib_a/lib.nr', readFileSync(join(__dirname, libASourcePath), 'utf-8')); + sourceMap.add_source_code('lib_b/lib.nr', readFileSync(join(__dirname, libBSourcePath), 'utf-8')); + }); + + it('matching nargos compilation - context-api', async () => { + const compilerContext = new CompilerContext(sourceMap); + + // Process root crate + const root_crate_id = compilerContext.process_root_crate('script/main.nr'); + // Process dependencies + // + // This can be direct dependencies or transitive dependencies + // I have named these crate_id_1 and crate_id_2 instead of `lib_a_crate_id` and `lib_b_crate_id` + // because the names of crates in a dependency graph are not determined by the actual package. + // + // It is true that each package is given a name, but if I include a `lib_a` as a dependency + // in my library, I do not need to refer to it as `lib_a` in my dependency graph. + // See https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml + // + // If you have looked at graphs before, then you can think of the dependency graph as a directed acyclic graph (DAG) + const crate_id_1 = compilerContext.process_dependency_crate('lib_a/lib.nr'); + const crate_id_2 = compilerContext.process_dependency_crate('lib_b/lib.nr'); + + // Root crate depends on `crate_id_1` and this edge is called `lib_a` + compilerContext.add_dependency_edge('lib_a', root_crate_id, crate_id_1); + // `crate_id_1` depends on `crate_id_2` and this edge is called `lib_b` + compilerContext.add_dependency_edge('lib_b', crate_id_1, crate_id_2); + + const program_width = 3; + const wasmCircuit = await compilerContext.compile_program(program_width); + + const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); + + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + + // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); + }).timeout(10e3); + + it('matching nargos compilation - context-implementation-compile-api', async () => { + const wasmCircuit = await compile_( + 'script/main.nr', + false, + { + root_dependencies: ['lib_a'], + library_dependencies: { + lib_a: ['lib_b'], + }, + }, + sourceMap, + ); + + const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); + + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + + // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); + }).timeout(10e3); + }); }); From ea18bed5eb2dde577233ec0c7d2a0a28874d8efe Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 18:52:03 +0000 Subject: [PATCH 062/137] chore: Compare noir versions when testing that the wasm compiled artefact is equal to the natively compiled artefact (#3833) # Description Since we don't want these checked in and these are compiled manually, they can get out of sync if you build the wasm and do not do `noirup -p .` and then recompile the example programs. The error message will say that the bytecodes produced are different, with this change the test will first tell you that the versions are different. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/wasm/test/browser/index.test.ts | 2 ++ compiler/wasm/test/node/index.test.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/compiler/wasm/test/browser/index.test.ts b/compiler/wasm/test/browser/index.test.ts index 346c20c834c..80f4218d788 100644 --- a/compiler/wasm/test/browser/index.test.ts +++ b/compiler/wasm/test/browser/index.test.ts @@ -39,6 +39,7 @@ describe('noir wasm', () => { } // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); @@ -77,6 +78,7 @@ describe('noir wasm', () => { const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index 390cc940361..57c58788ad3 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -33,6 +33,7 @@ describe('noir wasm compilation', () => { } // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); @@ -67,6 +68,7 @@ describe('noir wasm compilation', () => { } // We don't expect the hashes to match due to how `noir_wasm` handles dependencies + expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); From fa1cf5f03aa21b001c31ebb9ce405e3c2859bb57 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sat, 16 Dec 2023 20:46:29 +0000 Subject: [PATCH 063/137] chore!: Remove backend field from artifacts (#3819) # Description In `kw/remove-partial-backend-code` we removed the opcodes supported feature, which means that artifacts are no longer compiled based on a backends feature set. Closes #1388 ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- compiler/wasm/src/compile.rs | 6 ------ compiler/wasm/test/browser/index.test.ts | 2 -- compiler/wasm/test/node/index.test.ts | 4 ---- tooling/backend_interface/src/lib.rs | 2 +- tooling/nargo/src/artifacts/contract.rs | 2 -- tooling/nargo/src/artifacts/program.rs | 1 - tooling/nargo_cli/src/backends.rs | 2 +- tooling/nargo_cli/src/cli/compile_cmd.rs | 5 ----- tooling/nargo_cli/src/cli/init_cmd.rs | 8 +------- tooling/nargo_cli/src/cli/mod.rs | 2 +- tooling/nargo_toml/src/lib.rs | 1 - 11 files changed, 4 insertions(+), 31 deletions(-) diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 6171267cb03..f2487eecca6 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -20,8 +20,6 @@ use wasm_bindgen::prelude::*; use crate::errors::{CompileError, JsCompileError}; -const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; - #[wasm_bindgen(typescript_custom_section)] const DEPENDENCY_GRAPH: &'static str = r#" export type DependencyGraph = { @@ -32,14 +30,12 @@ export type DependencyGraph = { export type CompiledContract = { noir_version: string; name: string; - backend: string; functions: Array; events: Array; }; export type CompiledProgram = { noir_version: string; - backend: string; abi: any; bytecode: string; } @@ -285,7 +281,6 @@ pub(crate) fn preprocess_program(program: CompiledProgram) -> CompileResult { let preprocessed_program = PreprocessedProgram { hash: program.hash, - backend: String::from(BACKEND_IDENTIFIER), abi: program.abi, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), bytecode: program.circuit, @@ -316,7 +311,6 @@ pub(crate) fn preprocess_contract(contract: CompiledContract) -> CompileResult { let preprocessed_contract = PreprocessedContract { noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), name: contract.name, - backend: String::from(BACKEND_IDENTIFIER), functions: preprocessed_functions, events: contract.events, }; diff --git a/compiler/wasm/test/browser/index.test.ts b/compiler/wasm/test/browser/index.test.ts index 80f4218d788..7364a8a4d11 100644 --- a/compiler/wasm/test/browser/index.test.ts +++ b/compiler/wasm/test/browser/index.test.ts @@ -42,7 +42,6 @@ describe('noir wasm', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(20e3); // 20 seconds }); @@ -81,7 +80,6 @@ describe('noir wasm', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(20e3); // 20 seconds }); }); diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index 57c58788ad3..57c1b459d60 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -36,7 +36,6 @@ describe('noir wasm compilation', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); @@ -71,7 +70,6 @@ describe('noir wasm compilation', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); @@ -121,7 +119,6 @@ describe('noir wasm compilation', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); it('matching nargos compilation - context-implementation-compile-api', async () => { @@ -147,7 +144,6 @@ describe('noir wasm compilation', () => { expect(wasmCircuit.program.noir_version).to.eq(cliCircuit.noir_version); expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); }); diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index c5232c3473a..8ed164fc217 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -8,7 +8,7 @@ mod download; mod proof_system; mod smart_contract; -use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; +pub use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use bb_abstraction_leaks::BB_VERSION; use cli::VersionCommand; pub use download::download_backend; diff --git a/tooling/nargo/src/artifacts/contract.rs b/tooling/nargo/src/artifacts/contract.rs index f9e8d45b02e..4ade4f5660e 100644 --- a/tooling/nargo/src/artifacts/contract.rs +++ b/tooling/nargo/src/artifacts/contract.rs @@ -14,8 +14,6 @@ pub struct PreprocessedContract { pub noir_version: String, /// The name of the contract. pub name: String, - /// The identifier of the proving backend which this contract has been compiled for. - pub backend: String, /// Each of the contract's functions are compiled into a separate program stored in this `Vec`. pub functions: Vec, /// All the events defined inside the contract scope. diff --git a/tooling/nargo/src/artifacts/program.rs b/tooling/nargo/src/artifacts/program.rs index 890b6c55f7d..664db0adca4 100644 --- a/tooling/nargo/src/artifacts/program.rs +++ b/tooling/nargo/src/artifacts/program.rs @@ -17,7 +17,6 @@ pub struct PreprocessedProgram { /// 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, #[serde( diff --git a/tooling/nargo_cli/src/backends.rs b/tooling/nargo_cli/src/backends.rs index 8b1da2cd118..2b3e9d8861f 100644 --- a/tooling/nargo_cli/src/backends.rs +++ b/tooling/nargo_cli/src/backends.rs @@ -7,7 +7,7 @@ fn active_backend_file_path() -> PathBuf { backends_directory().join(".selected_backend") } -pub(crate) const ACVM_BACKEND_BARRETENBERG: &str = "acvm-backend-barretenberg"; +pub(crate) use backend_interface::ACVM_BACKEND_BARRETENBERG; pub(crate) fn clear_active_backend() { let active_backend_file = active_backend_file_path(); diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index f0fb0cc1ec7..b686adf6f50 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -29,9 +29,6 @@ use super::fs::program::{ use super::NargoConfig; use rayon::prelude::*; -// TODO(#1388): pull this from backend. -const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; - /// Compile the program and its secret execution trace into ACIR format #[derive(Debug, Clone, Args)] pub(crate) struct CompileCommand { @@ -233,7 +230,6 @@ fn save_program( ) { let preprocessed_program = PreprocessedProgram { hash: program.hash, - backend: String::from(BACKEND_IDENTIFIER), abi: program.abi, noir_version: program.noir_version, bytecode: program.circuit, @@ -275,7 +271,6 @@ fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Pa let preprocessed_contract = PreprocessedContract { noir_version: contract.noir_version, name: contract.name, - backend: String::from(BACKEND_IDENTIFIER), functions: preprocessed_functions, events: contract.events, }; diff --git a/tooling/nargo_cli/src/cli/init_cmd.rs b/tooling/nargo_cli/src/cli/init_cmd.rs index e53c2e4cdc9..dd3af97ecd6 100644 --- a/tooling/nargo_cli/src/cli/init_cmd.rs +++ b/tooling/nargo_cli/src/cli/init_cmd.rs @@ -1,4 +1,3 @@ -use crate::backends::Backend; use crate::errors::CliError; use super::fs::{create_named_dir, write_to_file}; @@ -34,12 +33,7 @@ const BIN_EXAMPLE: &str = include_str!("./noir_template_files/binary.nr"); const CONTRACT_EXAMPLE: &str = include_str!("./noir_template_files/contract.nr"); const LIB_EXAMPLE: &str = include_str!("./noir_template_files/library.nr"); -pub(crate) fn run( - // Backend is currently unused, but we might want to use it to inform the "new" template in the future - _backend: &Backend, - args: InitCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: InitCommand, config: NargoConfig) -> Result<(), CliError> { let package_name = match args.name { Some(name) => name, None => { diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 88c6b57a98c..448e28fb6a7 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -100,7 +100,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { match command { NargoCommand::New(args) => new_cmd::run(&backend, args, config), - NargoCommand::Init(args) => init_cmd::run(&backend, args, config), + NargoCommand::Init(args) => init_cmd::run(args, config), NargoCommand::Check(args) => check_cmd::run(&backend, args, config), NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 56024f8ed42..6c77fe85f2b 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -270,7 +270,6 @@ struct PackageMetadata { // We also state that ACIR and the compiler will upgrade in lockstep. // so you will not need to supply an ACIR and compiler version compiler_version: Option, - backend: Option, license: Option, } From 02ba130824cf0242bed71f14244ab896252974b1 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sun, 17 Dec 2023 20:52:56 +0000 Subject: [PATCH 064/137] chore: Move build script for stdlib from `fm` to `noirc_driver` (#3848) # Description This moves the build.rs file to `noirc_driver`'s build.rs since that is the crate which now embeds the noir_stdlib ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/fm/build.rs | 20 -------------------- compiler/noirc_driver/build.rs | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 20 deletions(-) delete mode 100644 compiler/fm/build.rs diff --git a/compiler/fm/build.rs b/compiler/fm/build.rs deleted file mode 100644 index 747ab4fe1a2..00000000000 --- a/compiler/fm/build.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::path::Path; - -/// Expects that the given directory is an existing path -fn rerun_if_stdlib_changes(directory: &Path) { - for entry in std::fs::read_dir(directory).unwrap() { - let path = entry.unwrap().path(); - - if path.is_dir() { - rerun_if_stdlib_changes(&path); - } else { - // Tell Cargo that if the given file changes, to rerun this build script. - println!("cargo:rerun-if-changed={}", path.to_string_lossy()); - } - } -} - -fn main() { - let stdlib_src_dir = Path::new("../../noir_stdlib/"); - rerun_if_stdlib_changes(stdlib_src_dir); -} diff --git a/compiler/noirc_driver/build.rs b/compiler/noirc_driver/build.rs index 6bef7f1fda7..73a56142075 100644 --- a/compiler/noirc_driver/build.rs +++ b/compiler/noirc_driver/build.rs @@ -1,4 +1,5 @@ const GIT_COMMIT: &&str = &"GIT_COMMIT"; +use std::path::Path; fn main() { // Only use build_data if the environment variable isn't set @@ -8,4 +9,21 @@ fn main() { build_data::set_GIT_DIRTY(); build_data::no_debug_rebuilds(); } + + let stdlib_src_dir = Path::new("../../noir_stdlib/"); + rerun_if_stdlib_changes(stdlib_src_dir); +} + +/// Expects that the given directory is an existing path +fn rerun_if_stdlib_changes(directory: &Path) { + for entry in std::fs::read_dir(directory).unwrap() { + let path = entry.unwrap().path(); + + if path.is_dir() { + rerun_if_stdlib_changes(&path); + } else { + // Tell Cargo that if the given file changes, to rerun this build script. + println!("cargo:rerun-if-changed={}", path.to_string_lossy()); + } + } } From 114be2fbba5622e6b05ec87fc9c5f25b328ce542 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sun, 17 Dec 2023 21:21:42 +0000 Subject: [PATCH 065/137] chore: rename acir opcode from `pedersen` to `pedersen_commitment` (#3836) # Description Previously was a breaking change to backends, which is why it was delayed. Since we now no longer support partial backeds, this is not a breaking change as we are not reading an info.json file anymore, or more precisely we are not matching on the opcodes_supported field ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acir/src/circuit/black_box_functions.rs | 4 ++-- noir_stdlib/src/hash.nr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index d00cd6d28df..dec60c09077 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -61,7 +61,7 @@ impl BlackBoxFunc { BlackBoxFunc::SHA256 => "sha256", BlackBoxFunc::SchnorrVerify => "schnorr_verify", BlackBoxFunc::Blake2s => "blake2s", - BlackBoxFunc::PedersenCommitment => "pedersen", + BlackBoxFunc::PedersenCommitment => "pedersen_commitment", BlackBoxFunc::PedersenHash => "pedersen_hash", BlackBoxFunc::HashToField128Security => "hash_to_field_128_security", BlackBoxFunc::EcdsaSecp256k1 => "ecdsa_secp256k1", @@ -79,7 +79,7 @@ impl BlackBoxFunc { "sha256" => Some(BlackBoxFunc::SHA256), "schnorr_verify" => Some(BlackBoxFunc::SchnorrVerify), "blake2s" => Some(BlackBoxFunc::Blake2s), - "pedersen" => Some(BlackBoxFunc::PedersenCommitment), + "pedersen_commitment" => Some(BlackBoxFunc::PedersenCommitment), "pedersen_hash" => Some(BlackBoxFunc::PedersenHash), "hash_to_field_128_security" => Some(BlackBoxFunc::HashToField128Security), "ecdsa_secp256k1" => Some(BlackBoxFunc::EcdsaSecp256k1), diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 157d6518367..ad7e4f2e28f 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -16,7 +16,7 @@ pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { pedersen_commitment_with_separator(input, 0) } -#[foreign(pedersen)] +#[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(_input: [Field; N], _separator: u32) -> [Field; 2] {} pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { From e8aacd3b4b39c8f9db0c98af3460970fb3a13518 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Sun, 17 Dec 2023 22:52:28 +0000 Subject: [PATCH 066/137] chore: Compiler `Context` instantiates a new `CrateGraph` internally (#3847) # Description This is a minor cleanup task. Everywhere we created a CompilerContext, we were passing in a default CrateGraph. This PR just creates the default CrateGraph internally, so that the caller does not need to. If in the future, we decide to want to pass a populated CrateGraph, we can create a `with_crate_graph` method to account for the edge case. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/hir/mod.rs | 3 ++- compiler/noirc_frontend/src/tests.rs | 3 +-- compiler/wasm/src/compile.rs | 13 ++++--------- compiler/wasm/src/compile_new.rs | 12 +++++------- tooling/nargo/src/lib.rs | 5 ++--- 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index 3a435f302af..adeca7cf2ba 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -36,7 +36,8 @@ pub enum FunctionNameMatch<'a> { } impl Context { - pub fn new(file_manager: FileManager, crate_graph: CrateGraph) -> Context { + pub fn new(file_manager: FileManager) -> Context { + let crate_graph = CrateGraph::default(); Context { def_interner: NodeInterner::default(), def_maps: BTreeMap::new(), diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 3f4755aa0ef..60498b22c96 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -53,8 +53,7 @@ mod test { ) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { let root = std::path::Path::new("/"); let fm = FileManager::new(root); - let graph = CrateGraph::default(); - let mut context = Context::new(fm, graph); + let mut context = Context::new(fm); let root_file_id = FileId::dummy(); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); let (program, parser_errors) = parse_program(src); diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index f2487eecca6..8685d6093e6 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -11,7 +11,7 @@ use noirc_driver::{ CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::{ - graph::{CrateGraph, CrateId, CrateName}, + graph::{CrateId, CrateName}, hir::Context, }; use serde::Deserialize; @@ -169,8 +169,7 @@ pub fn compile( let fm = file_manager_with_source_map(file_source_map); - let graph = CrateGraph::default(); - let mut context = Context::new(fm, graph); + let mut context = Context::new(fm); let path = Path::new(&entry_point); let crate_id = prepare_crate(&mut context, path); @@ -321,10 +320,7 @@ pub(crate) fn preprocess_contract(contract: CompiledContract) -> CompileResult { #[cfg(test)] mod test { use noirc_driver::prepare_crate; - use noirc_frontend::{ - graph::{CrateGraph, CrateName}, - hir::Context, - }; + use noirc_frontend::{graph::CrateName, hir::Context}; use crate::compile::PathToFileSourceMap; @@ -336,8 +332,7 @@ mod test { // Add this due to us calling prepare_crate on "/main.nr" below fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); - let graph = CrateGraph::default(); - let mut context = Context::new(fm, graph); + let mut context = Context::new(fm); prepare_crate(&mut context, Path::new("/main.nr")); context diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs index 5c0a06b18f0..2e80fa1c1e4 100644 --- a/compiler/wasm/src/compile_new.rs +++ b/compiler/wasm/src/compile_new.rs @@ -7,7 +7,7 @@ use noirc_driver::{ add_dep, compile_contract, compile_main, prepare_crate, prepare_dependency, CompileOptions, }; use noirc_frontend::{ - graph::{CrateGraph, CrateId, CrateName}, + graph::{CrateId, CrateName}, hir::Context, }; use std::path::Path; @@ -32,12 +32,11 @@ impl CompilerContext { console_error_panic_hook::set_once(); let fm = file_manager_with_source_map(source_map); - let graph = CrateGraph::default(); - CompilerContext { context: Context::new(fm, graph) } + CompilerContext { context: Context::new(fm) } } #[cfg(test)] - pub(crate) fn crate_graph(&self) -> &CrateGraph { + pub(crate) fn crate_graph(&self) -> &noirc_frontend::graph::CrateGraph { &self.context.crate_graph } #[cfg(test)] @@ -223,7 +222,7 @@ pub fn compile_( #[cfg(test)] mod test { use noirc_driver::prepare_crate; - use noirc_frontend::{graph::CrateGraph, hir::Context}; + use noirc_frontend::hir::Context; use crate::compile::{file_manager_with_source_map, PathToFileSourceMap}; @@ -236,8 +235,7 @@ mod test { // Add this due to us calling prepare_crate on "/main.nr" below fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); - let graph = CrateGraph::default(); - let mut context = Context::new(fm, graph); + let mut context = Context::new(fm); prepare_crate(&mut context, Path::new("/main.nr")); CompilerContext { context } diff --git a/tooling/nargo/src/lib.rs b/tooling/nargo/src/lib.rs index 6f3d36febba..f0c7277060f 100644 --- a/tooling/nargo/src/lib.rs +++ b/tooling/nargo/src/lib.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use fm::FileManager; use noirc_driver::{add_dep, prepare_crate, prepare_dependency}; use noirc_frontend::{ - graph::{CrateGraph, CrateId, CrateName}, + graph::{CrateId, CrateName}, hir::Context, }; use package::{Dependency, Package}; @@ -91,8 +91,7 @@ pub fn prepare_package(package: &Package) -> (Context, CrateId) { let mut fm = FileManager::new(&package.root_dir); insert_all_files_for_package_into_file_manager(package, &mut fm); - let graph = CrateGraph::default(); - let mut context = Context::new(fm, graph); + let mut context = Context::new(fm); let crate_id = prepare_crate(&mut context, &package.entry_path); From dc100f2e3243ed42f483e531e717b9f2d86b5ba6 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:56:50 +0000 Subject: [PATCH 067/137] chore(ci): fix versioning of docs in release PR (#3851) # Description ## Problem\* Resolves ## Summary\* Fixes the issue in #3828 where we're trying to read from the release-please job as if it were the release-please action. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/release.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dbd1b2f210..3b2393eaa8f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,7 @@ jobs: outputs: release-pr: ${{ steps.release.outputs.pr }} tag-name: ${{ steps.release.outputs.tag_name }} + pending-release-semver: v${{ steps.release.outputs.major }}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}} runs-on: ubuntu-latest steps: - name: Run release-please @@ -59,9 +60,7 @@ jobs: needs: [release-please, update-acvm-workspace-package-versions] if: ${{ needs.release-please.outputs.release-pr }} runs-on: ubuntu-latest - env: - PENDING_RELEASE_SEMVER: v${{ needs.release-please.outputs.major }}.${{needs.release-please.outputs.minor}}.${{needs.release-please.outputs.patch}} - + steps: - name: Checkout release branch uses: actions/checkout@v4 @@ -79,7 +78,7 @@ jobs: - name: Cut a new version working-directory: ./docs - run: yarn docusaurus docs:version ${{ env.PENDING_RELEASE_SEMVER }} + run: yarn docusaurus docs:version ${{ needs.release-please.outputs.pending-release-semver }} - name: Configure git run: | @@ -89,7 +88,7 @@ jobs: - name: Commit new documentation version run: | git add . - git commit -m "chore(docs): cut new docs version for tag ${{ env.PENDING_RELEASE_SEMVER }}" + git commit -m "chore(docs): cut new docs version for tag ${{ needs.release-please.outputs.pending-release-semver }}" git push build-binaries: From 13d70ce4091946b1ee5851d73c87ba3a0731c9f3 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 18 Dec 2023 16:05:17 +0000 Subject: [PATCH 068/137] chore: `fetch_file` now returns ` &str` instead of a `File` (#3846) # Description This makes the API more uniform because to add a file, we call: ``` pub fn add_file_with_source(&mut self, file_name: &Path, source: String) -> Option { ``` and now to fetch a file we call: ``` pub fn fetch_file(&self, file_id: FileId) -> &str; ``` Instead of returning a `File` which was not present when we were adding a File ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/fm/src/lib.rs | 4 ++-- compiler/noirc_driver/src/debug.rs | 2 +- compiler/noirc_frontend/src/hir/def_map/mod.rs | 4 ++-- tooling/nargo/src/artifacts/debug.rs | 2 +- tooling/nargo_cli/src/cli/fmt_cmd.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 47b245eea2e..4870a6c283b 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -88,9 +88,9 @@ impl FileManager { assert!(old_value.is_none(), "ice: the same path was inserted into the file manager twice"); } - pub fn fetch_file(&self, file_id: FileId) -> File { + pub fn fetch_file(&self, file_id: FileId) -> &str { // Unwrap as we ensure that all file_id's map to a corresponding file in the file map - self.file_map.get_file(file_id).unwrap() + self.file_map.get_file(file_id).unwrap().source() } pub fn path(&self, file_id: FileId) -> &Path { diff --git a/compiler/noirc_driver/src/debug.rs b/compiler/noirc_driver/src/debug.rs index 144e636b534..84a3e143357 100644 --- a/compiler/noirc_driver/src/debug.rs +++ b/compiler/noirc_driver/src/debug.rs @@ -31,7 +31,7 @@ pub(crate) fn filter_relevant_files( let mut file_map = BTreeMap::new(); for file_id in files_with_debug_symbols { - let file_source = file_manager.fetch_file(file_id).source(); + let file_source = file_manager.fetch_file(file_id); file_map.insert( file_id, diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 026f407981d..20f05532ce4 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -270,8 +270,8 @@ pub struct Contract { /// Given a FileId, fetch the File, from the FileManager and parse it's content pub fn parse_file(fm: &FileManager, file_id: FileId) -> (ParsedModule, Vec) { - let file = fm.fetch_file(file_id); - parse_program(file.source()) + let file_source = fm.fetch_file(file_id); + parse_program(file_source) } impl std::ops::Index for CrateDefMap { diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index 40acc7db8f8..324c476d13d 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -34,7 +34,7 @@ impl DebugArtifact { .collect(); for file_id in files_with_debug_symbols { - let file_source = file_manager.fetch_file(file_id).source(); + let file_source = file_manager.fetch_file(file_id); file_map.insert( file_id, diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index 0c2ca71eba3..e62fc560217 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -62,7 +62,7 @@ pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliErr return Ok(()); } - let original = file_manager.fetch_file(file_id).source(); + let original = file_manager.fetch_file(file_id); let formatted = nargo_fmt::format(original, parsed_module, &config); if check_mode { From 9e5d0e813d61a0bfb5ee68174ed287c5a20f1579 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 18 Dec 2023 17:05:13 +0000 Subject: [PATCH 069/137] chore!: Remove unused methods on ACIR opcodes (#3841) # Description These were originally added for manual serialization but now we use serde. They seem like a nice to have, though I'd rather just add them back once we have a proper usecase for them ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acir/src/circuit/directives.rs | 10 --------- acvm-repo/acir/src/circuit/opcodes.rs | 26 ------------------------ acvm-repo/brillig/src/opcodes.rs | 22 -------------------- 3 files changed, 58 deletions(-) diff --git a/acvm-repo/acir/src/circuit/directives.rs b/acvm-repo/acir/src/circuit/directives.rs index a86eb525c1f..c3a5b055f19 100644 --- a/acvm-repo/acir/src/circuit/directives.rs +++ b/acvm-repo/acir/src/circuit/directives.rs @@ -34,13 +34,3 @@ pub enum Directive { sort_by: Vec, // specify primary index to sort by, then the secondary,... For instance, if tuple is 2 and sort_by is [1,0], then a=[(a0,b0),..] is sorted by bi and then ai. }, } - -impl Directive { - pub fn name(&self) -> &str { - match self { - Directive::Quotient(_) => "quotient", - Directive::ToLeRadix { .. } => "to_le_radix", - Directive::PermutationSort { .. } => "permutation_sort", - } - } -} diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 62566fee7fe..0e15fe3757c 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -33,32 +33,6 @@ pub enum Opcode { }, } -impl Opcode { - // TODO We can add a domain separator by doing something like: - // TODO concat!("directive:", directive.name) - pub fn name(&self) -> &str { - match self { - Opcode::Arithmetic(_) => "arithmetic", - Opcode::Directive(directive) => directive.name(), - Opcode::BlackBoxFuncCall(g) => g.name(), - Opcode::Brillig(_) => "brillig", - Opcode::MemoryOp { .. } => "mem", - Opcode::MemoryInit { .. } => "init memory block", - } - } - - pub fn is_arithmetic(&self) -> bool { - matches!(self, Opcode::Arithmetic(_)) - } - - pub fn arithmetic(self) -> Option { - match self { - Opcode::Arithmetic(expr) => Some(expr), - _ => None, - } - } -} - impl std::fmt::Display for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 44d90acde47..79295cc6e5d 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -133,28 +133,6 @@ pub enum BrilligOpcode { Stop, } -impl BrilligOpcode { - pub fn name(&self) -> &'static str { - match self { - BrilligOpcode::BinaryFieldOp { .. } => "binary_field_op", - BrilligOpcode::BinaryIntOp { .. } => "binary_int_op", - BrilligOpcode::JumpIfNot { .. } => "jmp_if_not", - BrilligOpcode::JumpIf { .. } => "jmp_if", - BrilligOpcode::Jump { .. } => "jmp", - BrilligOpcode::Call { .. } => "call", - BrilligOpcode::Const { .. } => "const", - BrilligOpcode::Return => "return", - BrilligOpcode::ForeignCall { .. } => "foreign_call", - BrilligOpcode::Mov { .. } => "mov", - BrilligOpcode::Load { .. } => "load", - BrilligOpcode::Store { .. } => "store", - BrilligOpcode::BlackBox(_) => "black_box", - BrilligOpcode::Trap => "trap", - BrilligOpcode::Stop => "stop", - } - } -} - /// Binary fixed-length field expressions #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum BinaryFieldOp { From 3fae4a03fded4e3f5065e7461c563f7e39745604 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 18 Dec 2023 17:41:29 +0000 Subject: [PATCH 070/137] chore: Release Noir(0.22.0) (#3825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :robot: I have created a release *beep* *boop* ---
0.22.0 ## [0.22.0](https://github.com/noir-lang/noir/compare/v0.21.0...v0.22.0) (2023-12-18) ### ⚠ BREAKING CHANGES * Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) * Remove backend field from artifacts ([#3819](https://github.com/noir-lang/noir/issues/3819)) * Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ### Features * Add context-centric based API for noir_wasm ([#3798](https://github.com/noir-lang/noir/issues/3798)) ([19155d0](https://github.com/noir-lang/noir/commit/19155d02a1248c85e94f14a2a0bb383a4edeb16f)) ### Miscellaneous Chores * Remove backend field from artifacts ([#3819](https://github.com/noir-lang/noir/issues/3819)) ([fa1cf5f](https://github.com/noir-lang/noir/commit/fa1cf5f03aa21b001c31ebb9ce405e3c2859bb57)) * Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) * Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579))
0.38.0 ## [0.38.0](https://github.com/noir-lang/noir/compare/v0.37.1...v0.38.0) (2023-12-18) ### ⚠ BREAKING CHANGES * Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) * Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ### Features * Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) * Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) ### Bug Fixes * Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) ### Miscellaneous Chores * Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) * Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579))
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 4 +- CHANGELOG.md | 20 + Cargo.lock | 52 +-- Cargo.toml | 16 +- acvm-repo/CHANGELOG.md | 24 ++ acvm-repo/acir/Cargo.toml | 2 +- acvm-repo/acir_field/Cargo.toml | 2 +- acvm-repo/acvm/Cargo.toml | 2 +- acvm-repo/acvm_js/Cargo.toml | 2 +- acvm-repo/acvm_js/package.json | 2 +- .../barretenberg_blackbox_solver/Cargo.toml | 2 +- acvm-repo/blackbox_solver/Cargo.toml | 2 +- acvm-repo/brillig/Cargo.toml | 2 +- acvm-repo/brillig_vm/Cargo.toml | 2 +- compiler/wasm/package.json | 2 +- .../explainers/explainer-recursion.md | 175 +++++++++ .../version-v../explanations/noir/traits.md | 348 ++++++++++++++++++ .../explanations/standard_library/traits.md | 140 +++++++ .../getting_started/_category_.json | 5 + .../getting_started/create_a_project.md | 142 +++++++ .../installation/_category_.json | 6 + .../getting_started/installation/index.md | 45 +++ .../installation/other_install_methods.md | 190 ++++++++++ .../getting_started/project_breakdown.md | 199 ++++++++++ .../getting_started/tooling/_category_.json | 6 + .../getting_started/tooling/index.md | 33 ++ .../tooling/language_server.md | 43 +++ .../getting_started/tooling/testing.md | 62 ++++ .../version-v../how_to/_category_.json | 5 + .../version-v../how_to/how-to-recursion.md | 184 +++++++++ .../version-v../how_to/merkle-proof.mdx | 48 +++ .../version-v../how_to/solidity_verifier.md | 130 +++++++ docs/versioned_docs/version-v../index.md | 85 +++++ .../version-v../migration_notes.md | 91 +++++ .../modules_packages_crates/_category_.json | 6 + .../crates_and_packages.md | 43 +++ .../modules_packages_crates/dependencies.md | 124 +++++++ .../noir/modules_packages_crates/modules.md | 105 ++++++ .../modules_packages_crates/workspaces.md | 40 ++ .../noir/standard_library/_category_.json | 6 + .../noir/standard_library/black_box_fns.md | 46 +++ .../cryptographic_primitives/_category_.json | 5 + .../cryptographic_primitives/ec_primitives.md | 102 +++++ .../ecdsa_sig_verification.mdx | 46 +++ .../cryptographic_primitives/eddsa.mdx | 18 + .../cryptographic_primitives/hashes.mdx | 168 +++++++++ .../cryptographic_primitives/index.md | 14 + .../cryptographic_primitives/scalar.mdx | 28 ++ .../cryptographic_primitives/schnorr.mdx | 38 ++ .../noir/standard_library/logging.md | 77 ++++ .../noir/standard_library/merkle_trees.md | 58 +++ .../noir/standard_library/options.md | 99 +++++ .../noir/standard_library/recursion.md | 90 +++++ .../noir/standard_library/zeroed.md | 25 ++ .../version-v../noir/syntax/_category_.json | 6 + .../version-v../noir/syntax/assert.md | 27 ++ .../version-v../noir/syntax/comments.md | 33 ++ .../version-v../noir/syntax/control_flow.md | 45 +++ .../version-v../noir/syntax/data_bus.md | 21 ++ .../noir/syntax/data_types/_category_.json | 5 + .../noir/syntax/data_types/arrays.md | 245 ++++++++++++ .../noir/syntax/data_types/booleans.md | 31 ++ .../noir/syntax/data_types/fields.md | 166 +++++++++ .../noir/syntax/data_types/function_types.md | 26 ++ .../noir/syntax/data_types/index.md | 96 +++++ .../noir/syntax/data_types/integers.md | 113 ++++++ .../noir/syntax/data_types/references.md | 23 ++ .../noir/syntax/data_types/slices.mdx | 147 ++++++++ .../noir/syntax/data_types/strings.md | 80 ++++ .../noir/syntax/data_types/structs.md | 70 ++++ .../noir/syntax/data_types/tuples.md | 48 +++ .../noir/syntax/data_types/vectors.mdx | 173 +++++++++ .../version-v../noir/syntax/distinct.md | 64 ++++ .../version-v../noir/syntax/functions.md | 226 ++++++++++++ .../version-v../noir/syntax/generics.md | 114 ++++++ .../version-v../noir/syntax/lambdas.md | 81 ++++ .../version-v../noir/syntax/mutability.md | 93 +++++ .../version-v../noir/syntax/ops.md | 98 +++++ .../version-v../noir/syntax/shadowing.md | 44 +++ .../version-v../noir/syntax/unconstrained.md | 95 +++++ .../NoirJS/backend_barretenberg/.nojekyll | 1 + .../classes/BarretenbergBackend.md | 185 ++++++++++ .../NoirJS/backend_barretenberg/index.md | 45 +++ .../interfaces/Backend.md | 132 +++++++ .../type-aliases/BackendOptions.md | 19 + .../type-aliases/CompiledCircuit.md | 20 + .../type-aliases/ProofData.md | 20 + .../backend_barretenberg/typedoc-sidebar.cjs | 4 + .../reference/NoirJS/noir_js/.nojekyll | 1 + .../reference/NoirJS/noir_js/classes/Noir.md | 132 +++++++ .../reference/NoirJS/noir_js/functions/and.md | 22 ++ .../NoirJS/noir_js/functions/blake2s256.md | 21 ++ .../functions/ecdsa_secp256k1_verify.md | 29 ++ .../functions/ecdsa_secp256r1_verify.md | 28 ++ .../NoirJS/noir_js/functions/keccak256.md | 21 ++ .../NoirJS/noir_js/functions/sha256.md | 21 ++ .../reference/NoirJS/noir_js/functions/xor.md | 22 ++ .../reference/NoirJS/noir_js/index.md | 37 ++ .../noir_js/type-aliases/CompiledCircuit.md | 20 + .../type-aliases/ForeignCallHandler.md | 24 ++ .../noir_js/type-aliases/ForeignCallInput.md | 9 + .../noir_js/type-aliases/ForeignCallOutput.md | 9 + .../NoirJS/noir_js/type-aliases/InputMap.md | 13 + .../NoirJS/noir_js/type-aliases/ProofData.md | 20 + .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 + .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 + .../version-v../reference/_category_.json | 5 + .../version-v../reference/nargo_commands.md | 250 +++++++++++++ .../version-v../tutorials/noirjs_app.md | 261 +++++++++++++ .../version-v..-sidebars.json | 83 +++++ flake.nix | 2 +- tooling/noir_codegen/package.json | 2 +- tooling/noir_js/package.json | 2 +- .../noir_js_backend_barretenberg/package.json | 2 +- tooling/noir_js_types/package.json | 2 +- tooling/noirc_abi_wasm/package.json | 2 +- 116 files changed, 6808 insertions(+), 52 deletions(-) create mode 100644 docs/versioned_docs/version-v../explainers/explainer-recursion.md create mode 100644 docs/versioned_docs/version-v../explanations/noir/traits.md create mode 100644 docs/versioned_docs/version-v../explanations/standard_library/traits.md create mode 100644 docs/versioned_docs/version-v../getting_started/_category_.json create mode 100644 docs/versioned_docs/version-v../getting_started/create_a_project.md create mode 100644 docs/versioned_docs/version-v../getting_started/installation/_category_.json create mode 100644 docs/versioned_docs/version-v../getting_started/installation/index.md create mode 100644 docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md create mode 100644 docs/versioned_docs/version-v../getting_started/project_breakdown.md create mode 100644 docs/versioned_docs/version-v../getting_started/tooling/_category_.json create mode 100644 docs/versioned_docs/version-v../getting_started/tooling/index.md create mode 100644 docs/versioned_docs/version-v../getting_started/tooling/language_server.md create mode 100644 docs/versioned_docs/version-v../getting_started/tooling/testing.md create mode 100644 docs/versioned_docs/version-v../how_to/_category_.json create mode 100644 docs/versioned_docs/version-v../how_to/how-to-recursion.md create mode 100644 docs/versioned_docs/version-v../how_to/merkle-proof.mdx create mode 100644 docs/versioned_docs/version-v../how_to/solidity_verifier.md create mode 100644 docs/versioned_docs/version-v../index.md create mode 100644 docs/versioned_docs/version-v../migration_notes.md create mode 100644 docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json create mode 100644 docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md create mode 100644 docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md create mode 100644 docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md create mode 100644 docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/_category_.json create mode 100644 docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx create mode 100644 docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx create mode 100644 docs/versioned_docs/version-v../noir/standard_library/logging.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/options.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/recursion.md create mode 100644 docs/versioned_docs/version-v../noir/standard_library/zeroed.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/_category_.json create mode 100644 docs/versioned_docs/version-v../noir/syntax/assert.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/comments.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/control_flow.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_bus.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/fields.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/index.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/integers.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/references.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/strings.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/structs.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx create mode 100644 docs/versioned_docs/version-v../noir/syntax/distinct.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/functions.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/generics.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/lambdas.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/mutability.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/ops.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/shadowing.md create mode 100644 docs/versioned_docs/version-v../noir/syntax/unconstrained.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md create mode 100644 docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs create mode 100644 docs/versioned_docs/version-v../reference/_category_.json create mode 100644 docs/versioned_docs/version-v../reference/nargo_commands.md create mode 100644 docs/versioned_docs/version-v../tutorials/noirjs_app.md create mode 100644 docs/versioned_sidebars/version-v..-sidebars.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d722662cd12..01f6fb140b1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.21.0", - "acvm-repo": "0.37.1" + ".": "0.22.0", + "acvm-repo": "0.38.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a6fdcef0fa..0f3f6b02245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [0.22.0](https://github.com/noir-lang/noir/compare/v0.21.0...v0.22.0) (2023-12-18) + + +### ⚠ BREAKING CHANGES + +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) +* Remove backend field from artifacts ([#3819](https://github.com/noir-lang/noir/issues/3819)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) + +### Features + +* Add context-centric based API for noir_wasm ([#3798](https://github.com/noir-lang/noir/issues/3798)) ([19155d0](https://github.com/noir-lang/noir/commit/19155d02a1248c85e94f14a2a0bb383a4edeb16f)) + + +### Miscellaneous Chores + +* Remove backend field from artifacts ([#3819](https://github.com/noir-lang/noir/issues/3819)) ([fa1cf5f](https://github.com/noir-lang/noir/commit/fa1cf5f03aa21b001c31ebb9ce405e3c2859bb57)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) + ## [0.21.0](https://github.com/noir-lang/noir/compare/v0.20.0...v0.21.0) (2023-12-15) diff --git a/Cargo.lock b/Cargo.lock index 129840f67f0..7f964cd58ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir_field", "base64", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.37.1" +version = "0.38.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -54,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir", "blake2", @@ -67,7 +67,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acvm", "barretenberg_blackbox_solver", @@ -210,7 +210,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arena" -version = "0.21.0" +version = "0.22.0" dependencies = [ "generational-arena", ] @@ -419,7 +419,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.21.0" +version = "0.22.0" dependencies = [ "iter-extended", "noirc_frontend", @@ -462,7 +462,7 @@ dependencies = [ [[package]] name = "barretenberg_blackbox_solver" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -586,7 +586,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir_field", "serde", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.37.1" +version = "0.38.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -1632,7 +1632,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.21.0" +version = "0.22.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -2208,7 +2208,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.21.0" +version = "0.22.0" [[package]] name = "itertools" @@ -2430,7 +2430,7 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nargo" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "codespan-reporting", @@ -2452,7 +2452,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "assert_cmd", @@ -2505,7 +2505,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.21.0" +version = "0.22.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2517,7 +2517,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.21.0" +version = "0.22.0" dependencies = [ "dirs", "fm", @@ -2566,7 +2566,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "codespan-reporting", @@ -2580,7 +2580,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "async-lsp", @@ -2603,7 +2603,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "build-data", @@ -2624,7 +2624,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "iter-extended", @@ -2641,7 +2641,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "build-data", @@ -2658,7 +2658,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "aztec_macros", @@ -2678,7 +2678,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "chumsky", @@ -2692,7 +2692,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "fxhash", @@ -2708,7 +2708,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "arena", @@ -2732,7 +2732,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.21.0" +version = "0.22.0" dependencies = [ "acvm", "iter-extended", diff --git a/Cargo.toml b/Cargo.toml index 5a7499f21a8..aaf060552e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.21.0" +version = "0.22.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -49,14 +49,14 @@ repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.37.1", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.37.1", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.37.1", path = "acvm-repo/acvm" } +acir_field = { version = "0.38.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.38.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.38.0", path = "acvm-repo/acvm" } stdlib = { version = "0.37.1", package = "acvm_stdlib", path = "acvm-repo/stdlib", default-features = false } -brillig = { version = "0.37.1", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.37.1", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.37.1", path = "acvm-repo/blackbox_solver", default-features = false } -barretenberg_blackbox_solver = { version = "0.37.1", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } +brillig = { version = "0.38.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.38.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.38.0", path = "acvm-repo/blackbox_solver", default-features = false } +barretenberg_blackbox_solver = { version = "0.38.0", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } # Noir compiler workspace dependencies arena = { path = "compiler/utils/arena" } diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index d65863989dd..0bd38fd3307 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.38.0](https://github.com/noir-lang/noir/compare/v0.37.1...v0.38.0) (2023-12-18) + + +### ⚠ BREAKING CHANGES + +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) + +### Features + +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) + + +### Bug Fixes + +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) + + +### Miscellaneous Chores + +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) + ## [0.37.1](https://github.com/noir-lang/noir/compare/v0.37.0...v0.37.1) (2023-12-15) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index 6c9b76561e4..a0877120a58 100644 --- a/acvm-repo/acir/Cargo.toml +++ b/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 0f17d7b4959..cedfc66e734 100644 --- a/acvm-repo/acir_field/Cargo.toml +++ b/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 498d1a80fe1..5fdf44cbd5e 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index c788919666f..22bd6e5aa7e 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index fbc76a1ee62..9f265dd676a 100644 --- a/acvm-repo/acvm_js/package.json +++ b/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.37.1", + "version": "0.38.0", "repository": { "type": "git", "url": "https://github.com/noir-lang/acvm.git" diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index 09b8286a1f1..01f5e6ca950 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "barretenberg_blackbox_solver" description = "A wrapper around a barretenberg WASM binary to execute black box functions for which there is no rust implementation" # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 39dd35637a9..be2a58417f4 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index d57f4ed26fa..ee8651faeec 100644 --- a/acvm-repo/brillig/Cargo.toml +++ b/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig_vm/Cargo.toml b/acvm-repo/brillig_vm/Cargo.toml index b28e472636f..91bef2572bb 100644 --- a/acvm-repo/brillig_vm/Cargo.toml +++ b/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.37.1" +version = "0.38.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index 40774c3449b..352142eb3e3 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.21.0", + "version": "0.22.0", "license": "(MIT OR Apache-2.0)", "main": "./nodejs/noir_wasm.js", "types": "./web/noir_wasm.d.ts", diff --git a/docs/versioned_docs/version-v../explainers/explainer-recursion.md b/docs/versioned_docs/version-v../explainers/explainer-recursion.md new file mode 100644 index 00000000000..cc431a878dc --- /dev/null +++ b/docs/versioned_docs/version-v../explainers/explainer-recursion.md @@ -0,0 +1,175 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation Objects", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +So, Alice started thinking: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +So, the tallier puts all the votes in a merkle tree, and everyone can also prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He could find it more efficient to generate a proof for that setup phase separately, and verifying it in his actual business logic section of the circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof +- The input aggregation object + +It also returns the `output aggregation object`. These aggregation objects can be confusing at times, so let's dive in a little bit. + +### Aggregation objects + +Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. + +In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he is verifying a proof, so it needs to output an `aggregation object`: he is generating a recursive proof! +- Alice verifies Bob's *recursive proof*, and uses Bob's `output aggregation object` as the `input aggregation object` in her proof... Which in turn, generates another `output aggregation object`. + +One should notice that when Bob generates his first proof, he has no input aggregation object. Because he is not verifying an recursive proof, he has no `input aggregation object`. In this case, he may use zeros instead. + +We can imagine the `aggregation object` as the baton in a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursiveness would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. diff --git a/docs/versioned_docs/version-v../explanations/noir/traits.md b/docs/versioned_docs/version-v../explanations/noir/traits.md new file mode 100644 index 00000000000..7ba07e74f40 --- /dev/null +++ b/docs/versioned_docs/version-v../explanations/noir/traits.md @@ -0,0 +1,348 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v../explanations/standard_library/traits.md b/docs/versioned_docs/version-v../explanations/standard_library/traits.md new file mode 100644 index 00000000000..63b4f3d6f0b --- /dev/null +++ b/docs/versioned_docs/version-v../explanations/standard_library/traits.md @@ -0,0 +1,140 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust +trait Default { + fn default() -> Self; +} +``` + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + +## `std::ops` + +### `std::ops::Eq` + +```rust +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +Returns `true` if `self` is equal to `other`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Although Noir does not currently have operator overloading, in the future implementing these +traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust +trait Add { + fn add(self, other: Self) -> Self; +} + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +trait Div { + fn div(self, other: Self) -> Self; +} +``` + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` diff --git a/docs/versioned_docs/version-v../getting_started/_category_.json b/docs/versioned_docs/version-v../getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../getting_started/create_a_project.md b/docs/versioned_docs/version-v../getting_started/create_a_project.md new file mode 100644 index 00000000000..f10916c39c5 --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/create_a_project.md @@ -0,0 +1,142 @@ +--- +title: Creating A Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ that contains the source code and environmental options of your Noir program +respectively. + +### Intro to Noir Syntax + +Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +The first line of the program specifies the program's inputs: + +```rust +x : Field, y : pub Field +``` + +Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the +keyword `pub` (e.g. `y`). To learn more about private and public values, check the +[Data Types](../noir/syntax/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../noir/syntax/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution on our Noir program. + +Fill in input values for execution in the _Prover.toml_ file. For example: + +```toml +x = "1" +y = "2" +``` + +Prove the valid execution of your Noir program: + +```sh +nargo prove +``` + +A new folder _proofs_ would then be generated in your project directory, containing the proof file +`.proof`, where the project name is defined in Nargo.toml. + +The _Verifier.toml_ file would also be updated with the public values computed from program +execution (in this case the value of `y`): + +```toml +y = "0x0000000000000000000000000000000000000000000000000000000000000002" +``` + +> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. + +## Verify Our Noir Program + +Once a proof is generated, we can verify correct execution of our Noir program by verifying the +proof file. + +Verify your proof by running: + +```sh +nargo verify +``` + +The verification will complete in silence if it is successful. If it fails, it will log the +corresponding error instead. + +Congratulations, you have now created and verified a proof for your very first Noir program! + +In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v../getting_started/installation/_category_.json b/docs/versioned_docs/version-v../getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../getting_started/installation/index.md b/docs/versioned_docs/version-v../getting_started/installation/index.md new file mode 100644 index 00000000000..ddb8a250eb4 --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/installation/index.md @@ -0,0 +1,45 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo though the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. diff --git a/docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..36f05657277 --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md @@ -0,0 +1,190 @@ +--- +title: Alternative Install Methods +description: + There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Shell & editor experience + Building and testing + Uninstalling Nargo + Noir vs code extension +] +sidebar_position: 1 +--- + + +## Installation + +The most common method of installing Nargo is through [Noirup](./index.md) + +However, there are other methods for installing Nargo: + +- [Binaries](#binaries) +- [Compiling from Source](#compile-from-source) +- [WSL for Windows](#wsl-for-windows) + +### Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --version`. You should get a version number. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +### Option 3: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 4: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](./index.md). + +## Uninstalling Nargo + +### Noirup + +If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` diff --git a/docs/versioned_docs/version-v../getting_started/project_breakdown.md b/docs/versioned_docs/version-v../getting_started/project_breakdown.md new file mode 100644 index 00000000000..5a214804f7b --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program in section _1.2_. We elaborate on the project +structure and what the `prove` and `verify` commands did in the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Verifier.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Verifier.toml + +_Verifier.toml_ contains public in/output values computed when executing the Noir program. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noirstarter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section requires a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is +constrained by the proof of the execution of said program (i.e. if the condition was not met, the +verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and +public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo prove` is executed, two processes happen: + +1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` + is not equal. This not equal constraint is due to the line `assert(x != y)`. + +2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: + +```bash +nargo prove +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: + +```bash +nargo prove -p OtherProver +``` + +## Verifying a Proof + +When the command `nargo verify` is executed, two processes happen: + +1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) + +2. If that file is found, the proof's validity is checked + +> **Note:** The validity of the proof is linked to the current Noir program; if the program is +> changed and the verifier verifies the proof, it will fail because the proof is not valid for the +> _modified_ Noir program. + +In production, the prover and the verifier are usually two separate entities. A prover would +retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the +verifier. The verifier would then retrieve the public inputs from usually external sources and +verifies the validity of the proof against it. + +Take a private asset transfer as an example: + +A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and +public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof +and submit it to the verifier smart contract. + +The verifier contract would then draw the user's encrypted balance directly from the blockchain and +verify the proof submitted against it. If the verification passes, additional functions in the +verifier contract could trigger (e.g. approve the asset transfer). + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/docs/versioned_docs/version-v../getting_started/tooling/_category_.json b/docs/versioned_docs/version-v../getting_started/tooling/_category_.json new file mode 100644 index 00000000000..dff520ebc41 --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 3, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../getting_started/tooling/index.md b/docs/versioned_docs/version-v../getting_started/tooling/index.md new file mode 100644 index 00000000000..55df833005a --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/tooling/index.md @@ -0,0 +1,33 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## Playground + +The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/docs/versioned_docs/version-v../getting_started/tooling/language_server.md b/docs/versioned_docs/version-v../getting_started/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v../getting_started/tooling/testing.md b/docs/versioned_docs/version-v../getting_started/tooling/testing.md new file mode 100644 index 00000000000..868a061200d --- /dev/null +++ b/docs/versioned_docs/version-v../getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +the contraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/docs/versioned_docs/version-v../how_to/_category_.json b/docs/versioned_docs/version-v../how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v../how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../how_to/how-to-recursion.md b/docs/versioned_docs/version-v../how_to/how-to-recursion.md new file mode 100644 index 00000000000..226f7e6e73d --- /dev/null +++ b/docs/versioned_docs/version-v../how_to/how-to-recursion.md @@ -0,0 +1,184 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. Meaning it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. Which means these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume these two: + +- `main`: a circuit of type `assert(x != y)` +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursiveness, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateIntermediateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit are we actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*. So it is Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyIntermediateProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate the intermediate artifacts: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateIntermediateProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]`. However, currently the backend doesn't remove the public inputs from the proof when converting it. + +This means that if your `main` circuit has two public inputs, then you should also modify the recursive circuit to accept a proof with the public inputs appended. This means that in our example, since `y` is a public input, our `proofAsFields` is of type `[Field; 94]`. + +Verification keys in Barretenberg are always of size 114. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, + input_aggregation_object: Array(16).fill(0) // this circuit is verifying a non-recursive proof, so there's no input aggregation object: just use zero +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateFinalProof(witness) +const verified = backend.verifyFinalProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! In that case, you should keep in mind the `returnValue`, as it will contain the `input_aggregation_object` for the next proof. + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { +main: mainJSON, +recursive: recursiveJSON +} +const backends = { +main: new BarretenbergBackend(circuits.main), +recursive: new BarretenbergBackend(circuits.recursive) +} +const noirs = { +main: new Noir(circuits.main, backends.main), +recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noirs.main.execute(input) +const proof = await backends.main.generateIntermediateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyIntermediateProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateIntermediateProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noirs.recursive.generateFinalProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v../how_to/merkle-proof.mdx b/docs/versioned_docs/version-v../how_to/merkle-proof.mdx new file mode 100644 index 00000000000..34074659ac1 --- /dev/null +++ b/docs/versioned_docs/version-v../how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v../how_to/solidity_verifier.md b/docs/versioned_docs/version-v../how_to/solidity_verifier.md new file mode 100644 index 00000000000..8022b0e5f20 --- /dev/null +++ b/docs/versioned_docs/version-v../how_to/solidity_verifier.md @@ -0,0 +1,130 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +--- + +For certain applications, it may be desirable to run the verifier as a smart contract instead of on +a local machine. + +Compile a Solidity verifier contract for your Noir program by running: + +```sh +nargo codegen-verifier +``` + +A new `contract` folder would then be generated in your project directory, containing the Solidity +file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. + +> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract +> platforms as long as the proving backend supplies an implementation. +> +> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in +> Solidity only for the time being. + +## Verify + +To verify a proof using the Solidity verifier contract, call the `verify` function with the +following signature: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): + +```solidity +function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { + // ... + bytes32[] memory publicInputs = new bytes32[](4); + publicInputs[0] = merkleRoot; + publicInputs[1] = bytes32(proposalId); + publicInputs[2] = bytes32(vote); + publicInputs[3] = nullifierHash; + require(verifier.verify(proof, publicInputs), "Invalid proof"); +``` + +### Public Inputs + +:::tip + +A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in +Noir. + +Under the hood, the return value is passed as an input to the circuit and is checked at the end of +the circuit program. + +::: + +The verifier contract uses the output (return) value of a Noir program as a public input. So if you +have the following function + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an +error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. + +#### Struct inputs + +Consider the following program: + +```rust +struct Type1 { + val1: Field, + val2: Field, +} + +struct Nested { + t1: Type1, + is_true: bool, +} + +fn main(x: pub Field, nested: pub Nested, y: pub Field) { + //... +} +``` + +Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +## Noir for EVM chains + +You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. + +### Unsupported chains + +Unfortunately not all "EVM" chains are supported. + +**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v../index.md b/docs/versioned_docs/version-v../index.md new file mode 100644 index 00000000000..016832f9f5e --- /dev/null +++ b/docs/versioned_docs/version-v../index.md @@ -0,0 +1,85 @@ +--- +title: Noir +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to + an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. +keywords: + [ + Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language, + ] +sidebar_position: 0 +--- + +## What's new about Noir? + +Noir, a domain-specific language crafted for SNARK proving systems, stands out with its simplicity, flexibility, +and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, +Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, +depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's +barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin +backend, among others. + +This innovative design introduces unique challenges, yet it strategically separates the programming language from the +backend. Noir's approach echoes the modular philosophy of LLVM, offering developers a versatile toolkit for cryptographic +programming. + +## Who is Noir for? + +### Solidity Developers + +Noir streamlines the creation of Solidity contracts that interface with SNARK systems. +[`Utilize the nargo codegen-verifier`](./reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier +contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim +to modularize this process for even greater ease of use. + +Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be +modularised in the future; however, as of the alpha, you can use the + command to create a verifier contract. + +### Protocol Developers + +Should the Aztec backend not align with your existing tech stack, or if you're inclined to integrate alternative +proving systems, Noir's agnostic compilation to a proof-agnostic intermediate language offers unmatched flexibility. +This allows protocol engineers the freedom to substitute the default PLONK-based system with an alternative of their +choice, tailoring the proving system to their specific needs. + +### Blockchain developers + +Blockchain developers often face environmental constraints, such as predetermined proving systems and smart contract +languages. Noir addresses this by enabling the implementation of custom proving system backends and smart contract +interfaces, ensuring seamless integration with your blockchain's architecture, and expanding the horizons for innovation +within your projects. + +## Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the +[awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains + the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage + proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing + for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and + return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of + sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data + type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, + allowing results that aren't whole numbers + +See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v../migration_notes.md b/docs/versioned_docs/version-v../migration_notes.md new file mode 100644 index 00000000000..d5d0682cf0c --- /dev/null +++ b/docs/versioned_docs/version-v../migration_notes.md @@ -0,0 +1,91 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](noir/syntax/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with you Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..aae6795b229 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts). + +### Crate Root + +Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. + +## Packages + +A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. + +A package _must_ contain either a library or a binary crate, but not both. + +### Differences from Cargo Packages + +One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. + +In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..57f0f9fd420 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── liba + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +libA = { path = "../liba" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local liba referenced above: + +```rust +use dep::ecrecover; +use dep::libA; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use dep::std::hash::sha256; +use dep::std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use dep::phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..f9f15aee8be --- /dev/null +++ b/docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organise files. Without modules all of your code would need to live in a single +file. In Noir, the compiler does not automatically scan all of your files to detect modules. This +must be done explicitly by the developer. + +## Examples + +### Importing a module in the crate root + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo.nr` + +```rust +fn from_foo() {} +``` + +In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module +declaration `mod foo` which prompts it to look for a foo.nr file. + +Visually this module hierarchy looks like the following : + +``` +crate + ├── main + │ + └── foo + └── from_foo + +``` + +### Importing a module throughout the tree + +All modules are accessible from the `crate::` namespace. + +``` +crate + ├── bar + ├── foo + └── main + +``` + +In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. + +### Sub-modules + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +fn from_bar() {} +``` + +In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule +of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the +compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` + +Visually the module hierarchy looks as follows: + +``` +crate + ├── main + │ + └── foo + ├── from_foo + └── bar + └── from_bar +``` diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..67a1dafa372 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md @@ -0,0 +1,40 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│   ├── a +│   │   ├── Nargo.toml +│   │   └── src +│   │   └── main.nr +│   └── b +│   ├── Nargo.toml +│   └── src +│   └── main.nr +├── Nargo.toml +└── Prover.toml +``` + +You can define a workspace in Nargo.toml like so: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v../noir/standard_library/_category_.json b/docs/versioned_docs/version-v../noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..1dfabfe8f22 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md @@ -0,0 +1,46 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +:::warning + +It is likely that not all backends will support a particular black box function. + +::: + +Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. + +Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: + +```rust +#[foreign(sha256)] +fn sha256(_input : [u8; N]) -> [u8; 32] {} +``` + +## Function list + +Here is a list of the current black box functions that are supported by UltraPlonk: + +- AES +- [SHA256](./cryptographic_primitives/hashes#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr) +- [Blake2s](./cryptographic_primitives/hashes#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [Compute merkle root](./merkle_trees#compute_merkle_root) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..8d573adb3be --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) +illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more +interesting examples in Noir would be: + +Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key +from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, +for example, this code would do: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; + +fn bjj_pub_key(priv_key: Field) -> Point +{ + + let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); + + let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); + + bjj.mul(priv_key,base_pt) +} +``` + +This would come in handy in a Merkle proof. + +- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash + function. See + [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for + the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..1376c51dfde --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,46 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..a9c10da6c06 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,18 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + + diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..9250cb4a0c0 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,168 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust +fn sha256(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust +fn blake2s(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust +fn pedersen_hash(_input : [Field]) -> Field +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::pedersen_hash(x); +} +``` + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust +fn pedersen_commitment(_input : [Field]) -> [Field; 2] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let commitment = std::hash::pedersen_commitment(x); +} +``` + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes +(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes +of the input. + +```rust +fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let message_size = 4; + let hash = std::hash::keccak256(x, message_size); +} +``` + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust +fn main() +{ + let hash_2 = std::hash::poseidon::bn254::hash_2([1, 2]); + assert(hash2 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); +} +``` + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field; N]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + + diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..1e686303c18 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,28 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust +fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] +``` + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + std::println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..7a2c9c20226 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,38 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust +fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool +``` + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + diff --git a/docs/versioned_docs/version-v../noir/standard_library/logging.md b/docs/versioned_docs/version-v../noir/standard_library/logging.md new file mode 100644 index 00000000000..16daf922e15 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/logging.md @@ -0,0 +1,77 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constrains with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +use dep::std; + +struct Person { + age : Field, + height : Field, +} + +fn main(age : Field, height : Field) { + let person = Person { age : age, height : height }; + std::println(person); + std::println(age + height); + std::println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + std::println(fmt_str); + + let s = myStruct { y: x, x: y }; + std::println(s); + + std::println(f"i: {i}, s: {s}"); + + std::println(x); + std::println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + std::println(f"s: {s}, foo: {foo}"); + + std::println(15); // prints 0x0f, implicit Field + std::println(-1 as u8); // prints 255 + std::println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +std::println(person); +std::print(person); + +std::println("Hello world!"); // Prints with a newline at the end of the input +std::print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..5b45617812a --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + std::println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v../noir/standard_library/options.md b/docs/versioned_docs/version-v../noir/standard_library/options.md new file mode 100644 index 00000000000..3d3139fb98b --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/options.md @@ -0,0 +1,99 @@ +--- +title: Option Type +--- + +The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. + +```rust +struct Option { + None, + Some(T), +} +``` + +You can import the Option type into your Noir program like so: + +```rust +use dep::std::option::Option; + +fn main() { + let none = Option::none(); + let some = Option::some(3); +} +``` + +See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. + +## Methods + +### none + +Constructs a none value. + +### some + +Constructs a some wrapper around a given value. + +### is_none + +Returns true if the Option is None. + +### is_some + +Returns true of the Option is Some. + +### unwrap + +Asserts `self.is_some()` and returns the wrapped value. + +### unwrap_unchecked + +Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. + +### unwrap_or + +Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + +### unwrap_or_else + +Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. + +### map + +If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + +### map_or + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + +### map_or_else + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + +### and + +Returns None if self is None. Otherwise, this returns `other`. + +### and_then + +If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. + +### or + +If self is Some, return self. Otherwise, return `other`. + +### or_else + +If self is Some, return self. Otherwise, return `default()`. + +### xor + +If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. + +### filter + +Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. + +### flatten + +Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/docs/versioned_docs/version-v../noir/standard_library/recursion.md b/docs/versioned_docs/version-v../noir/standard_library/recursion.md new file mode 100644 index 00000000000..67962082a8f --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/recursion.md @@ -0,0 +1,90 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] +--- + +Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. + +The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. + +```rust +#[foreign(verify_proof)] +fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 94], + public_inputs : [Field; 1], + key_hash : Field, + input_aggregation_object : [Field; 16], + proof_b : [Field; 94], +) -> pub [Field; 16] { + let output_aggregation_object_a = std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash, + input_aggregation_object + ); + + let output_aggregation_object = std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash, + output_aggregation_object_a + ); + + let mut output = [0; 16]; + for i in 0..16 { + output[i] = output_aggregation_object[i]; + } + output +} +``` + +## Parameters + +### `verification_key` + +The verification key for the zk program that is being verified. + +### `proof` + +The proof for the zk program that is being verified. + +### `public_inputs` + +These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. + +### `key_hash` + +A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. + +### `input_aggregation_object` + +An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. + +## Return value + +### `output_aggregation_object` + +This is the result of a recursive aggregation and is what will be fed into the next verifier. +The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. + +## Example + +You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/docs/versioned_docs/version-v../noir/standard_library/zeroed.md b/docs/versioned_docs/version-v../noir/standard_library/zeroed.md new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/standard_library/zeroed.md @@ -0,0 +1,25 @@ +--- +title: Zeroed Function +description: + The zeroed function returns a zeroed value of any type. +keywords: + [ + zeroed + ] +--- + +Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. + +You can access the function at `std::unsafe::zeroed`. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v../noir/syntax/_category_.json b/docs/versioned_docs/version-v../noir/syntax/_category_.json new file mode 100644 index 00000000000..666b691ae91 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Syntax", + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../noir/syntax/assert.md b/docs/versioned_docs/version-v../noir/syntax/assert.md new file mode 100644 index 00000000000..c5f9aff139c --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/assert.md @@ -0,0 +1,27 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/docs/versioned_docs/version-v../noir/syntax/comments.md b/docs/versioned_docs/version-v../noir/syntax/comments.md new file mode 100644 index 00000000000..f76ab49094b --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 9 +--- + +A comment is a line in your codebase which the compiler ignores, however it can be read by +programmers. + +Here is a single line comment: + +```rust +// This is a comment and is ignored +``` + +`//` is used to tell the compiler to ignore the rest of the line. + +Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. + +Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. + +```rust +/* + This is a block comment describing a complex function. +*/ +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/control_flow.md b/docs/versioned_docs/version-v../noir/syntax/control_flow.md new file mode 100644 index 00000000000..4ce65236db3 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/control_flow.md @@ -0,0 +1,45 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_bus.md b/docs/versioned_docs/version-v../noir/syntax/data_bus.md new file mode 100644 index 00000000000..6c7e9b60891 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 12 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json b/docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md b/docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md new file mode 100644 index 00000000000..075d39dadd4 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md @@ -0,0 +1,245 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays: + +### len + +Returns the length of an array + +```rust +fn len(_array: [T; N]) -> comptime Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(_array: [T; N]) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md b/docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/fields.md b/docs/versioned_docs/version-v../noir/syntax/data_types/fields.md new file mode 100644 index 00000000000..a1c67945d66 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/fields.md @@ -0,0 +1,166 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md b/docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md new file mode 100644 index 00000000000..61e4076adaf --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](@site/docs/noir/syntax/lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/index.md b/docs/versioned_docs/version-v../noir/syntax/data_types/index.md new file mode 100644 index 00000000000..52e568e9b7e --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/index.md @@ -0,0 +1,96 @@ +--- +title: Data Types +description: + Get a clear understanding of the two categories of Noir data types - primitive types and compound + types. Learn about their characteristics, differences, and how to use them in your Noir + programming. +keywords: + [ + noir, + data types, + primitive types, + compound types, + private types, + public types, + ] +--- + +Every value in Noir has a type, which determines which operations are valid for it. + +All values in Noir are fundamentally composed of `Field` elements. For a more approachable +developing experience, abstractions are added on top to introduce different data types in Noir. + +Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound +types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or +public. + +## Private & Public Types + +A **private value** is known only to the Prover, while a **public value** is known by both the +Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All +primitive types (including individual fields of compound types) in Noir are private by default, and +can be marked public when certain values are intended to be revealed to the Verifier. + +> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once +> the proofs are verified on-chain the values can be considered known to everyone that has access to +> that blockchain. + +Public data types are treated no differently to private types apart from the fact that their values +will be revealed in proofs generated. Simply changing the value of a public type will not change the +circuit (where the same goes for changing values of private types as well). + +_Private values_ are also referred to as _witnesses_ sometimes. + +> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different +> meaning than when applied to a function (e.g. `pub fn foo() {}`). +> +> The former is a visibility modifier for the Prover to interpret if a value should be made known to +> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a +> function should be made accessible to external Noir programs like in other languages. + +### pub Modifier + +All data types in Noir are private by default. Types are explicitly declared as public using the +`pub` modifier: + +```rust +fn main(x : Field, y : pub Field) -> pub Field { + x + y +} +``` + +In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note +that visibility is handled **per variable**, so it is perfectly valid to have one input that is +private and another that is public. + +> **Note:** Public types can only be declared through parameters on `main`. + +## Type Aliases + +A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: + +```rust +type Id = u8; + +fn main() { + let id: Id = 1; + let zero: u8 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can also be used with [generics](@site/docs/noir/syntax/generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +### BigInt + +You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/integers.md b/docs/versioned_docs/version-v../noir/syntax/data_types/integers.md new file mode 100644 index 00000000000..7d1e83cf4e9 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/integers.md @@ -0,0 +1,113 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +:::tip + +If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. + +::: + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo prove +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust +use dep::std; + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x + y) +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/references.md b/docs/versioned_docs/version-v../noir/syntax/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx b/docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx new file mode 100644 index 00000000000..4a6ee816aa2 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx @@ -0,0 +1,147 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/strings.md b/docs/versioned_docs/version-v../noir/syntax/data_types/strings.md new file mode 100644 index 00000000000..8d76d4ca654 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`std::println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + std::println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/structs.md b/docs/versioned_docs/version-v../noir/syntax/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md b/docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx b/docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx new file mode 100644 index 00000000000..10e35711b74 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx @@ -0,0 +1,173 @@ +--- +title: Vectors +description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. + +Example: + +```rust +use dep::std::collections::vec::Vec; + +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self { + Self { slice: [] } +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self { + Self { slice } +} +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T { + self.slice[index] +} +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice([10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); +} +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) { + self.slice = self.slice.insert(index, elem); +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T { + let (new_slice, elem) = self.slice.remove(index); + self.slice = new_slice; + elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field { + self.slice.len() +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/distinct.md b/docs/versioned_docs/version-v../noir/syntax/distinct.md new file mode 100644 index 00000000000..b59e0296b23 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 10 +--- + +The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures +that the witnesses being returned as public inputs are all unique. + +The `distinct` keyword is only used for return values on program entry points (usually the `main()` +function). + +When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. + +You can read more about the problem this solves +[here](https://github.com/noir-lang/noir/issues/1183). + +## Example + +Without the `distinct` keyword, the following program + +```rust +fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + "return_witnesses": [3, 2, 4, 4] + } +} +``` + +Whereas (with the `distinct` keyword) + +```rust +fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + //... + "return_witnesses": [3, 4, 5, 6] + } +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/functions.md b/docs/versioned_docs/version-v../noir/syntax/functions.md new file mode 100644 index 00000000000..48aba9cd058 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v../noir/syntax/generics.md b/docs/versioned_docs/version-v../noir/syntax/generics.md new file mode 100644 index 00000000000..443ca2b45a5 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/generics.md @@ -0,0 +1,114 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 6 +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn new(value: T) -> Self { + Self { value, count: 1 } + } + + fn increment(mut repeated: Self) -> Self { + repeated.count += 1; + repeated + } + + fn print(self) { + for _i in 0 .. self.count { + dep::std::println(self.value); + } + } +} + +fn main() { + let mut repeated = RepeatedValue::new("Hello!"); + repeated = repeated.increment(); + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks just like using regular generics, but these generics can resolve to +integers at compile-time, rather than resolving to types. Here's an example of a struct that is +generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in +Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also +requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? + +The answer is that we can translate this by passing in the function manually. Here's an example of +implementing array equality in Noir: + +```rust +fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { + if array1.len() != array2.len() { + false + } else { + let mut result = true; + for i in 0 .. array1.len() { + result &= elem_eq(array1[i], array2[i]); + } + result + } +} + +fn main() { + assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); + + // We can use array_eq even for arrays of structs, as long as we have + // an equality function for these structs we can pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} +``` + +You can see an example of generics in the tests +[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v../noir/syntax/lambdas.md b/docs/versioned_docs/version-v../noir/syntax/lambdas.md new file mode 100644 index 00000000000..e0a267adfda --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 8 +--- + +## Introduction + +Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +A block can be used as the body of a lambda, allowing you to declare local variables inside it: + +```rust +let cool = || { + let x = 100; + let y = 100; + x + y +} + +assert(cool() == 200); +``` + +## Closures + +Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: + +```rust +fn main() { + let x = 100; + let closure = || x + 150; + assert(closure() == 250); +} +``` + +## Passing closures to higher-order functions + +It may catch you by surprise that the following code fails to compile: + +```rust +fn foo(f: fn () -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // error :( +} +``` + +The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` +expects a regular function as an argument - those are incompatible. +:::note + +Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. + +E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. + +::: +The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - +in this example that's `(Field, Field)`. + +The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called +with closures with any environment, as well as with regular functions: + +```rust +fn foo(f: fn[Env]() -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // compiles fine + assert(foo(|| 60) == 60); // compiles fine +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/mutability.md b/docs/versioned_docs/version-v../noir/syntax/mutability.md new file mode 100644 index 00000000000..58e9c1cecfb --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/mutability.md @@ -0,0 +1,93 @@ +--- +title: Mutability +description: + Learn about mutable variables, constants, and globals in Noir programming language. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +sidebar_position: 7 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Comptime Values + +:::warning + +The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. + +::: + +## Globals + +Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array +annotations for function parameters and can be imported from submodules. + +```rust +global N: Field = 5; // Same as `global N: Field = 5` + +fn main(x : Field, y : [Field; N]) { + let res = x * N; + + assert(res == y[0]); + + let res2 = x * mysubmodule::N; + assert(res != res2); +} + +mod mysubmodule { + use dep::std; + + global N: Field = 10; + + fn my_helper() -> Field { + let x = N; + x + } +} +``` + +## Why only local mutability? + +Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting +without applying additional overhead to the user. Modeling a mutable reference is not as +straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v../noir/syntax/ops.md b/docs/versioned_docs/version-v../noir/syntax/ops.md new file mode 100644 index 00000000000..977c8ba1203 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/shadowing.md b/docs/versioned_docs/version-v../noir/syntax/shadowing.md new file mode 100644 index 00000000000..b5a6b6b38b9 --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 11 +--- + +Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. + +For example, the following function is valid in Noir: + +```rust +fn main() { + let x = 5; + + { + let x = x * 2; + assert (x == 10); + } + + assert (x == 5); +} +``` + +In this example, a variable x is first defined with the value 5. + +The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. + +When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. + +## Temporal mutability + +One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. + +```rust +fn main() { + let age = 30; + // age = age + 5; // Would error as `age` is immutable by default. + + let mut age = age + 5; // Temporarily mutates `age` with a new value. + + let age = age; // Locks `age`'s mutability again. + + assert (age == 35); +} +``` diff --git a/docs/versioned_docs/version-v../noir/syntax/unconstrained.md b/docs/versioned_docs/version-v../noir/syntax/unconstrained.md new file mode 100644 index 00000000000..7a61d3953ef --- /dev/null +++ b/docs/versioned_docs/version-v../noir/syntax/unconstrained.md @@ -0,0 +1,95 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. + +## Why? + +Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. + +Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. + +Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. + +A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. + +## Example + +An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. + +Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 +Backend circuit size: 3619 +``` + +A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 +Backend circuit size: 3143 +``` + +Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. + +It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. + +We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: + +```rust +fn main(num: u72) -> pub [u8; 8] { + let out = u72_to_u8(num); + + let mut reconstructed_num: u72 = 0; + for i in 0..8 { + reconstructed_num += (out[i] as u72 << (56 - (8 * i))); + } + assert(num == reconstructed_num); + out +} + +unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8))) as u8; + } + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 +Backend circuit size: 2902 +``` + +This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). + +Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..5cbe9421b92 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..bfbecb52864 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,45 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +## Functions + +### flattenPublicInputs() + +```ts +flattenPublicInputs(publicInputs): string[] +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `WitnessMap` | + +#### Returns + +`string`[] + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 00000000000..3eb9645c8d2 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..266ade75d17 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 00000000000..3eb360a78f1 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..2aaa55bccf6 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..34e20d99684 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalProof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..0ba5783f0d5 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..8b9e35bc9a1 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md @@ -0,0 +1,37 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [InputMap](type-aliases/InputMap.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md new file mode 100644 index 00000000000..c714e999d93 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md @@ -0,0 +1,13 @@ +# InputMap + +```ts +type InputMap: object; +``` + +## Index signature + + \[`key`: `string`\]: `InputValue` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md new file mode 100644 index 00000000000..3eb360a78f1 --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..fe2629ddc9f --- /dev/null +++ b/docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v../reference/_category_.json b/docs/versioned_docs/version-v../reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v../reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v../reference/nargo_commands.md b/docs/versioned_docs/version-v../reference/nargo_commands.md new file mode 100644 index 00000000000..ff3dee8973f --- /dev/null +++ b/docs/versioned_docs/version-v../reference/nargo_commands.md @@ -0,0 +1,250 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +## General options + +| Option | Description | +| -------------------- | -------------------------------------------------- | +| `--show-ssa` | Emit debug information for the intermediate SSA IR | +| `--deny-warnings` | Quit execution when warnings are emitted | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo help [subcommand]` + +Prints the list of available commands or specific information of a subcommand. + +_Arguments_ + +| Argument | Description | +| -------------- | -------------------------------------------- | +| `` | The subcommand whose help message to display | + +## `nargo backend` + +Installs and selects custom backends used to generate and verify proofs. + +### Commands + +| Command | Description | +| ----------- | --------------------------------------------------------- | +| `current` | Prints the name of the currently active backend | +| `ls` | Prints the list of currently installed backends | +| `use` | Select the backend to use | +| `install` | Install a new backend from a URL | +| `uninstall` | Uninstalls a backend | +| `help` | Print this message or the help of the given subcommand(s) | + +### Options + +| Option | Description | +| ------------ | ----------- | +| `-h, --help` | Print help | + +## `nargo check` + +Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output +values of the Noir program respectively. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to check | +| `--workspace` | Check all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +### `nargo codegen-verifier` + +Generate a Solidity verifier smart contract for the program. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to codegen | +| `--workspace` | Codegen all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo compile` + +Compile the program into a JSON build artifact file containing the ACIR representation and the ABI +of the circuit. This build artifact can then be used to generate and verify proofs. + +You can also use "build" as an alias for compile (e.g. `nargo build`). + +### Options + +| Option | Description | +| --------------------- | ------------------------------------------------------------ | +| `--package ` | The name of the package to compile | +| `--workspace` | Compile all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo new ` + +Creates a new Noir project in a new folder. + +**Arguments** + +| Argument | Description | +| -------- | -------------------------------- | +| `` | The path to save the new project | + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: package directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo init` + +Creates a new Noir project in the current directory. + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: current directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo execute [WITNESS_NAME]` + +Runs the Noir program and prints its return value. + +**Arguments** + +| Argument | Description | +| ---------------- | ----------------------------------------- | +| `[WITNESS_NAME]` | Write the execution witness to named file | + +### Options + +| Option | Description | +| --------------------------------- | ------------------------------------------------------------------------------------ | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `--package ` | The name of the package to execute | +| `--workspace` | Execute all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +_Usage_ + +The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which +must be filled in. + +To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A +`.tr` file will then be saved in the `./target` folder. + +## `nargo prove` + +Creates a proof for the program. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--verify` | Verify proof after proving | +| `--package ` | The name of the package to prove | +| `--workspace` | Prove all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--package ` | The name of the package to verify | +| `--workspace` | Verify all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo test [TEST_NAME]` + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. + +Takes an optional `--exact` flag which allows you to select tests based on an exact name. + +See an example on the [testing page](../getting_started/tooling/testing.md). + +### Options + +| Option | Description | +| --------------------- | -------------------------------------- | +| `--show-output` | Display output of `println` statements | +| `--exact` | Only run tests that match exactly | +| `--package ` | The name of the package to test | +| `--workspace` | Test all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo info` + +Prints a table containing the information of the package. + +Currently the table provide + +1. The number of ACIR opcodes +2. The final number gates in the circuit used by a backend + +If the file contains a contract the table will provide the +above information about each function of the contract. + +## `nargo lsp` + +Start a long-running Language Server process that communicates over stdin/stdout. +Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). + +## `nargo fmt` + +Automatically formats your Noir source code based on the default formatting settings. diff --git a/docs/versioned_docs/version-v../tutorials/noirjs_app.md b/docs/versioned_docs/version-v../tutorials/noirjs_app.md new file mode 100644 index 00000000000..302ee4aeade --- /dev/null +++ b/docs/versioned_docs/version-v../tutorials/noirjs_app.md @@ -0,0 +1,261 @@ +--- +title: Tiny NoirJS app +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] +sidebar_position: 0 +--- + +NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Before we start + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. + +In this guide, we will be pinned to 0.17.0. + +::: + +Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). + +First of all, follow the the [Nargo guide](../getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: + +```bash +nargo compile +``` + +Your folder structure should look like: + +```tree +. +└── circuit + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +## Starting a new project + +Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. + +## Installing dependencies + +We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: + +```bash +npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 +``` + +To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: + +```bash +npm i --save-dev vite rollup-plugin-copy +``` + +Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: + +```json + "start": "vite --open" +``` + +If you want do build a static website, you can also add some build and preview scripts: + +```json + "build": "vite build", + "preview": "vite preview" +``` + +## Vite plugins + +Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. + +```js +import { defineConfig } from 'vite'; +import copy from 'rollup-plugin-copy'; +import fs from 'fs'; +import path from 'path'; + +const wasmContentTypePlugin = { + name: 'wasm-content-type-plugin', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm'); + const newPath = req.url.replace('deps', 'dist'); + const targetPath = path.join(__dirname, newPath); + const wasmContent = fs.readFileSync(targetPath); + return res.end(wasmContent); + } + next(); + }); + }, +}; + +export default defineConfig(({ command }) => { + if (command === 'serve') { + return { + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +## HTML + +Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: + +```html + + + + + + +

Very basic Noir app

+
+

Logs

+

Proof

+
+ + +``` + +## Some good old vanilla Javascript + +Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: + +```js +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} +``` + +We can manipulate our website with this little function, so we can see our website working. + +## Adding Noir + +If you come from the previous page, your folder structure should look like this: + +```tree +├── app.js +├── circuit +│ ├── Nargo.toml +│ ├── src +│ │ └── main.nr +│ └── target +│ └── circuit.json +├── index.html +├── package.json +└── vite.config.js +``` + +You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. + +## Importing our dependencies + +We're starting with the good stuff now. At the top of the new javascript file, import the packages: + +```ts +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: + +```ts +import circuit from './circuit/target/circuit.json'; +``` + +## Write code + +:::note + +We're gonna be adding code inside the `document.addEventListener...etc` block: + +```js +// forget stuff here +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); +// forget stuff here +``` + +::: + +Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: + +```ts +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +``` + +## Proving + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +const input = { x: 1, y: 2 }; +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateFinalProof(input); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. + +In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyFinalProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +By saving, your app will refresh and here's our complete Tiny Noir App! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/next-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/docs/versioned_sidebars/version-v..-sidebars.json b/docs/versioned_sidebars/version-v..-sidebars.json new file mode 100644 index 00000000000..b16f79cc176 --- /dev/null +++ b/docs/versioned_sidebars/version-v..-sidebars.json @@ -0,0 +1,83 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/flake.nix b/flake.nix index 6688ef6ea85..6a146becbb8 100644 --- a/flake.nix +++ b/flake.nix @@ -73,7 +73,7 @@ # Configuration shared between builds config = { # x-release-please-start-version - version = "0.21.0"; + version = "0.22.0"; # x-release-please-end src = pkgs.lib.cleanSourceWith { diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json index 45ec7f71c6b..3ae31d9834f 100644 --- a/tooling/noir_codegen/package.json +++ b/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.21.0", + "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index ddbbc1a0de2..d5ea4b4ad5d 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.21.0", + "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index db67d1b9715..c34b8dfc825 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.21.0", + "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index 8359a459963..51856cfe465 100644 --- a/tooling/noir_js_types/package.json +++ b/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.21.0", + "version": "0.22.0", "license": "(MIT OR Apache-2.0)", "files": [ "lib", diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index b59a077bd75..5b2cd344eab 100644 --- a/tooling/noirc_abi_wasm/package.json +++ b/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.21.0", + "version": "0.22.0", "license": "(MIT OR Apache-2.0)", "files": [ "nodejs", From 426fc34486d1472b326efac17c2a4a68ee1a62de Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 18 Dec 2023 19:13:55 +0000 Subject: [PATCH 071/137] chore: Rename `NpLanguage` to `ExpressionWidth` (#3834) # Description NpLanguage does not encapsulate what we want to describe here. We simply want to specify an expression width and a particular backend will need to decide as to what configuration their backend supports. To elaborate, imagine a new np language came out which was popular; before this PR, we may need to add in another variant. However, with this change, the new backend will just target whatever width makes sense for this new proving system. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acvm/src/compiler/mod.rs | 9 ++++-- .../acvm/src/compiler/transformers/csat.rs | 2 +- .../acvm/src/compiler/transformers/mod.rs | 17 ++++++----- acvm-repo/acvm/src/lib.rs | 16 ++++++---- compiler/wasm/src/compile.rs | 8 ++--- compiler/wasm/src/compile_new.rs | 4 +-- tooling/backend_interface/src/cli/info.rs | 18 +++++------ tooling/backend_interface/src/proof_system.rs | 18 ++++++----- tooling/lsp/src/requests/profile_run.rs | 6 ++-- tooling/nargo/src/ops/compile.rs | 16 +++++----- tooling/nargo/src/ops/optimize.rs | 17 +++++++---- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 10 +++---- tooling/nargo_cli/src/cli/compile_cmd.rs | 24 +++++++-------- tooling/nargo_cli/src/cli/debug_cmd.rs | 4 +-- tooling/nargo_cli/src/cli/execute_cmd.rs | 4 +-- tooling/nargo_cli/src/cli/info_cmd.rs | 30 +++++++++---------- tooling/nargo_cli/src/cli/prove_cmd.rs | 5 ++-- tooling/nargo_cli/src/cli/verify_cmd.rs | 5 ++-- 18 files changed, 118 insertions(+), 95 deletions(-) diff --git a/acvm-repo/acvm/src/compiler/mod.rs b/acvm-repo/acvm/src/compiler/mod.rs index 1a73f841f3d..ccb043914d6 100644 --- a/acvm-repo/acvm/src/compiler/mod.rs +++ b/acvm-repo/acvm/src/compiler/mod.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use acir::circuit::{Circuit, OpcodeLocation}; -use crate::Language; +use crate::ExpressionWidth; // The various passes that we can use over ACIR mod optimizers; @@ -69,11 +69,14 @@ fn transform_assert_messages( } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn compile(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) { +pub fn compile( + acir: Circuit, + expression_width: ExpressionWidth, +) -> (Circuit, AcirTransformationMap) { let (acir, acir_opcode_positions) = optimize_internal(acir); let (mut acir, acir_opcode_positions) = - transform_internal(acir, np_language, acir_opcode_positions); + transform_internal(acir, expression_width, acir_opcode_positions); let transformation_map = AcirTransformationMap::new(acir_opcode_positions); diff --git a/acvm-repo/acvm/src/compiler/transformers/csat.rs b/acvm-repo/acvm/src/compiler/transformers/csat.rs index 9f89ac4671a..0d1ab87aae5 100644 --- a/acvm-repo/acvm/src/compiler/transformers/csat.rs +++ b/acvm-repo/acvm/src/compiler/transformers/csat.rs @@ -9,7 +9,7 @@ use indexmap::IndexMap; /// A transformer which processes any [`Expression`]s to break them up such that they /// fit within the [`ProofSystemCompiler`][crate::ProofSystemCompiler]'s width. /// -/// This transformer is only used when targetting the [`PLONKCSat`][crate::Language::PLONKCSat] language. +/// This transformer is only used when targeting the [`Bounded`][crate::ExpressionWidth::Bounded] configuration. /// /// This is done by creating intermediate variables to hold partial calculations and then combining them /// to calculate the original expression. diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index fc406ba2b54..2a3e28c536a 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -5,7 +5,7 @@ use acir::{ }; use indexmap::IndexMap; -use crate::Language; +use crate::ExpressionWidth; mod csat; mod r1cs; @@ -16,13 +16,16 @@ pub(crate) use r1cs::R1CSTransformer; use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn transform(acir: Circuit, np_language: Language) -> (Circuit, AcirTransformationMap) { +pub fn transform( + acir: Circuit, + expression_width: ExpressionWidth, +) -> (Circuit, AcirTransformationMap) { // Track original acir opcode positions throughout the transformation passes of the compilation // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) let acir_opcode_positions = acir.opcodes.iter().enumerate().map(|(i, _)| i).collect(); let (mut acir, acir_opcode_positions) = - transform_internal(acir, np_language, acir_opcode_positions); + transform_internal(acir, expression_width, acir_opcode_positions); let transformation_map = AcirTransformationMap::new(acir_opcode_positions); @@ -36,17 +39,17 @@ pub fn transform(acir: Circuit, np_language: Language) -> (Circuit, AcirTransfor /// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations. pub(super) fn transform_internal( acir: Circuit, - np_language: Language, + expression_width: ExpressionWidth, acir_opcode_positions: Vec, ) -> (Circuit, Vec) { log::trace!("Start circuit transformation"); - let mut transformer = match &np_language { - crate::Language::R1CS => { + let mut transformer = match &expression_width { + crate::ExpressionWidth::Unbounded => { let transformer = R1CSTransformer::new(acir); return (transformer.transform(), acir_opcode_positions); } - crate::Language::PLONKCSat { width } => { + crate::ExpressionWidth::Bounded { width } => { let mut csat = CSatTransformer::new(*width); for value in acir.circuit_arguments() { csat.mark_solvable(value); diff --git a/acvm-repo/acvm/src/lib.rs b/acvm-repo/acvm/src/lib.rs index 0ab037a2e4b..626bb2c9b91 100644 --- a/acvm-repo/acvm/src/lib.rs +++ b/acvm-repo/acvm/src/lib.rs @@ -18,10 +18,16 @@ pub use brillig_vm; // re-export blackbox solver pub use acvm_blackbox_solver as blackbox_solver; -/// Supported NP complete languages -/// This might need to be in ACIR instead +/// Specifies the maximum width of the expressions which will be constrained. +/// +/// Unbounded Expressions are useful if you are eventually going to pass the ACIR +/// into a proving system which supports R1CS. +/// +/// Bounded Expressions are useful if you are eventually going to pass the ACIR +/// into a proving system which supports PLONK, where arithmetic expressions have a +/// finite fan-in. #[derive(Debug, Clone, Copy)] -pub enum Language { - R1CS, - PLONKCSat { width: usize }, +pub enum ExpressionWidth { + Unbounded, + Bounded { width: usize }, } diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 8685d6093e6..4012effd947 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -178,8 +178,8 @@ pub fn compile( let compile_options = CompileOptions::default(); - // For now we default to plonk width = 3, though we can add it as a parameter - let np_language = acvm::Language::PLONKCSat { width: 3 }; + // For now we default to a bounded width of 3, though we can add it as a parameter + let expression_width = acvm::ExpressionWidth::Bounded { width: 3 }; if contracts.unwrap_or_default() { let compiled_contract = compile_contract(&mut context, crate_id, &compile_options) @@ -192,7 +192,7 @@ pub fn compile( })? .0; - let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language); + let optimized_contract = nargo::ops::optimize_contract(compiled_contract, expression_width); let compile_output = preprocess_contract(optimized_contract); Ok(JsCompileResult::new(compile_output)) @@ -207,7 +207,7 @@ pub fn compile( })? .0; - let optimized_program = nargo::ops::optimize_program(compiled_program, np_language); + let optimized_program = nargo::ops::optimize_program(compiled_program, expression_width); let compile_output = preprocess_program(optimized_program); Ok(JsCompileResult::new(compile_output)) diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs index 2e80fa1c1e4..cd09d0fcc49 100644 --- a/compiler/wasm/src/compile_new.rs +++ b/compiler/wasm/src/compile_new.rs @@ -89,7 +89,7 @@ impl CompilerContext { program_width: usize, ) -> Result { let compile_options = CompileOptions::default(); - let np_language = acvm::Language::PLONKCSat { width: program_width }; + let np_language = acvm::ExpressionWidth::Bounded { width: program_width }; let root_crate_id = *self.context.root_crate_id(); @@ -115,7 +115,7 @@ impl CompilerContext { program_width: usize, ) -> Result { let compile_options = CompileOptions::default(); - let np_language = acvm::Language::PLONKCSat { width: program_width }; + let np_language = acvm::ExpressionWidth::Bounded { width: program_width }; let root_crate_id = *self.context.root_crate_id(); let compiled_contract = diff --git a/tooling/backend_interface/src/cli/info.rs b/tooling/backend_interface/src/cli/info.rs index 1aa2e640b15..81b811f0e32 100644 --- a/tooling/backend_interface/src/cli/info.rs +++ b/tooling/backend_interface/src/cli/info.rs @@ -1,4 +1,4 @@ -use acvm::Language; +use acvm::ExpressionWidth; use serde::Deserialize; use std::path::{Path, PathBuf}; @@ -28,7 +28,7 @@ struct LanguageResponse { } impl InfoCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { + pub(crate) fn run(self, binary_path: &Path) -> Result { let mut command = std::process::Command::new(binary_path); command.arg("info").arg("-c").arg(self.crs_path).arg("-o").arg("-"); @@ -41,16 +41,16 @@ impl InfoCommand { let backend_info: InfoResponse = serde_json::from_slice(&output.stdout).expect("Backend should return valid json"); - let language: Language = match backend_info.language.name.as_str() { + let expression_width: ExpressionWidth = match backend_info.language.name.as_str() { "PLONK-CSAT" => { let width = backend_info.language.width.unwrap(); - Language::PLONKCSat { width } + ExpressionWidth::Bounded { width } } - "R1CS" => Language::R1CS, - _ => panic!("Unknown langauge"), + "R1CS" => ExpressionWidth::Unbounded, + _ => panic!("Unknown Expression width configuration"), }; - Ok(language) + Ok(expression_width) } } @@ -59,9 +59,9 @@ fn info_command() -> Result<(), BackendError> { let backend = crate::get_mock_backend()?; let crs_path = backend.backend_directory(); - let language = InfoCommand { crs_path }.run(backend.binary_path())?; + let expression_width = InfoCommand { crs_path }.run(backend.binary_path())?; - assert!(matches!(language, Language::PLONKCSat { width: 3 })); + assert!(matches!(expression_width, ExpressionWidth::Bounded { width: 3 })); Ok(()) } diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index 1de4b352bf7..01842a81da9 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -3,8 +3,8 @@ use std::io::Write; use std::path::Path; use acvm::acir::{circuit::Circuit, native_types::WitnessMap}; +use acvm::ExpressionWidth; use acvm::FieldElement; -use acvm::Language; use tempfile::tempdir; use crate::cli::{ @@ -30,20 +30,22 @@ impl Backend { .run(binary_path) } - pub fn get_backend_info(&self) -> Result { + pub fn get_backend_info(&self) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; InfoCommand { crs_path: self.crs_directory() }.run(binary_path) } - /// If we cannot get a valid backend, returns Plonk with width 3 + /// If we cannot get a valid backend, returns `ExpressionWidth::Bound { width: 3 }`` /// The function also prints a message saying we could not find a backend - pub fn get_backend_info_or_default(&self) -> Language { - if let Ok(language) = self.get_backend_info() { - language + pub fn get_backend_info_or_default(&self) -> ExpressionWidth { + if let Ok(expression_width) = self.get_backend_info() { + expression_width } else { - log::warn!("No valid backend found, defaulting to Plonk with width 3"); - Language::PLONKCSat { width: 3 } + log::warn!( + "No valid backend found, ExpressionWidth defaulting to Bounded with a width of 3" + ); + ExpressionWidth::Bounded { width: 3 } } } diff --git a/tooling/lsp/src/requests/profile_run.rs b/tooling/lsp/src/requests/profile_run.rs index 231003e1e83..4c4d7f11fde 100644 --- a/tooling/lsp/src/requests/profile_run.rs +++ b/tooling/lsp/src/requests/profile_run.rs @@ -3,7 +3,7 @@ use std::{ future::{self, Future}, }; -use acvm::Language; +use acvm::ExpressionWidth; use async_lsp::{ErrorCode, ResponseError}; use nargo::artifacts::debug::DebugArtifact; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -57,13 +57,13 @@ fn on_profile_run_request_inner( .cloned() .partition(|package| package.is_binary()); - let np_language = Language::PLONKCSat { width: 3 }; + let expression_width = ExpressionWidth::Bounded { width: 3 }; let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace( &workspace, &binary_packages, &contract_packages, - np_language, + expression_width, &CompileOptions::default(), ) .map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?; diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index c23ab242ae4..1a9e0a6c115 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -1,4 +1,4 @@ -use acvm::Language; +use acvm::ExpressionWidth; use fm::FileManager; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; @@ -17,18 +17,18 @@ pub fn compile_workspace( workspace: &Workspace, binary_packages: &[Package], contract_packages: &[Package], - np_language: Language, + expression_width: ExpressionWidth, compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CompileError> { // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() - .map(|package| compile_program(workspace, package, compile_options, np_language)) + .map(|package| compile_program(workspace, package, compile_options, expression_width)) .collect(); let contract_results: Vec<(FileManager, CompilationResult)> = contract_packages .par_iter() - .map(|package| compile_contract(package, compile_options, np_language)) + .map(|package| compile_contract(package, compile_options, expression_width)) .collect(); // Report any warnings/errors which were encountered during compilation. @@ -62,7 +62,7 @@ pub fn compile_program( workspace: &Workspace, package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); @@ -79,7 +79,7 @@ pub fn compile_program( }; // Apply backend specific optimizations. - let optimized_program = crate::ops::optimize_program(program, np_language); + let optimized_program = crate::ops::optimize_program(program, expression_width); (context.file_manager, Ok((optimized_program, warnings))) } @@ -87,7 +87,7 @@ pub fn compile_program( fn compile_contract( package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = @@ -98,7 +98,7 @@ fn compile_contract( } }; - let optimized_contract = crate::ops::optimize_contract(contract, np_language); + let optimized_contract = crate::ops::optimize_contract(contract, expression_width); (context.file_manager, Ok((optimized_contract, warnings))) } diff --git a/tooling/nargo/src/ops/optimize.rs b/tooling/nargo/src/ops/optimize.rs index 6f96a49d04f..d3a36dd65ac 100644 --- a/tooling/nargo/src/ops/optimize.rs +++ b/tooling/nargo/src/ops/optimize.rs @@ -1,19 +1,26 @@ -use acvm::Language; +use acvm::ExpressionWidth; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -pub fn optimize_program(mut program: CompiledProgram, np_language: Language) -> CompiledProgram { - let (optimized_circuit, location_map) = acvm::compiler::compile(program.circuit, np_language); +pub fn optimize_program( + mut program: CompiledProgram, + expression_width: ExpressionWidth, +) -> CompiledProgram { + let (optimized_circuit, location_map) = + acvm::compiler::compile(program.circuit, expression_width); program.circuit = optimized_circuit; program.debug.update_acir(location_map); program } -pub fn optimize_contract(contract: CompiledContract, np_language: Language) -> CompiledContract { +pub fn optimize_contract( + contract: CompiledContract, + expression_width: ExpressionWidth, +) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode, np_language); + acvm::compiler::compile(func.bytecode, expression_width); func.bytecode = optimized_bytecode; func.debug.update_acir(location_map); func diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index dfda25043f3..b72ce01e1a9 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -6,7 +6,7 @@ use super::{ use crate::backends::Backend; use crate::errors::CliError; -use acvm::Language; +use acvm::ExpressionWidth; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use clap::Args; use nargo::package::Package; @@ -45,14 +45,14 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let np_language = backend.get_backend_info()?; + let expression_width = backend.get_backend_info()?; for package in &workspace { let smart_contract_string = smart_contract_for_package( &workspace, backend, package, &args.compile_options, - np_language, + expression_width, )?; let contract_dir = workspace.contracts_directory_path(package); @@ -71,9 +71,9 @@ fn smart_contract_for_package( backend: &Backend, package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> Result { - let program = compile_bin_package(workspace, package, compile_options, np_language)?; + let program = compile_bin_package(workspace, package, compile_options, expression_width)?; let mut smart_contract_string = backend.eth_contract(&program.circuit)?; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index b686adf6f50..5ee053c5088 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,6 +1,6 @@ use std::path::Path; -use acvm::Language; +use acvm::ExpressionWidth; use fm::FileManager; use iter_extended::vecmap; use nargo::artifacts::contract::PreprocessedContract; @@ -67,12 +67,12 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let np_language = backend.get_backend_info_or_default(); + let expression_width = backend.get_backend_info_or_default(); let (_, compiled_contracts) = compile_workspace( &workspace, &binary_packages, &contract_packages, - np_language, + expression_width, &args.compile_options, )?; @@ -88,18 +88,18 @@ pub(super) fn compile_workspace( workspace: &Workspace, binary_packages: &[Package], contract_packages: &[Package], - np_language: Language, + expression_width: ExpressionWidth, compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CliError> { // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() - .map(|package| compile_program(workspace, package, compile_options, np_language)) + .map(|package| compile_program(workspace, package, compile_options, expression_width)) .collect(); let contract_results: Vec<(FileManager, CompilationResult)> = contract_packages .par_iter() - .map(|package| compile_contract(package, compile_options, np_language)) + .map(|package| compile_contract(package, compile_options, expression_width)) .collect(); // Report any warnings/errors which were encountered during compilation. @@ -133,14 +133,14 @@ pub(crate) fn compile_bin_package( workspace: &Workspace, package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> Result { if package.is_library() { return Err(CompileError::LibraryCrate(package.name.clone()).into()); } let (file_manager, compilation_result) = - compile_program(workspace, package, compile_options, np_language); + compile_program(workspace, package, compile_options, expression_width); let program = report_errors( compilation_result, @@ -156,7 +156,7 @@ fn compile_program( workspace: &Workspace, package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); @@ -196,7 +196,7 @@ fn compile_program( }; // Apply backend specific optimizations. - let optimized_program = nargo::ops::optimize_program(program, np_language); + let optimized_program = nargo::ops::optimize_program(program, expression_width); let only_acir = compile_options.only_acir; save_program(optimized_program.clone(), package, &workspace.target_directory_path(), only_acir); @@ -206,7 +206,7 @@ fn compile_program( fn compile_contract( package: &Package, compile_options: &CompileOptions, - np_language: Language, + expression_width: ExpressionWidth, ) -> (FileManager, CompilationResult) { let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = @@ -217,7 +217,7 @@ fn compile_contract( } }; - let optimized_contract = nargo::ops::optimize_contract(contract, np_language); + let optimized_contract = nargo::ops::optimize_contract(contract, expression_width); (context.file_manager, Ok((optimized_contract, warnings))) } diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index ba07b3b096c..6eab626a08d 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -49,7 +49,7 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; let target_dir = &workspace.target_directory_path(); - let np_language = backend.get_backend_info()?; + let expression_width = backend.get_backend_info()?; let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { println!( @@ -59,7 +59,7 @@ pub(crate) fn run( }; let compiled_program = - compile_bin_package(&workspace, package, &args.compile_options, np_language)?; + compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir) } diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index ac3d80fe1fe..10760f43a45 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -56,10 +56,10 @@ pub(crate) fn run( )?; let target_dir = &workspace.target_directory_path(); - let np_language = backend.get_backend_info_or_default(); + let expression_width = backend.get_backend_info_or_default(); for package in &workspace { let compiled_program = - compile_bin_package(&workspace, package, &args.compile_options, np_language)?; + compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; let (return_value, solved_witness) = execute_program_and_decode(compiled_program, package, &args.prover_name)?; diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index 9c2f10aab80..e25051c1df7 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use acvm::Language; +use acvm::ExpressionWidth; use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; @@ -67,12 +67,12 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let np_language = backend.get_backend_info_or_default(); + let expression_width = backend.get_backend_info_or_default(); let (compiled_programs, compiled_contracts) = compile_workspace( &workspace, &binary_packages, &contract_packages, - np_language, + expression_width, &args.compile_options, )?; @@ -97,13 +97,13 @@ pub(crate) fn run( .into_par_iter() .zip(compiled_programs) .map(|(package, program)| { - count_opcodes_and_gates_in_program(backend, program, &package, np_language) + count_opcodes_and_gates_in_program(backend, program, &package, expression_width) }) .collect::>()?; let contract_info = compiled_contracts .into_par_iter() - .map(|contract| count_opcodes_and_gates_in_contract(backend, contract, np_language)) + .map(|contract| count_opcodes_and_gates_in_contract(backend, contract, expression_width)) .collect::>()?; let info_report = InfoReport { programs: program_info, contracts: contract_info }; @@ -114,7 +114,7 @@ pub(crate) fn run( } else { // Otherwise print human-readable table. if !info_report.programs.is_empty() { - let mut program_table = table!([Fm->"Package", Fm->"Language", Fm->"ACIR Opcodes", Fm->"Backend Circuit Size"]); + let mut program_table = table!([Fm->"Package", Fm->"Expression Width", Fm->"ACIR Opcodes", Fm->"Backend Circuit Size"]); for program in info_report.programs { program_table.add_row(program.into()); @@ -125,7 +125,7 @@ pub(crate) fn run( let mut contract_table = table!([ Fm->"Contract", Fm->"Function", - Fm->"Language", + Fm->"Expression Width", Fm->"ACIR Opcodes", Fm->"Backend Circuit Size" ]); @@ -202,7 +202,7 @@ struct InfoReport { struct ProgramInfo { name: String, #[serde(skip)] - language: Language, + expression_width: ExpressionWidth, acir_opcodes: usize, circuit_size: u32, } @@ -211,7 +211,7 @@ impl From for Row { fn from(program_info: ProgramInfo) -> Self { row![ Fm->format!("{}", program_info.name), - format!("{:?}", program_info.language), + format!("{:?}", program_info.expression_width), Fc->format!("{}", program_info.acir_opcodes), Fc->format!("{}", program_info.circuit_size), ] @@ -222,7 +222,7 @@ impl From for Row { struct ContractInfo { name: String, #[serde(skip)] - language: Language, + expression_width: ExpressionWidth, functions: Vec, } @@ -239,7 +239,7 @@ impl From for Vec { row![ Fm->format!("{}", contract_info.name), Fc->format!("{}", function.name), - format!("{:?}", contract_info.language), + format!("{:?}", contract_info.expression_width), Fc->format!("{}", function.acir_opcodes), Fc->format!("{}", function.circuit_size), ] @@ -251,11 +251,11 @@ fn count_opcodes_and_gates_in_program( backend: &Backend, compiled_program: CompiledProgram, package: &Package, - language: Language, + expression_width: ExpressionWidth, ) -> Result { Ok(ProgramInfo { name: package.name.to_string(), - language, + expression_width, acir_opcodes: compiled_program.circuit.opcodes.len(), circuit_size: backend.get_exact_circuit_size(&compiled_program.circuit)?, }) @@ -264,7 +264,7 @@ fn count_opcodes_and_gates_in_program( fn count_opcodes_and_gates_in_contract( backend: &Backend, contract: CompiledContract, - language: Language, + expression_width: ExpressionWidth, ) -> Result { let functions = contract .functions @@ -278,5 +278,5 @@ fn count_opcodes_and_gates_in_contract( }) .collect::>()?; - Ok(ContractInfo { name: contract.name, language, functions }) + Ok(ContractInfo { name: contract.name, expression_width, functions }) } diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index da8812fc93b..cb1751e7cef 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -57,9 +57,10 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let np_language = backend.get_backend_info()?; + let expression_width = backend.get_backend_info()?; for package in &workspace { - let program = compile_bin_package(&workspace, package, &args.compile_options, np_language)?; + let program = + compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; prove_package( backend, diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 53b046a5b76..9659286b5ab 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -48,9 +48,10 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let np_language = backend.get_backend_info()?; + let expression_width = backend.get_backend_info()?; for package in &workspace { - let program = compile_bin_package(&workspace, package, &args.compile_options, np_language)?; + let program = + compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; verify_package(backend, &workspace, package, program, &args.verifier_name)?; } From fa639f0815441b56f04fbfbc2c07b159c3ee222d Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 18 Dec 2023 23:56:44 +0000 Subject: [PATCH 072/137] chore: clippy fix (#3860) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 60498b22c96..cd0c34f7e09 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -21,7 +21,6 @@ mod test { use crate::hir::Context; use crate::node_interner::{NodeInterner, StmtId}; - use crate::graph::CrateGraph; use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir_def::expr::HirExpression; use crate::hir_def::stmt::HirStatement; From 698d5fda686b3252cedd4c7af6ec1edc2e2d2938 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Tue, 19 Dec 2023 01:12:40 +0100 Subject: [PATCH 073/137] chore: Remove docker cargo test in favor of new flow (#3861) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/test-cargo.yml | 51 -------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .github/workflows/test-cargo.yml diff --git a/.github/workflows/test-cargo.yml b/.github/workflows/test-cargo.yml deleted file mode 100644 index 8d414daa75b..00000000000 --- a/.github/workflows/test-cargo.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Test cargo - -on: - pull_request: - merge_group: - push: - branches: - - master - -# This will cancel previous runs when a branch or PR is updated -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - build: - name: Test cargo - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Get current date - id: date - run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE - - name: prepare docker images tags - id: prep - run: | - REGISTRY="ghcr.io" - IMG="${REGISTRY}/${{ github.repository }}" - IMAGE=$(echo "$IMG" | tr '[:upper:]' '[:lower:]') - TAGS="${IMAGE}:${{ github.sha }}" - TAGS="${TAGS},${IMAGE}:latest,${IMAGE}:v${{ steps.date.outputs.date }}" - echo ::set-output name=tags::${TAGS} - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Test cargo - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile.ci - tags: ${{ steps.prep.outputs.tags }} - target: test-cargo - cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file From 34fd978d206789a9e9f5167bfd690a34386834d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Tue, 19 Dec 2023 09:31:12 +0000 Subject: [PATCH 074/137] fix: Acir gen doesn't panic on unsupported BB function (#3866) # Description ## Problem\* Resolves #3865 ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 1f85145260d..e039a7793c0 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1605,28 +1605,40 @@ fn execute_brillig( _signature: &[u8], _message: &[u8], ) -> Result { - unimplemented!("SchnorrVerify is not supported") + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::SchnorrVerify, + "SchnorrVerify is not supported".to_string(), + )) } fn pedersen_commitment( &self, _inputs: &[FieldElement], _domain_separator: u32, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - unimplemented!("PedersenCommitment is not supported") + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::PedersenCommitment, + "PedersenCommitment is not supported".to_string(), + )) } fn pedersen_hash( &self, _inputs: &[FieldElement], _domain_separator: u32, ) -> Result { - unimplemented!("PedersenHash is not supported") + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::PedersenHash, + "PedersenHash is not supported".to_string(), + )) } fn fixed_base_scalar_mul( &self, _low: &FieldElement, _high: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - unimplemented!("FixedBaseScalarMul is not supported") + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "FixedBaseScalarMul is not supported".to_string(), + )) } } From decbd0f0c019844cd2b235e7804d2f6ba7b23897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Tue, 19 Dec 2023 09:36:35 +0000 Subject: [PATCH 075/137] fix: Don't fail if no tests and the user didn't provide a pattern (#3864) # Description Workspaces typically contain some crates with no tests (especially binary crates that are only entry points). Running tests without specifying a test name on a crate won't fail with this PR if that crate has no tests. ## Problem\* Possible approach to #3863 ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/nargo_cli/src/cli/test_cmd.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 43cfecd17e9..fcad4d4ee9f 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -98,18 +98,21 @@ fn run_tests( let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, fn_name); let count_all = test_functions.len(); if count_all == 0 { - return match &fn_name { - FunctionNameMatch::Anything => { - Err(CliError::Generic(format!("[{}] Found 0 tests.", package.name))) + match &fn_name { + FunctionNameMatch::Exact(pattern) => { + return Err(CliError::Generic(format!( + "[{}] Found 0 tests matching input '{pattern}'.", + package.name + ))) } - FunctionNameMatch::Exact(pattern) => Err(CliError::Generic(format!( - "[{}] Found 0 tests matching input '{pattern}'.", - package.name - ))), - FunctionNameMatch::Contains(pattern) => Err(CliError::Generic(format!( - "[{}] Found 0 tests containing '{pattern}'.", - package.name - ))), + FunctionNameMatch::Contains(pattern) => { + return Err(CliError::Generic(format!( + "[{}] Found 0 tests containing '{pattern}'.", + package.name + ))) + } + // If we are running all tests in a crate, having none is not an error + FunctionNameMatch::Anything => {} }; } From d229963bc3b83a86b36e5d71a7153da694101325 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:10:18 +0000 Subject: [PATCH 076/137] chore: correct MSRV listed in `Cargo.toml` (#3872) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index aaf060552e7..259eec330a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ version = "0.22.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" -rust-version = "1.66" +rust-version = "1.71.1" license = "MIT OR Apache-2.0" repository = "https://github.com/noir-lang/noir/" From a40269a4ea606e869fa06704790c56e359e37f8e Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:10:45 +0000 Subject: [PATCH 077/137] chore: fix docs for 0.22.0 version (#3871) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/index.md | 3 +-- .../explainers/explainer-recursion.md | 0 .../explanations/noir/traits.md | 0 .../explanations/standard_library/traits.md | 0 .../getting_started/_category_.json | 0 .../getting_started/create_a_project.md | 0 .../getting_started/installation/_category_.json | 0 .../getting_started/installation/index.md | 0 .../getting_started/installation/other_install_methods.md | 0 .../getting_started/project_breakdown.md | 0 .../getting_started/tooling/_category_.json | 0 .../getting_started/tooling/index.md | 0 .../getting_started/tooling/language_server.md | 0 .../getting_started/tooling/testing.md | 0 .../{version-v.. => version-v0.22.0}/how_to/_category_.json | 0 .../how_to/how-to-recursion.md | 0 .../{version-v.. => version-v0.22.0}/how_to/merkle-proof.mdx | 0 .../how_to/solidity_verifier.md | 0 docs/versioned_docs/{version-v.. => version-v0.22.0}/index.md | 3 +-- .../{version-v.. => version-v0.22.0}/migration_notes.md | 0 .../noir/modules_packages_crates/_category_.json | 0 .../noir/modules_packages_crates/crates_and_packages.md | 0 .../noir/modules_packages_crates/dependencies.md | 0 .../noir/modules_packages_crates/modules.md | 0 .../noir/modules_packages_crates/workspaces.md | 0 .../noir/standard_library/_category_.json | 0 .../noir/standard_library/black_box_fns.md | 0 .../standard_library/cryptographic_primitives/_category_.json | 0 .../standard_library/cryptographic_primitives/ec_primitives.md | 0 .../cryptographic_primitives/ecdsa_sig_verification.mdx | 0 .../noir/standard_library/cryptographic_primitives/eddsa.mdx | 0 .../noir/standard_library/cryptographic_primitives/hashes.mdx | 0 .../noir/standard_library/cryptographic_primitives/index.md | 0 .../noir/standard_library/cryptographic_primitives/scalar.mdx | 0 .../noir/standard_library/cryptographic_primitives/schnorr.mdx | 0 .../noir/standard_library/logging.md | 0 .../noir/standard_library/merkle_trees.md | 0 .../noir/standard_library/options.md | 0 .../noir/standard_library/recursion.md | 0 .../noir/standard_library/zeroed.md | 0 .../noir/syntax/_category_.json | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/assert.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/comments.md | 0 .../noir/syntax/control_flow.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/data_bus.md | 0 .../noir/syntax/data_types/_category_.json | 0 .../noir/syntax/data_types/arrays.md | 0 .../noir/syntax/data_types/booleans.md | 0 .../noir/syntax/data_types/fields.md | 0 .../noir/syntax/data_types/function_types.md | 0 .../noir/syntax/data_types/index.md | 0 .../noir/syntax/data_types/integers.md | 0 .../noir/syntax/data_types/references.md | 0 .../noir/syntax/data_types/slices.mdx | 0 .../noir/syntax/data_types/strings.md | 0 .../noir/syntax/data_types/structs.md | 0 .../noir/syntax/data_types/tuples.md | 0 .../noir/syntax/data_types/vectors.mdx | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/distinct.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/functions.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/generics.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/lambdas.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/mutability.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/ops.md | 0 .../{version-v.. => version-v0.22.0}/noir/syntax/shadowing.md | 0 .../noir/syntax/unconstrained.md | 0 .../reference/NoirJS/backend_barretenberg/.nojekyll | 0 .../NoirJS/backend_barretenberg/classes/BarretenbergBackend.md | 0 .../reference/NoirJS/backend_barretenberg/index.md | 0 .../NoirJS/backend_barretenberg/interfaces/Backend.md | 0 .../NoirJS/backend_barretenberg/type-aliases/BackendOptions.md | 0 .../backend_barretenberg/type-aliases/CompiledCircuit.md | 0 .../NoirJS/backend_barretenberg/type-aliases/ProofData.md | 0 .../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs | 0 .../reference/NoirJS/noir_js/.nojekyll | 0 .../reference/NoirJS/noir_js/classes/Noir.md | 0 .../reference/NoirJS/noir_js/functions/and.md | 0 .../reference/NoirJS/noir_js/functions/blake2s256.md | 0 .../NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md | 0 .../NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md | 0 .../reference/NoirJS/noir_js/functions/keccak256.md | 0 .../reference/NoirJS/noir_js/functions/sha256.md | 0 .../reference/NoirJS/noir_js/functions/xor.md | 0 .../reference/NoirJS/noir_js/index.md | 0 .../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md | 0 .../NoirJS/noir_js/type-aliases/ForeignCallHandler.md | 0 .../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md | 0 .../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md | 0 .../reference/NoirJS/noir_js/type-aliases/InputMap.md | 0 .../reference/NoirJS/noir_js/type-aliases/ProofData.md | 0 .../reference/NoirJS/noir_js/type-aliases/WitnessMap.md | 0 .../reference/NoirJS/noir_js/typedoc-sidebar.cjs | 0 .../{version-v.. => version-v0.22.0}/reference/_category_.json | 0 .../reference/nargo_commands.md | 0 .../{version-v.. => version-v0.22.0}/tutorials/noirjs_app.md | 0 95 files changed, 2 insertions(+), 4 deletions(-) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/explainers/explainer-recursion.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/explanations/noir/traits.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/explanations/standard_library/traits.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/create_a_project.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/installation/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/installation/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/installation/other_install_methods.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/project_breakdown.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/tooling/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/tooling/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/tooling/language_server.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/getting_started/tooling/testing.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/how_to/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/how_to/how-to-recursion.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/how_to/merkle-proof.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/how_to/solidity_verifier.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/index.md (98%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/migration_notes.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/modules_packages_crates/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/modules_packages_crates/crates_and_packages.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/modules_packages_crates/dependencies.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/modules_packages_crates/modules.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/modules_packages_crates/workspaces.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/black_box_fns.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/ec_primitives.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/eddsa.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/hashes.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/scalar.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/cryptographic_primitives/schnorr.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/logging.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/merkle_trees.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/options.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/recursion.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/standard_library/zeroed.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/assert.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/comments.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/control_flow.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_bus.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/arrays.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/booleans.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/fields.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/function_types.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/integers.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/references.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/slices.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/strings.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/structs.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/tuples.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/data_types/vectors.mdx (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/distinct.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/functions.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/generics.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/lambdas.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/mutability.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/ops.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/shadowing.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/noir/syntax/unconstrained.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/.nojekyll (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/interfaces/Backend.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/.nojekyll (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/classes/Noir.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/and.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/blake2s256.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/keccak256.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/sha256.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/functions/xor.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/index.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/InputMap.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/ProofData.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/type-aliases/WitnessMap.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/NoirJS/noir_js/typedoc-sidebar.cjs (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/_category_.json (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/reference/nargo_commands.md (100%) rename docs/versioned_docs/{version-v.. => version-v0.22.0}/tutorials/noirjs_app.md (100%) diff --git a/docs/docs/index.md b/docs/docs/index.md index 016832f9f5e..e1ec3362c1f 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -43,8 +43,7 @@ contracts efficiently. While the current alpha version offers this as a direct f to modularize this process for even greater ease of use. Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be -modularised in the future; however, as of the alpha, you can use the - command to create a verifier contract. +modularised in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. ### Protocol Developers diff --git a/docs/versioned_docs/version-v../explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md similarity index 100% rename from docs/versioned_docs/version-v../explainers/explainer-recursion.md rename to docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md diff --git a/docs/versioned_docs/version-v../explanations/noir/traits.md b/docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md similarity index 100% rename from docs/versioned_docs/version-v../explanations/noir/traits.md rename to docs/versioned_docs/version-v0.22.0/explanations/noir/traits.md diff --git a/docs/versioned_docs/version-v../explanations/standard_library/traits.md b/docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md similarity index 100% rename from docs/versioned_docs/version-v../explanations/standard_library/traits.md rename to docs/versioned_docs/version-v0.22.0/explanations/standard_library/traits.md diff --git a/docs/versioned_docs/version-v../getting_started/_category_.json b/docs/versioned_docs/version-v0.22.0/getting_started/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../getting_started/_category_.json rename to docs/versioned_docs/version-v0.22.0/getting_started/_category_.json diff --git a/docs/versioned_docs/version-v../getting_started/create_a_project.md b/docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/create_a_project.md rename to docs/versioned_docs/version-v0.22.0/getting_started/create_a_project.md diff --git a/docs/versioned_docs/version-v../getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.22.0/getting_started/installation/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../getting_started/installation/_category_.json rename to docs/versioned_docs/version-v0.22.0/getting_started/installation/_category_.json diff --git a/docs/versioned_docs/version-v../getting_started/installation/index.md b/docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/installation/index.md rename to docs/versioned_docs/version-v0.22.0/getting_started/installation/index.md diff --git a/docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/installation/other_install_methods.md rename to docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md diff --git a/docs/versioned_docs/version-v../getting_started/project_breakdown.md b/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/project_breakdown.md rename to docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md diff --git a/docs/versioned_docs/version-v../getting_started/tooling/_category_.json b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../getting_started/tooling/_category_.json rename to docs/versioned_docs/version-v0.22.0/getting_started/tooling/_category_.json diff --git a/docs/versioned_docs/version-v../getting_started/tooling/index.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/tooling/index.md rename to docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md diff --git a/docs/versioned_docs/version-v../getting_started/tooling/language_server.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/language_server.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/tooling/language_server.md rename to docs/versioned_docs/version-v0.22.0/getting_started/tooling/language_server.md diff --git a/docs/versioned_docs/version-v../getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md similarity index 100% rename from docs/versioned_docs/version-v../getting_started/tooling/testing.md rename to docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md diff --git a/docs/versioned_docs/version-v../how_to/_category_.json b/docs/versioned_docs/version-v0.22.0/how_to/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../how_to/_category_.json rename to docs/versioned_docs/version-v0.22.0/how_to/_category_.json diff --git a/docs/versioned_docs/version-v../how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md similarity index 100% rename from docs/versioned_docs/version-v../how_to/how-to-recursion.md rename to docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md diff --git a/docs/versioned_docs/version-v../how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx similarity index 100% rename from docs/versioned_docs/version-v../how_to/merkle-proof.mdx rename to docs/versioned_docs/version-v0.22.0/how_to/merkle-proof.mdx diff --git a/docs/versioned_docs/version-v../how_to/solidity_verifier.md b/docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-v../how_to/solidity_verifier.md rename to docs/versioned_docs/version-v0.22.0/how_to/solidity_verifier.md diff --git a/docs/versioned_docs/version-v../index.md b/docs/versioned_docs/version-v0.22.0/index.md similarity index 98% rename from docs/versioned_docs/version-v../index.md rename to docs/versioned_docs/version-v0.22.0/index.md index 016832f9f5e..e1ec3362c1f 100644 --- a/docs/versioned_docs/version-v../index.md +++ b/docs/versioned_docs/version-v0.22.0/index.md @@ -43,8 +43,7 @@ contracts efficiently. While the current alpha version offers this as a direct f to modularize this process for even greater ease of use. Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be -modularised in the future; however, as of the alpha, you can use the - command to create a verifier contract. +modularised in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. ### Protocol Developers diff --git a/docs/versioned_docs/version-v../migration_notes.md b/docs/versioned_docs/version-v0.22.0/migration_notes.md similarity index 100% rename from docs/versioned_docs/version-v../migration_notes.md rename to docs/versioned_docs/version-v0.22.0/migration_notes.md diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../noir/modules_packages_crates/_category_.json rename to docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/_category_.json diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-v../noir/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md similarity index 100% rename from docs/versioned_docs/version-v../noir/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-v../noir/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md similarity index 100% rename from docs/versioned_docs/version-v../noir/modules_packages_crates/workspaces.md rename to docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.22.0/noir/standard_library/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/_category_.json rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/_category_.json diff --git a/docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/black_box_fns.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/_category_.json rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/_category_.json diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ec_primitives.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ec_primitives.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/eddsa.mdx rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/eddsa.mdx diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/hashes.mdx rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/hashes.mdx diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/index.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/index.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/index.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/scalar.mdx rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/scalar.mdx diff --git a/docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/cryptographic_primitives/schnorr.mdx rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/cryptographic_primitives/schnorr.mdx diff --git a/docs/versioned_docs/version-v../noir/standard_library/logging.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/logging.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/options.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/options.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/options.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/recursion.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md diff --git a/docs/versioned_docs/version-v../noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-v../noir/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.22.0/noir/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v../noir/syntax/_category_.json b/docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/_category_.json rename to docs/versioned_docs/version-v0.22.0/noir/syntax/_category_.json diff --git a/docs/versioned_docs/version-v../noir/syntax/assert.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/assert.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/assert.md diff --git a/docs/versioned_docs/version-v../noir/syntax/comments.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/comments.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/comments.md diff --git a/docs/versioned_docs/version-v../noir/syntax/control_flow.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/control_flow.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/control_flow.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_bus.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_bus.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_bus.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/_category_.json rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/_category_.json diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/arrays.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/booleans.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/fields.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/fields.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/fields.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/function_types.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/index.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/index.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/integers.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/integers.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/integers.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/references.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/references.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/references.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/references.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/slices.mdx rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/slices.mdx diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/strings.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/strings.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/structs.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/structs.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/structs.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/structs.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/tuples.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/tuples.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/tuples.md diff --git a/docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/data_types/vectors.mdx rename to docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/vectors.mdx diff --git a/docs/versioned_docs/version-v../noir/syntax/distinct.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/distinct.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/distinct.md diff --git a/docs/versioned_docs/version-v../noir/syntax/functions.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/functions.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/functions.md diff --git a/docs/versioned_docs/version-v../noir/syntax/generics.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/generics.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/generics.md diff --git a/docs/versioned_docs/version-v../noir/syntax/lambdas.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/lambdas.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/lambdas.md diff --git a/docs/versioned_docs/version-v../noir/syntax/mutability.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/mutability.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md diff --git a/docs/versioned_docs/version-v../noir/syntax/ops.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/ops.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md diff --git a/docs/versioned_docs/version-v../noir/syntax/shadowing.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/shadowing.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/shadowing.md diff --git a/docs/versioned_docs/version-v../noir/syntax/unconstrained.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md similarity index 100% rename from docs/versioned_docs/version-v../noir/syntax/unconstrained.md rename to docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/.nojekyll rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/.nojekyll diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/index.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/index.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/interfaces/Backend.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/.nojekyll rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/.nojekyll diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/classes/Noir.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/classes/Noir.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/and.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/and.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/blake2s256.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/blake2s256.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/keccak256.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/keccak256.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/sha256.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/sha256.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/functions/xor.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/functions/xor.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/index.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/index.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/InputMap.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/InputMap.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/ProofData.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/ProofData.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/type-aliases/WitnessMap.md rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md diff --git a/docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs similarity index 100% rename from docs/versioned_docs/version-v../reference/NoirJS/noir_js/typedoc-sidebar.cjs rename to docs/versioned_docs/version-v0.22.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs diff --git a/docs/versioned_docs/version-v../reference/_category_.json b/docs/versioned_docs/version-v0.22.0/reference/_category_.json similarity index 100% rename from docs/versioned_docs/version-v../reference/_category_.json rename to docs/versioned_docs/version-v0.22.0/reference/_category_.json diff --git a/docs/versioned_docs/version-v../reference/nargo_commands.md b/docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md similarity index 100% rename from docs/versioned_docs/version-v../reference/nargo_commands.md rename to docs/versioned_docs/version-v0.22.0/reference/nargo_commands.md diff --git a/docs/versioned_docs/version-v../tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md similarity index 100% rename from docs/versioned_docs/version-v../tutorials/noirjs_app.md rename to docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md From 9b713f8cf599df262a12ec1098136c50b2b46766 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:11:59 +0000 Subject: [PATCH 078/137] fix: allow abi encoding arrays of structs from JS (#3867) # Description ## Problem\* Resolves ## Summary\* We currently do not allow arrays of structs when abi encoding from JS due to the `InputValue` type being too restrictive. This PR loosens this and adds a test to demonstrate how this is used. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/noirc_abi_wasm/src/lib.rs | 2 +- .../test/browser/structs.test.ts | 26 ++++++ .../noirc_abi_wasm/test/node/structs.test.ts | 22 ++++++ tooling/noirc_abi_wasm/test/shared/structs.ts | 79 +++++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 tooling/noirc_abi_wasm/test/browser/structs.test.ts create mode 100644 tooling/noirc_abi_wasm/test/node/structs.test.ts create mode 100644 tooling/noirc_abi_wasm/test/shared/structs.ts diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs index fb4c295b8c8..281ec712c39 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -27,7 +27,7 @@ use js_witness_map::JsWitnessMap; #[wasm_bindgen(typescript_custom_section)] const INPUT_MAP: &'static str = r#" export type Field = string | number | boolean; -export type InputValue = Field | Field[] | InputMap; +export type InputValue = Field | Field[] | InputMap | InputMap[]; export type InputMap = { [key: string]: InputValue }; "#; diff --git a/tooling/noirc_abi_wasm/test/browser/structs.test.ts b/tooling/noirc_abi_wasm/test/browser/structs.test.ts new file mode 100644 index 00000000000..84352d986ab --- /dev/null +++ b/tooling/noirc_abi_wasm/test/browser/structs.test.ts @@ -0,0 +1,26 @@ +import { expect } from '@esm-bundle/chai'; +import initNoirAbi, { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi'; +import { MyNestedStruct, MyStruct } from '../shared/structs'; +import { DecodedInputs } from '../types'; + +beforeEach(async () => { + await initNoirAbi(); +}); + +it('correctly handles struct inputs', async () => { + const { abi, inputs } = await import('../shared/structs'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const struct_arg: MyStruct = inputs.struct_arg as MyStruct; + const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[]; + const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct; + + expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo)); + expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo)); + expect(decoded_inputs.return_value).to.be.null; +}); diff --git a/tooling/noirc_abi_wasm/test/node/structs.test.ts b/tooling/noirc_abi_wasm/test/node/structs.test.ts new file mode 100644 index 00000000000..a7d104b46d3 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/node/structs.test.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi'; +import { MyNestedStruct, MyStruct } from '../shared/structs'; +import { DecodedInputs } from '../types'; + +it('correctly handles struct inputs', async () => { + const { abi, inputs } = await import('../shared/structs'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const struct_arg: MyStruct = inputs.struct_arg as MyStruct; + const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[]; + const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct; + + expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo)); + expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo)); + expect(decoded_inputs.return_value).to.be.null; +}); diff --git a/tooling/noirc_abi_wasm/test/shared/structs.ts b/tooling/noirc_abi_wasm/test/shared/structs.ts new file mode 100644 index 00000000000..6614f8f278e --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/structs.ts @@ -0,0 +1,79 @@ +import { Abi, Field, InputMap } from '@noir-lang/noirc_abi'; + +export type MyStruct = { + foo: Field; +}; + +export type MyNestedStruct = { + foo: MyStruct; +}; + +export const abi: Abi = { + parameters: [ + { + name: 'struct_arg', + type: { kind: 'struct', path: 'MyStruct', fields: [{ name: 'foo', type: { kind: 'field' } }] }, + visibility: 'private', + }, + { + name: 'struct_array_arg', + type: { + kind: 'array', + type: { + kind: 'struct', + path: 'MyStruct', + fields: [{ name: 'foo', type: { kind: 'field' } }], + }, + length: 3, + }, + visibility: 'private', + }, + { + name: 'nested_struct_arg', + type: { + kind: 'struct', + path: 'MyNestedStruct', + fields: [ + { + name: 'foo', + type: { + kind: 'struct', + path: 'MyStruct', + fields: [{ name: 'foo', type: { kind: 'field' } }], + }, + }, + ], + }, + visibility: 'private', + }, + ], + param_witnesses: { + struct_arg: [{ start: 1, end: 2 }], + struct_array_arg: [{ start: 2, end: 5 }], + nested_struct_arg: [{ start: 5, end: 6 }], + }, + return_type: null, + return_witnesses: [], +}; + +export const inputs: InputMap = { + struct_arg: { + foo: '1', + }, + struct_array_arg: [ + { + foo: '2', + }, + { + foo: '3', + }, + { + foo: '4', + }, + ], + nested_struct_arg: { + foo: { + foo: '5', + }, + }, +}; From 12d884e2b74efab7257626d8878ea1a7455ecf85 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:15:47 +0000 Subject: [PATCH 079/137] chore!: remove circuit methods from noir_wasm (#3869) # Description ## Problem\* Resolves ## Summary\* This PR removes the unused `circuit` module from `noir_wasm`. We never need to use these methods as all they do is convert between the canonical circuit serialisation format and a huge serde-ed json representation. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/wasm/src/circuit.rs | 18 ------------------ compiler/wasm/src/lib.rs | 2 -- 2 files changed, 20 deletions(-) delete mode 100644 compiler/wasm/src/circuit.rs diff --git a/compiler/wasm/src/circuit.rs b/compiler/wasm/src/circuit.rs deleted file mode 100644 index fdd9a7d9a20..00000000000 --- a/compiler/wasm/src/circuit.rs +++ /dev/null @@ -1,18 +0,0 @@ -use acvm::acir::circuit::Circuit; -use gloo_utils::format::JsValueSerdeExt; -use wasm_bindgen::prelude::*; - -// Deserializes bytes into ACIR structure -#[wasm_bindgen] -pub fn acir_read_bytes(bytes: Vec) -> JsValue { - console_error_panic_hook::set_once(); - let circuit = Circuit::deserialize_circuit(&bytes).unwrap(); - ::from_serde(&circuit).unwrap() -} - -#[wasm_bindgen] -pub fn acir_write_bytes(acir: JsValue) -> Vec { - console_error_panic_hook::set_once(); - let circuit: Circuit = JsValueSerdeExt::into_serde(&acir).unwrap(); - Circuit::serialize_circuit(&circuit) -} diff --git a/compiler/wasm/src/lib.rs b/compiler/wasm/src/lib.rs index 43095fee4d4..d0394589578 100644 --- a/compiler/wasm/src/lib.rs +++ b/compiler/wasm/src/lib.rs @@ -12,12 +12,10 @@ use serde::{Deserialize, Serialize}; use std::str::FromStr; use wasm_bindgen::prelude::*; -mod circuit; mod compile; mod compile_new; mod errors; -pub use circuit::{acir_read_bytes, acir_write_bytes}; pub use compile::compile; // Expose the new Context-Centric API From bcbd49b8b44749e149f83c1240094fa2f0a19087 Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:24:07 +0100 Subject: [PATCH 080/137] feat: comparison for signed integers (#3873) # Description ## Problem\* Resolves ## Summary\* Implement comparison for signed integers. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. Co-authored-by: kevaundray --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 50 +++++++++++++++++++ .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 17 ++++--- .../signed_comparison/Nargo.toml | 6 +++ .../signed_comparison/Prover.toml | 3 ++ .../signed_comparison/src/main.nr | 13 +++++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 test_programs/execution_success/signed_comparison/Nargo.toml create mode 100644 test_programs/execution_success/signed_comparison/Prover.toml create mode 100644 test_programs/execution_success/signed_comparison/src/main.nr diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index e039a7793c0..05a22ab6aad 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -936,6 +936,56 @@ impl AcirContext { Ok(remainder) } + /// Returns an 'AcirVar' containing the boolean value lhs diff<2^n, because the 2-complement representation keeps the ordering (e.g in 8 bits -1 is 255 > -2 = 254) + /// If not, lhs positive => diff > 2^n + /// and lhs negative => diff <= 2^n => diff < 2^n (because signs are not the same, so lhs != rhs and so diff != 2^n) + pub(crate) fn less_than_signed( + &mut self, + lhs: AcirVar, + rhs: AcirVar, + bit_count: u32, + predicate: AcirVar, + ) -> Result { + let pow_last = self.add_constant(FieldElement::from(1_u128 << (bit_count - 1))); + let pow = self.add_constant(FieldElement::from(1_u128 << (bit_count))); + + // We check whether the inputs have same sign or not by computing the XOR of their bit sign + let lhs_sign = self.div_var( + lhs, + pow_last, + AcirType::NumericType(NumericType::Unsigned { bit_size: bit_count }), + predicate, + )?; + let rhs_sign = self.div_var( + rhs, + pow_last, + AcirType::NumericType(NumericType::Unsigned { bit_size: bit_count }), + predicate, + )?; + let same_sign = self.xor_var( + lhs_sign, + rhs_sign, + AcirType::NumericType(NumericType::Signed { bit_size: 1 }), + )?; + + // We compute the input difference + let no_underflow = self.add_var(lhs, pow)?; + let diff = self.sub_var(no_underflow, rhs)?; + + // We check the 'bit sign' of the difference + let diff_sign = self.less_than_var(diff, pow, bit_count + 1, predicate)?; + + // Then the result is simply diff_sign XOR same_sign (can be checked with a truth table) + self.xor_var( + diff_sign, + same_sign, + AcirType::NumericType(NumericType::Signed { bit_size: 1 }), + ) + } + /// Returns an `AcirVar` which will be `1` if lhs >= rhs /// and `0` otherwise. pub(crate) fn more_than_eq_var( diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index d73bb514e02..01056355915 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1569,12 +1569,17 @@ impl Context { // Note: that this produces unnecessary constraints when // this Eq instruction is being used for a constrain statement BinaryOp::Eq => self.acir_context.eq_var(lhs, rhs), - BinaryOp::Lt => self.acir_context.less_than_var( - lhs, - rhs, - bit_count, - self.current_side_effects_enabled_var, - ), + BinaryOp::Lt => match binary_type { + AcirType::NumericType(NumericType::Signed { .. }) => self + .acir_context + .less_than_signed(lhs, rhs, bit_count, self.current_side_effects_enabled_var), + _ => self.acir_context.less_than_var( + lhs, + rhs, + bit_count, + self.current_side_effects_enabled_var, + ), + }, BinaryOp::Xor => self.acir_context.xor_var(lhs, rhs, binary_type), BinaryOp::And => self.acir_context.and_var(lhs, rhs, binary_type), BinaryOp::Or => self.acir_context.or_var(lhs, rhs, binary_type), diff --git a/test_programs/execution_success/signed_comparison/Nargo.toml b/test_programs/execution_success/signed_comparison/Nargo.toml new file mode 100644 index 00000000000..c8de162877b --- /dev/null +++ b/test_programs/execution_success/signed_comparison/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_comparison" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/signed_comparison/Prover.toml b/test_programs/execution_success/signed_comparison/Prover.toml new file mode 100644 index 00000000000..e0e584b7380 --- /dev/null +++ b/test_programs/execution_success/signed_comparison/Prover.toml @@ -0,0 +1,3 @@ +x = "5" +y = "8" +z = "-15" diff --git a/test_programs/execution_success/signed_comparison/src/main.nr b/test_programs/execution_success/signed_comparison/src/main.nr new file mode 100644 index 00000000000..d020be380fb --- /dev/null +++ b/test_programs/execution_success/signed_comparison/src/main.nr @@ -0,0 +1,13 @@ +use dep::std; + +fn main(mut x: i8, mut y: i8, z: i8) { + let mut s1: i8 = 5; + let mut s2: i8 = 8; + assert(-1 as i8 < 0); + assert(x < y); + assert(-x < y); + assert(-y < -x); + assert((z > x) == false); + assert(x <= s1); + assert(z < x - y - s2); +} From 04dc47839ecb7147354e638bfcc92539f471d565 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 19 Dec 2023 13:59:06 +0000 Subject: [PATCH 081/137] chore: Push `FileManager` population up to `nargo_cli` (#3844) # Description This tries to undo some of the changes done in #3496 where cli methods were moved into the nargo library. This pushes the populating of the file manager up to the cli commands, in most places this is just after the workspace has been resolved. A possible next step after this is to have the nargo library to no longer ask for a file manager struct, but instead it asks for a FileManager trait which the previous FileManager struct would implement. ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: Tom French --- compiler/fm/src/file_map.rs | 2 +- compiler/fm/src/lib.rs | 2 +- compiler/noirc_driver/src/lib.rs | 27 +++++++-- compiler/noirc_frontend/src/hir/mod.rs | 27 ++++++--- compiler/wasm/src/compile.rs | 9 +-- compiler/wasm/src/compile_new.rs | 4 +- tooling/lsp/src/notifications/mod.rs | 9 ++- tooling/lsp/src/requests/goto_definition.rs | 8 ++- tooling/lsp/src/requests/profile_run.rs | 10 +++- tooling/lsp/src/requests/test_run.rs | 10 +++- tooling/lsp/src/requests/tests.rs | 9 ++- tooling/nargo/src/lib.rs | 20 +++++-- tooling/nargo/src/ops/compile.rs | 42 +++++++------- tooling/nargo_cli/src/cli/check_cmd.rs | 22 ++++++-- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 12 +++- tooling/nargo_cli/src/cli/compile_cmd.rs | 55 +++++++++++-------- tooling/nargo_cli/src/cli/debug_cmd.rs | 17 +++++- tooling/nargo_cli/src/cli/execute_cmd.rs | 17 +++++- tooling/nargo_cli/src/cli/fmt_cmd.rs | 19 +++---- tooling/nargo_cli/src/cli/info_cmd.rs | 12 +++- tooling/nargo_cli/src/cli/prove_cmd.rs | 17 +++++- tooling/nargo_cli/src/cli/test_cmd.rs | 19 ++++++- tooling/nargo_cli/src/cli/verify_cmd.rs | 17 +++++- 23 files changed, 275 insertions(+), 111 deletions(-) diff --git a/compiler/fm/src/file_map.rs b/compiler/fm/src/file_map.rs index 0cbdc535e40..c4d7002a082 100644 --- a/compiler/fm/src/file_map.rs +++ b/compiler/fm/src/file_map.rs @@ -30,7 +30,7 @@ impl From<&PathBuf> for PathString { PathString::from(pb.to_owned()) } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct FileMap { files: SimpleFiles, name_to_id: HashMap, diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 4870a6c283b..55fb762479f 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -16,7 +16,7 @@ use std::{ }; pub const FILE_EXTENSION: &str = "nr"; - +#[derive(Clone)] pub struct FileManager { root: PathBuf, file_map: FileMap, diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 24b159568f2..926e541c2f3 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -4,7 +4,7 @@ #![warn(clippy::semicolon_if_nothing_returned)] use clap::Args; -use fm::FileId; +use fm::{FileId, FileManager}; use iter_extended::vecmap; use noirc_abi::{AbiParameter, AbiType, ContractEvent}; use noirc_errors::{CustomDiagnostic, FileDiagnostic}; @@ -81,17 +81,36 @@ pub type ErrorsAndWarnings = Vec; /// Helper type for connecting a compilation artifact to the errors or warnings which were produced during compilation. pub type CompilationResult = Result<(T, Warnings), ErrorsAndWarnings>; -/// Adds the file from the file system at `Path` to the crate graph as a root file -pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { +/// Helper method to return a file manager instance with the stdlib already added +/// +/// TODO: This should become the canonical way to create a file manager and +/// TODO if we use a File manager trait, we can move file manager into this crate +/// TODO as a module +pub fn file_manager_with_stdlib(root: &Path) -> FileManager { + let mut file_manager = FileManager::new(root); + + add_stdlib_source_to_file_manager(&mut file_manager); + + file_manager +} + +/// Adds the source code for the stdlib into the file manager +fn add_stdlib_source_to_file_manager(file_manager: &mut FileManager) { // Add the stdlib contents to the file manager, since every package automatically has a dependency // on the stdlib. For other dependencies, we read the package.Dependencies file to add their file // contents to the file manager. However since the dependency on the stdlib is implicit, we need // to manually add it here. let stdlib_paths_with_source = stdlib::stdlib_paths_with_source(); for (path, source) in stdlib_paths_with_source { - context.file_manager.add_file_with_source_canonical_path(Path::new(&path), source); + file_manager.add_file_with_source_canonical_path(Path::new(&path), source); } +} +/// Adds the file from the file system at `Path` to the crate graph as a root file +/// +/// Note: This methods adds the stdlib as a dependency to the crate. +/// This assumes that the stdlib has already been added to the file manager. +pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr"); let std_file_id = context .file_manager diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index adeca7cf2ba..25875385fd9 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -10,6 +10,7 @@ use crate::node_interner::{FuncId, NodeInterner, StructId}; use def_map::{Contract, CrateDefMap}; use fm::FileManager; use noirc_errors::Location; +use std::borrow::Cow; use std::collections::BTreeMap; use self::def_map::TestFunction; @@ -17,11 +18,14 @@ use self::def_map::TestFunction; /// Helper object which groups together several useful context objects used /// during name resolution. Once name resolution is finished, only the /// def_interner is required for type inference and monomorphization. -pub struct Context { +pub struct Context<'file_manager> { pub def_interner: NodeInterner, pub crate_graph: CrateGraph, pub(crate) def_maps: BTreeMap, - pub file_manager: FileManager, + // In the WASM context, we take ownership of the file manager, + // which is why this needs to be a Cow. In all use-cases, the file manager + // is read-only however, once it has been passed to the Context. + pub file_manager: Cow<'file_manager, FileManager>, /// A map of each file that already has been visited from a prior `mod foo;` declaration. /// This is used to issue an error if a second `mod foo;` is declared to the same file. @@ -35,15 +39,24 @@ pub enum FunctionNameMatch<'a> { Contains(&'a str), } -impl Context { - pub fn new(file_manager: FileManager) -> Context { - let crate_graph = CrateGraph::default(); +impl Context<'_> { + pub fn new(file_manager: FileManager) -> Context<'static> { Context { def_interner: NodeInterner::default(), def_maps: BTreeMap::new(), visited_files: BTreeMap::new(), - crate_graph, - file_manager, + crate_graph: CrateGraph::default(), + file_manager: Cow::Owned(file_manager), + } + } + + pub fn from_ref_file_manager(file_manager: &FileManager) -> Context<'_> { + Context { + def_interner: NodeInterner::default(), + def_maps: BTreeMap::new(), + visited_files: BTreeMap::new(), + crate_graph: CrateGraph::default(), + file_manager: Cow::Borrowed(file_manager), } } diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 4012effd947..c6ae0ae1f42 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -7,8 +7,9 @@ use nargo::artifacts::{ program::PreprocessedProgram, }; use noirc_driver::{ - add_dep, compile_contract, compile_main, prepare_crate, prepare_dependency, CompileOptions, - CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, + add_dep, compile_contract, compile_main, file_manager_with_stdlib, prepare_crate, + prepare_dependency, CompileOptions, CompiledContract, CompiledProgram, + NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::{ graph::{CrateId, CrateName}, @@ -224,7 +225,7 @@ pub fn compile( // should be considered as immutable. pub(crate) fn file_manager_with_source_map(source_map: PathToFileSourceMap) -> FileManager { let root = Path::new(""); - let mut fm = FileManager::new(root); + let mut fm = file_manager_with_stdlib(root); for (path, source) in source_map.0 { fm.add_file_with_source(path.as_path(), source); @@ -327,7 +328,7 @@ mod test { use super::{file_manager_with_source_map, process_dependency_graph, DependencyGraph}; use std::{collections::HashMap, path::Path}; - fn setup_test_context(source_map: PathToFileSourceMap) -> Context { + fn setup_test_context(source_map: PathToFileSourceMap) -> Context<'static> { let mut fm = file_manager_with_source_map(source_map); // Add this due to us calling prepare_crate on "/main.nr" below fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs index cd09d0fcc49..0cd1a2c50e5 100644 --- a/compiler/wasm/src/compile_new.rs +++ b/compiler/wasm/src/compile_new.rs @@ -18,7 +18,9 @@ use wasm_bindgen::prelude::wasm_bindgen; /// then the impl block is not picked up in javascript. #[wasm_bindgen] pub struct CompilerContext { - context: Context, + // `wasm_bindgen` currently doesn't allow lifetime parameters on structs so we must use a `'static` lifetime. + // `Context` must then own the `FileManager` to satisfy this lifetime. + context: Context<'static>, } #[wasm_bindgen(js_name = "CrateId")] diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 61f0d231738..d0ca8679e7e 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -1,9 +1,9 @@ use std::ops::ControlFlow; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; -use nargo::prepare_package; +use nargo::{insert_all_files_for_workspace_into_file_manager, prepare_package}; use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{check_crate, file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{DiagnosticKind, FileDiagnostic}; use crate::types::{ @@ -100,10 +100,13 @@ pub(super) fn on_did_save_text_document( } }; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let diagnostics: Vec<_> = workspace .into_iter() .flat_map(|package| -> Vec { - let (mut context, crate_id) = prepare_package(package); + let (mut context, crate_id) = prepare_package(&workspace_file_manager, package); let file_diagnostics = match check_crate(&mut context, crate_id, false, false) { Ok(((), warnings)) => warnings, diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 558851d4ecf..a23bde2e210 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -5,8 +5,9 @@ use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use fm::codespan_files::Error; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Location}; use lsp_types::{Position, Url}; +use nargo::insert_all_files_for_workspace_into_file_manager; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; +use noirc_driver::{file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; pub(crate) fn on_goto_definition_request( state: &mut LspState, @@ -51,8 +52,11 @@ fn on_goto_definition_inner( let mut definition_position = None; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + for package in &workspace { - let (mut context, crate_id) = nargo::prepare_package(package); + let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, package); // We ignore the warnings and errors produced by compilation while resolving the definition let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); diff --git a/tooling/lsp/src/requests/profile_run.rs b/tooling/lsp/src/requests/profile_run.rs index 4c4d7f11fde..6664475a68c 100644 --- a/tooling/lsp/src/requests/profile_run.rs +++ b/tooling/lsp/src/requests/profile_run.rs @@ -5,9 +5,11 @@ use std::{ use acvm::ExpressionWidth; use async_lsp::{ErrorCode, ResponseError}; -use nargo::artifacts::debug::DebugArtifact; +use nargo::{artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager}; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{CompileOptions, DebugFile, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, DebugFile, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_errors::{debug_info::OpCodesCount, Location}; use crate::{ @@ -48,6 +50,9 @@ fn on_profile_run_request_inner( ResponseError::new(ErrorCode::REQUEST_FAILED, err) })?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + // Since we filtered on crate name, this should be the only item in the iterator match workspace.into_iter().next() { Some(_package) => { @@ -60,6 +65,7 @@ fn on_profile_run_request_inner( let expression_width = ExpressionWidth::Bounded { width: 3 }; let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace( + &workspace_file_manager, &workspace, &binary_packages, &contract_packages, diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index e5245de426f..2a040a2e3e9 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -2,11 +2,14 @@ use std::future::{self, Future}; use async_lsp::{ErrorCode, ResponseError}; use nargo::{ + insert_all_files_for_workspace_into_file_manager, ops::{run_test, TestStatus}, prepare_package, }; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + check_crate, file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::hir::FunctionNameMatch; use crate::{ @@ -47,10 +50,13 @@ fn on_test_run_request_inner( ResponseError::new(ErrorCode::REQUEST_FAILED, err) })?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + // Since we filtered on crate name, this should be the only item in the iterator match workspace.into_iter().next() { Some(package) => { - let (mut context, crate_id) = prepare_package(package); + let (mut context, crate_id) = prepare_package(&workspace_file_manager, package); if check_crate(&mut context, crate_id, false, false).is_err() { let result = NargoTestRunResult { id: params.id.clone(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index 9a67eaae6db..0f717b9fb9e 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -2,9 +2,9 @@ use std::future::{self, Future}; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use lsp_types::{LogMessageParams, MessageType}; -use nargo::prepare_package; +use nargo::{insert_all_files_for_workspace_into_file_manager, prepare_package}; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{check_crate, file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; use crate::{ get_package_tests_in_crate, @@ -50,10 +50,13 @@ fn on_tests_request_inner( ResponseError::new(ErrorCode::REQUEST_FAILED, err) })?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let package_tests: Vec<_> = workspace .into_iter() .filter_map(|package| { - let (mut context, crate_id) = prepare_package(package); + let (mut context, crate_id) = prepare_package(&workspace_file_manager, package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails let _ = check_crate(&mut context, crate_id, false, false); diff --git a/tooling/nargo/src/lib.rs b/tooling/nargo/src/lib.rs index f0c7277060f..db54fd3d574 100644 --- a/tooling/nargo/src/lib.rs +++ b/tooling/nargo/src/lib.rs @@ -42,13 +42,21 @@ pub fn prepare_dependencies( } } +pub fn insert_all_files_for_workspace_into_file_manager( + workspace: &workspace::Workspace, + file_manager: &mut FileManager, +) { + for package in workspace.clone().into_iter() { + insert_all_files_for_package_into_file_manager(package, file_manager); + } +} // We will pre-populate the file manager with all the files in the package // This is so that we can avoid having to read from disk when we are compiling // // This does not require parsing because we are interested in the files under the src directory // it may turn out that we do not need to include some Noir files that we add to the file // manager -pub fn insert_all_files_for_package_into_file_manager( +fn insert_all_files_for_package_into_file_manager( package: &Package, file_manager: &mut FileManager, ) { @@ -87,11 +95,11 @@ fn insert_all_files_for_packages_dependencies_into_file_manager( } } -pub fn prepare_package(package: &Package) -> (Context, CrateId) { - let mut fm = FileManager::new(&package.root_dir); - insert_all_files_for_package_into_file_manager(package, &mut fm); - - let mut context = Context::new(fm); +pub fn prepare_package<'file_manager>( + file_manager: &'file_manager FileManager, + package: &Package, +) -> (Context<'file_manager>, CrateId) { + let mut context = Context::from_ref_file_manager(file_manager); let crate_id = prepare_crate(&mut context, &package.entry_path); diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index 1a9e0a6c115..bd395d03f67 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -14,6 +14,7 @@ use rayon::prelude::*; /// /// This function will return an error if there are any compilations errors reported. pub fn compile_workspace( + file_manager: &FileManager, workspace: &Workspace, binary_packages: &[Package], contract_packages: &[Package], @@ -21,23 +22,24 @@ pub fn compile_workspace( compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CompileError> { // Compile all of the packages in parallel. - let program_results: Vec<(FileManager, CompilationResult)> = binary_packages + let program_results: Vec> = binary_packages + .par_iter() + .map(|package| { + compile_program(file_manager, workspace, package, compile_options, expression_width) + }) + .collect(); + let contract_results: Vec> = contract_packages .par_iter() - .map(|package| compile_program(workspace, package, compile_options, expression_width)) + .map(|package| compile_contract(file_manager, package, compile_options, expression_width)) .collect(); - let contract_results: Vec<(FileManager, CompilationResult)> = - contract_packages - .par_iter() - .map(|package| compile_contract(package, compile_options, expression_width)) - .collect(); // Report any warnings/errors which were encountered during compilation. let compiled_programs: Vec = program_results .into_iter() - .map(|(file_manager, compilation_result)| { + .map(|compilation_result| { report_errors( compilation_result, - &file_manager, + file_manager, compile_options.deny_warnings, compile_options.silence_warnings, ) @@ -45,10 +47,10 @@ pub fn compile_workspace( .collect::>()?; let compiled_contracts: Vec = contract_results .into_iter() - .map(|(file_manager, compilation_result)| { + .map(|compilation_result| { report_errors( compilation_result, - &file_manager, + file_manager, compile_options.deny_warnings, compile_options.silence_warnings, ) @@ -59,12 +61,13 @@ pub fn compile_workspace( } pub fn compile_program( + file_manager: &FileManager, workspace: &Workspace, package: &Package, compile_options: &CompileOptions, expression_width: ExpressionWidth, -) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = prepare_package(package); +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -74,33 +77,34 @@ pub fn compile_program( match noirc_driver::compile_main(&mut context, crate_id, compile_options, None, true) { Ok(program_and_warnings) => program_and_warnings, Err(errors) => { - return (context.file_manager, Err(errors)); + return Err(errors); } }; // Apply backend specific optimizations. let optimized_program = crate::ops::optimize_program(program, expression_width); - (context.file_manager, Ok((optimized_program, warnings))) + Ok((optimized_program, warnings)) } fn compile_contract( + file_manager: &FileManager, package: &Package, compile_options: &CompileOptions, expression_width: ExpressionWidth, -) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = prepare_package(package); +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, Err(errors) => { - return (context.file_manager, Err(errors)); + return Err(errors); } }; let optimized_contract = crate::ops::optimize_contract(contract, expression_width); - (context.file_manager, Ok((optimized_contract, warnings))) + Ok((optimized_contract, warnings)) } pub(crate) fn report_errors( diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 0ea8186a237..e2db492fe9c 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -2,12 +2,17 @@ use crate::backends::Backend; use crate::errors::CliError; use clap::Args; +use fm::FileManager; use iter_extended::btree_map; -use nargo::{errors::CompileError, package::Package, prepare_package}; +use nargo::{ + errors::CompileError, insert_all_files_for_workspace_into_file_manager, package::Package, + prepare_package, +}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; use noirc_driver::{ - check_crate, compute_function_abi, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, + check_crate, compute_function_abi, file_manager_with_stdlib, CompileOptions, + NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::{ graph::{CrateId, CrateName}, @@ -47,15 +52,22 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + for package in &workspace { - check_package(package, &args.compile_options)?; + check_package(&workspace_file_manager, package, &args.compile_options)?; println!("[{}] Constraint system successfully built!", package.name); } Ok(()) } -fn check_package(package: &Package, compile_options: &CompileOptions) -> Result<(), CompileError> { - let (mut context, crate_id) = prepare_package(package); +fn check_package( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, +) -> Result<(), CompileError> { + let (mut context, crate_id) = prepare_package(file_manager, package); check_crate_and_report_errors( &mut context, crate_id, diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index b72ce01e1a9..fe79c0b8c23 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -9,10 +9,12 @@ use crate::errors::CliError; use acvm::ExpressionWidth; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use clap::Args; +use fm::FileManager; +use nargo::insert_all_files_for_workspace_into_file_manager; use nargo::package::Package; use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; /// Generates a Solidity verifier smart contract for the program @@ -45,9 +47,13 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let expression_width = backend.get_backend_info()?; for package in &workspace { let smart_contract_string = smart_contract_for_package( + &workspace_file_manager, &workspace, backend, package, @@ -67,13 +73,15 @@ pub(crate) fn run( } fn smart_contract_for_package( + file_manager: &FileManager, workspace: &Workspace, backend: &Backend, package: &Package, compile_options: &CompileOptions, expression_width: ExpressionWidth, ) -> Result { - let program = compile_bin_package(workspace, package, compile_options, expression_width)?; + let program = + compile_bin_package(file_manager, workspace, package, compile_options, expression_width)?; let mut smart_contract_string = backend.eth_contract(&program.circuit)?; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 5ee053c5088..661081778c3 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -8,10 +8,12 @@ use nargo::artifacts::contract::PreprocessedContractFunction; use nargo::artifacts::debug::DebugArtifact; use nargo::artifacts::program::PreprocessedProgram; use nargo::errors::CompileError; +use nargo::insert_all_files_for_workspace_into_file_manager; 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::file_manager_with_stdlib; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; use noirc_frontend::graph::CrateName; @@ -61,6 +63,9 @@ pub(crate) fn run( )?; let circuit_dir = workspace.target_directory_path(); + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() .filter(|package| !package.is_library()) @@ -69,6 +74,7 @@ pub(crate) fn run( let expression_width = backend.get_backend_info_or_default(); let (_, compiled_contracts) = compile_workspace( + &workspace_file_manager, &workspace, &binary_packages, &contract_packages, @@ -85,6 +91,7 @@ pub(crate) fn run( } pub(super) fn compile_workspace( + file_manager: &FileManager, workspace: &Workspace, binary_packages: &[Package], contract_packages: &[Package], @@ -92,23 +99,24 @@ pub(super) fn compile_workspace( compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CliError> { // Compile all of the packages in parallel. - let program_results: Vec<(FileManager, CompilationResult)> = binary_packages + let program_results: Vec> = binary_packages + .par_iter() + .map(|package| { + compile_program(file_manager, workspace, package, compile_options, expression_width) + }) + .collect(); + let contract_results: Vec> = contract_packages .par_iter() - .map(|package| compile_program(workspace, package, compile_options, expression_width)) + .map(|package| compile_contract(file_manager, package, compile_options, expression_width)) .collect(); - let contract_results: Vec<(FileManager, CompilationResult)> = - contract_packages - .par_iter() - .map(|package| compile_contract(package, compile_options, expression_width)) - .collect(); // Report any warnings/errors which were encountered during compilation. let compiled_programs: Vec = program_results .into_iter() - .map(|(file_manager, compilation_result)| { + .map(|compilation_result| { report_errors( compilation_result, - &file_manager, + file_manager, compile_options.deny_warnings, compile_options.silence_warnings, ) @@ -116,10 +124,10 @@ pub(super) fn compile_workspace( .collect::>()?; let compiled_contracts: Vec = contract_results .into_iter() - .map(|(file_manager, compilation_result)| { + .map(|compilation_result| { report_errors( compilation_result, - &file_manager, + file_manager, compile_options.deny_warnings, compile_options.silence_warnings, ) @@ -130,6 +138,7 @@ pub(super) fn compile_workspace( } pub(crate) fn compile_bin_package( + file_manager: &FileManager, workspace: &Workspace, package: &Package, compile_options: &CompileOptions, @@ -139,12 +148,12 @@ pub(crate) fn compile_bin_package( return Err(CompileError::LibraryCrate(package.name.clone()).into()); } - let (file_manager, compilation_result) = - compile_program(workspace, package, compile_options, expression_width); + let compilation_result = + compile_program(file_manager, workspace, package, compile_options, expression_width); let program = report_errors( compilation_result, - &file_manager, + file_manager, compile_options.deny_warnings, compile_options.silence_warnings, )?; @@ -153,12 +162,13 @@ pub(crate) fn compile_bin_package( } fn compile_program( + file_manager: &FileManager, workspace: &Workspace, package: &Package, compile_options: &CompileOptions, expression_width: ExpressionWidth, -) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = prepare_package(package); +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -191,7 +201,7 @@ fn compile_program( ) { Ok(program_and_warnings) => program_and_warnings, Err(errors) => { - return (context.file_manager, Err(errors)); + return Err(errors); } }; @@ -200,26 +210,27 @@ fn compile_program( let only_acir = compile_options.only_acir; save_program(optimized_program.clone(), package, &workspace.target_directory_path(), only_acir); - (context.file_manager, Ok((optimized_program, warnings))) + Ok((optimized_program, warnings)) } fn compile_contract( + file_manager: &FileManager, package: &Package, compile_options: &CompileOptions, expression_width: ExpressionWidth, -) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = prepare_package(package); +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, Err(errors) => { - return (context.file_manager, Err(errors)); + return Err(errors); } }; let optimized_contract = nargo::ops::optimize_contract(contract, expression_width); - (context.file_manager, Ok((optimized_contract, warnings))) + Ok((optimized_contract, warnings)) } fn save_program( diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 6eab626a08d..e603dfc5492 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -5,11 +5,14 @@ use clap::Args; use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; +use nargo::insert_all_files_for_workspace_into_file_manager; 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::InputMap; -use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -51,6 +54,9 @@ pub(crate) fn run( let target_dir = &workspace.target_directory_path(); let expression_width = backend.get_backend_info()?; + let mut workspace_file_manager = file_manager_with_stdlib(std::path::Path::new("")); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { println!( "No matching binary packages found in workspace. Only binary packages can be debugged." @@ -58,8 +64,13 @@ pub(crate) fn run( return Ok(()); }; - let compiled_program = - compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; + let compiled_program = compile_bin_package( + &workspace_file_manager, + &workspace, + package, + &args.compile_options, + expression_width, + )?; run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir) } diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index 10760f43a45..3d7af2ec4e5 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -4,12 +4,15 @@ use clap::Args; use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::try_to_diagnose_runtime_error; +use nargo::insert_all_files_for_workspace_into_file_manager; use nargo::ops::DefaultForeignCallExecutor; 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::InputMap; -use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -56,10 +59,18 @@ pub(crate) fn run( )?; let target_dir = &workspace.target_directory_path(); + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let expression_width = backend.get_backend_info_or_default(); for package in &workspace { - let compiled_program = - compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; + let compiled_program = compile_bin_package( + &workspace_file_manager, + &workspace, + package, + &args.compile_options, + expression_width, + )?; let (return_value, solved_witness) = execute_program_and_decode(compiled_program, package, &args.prover_name)?; diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index e62fc560217..78678559547 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -1,10 +1,9 @@ use std::{fs::DirEntry, path::Path}; use clap::Args; -use fm::FileManager; -use nargo::insert_all_files_for_package_into_file_manager; +use nargo::insert_all_files_for_workspace_into_file_manager; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; +use noirc_driver::{file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::CustomDiagnostic; use noirc_frontend::{hir::def_map::parse_file, parser::ParserError}; @@ -30,18 +29,18 @@ pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliErr Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let config = nargo_fmt::Config::read(&config.program_dir) .map_err(|err| CliError::Generic(err.to_string()))?; let mut check_exit_code_one = false; for package in &workspace { - let mut file_manager = FileManager::new(&package.root_dir); - insert_all_files_for_package_into_file_manager(package, &mut file_manager); - visit_noir_files(&package.root_dir.join("src"), &mut |entry| { - let file_id = file_manager.name_to_id(entry.path().to_path_buf()).expect("The file should exist since we added all files in the package into the file manager"); - let (parsed_module, errors) = parse_file(&file_manager, file_id); + let file_id = workspace_file_manager.name_to_id(entry.path().to_path_buf()).expect("The file should exist since we added all files in the package into the file manager"); + let (parsed_module, errors) = parse_file(&workspace_file_manager, file_id); let is_all_warnings = errors.iter().all(ParserError::is_warning); if !is_all_warnings { @@ -55,14 +54,14 @@ pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliErr let _ = super::compile_cmd::report_errors::<()>( Err(errors), - &file_manager, + &workspace_file_manager, false, false, ); return Ok(()); } - let original = file_manager.fetch_file(file_id); + let original = workspace_file_manager.fetch_file(file_id); let formatted = nargo_fmt::format(original, parsed_module, &config); if check_mode { diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index e25051c1df7..f983a19c0fd 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -4,10 +4,14 @@ use acvm::ExpressionWidth; use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; -use nargo::{artifacts::debug::DebugArtifact, package::Package}; +use nargo::{ + artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager, + package::Package, +}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{ - CompileOptions, CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, + file_manager_with_stdlib, CompileOptions, CompiledContract, CompiledProgram, + NOIR_ARTIFACT_VERSION_STRING, }; use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; @@ -61,6 +65,9 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() .filter(|package| !package.is_library()) @@ -69,6 +76,7 @@ pub(crate) fn run( let expression_width = backend.get_backend_info_or_default(); let (compiled_programs, compiled_contracts) = compile_workspace( + &workspace_file_manager, &workspace, &binary_packages, &contract_packages, diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index cb1751e7cef..2b1dd8c65f3 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -1,10 +1,13 @@ use clap::Args; use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; +use nargo::insert_all_files_for_workspace_into_file_manager; 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, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -57,10 +60,18 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let expression_width = backend.get_backend_info()?; for package in &workspace { - let program = - compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; + let program = compile_bin_package( + &workspace_file_manager, + &workspace, + package, + &args.compile_options, + expression_width, + )?; prove_package( backend, diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index fcad4d4ee9f..809994219cb 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -2,13 +2,15 @@ use std::io::Write; use acvm::BlackBoxFunctionSolver; use clap::Args; +use fm::FileManager; use nargo::{ + insert_all_files_for_workspace_into_file_manager, ops::{run_test, TestStatus}, package::Package, prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::{graph::CrateName, hir::FunctionNameMatch}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -57,6 +59,9 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let pattern = match &args.test_name { Some(name) => { if args.exact { @@ -73,20 +78,28 @@ pub(crate) fn run( for package in &workspace { // By unwrapping here with `?`, we stop the test runner upon a package failing // TODO: We should run the whole suite even if there are failures in a package - run_tests(&blackbox_solver, package, pattern, args.show_output, &args.compile_options)?; + run_tests( + &workspace_file_manager, + &blackbox_solver, + package, + pattern, + args.show_output, + &args.compile_options, + )?; } Ok(()) } fn run_tests( + file_manager: &FileManager, blackbox_solver: &S, package: &Package, fn_name: FunctionNameMatch, show_output: bool, compile_options: &CompileOptions, ) -> Result<(), CliError> { - let (mut context, crate_id) = prepare_package(package); + let (mut context, crate_id) = prepare_package(file_manager, package); check_crate_and_report_errors( &mut context, crate_id, diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 9659286b5ab..86d5e774cbe 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -7,11 +7,14 @@ use crate::{backends::Backend, errors::CliError}; use clap::Args; use nargo::constants::{PROOF_EXT, VERIFIER_INPUT_FILE}; +use nargo::insert_all_files_for_workspace_into_file_manager; 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, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::graph::CrateName; /// Given a proof and a program, verify whether the proof is valid @@ -48,10 +51,18 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let expression_width = backend.get_backend_info()?; for package in &workspace { - let program = - compile_bin_package(&workspace, package, &args.compile_options, expression_width)?; + let program = compile_bin_package( + &workspace_file_manager, + &workspace, + package, + &args.compile_options, + expression_width, + )?; verify_package(backend, &workspace, package, program, &args.verifier_name)?; } From c2c338864b858dc10825fc6f4ce67ad3ee8aca04 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Tue, 19 Dec 2023 09:02:15 -0500 Subject: [PATCH 082/137] chore: update bash script shebangs and dockerfiles (#3875) Development from Aztec. --------- Co-authored-by: ludamad Co-authored-by: ludamad Co-authored-by: kevaundray Co-authored-by: sirasistant Co-authored-by: Gregorio Juliana Co-authored-by: Tom French --- .github/actions/docs/build-status/script.sh | 2 +- Dockerfile | 17 +++++++---------- bootstrap.sh | 2 +- .../scripts/codegen-verifiers.sh | 2 +- scripts/bootstrap_native.sh | 8 ++++++-- scripts/bootstrap_packages.sh | 2 +- scripts/install_wasm-bindgen.sh | 2 +- test_programs/gates_report.sh | 2 +- test_programs/rebuild.sh | 4 ++-- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/actions/docs/build-status/script.sh b/.github/actions/docs/build-status/script.sh index 0b282557cf2..2e86de6c173 100755 --- a/.github/actions/docs/build-status/script.sh +++ b/.github/actions/docs/build-status/script.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash BRANCH_NAME=$(echo "$BRANCH_NAME" | sed -e "s#refs/[^/]*/##") DEPLOY_STATUS=$(curl -X GET "https://api.netlify.com/api/v1/sites/$SITE_ID/deploys?branch=$BRANCH_NAME" | jq -r '.[] | select(.created_at != null) | .state' | head -1) diff --git a/Dockerfile b/Dockerfile index ac818cb8bd2..000292e0a47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,12 @@ -FROM rust:alpine3.17 -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - bash +FROM rust:bookworm WORKDIR /usr/src/noir COPY . . RUN ./scripts/bootstrap_native.sh -# When running the container, mount the current working directory to /project. -FROM alpine:3.17 +# When running the container, mount the users home directory to same location. +FROM ubuntu:lunar +# 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 -WORKDIR /project -ENTRYPOINT ["/usr/src/noir/target/release/nargo"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/tini", "--", "/usr/src/noir/target/release/nargo"] \ No newline at end of file diff --git a/bootstrap.sh b/bootstrap.sh index bf672ac0ad2..5ebe7ade090 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0") diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh index b3a52217271..e377a3ee3f8 100644 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash self_path=$(dirname "$(readlink -f "$0")") diff --git a/scripts/bootstrap_native.sh b/scripts/bootstrap_native.sh index 481c76a263e..3e0e2ed853a 100755 --- a/scripts/bootstrap_native.sh +++ b/scripts/bootstrap_native.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. @@ -13,4 +13,8 @@ else fi # Build native. -cargo build --release +if [ -n "${DEBUG:-}" ]; then + cargo build +else + cargo build --release +fi diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh index 2f293d93faf..df4ee5b3aed 100755 --- a/scripts/bootstrap_packages.sh +++ b/scripts/bootstrap_packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. diff --git a/scripts/install_wasm-bindgen.sh b/scripts/install_wasm-bindgen.sh index 5e9f9127506..c6e85bac50b 100755 --- a/scripts/install_wasm-bindgen.sh +++ b/scripts/install_wasm-bindgen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. diff --git a/test_programs/gates_report.sh b/test_programs/gates_report.sh index e06e6812e9d..4192c581376 100755 --- a/test_programs/gates_report.sh +++ b/test_programs/gates_report.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # These tests are incompatible with gas reporting diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh index d879ca417ee..a3137920fd5 100755 --- a/test_programs/rebuild.sh +++ b/test_programs/rebuild.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e process_dir() { @@ -14,7 +14,7 @@ process_dir() { if [ -d ./target/ ]; then rm -r ./target/ fi - cargo run compile --only-acir && cargo run execute witness + nargo compile --only-acir && nargo execute witness if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then rm -r "$current_dir/acir_artifacts/$dir_name/target" From 7a4e84502fc4cfcb54c7e04f8ca9d9e6e66979ed Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:10:21 +0000 Subject: [PATCH 083/137] chore: rename `barretenberg_blackbox_solver` to `bn254_blackbox_solver` (#3874) # Description ## Problem\* Resolves ## Summary\* This PR renames `barretenberg_blackbox_solver` to `bn254_blackbox_solver` and marks it as not deprecated. This signifies that these blackbox solvers should work against all backends targetting the bn254 curve and not just barretenberg. That we're using barretenberg to solve them is then just an implementation detail. We've decided to retain the `BlackBoxFunctionSolver` trait to allow these solvers to be swapped out based on the `FieldElement` implementation and so the new `Bn254BlackBoxSolver` is not deprecated. ## Additional Context Now that this solver is tied to a curve rather than a particular backend, it's now proper to integrate it into the compiler such that we can solve black box functions such as that which caused #3865 ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/publish-acvm.yml | 4 +- Cargo.lock | 48 +++++++++--------- Cargo.toml | 4 +- acvm-repo/acvm_js/Cargo.toml | 8 +-- acvm-repo/acvm_js/src/execute.rs | 9 ++-- .../CHANGELOG.md | 0 .../Cargo.toml | 5 +- .../build.rs | 0 .../src/acvm_backend.wasm | Bin .../src/fixed_base_scalar_mul.rs | 0 .../src/lib.rs | 21 +++----- .../src/wasm/barretenberg_structures.rs | 0 .../src/wasm/mod.rs | 0 .../src/wasm/pedersen.rs | 0 .../src/wasm/schnorr.rs | 0 tooling/nargo_cli/Cargo.toml | 2 +- tooling/nargo_cli/src/cli/debug_cmd.rs | 4 +- tooling/nargo_cli/src/cli/execute_cmd.rs | 4 +- tooling/nargo_cli/src/cli/lsp_cmd.rs | 4 +- tooling/nargo_cli/src/cli/test_cmd.rs | 4 +- 20 files changed, 54 insertions(+), 63 deletions(-) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/CHANGELOG.md (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/Cargo.toml (87%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/build.rs (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/acvm_backend.wasm (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/fixed_base_scalar_mul.rs (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/lib.rs (82%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/wasm/barretenberg_structures.rs (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/wasm/mod.rs (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/wasm/pedersen.rs (100%) rename acvm-repo/{barretenberg_blackbox_solver => bn254_blackbox_solver}/src/wasm/schnorr.rs (100%) diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index 59a104e3f75..0251aaa0377 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -45,9 +45,9 @@ jobs: env: CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} - - name: Publish barretenberg_blackbox_solver + - name: Publish bn254_blackbox_solver run: | - cargo publish --package barretenberg_blackbox_solver + cargo publish --package bn254_blackbox_solver env: CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index 7f964cd58ef..122a685ba61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,7 +70,7 @@ name = "acvm_js" version = "0.38.0" dependencies = [ "acvm", - "barretenberg_blackbox_solver", + "bn254_blackbox_solver", "build-data", "cfg-if", "console_error_panic_hook", @@ -460,28 +460,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "barretenberg_blackbox_solver" -version = "0.38.0" -dependencies = [ - "acir", - "acvm_blackbox_solver", - "ark-ec", - "ark-ff", - "flate2", - "getrandom", - "grumpkin", - "js-sys", - "num-bigint", - "pkg-config", - "reqwest", - "rust-embed", - "tar", - "thiserror", - "wasm-bindgen-futures", - "wasmer", -] - [[package]] name = "base16ct" version = "0.1.1" @@ -584,6 +562,28 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bn254_blackbox_solver" +version = "0.38.0" +dependencies = [ + "acir", + "acvm_blackbox_solver", + "ark-ec", + "ark-ff", + "flate2", + "getrandom", + "grumpkin", + "js-sys", + "num-bigint", + "pkg-config", + "reqwest", + "rust-embed", + "tar", + "thiserror", + "wasm-bindgen-futures", + "wasmer", +] + [[package]] name = "brillig" version = "0.38.0" @@ -2459,8 +2459,8 @@ dependencies = [ "assert_fs", "async-lsp", "backend-interface", - "barretenberg_blackbox_solver", "bb_abstraction_leaks", + "bn254_blackbox_solver", "build-data", "clap", "color-eyre", diff --git a/Cargo.toml b/Cargo.toml index 259eec330a9..bec16277a9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ "acvm-repo/brillig", "acvm-repo/brillig_vm", "acvm-repo/blackbox_solver", - "acvm-repo/barretenberg_blackbox_solver", + "acvm-repo/bn254_blackbox_solver", ] default-members = ["tooling/nargo_cli"] resolver = "2" @@ -56,7 +56,7 @@ stdlib = { version = "0.37.1", package = "acvm_stdlib", path = "acvm-repo/stdlib brillig = { version = "0.38.0", path = "acvm-repo/brillig", default-features = false } brillig_vm = { version = "0.38.0", path = "acvm-repo/brillig_vm", default-features = false } acvm_blackbox_solver = { version = "0.38.0", path = "acvm-repo/blackbox_solver", default-features = false } -barretenberg_blackbox_solver = { version = "0.38.0", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "0.38.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies arena = { path = "compiler/utils/arena" } diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index 22bd6e5aa7e..06903fec3f5 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -19,8 +19,8 @@ crate-type = ["cdylib"] cfg-if = "1.0.0" [target.'cfg(target_arch = "wasm32")'.dependencies] -acvm = { path = "../acvm", default-features = false } -barretenberg_blackbox_solver = { path = "../barretenberg_blackbox_solver", default-features = false } +acvm.workspace = true +bn254_blackbox_solver = { workspace = true, optional = true } wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true @@ -41,5 +41,5 @@ wasm-bindgen-test.workspace = true [features] default = ["bn254"] -bn254 = ["acvm/bn254", "barretenberg_blackbox_solver/bn254"] -bls12_381 = ["acvm/bls12_381", "barretenberg_blackbox_solver/bls12_381"] +bn254 = ["acvm/bn254", "dep:bn254_blackbox_solver"] +bls12_381 = ["acvm/bls12_381"] diff --git a/acvm-repo/acvm_js/src/execute.rs b/acvm-repo/acvm_js/src/execute.rs index 81e2a11ed5a..439a929cc98 100644 --- a/acvm-repo/acvm_js/src/execute.rs +++ b/acvm-repo/acvm_js/src/execute.rs @@ -2,8 +2,7 @@ use acvm::{ acir::circuit::Circuit, pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}, }; -#[allow(deprecated)] -use barretenberg_blackbox_solver::BarretenbergSolver; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use js_sys::Error; use wasm_bindgen::prelude::wasm_bindgen; @@ -14,13 +13,11 @@ use crate::{ }; #[wasm_bindgen] -#[allow(deprecated)] -pub struct WasmBlackBoxFunctionSolver(BarretenbergSolver); +pub struct WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver); impl WasmBlackBoxFunctionSolver { async fn initialize() -> WasmBlackBoxFunctionSolver { - #[allow(deprecated)] - WasmBlackBoxFunctionSolver(BarretenbergSolver::initialize().await) + WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver::initialize().await) } } diff --git a/acvm-repo/barretenberg_blackbox_solver/CHANGELOG.md b/acvm-repo/bn254_blackbox_solver/CHANGELOG.md similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/CHANGELOG.md rename to acvm-repo/bn254_blackbox_solver/CHANGELOG.md diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/bn254_blackbox_solver/Cargo.toml similarity index 87% rename from acvm-repo/barretenberg_blackbox_solver/Cargo.toml rename to acvm-repo/bn254_blackbox_solver/Cargo.toml index 01f5e6ca950..b98bb370f74 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "barretenberg_blackbox_solver" -description = "A wrapper around a barretenberg WASM binary to execute black box functions for which there is no rust implementation" +name = "bn254_blackbox_solver" +description = "Solvers for black box functions which are specific for the bn254 curve" # x-release-please-start-version version = "0.38.0" # x-release-please-end @@ -54,4 +54,3 @@ reqwest = { version = "0.11.20", default-features = false, features = [ [features] default = ["bn254"] bn254 = ["acir/bn254"] -bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/barretenberg_blackbox_solver/build.rs b/acvm-repo/bn254_blackbox_solver/build.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/build.rs rename to acvm-repo/bn254_blackbox_solver/build.rs diff --git a/acvm-repo/barretenberg_blackbox_solver/src/acvm_backend.wasm b/acvm-repo/bn254_blackbox_solver/src/acvm_backend.wasm similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/acvm_backend.wasm rename to acvm-repo/bn254_blackbox_solver/src/acvm_backend.wasm diff --git a/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs rename to acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs diff --git a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs b/acvm-repo/bn254_blackbox_solver/src/lib.rs similarity index 82% rename from acvm-repo/barretenberg_blackbox_solver/src/lib.rs rename to acvm-repo/bn254_blackbox_solver/src/lib.rs index 5d2ab834536..e315c4650be 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs +++ b/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -13,36 +13,32 @@ use wasm::Barretenberg; use self::wasm::{Pedersen, SchnorrSig}; -#[deprecated = "The `BarretenbergSolver` is a temporary solution and will be removed in future."] -pub struct BarretenbergSolver { +pub struct Bn254BlackBoxSolver { blackbox_vendor: Barretenberg, } -#[allow(deprecated)] -impl BarretenbergSolver { +impl Bn254BlackBoxSolver { #[cfg(target_arch = "wasm32")] - pub async fn initialize() -> BarretenbergSolver { + pub async fn initialize() -> Bn254BlackBoxSolver { let blackbox_vendor = Barretenberg::initialize().await; - BarretenbergSolver { blackbox_vendor } + Bn254BlackBoxSolver { blackbox_vendor } } #[cfg(not(target_arch = "wasm32"))] - pub fn new() -> BarretenbergSolver { + pub fn new() -> Bn254BlackBoxSolver { let blackbox_vendor = Barretenberg::new(); - BarretenbergSolver { blackbox_vendor } + Bn254BlackBoxSolver { blackbox_vendor } } } #[cfg(not(target_arch = "wasm32"))] -#[allow(deprecated)] -impl Default for BarretenbergSolver { +impl Default for Bn254BlackBoxSolver { fn default() -> Self { Self::new() } } -#[allow(deprecated)] -impl BlackBoxFunctionSolver for BarretenbergSolver { +impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { fn schnorr_verify( &self, public_key_x: &FieldElement, @@ -57,7 +53,6 @@ impl BlackBoxFunctionSolver for BarretenbergSolver { let sig_s: [u8; 32] = signature[0..32].try_into().unwrap(); let sig_e: [u8; 32] = signature[32..64].try_into().unwrap(); - #[allow(deprecated)] self.blackbox_vendor.verify_signature(pub_key, sig_s, sig_e, message).map_err(|err| { BlackBoxResolutionError::Failed(BlackBoxFunc::SchnorrVerify, err.to_string()) }) diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/barretenberg_structures.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/barretenberg_structures.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/wasm/barretenberg_structures.rs rename to acvm-repo/bn254_blackbox_solver/src/wasm/barretenberg_structures.rs diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/mod.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs rename to acvm-repo/bn254_blackbox_solver/src/wasm/mod.rs diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/pedersen.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs rename to acvm-repo/bn254_blackbox_solver/src/wasm/pedersen.rs diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/schnorr.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/schnorr.rs similarity index 100% rename from acvm-repo/barretenberg_blackbox_solver/src/wasm/schnorr.rs rename to acvm-repo/bn254_blackbox_solver/src/wasm/schnorr.rs diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 2f99fefb778..839b81460ac 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -32,7 +32,7 @@ noirc_frontend.workspace = true noirc_abi.workspace = true noirc_errors.workspace = true acvm.workspace = true -barretenberg_blackbox_solver.workspace = true +bn254_blackbox_solver.workspace = true toml.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index e603dfc5492..f78a683aa8f 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use acvm::acir::native_types::WitnessMap; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use nargo::artifacts::debug::DebugArtifact; @@ -134,8 +135,7 @@ pub(crate) fn debug_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, ) -> Result, CliError> { - #[allow(deprecated)] - let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + let blackbox_solver = Bn254BlackBoxSolver::new(); let initial_witness = compiled_program.abi.encode(inputs_map, None)?; diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index 3d7af2ec4e5..f2d5bce5524 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -1,4 +1,5 @@ use acvm::acir::native_types::WitnessMap; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use nargo::artifacts::debug::DebugArtifact; @@ -107,8 +108,7 @@ pub(crate) fn execute_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, ) -> Result { - #[allow(deprecated)] - let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + let blackbox_solver = Bn254BlackBoxSolver::new(); let initial_witness = compiled_program.abi.encode(inputs_map, None)?; diff --git a/tooling/nargo_cli/src/cli/lsp_cmd.rs b/tooling/nargo_cli/src/cli/lsp_cmd.rs index a41bb877991..a78a0d4c3d7 100644 --- a/tooling/nargo_cli/src/cli/lsp_cmd.rs +++ b/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -2,6 +2,7 @@ use async_lsp::{ client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer, tracing::TracingLayer, }; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use noir_lsp::NargoLspService; use tower::ServiceBuilder; @@ -30,8 +31,7 @@ pub(crate) fn run( runtime.block_on(async { let (server, _) = async_lsp::MainLoop::new_server(|client| { - #[allow(deprecated)] - let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + let blackbox_solver = Bn254BlackBoxSolver::new(); let router = NargoLspService::new(&client, blackbox_solver); ServiceBuilder::new() diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 809994219cb..575af9938b6 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -1,6 +1,7 @@ use std::io::Write; use acvm::BlackBoxFunctionSolver; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; use nargo::{ @@ -73,8 +74,7 @@ pub(crate) fn run( None => FunctionNameMatch::Anything, }; - #[allow(deprecated)] - let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + let blackbox_solver = Bn254BlackBoxSolver::new(); for package in &workspace { // By unwrapping here with `?`, we stop the test runner upon a package failing // TODO: We should run the whole suite even if there are failures in a package From 2529977acd684219f57ef086415557cc07af043b Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:40:52 +0000 Subject: [PATCH 084/137] fix: allow lsp to run inside of a docker container (#3876) # Description ## Problem\* Resolves ## Summary\* This PR re-adds a change which was removed from #3875 which is required for the LSP to run inside of a docker container. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/nargo_cli/src/cli/lsp_cmd.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tooling/nargo_cli/src/cli/lsp_cmd.rs b/tooling/nargo_cli/src/cli/lsp_cmd.rs index a78a0d4c3d7..4a2801eaf6e 100644 --- a/tooling/nargo_cli/src/cli/lsp_cmd.rs +++ b/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -1,6 +1,6 @@ use async_lsp::{ - client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer, - panic::CatchUnwindLayer, server::LifecycleLayer, tracing::TracingLayer, + concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer, + tracing::TracingLayer, }; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; @@ -39,7 +39,6 @@ pub(crate) fn run( .layer(LifecycleLayer::default()) .layer(CatchUnwindLayer::default()) .layer(ConcurrencyLayer::default()) - .layer(ClientProcessMonitorLayer::new(client)) .service(router) }); From 1dcfcc5265f618685a783504b1d4be213e4cda2d Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:56:23 +0000 Subject: [PATCH 085/137] feat: add support for codegenning multiple functions which use the same structs in their interface (#3868) # Description ## Problem\* Resolves ## Summary\* This PR allows `noir_codegen` to gracefully handle multiple functions functions. Previously these would cause TS errors if they shared a struct between their function signatures as it would be codegenned twice. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/noir_codegen/src/index.ts | 20 +++--- tooling/noir_codegen/src/noir_types.ts | 70 +++++++++---------- .../noir_codegen/test/assert_lt/src/main.nr | 12 +++- .../test/assert_lt/target/assert_lt.json | 2 +- tooling/noir_codegen/test/index.test.ts | 8 ++- 5 files changed, 62 insertions(+), 50 deletions(-) diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts index 8d45b76bd7d..7bef216097a 100644 --- a/tooling/noir_codegen/src/index.ts +++ b/tooling/noir_codegen/src/index.ts @@ -1,5 +1,6 @@ +import { AbiType } from '@noir-lang/noirc_abi'; import { CompiledCircuit } from '@noir-lang/types'; -import { PrimitiveTypesUsed, generateTsInterface } from './noir_types.js'; +import { PrimitiveTypesUsed, generateTsInterface, codegenStructDefinitions } from './noir_types.js'; // TODO: reenable this. See `abiTypeToTs` for reasoning. // export type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }; @@ -19,26 +20,25 @@ const codegenFunction = ( const args = function_signature.inputs.map(([name]) => `${name}`).join(', '); const args_with_types = function_signature.inputs.map(([name, type]) => `${name}: ${type}`).join(', '); - return ` -export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)}; + return `export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)}; export async function ${name}(${args_with_types}): Promise<${function_signature.returnValue}> { const program = new Noir(${name}_circuit); const args: InputMap = { ${args} }; const { returnValue } = await program.execute(args); return returnValue as ${function_signature.returnValue}; -}`; +} +`; }; export const codegen = (programs: [string, CompiledCircuit][]): string => { let results = [codegenPrelude]; const primitiveTypeMap = new Map(); + const structTypeMap = new Map(); const functions: string[] = []; for (const [name, program] of programs) { - const [types_string, function_sig] = generateTsInterface(program.abi, primitiveTypeMap); - functions.push(types_string); - functions.push('\n'); + const function_sig = generateTsInterface(program.abi, structTypeMap, primitiveTypeMap); functions.push(codegenFunction(name, stripUnwantedFields(program), function_sig)); } @@ -48,9 +48,11 @@ export const codegen = (programs: [string, CompiledCircuit][]): string => { primitiveTypeAliases.push(`export type ${value.aliasName} = ${value.tsType};`); } - results = results.concat(...primitiveTypeAliases, ...functions); + const structTypeDefinitions: string = codegenStructDefinitions(structTypeMap, primitiveTypeMap); + + results = results.concat(...primitiveTypeAliases, '', structTypeDefinitions, ...functions); - return results.filter((val) => val !== '').join('\n'); + return results.join('\n'); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/tooling/noir_codegen/src/noir_types.ts b/tooling/noir_codegen/src/noir_types.ts index ba4f8650b3b..0c0e2b7c60f 100644 --- a/tooling/noir_codegen/src/noir_types.ts +++ b/tooling/noir_codegen/src/noir_types.ts @@ -112,43 +112,26 @@ function getLastComponentOfPath(str: string): string { */ function generateStructInterfaces( type: AbiType, - output: Set, + structsEncountered: Map, primitiveTypeMap: Map, -): string { - let result = ''; - +) { // Edge case to handle the array of structs case. - if (type.kind === 'array' && type.type.kind === 'struct' && !output.has(getLastComponentOfPath(type.type.path))) { - result += generateStructInterfaces(type.type, output, primitiveTypeMap); + if ( + type.kind === 'array' && + type.type.kind === 'struct' && + !structsEncountered.has(getLastComponentOfPath(type.type.path)) + ) { + generateStructInterfaces(type.type, structsEncountered, primitiveTypeMap); } - if (type.kind !== 'struct') return result; - - // List of structs encountered while viewing this type that we need to generate - // bindings for. - const typesEncountered = new Set(); - - // Codegen the struct and then its fields, so that the structs fields - // are defined before the struct itself. - let codeGeneratedStruct = ''; - let codeGeneratedStructFields = ''; + if (type.kind !== 'struct') return; const structName = getLastComponentOfPath(type.path); - if (!output.has(structName)) { - codeGeneratedStruct += `export type ${structName} = {\n`; + if (!structsEncountered.has(structName)) { for (const field of type.fields) { - codeGeneratedStruct += ` ${field.name}: ${abiTypeToTs(field.type, primitiveTypeMap)};\n`; - typesEncountered.add(field.type); - } - codeGeneratedStruct += `};`; - output.add(structName); - - // Generate code for the encountered structs in the field above - for (const type of typesEncountered) { - codeGeneratedStructFields += generateStructInterfaces(type, output, primitiveTypeMap); + generateStructInterfaces(field.type, structsEncountered, primitiveTypeMap); } + structsEncountered.set(structName, type.fields); } - - return codeGeneratedStructFields + '\n' + codeGeneratedStruct; } /** @@ -158,22 +141,37 @@ function generateStructInterfaces( */ export function generateTsInterface( abiObj: Abi, + structsEncountered: Map, primitiveTypeMap: Map, -): [string, { inputs: [string, string][]; returnValue: string | null }] { - let result = ``; - const outputStructs = new Set(); - +): { inputs: [string, string][]; returnValue: string | null } { // Define structs for composite types for (const param of abiObj.parameters) { - result += generateStructInterfaces(param.type, outputStructs, primitiveTypeMap); + generateStructInterfaces(param.type, structsEncountered, primitiveTypeMap); } // Generating Return type, if it exists if (abiObj.return_type != null) { - result += generateStructInterfaces(abiObj.return_type.abi_type, outputStructs, primitiveTypeMap); + generateStructInterfaces(abiObj.return_type.abi_type, structsEncountered, primitiveTypeMap); + } + + return getTsFunctionSignature(abiObj, primitiveTypeMap); +} + +export function codegenStructDefinitions( + structsEncountered: Map, + primitiveTypeMap: Map, +): string { + let codeGeneratedStruct = ''; + + for (const [structName, structFields] of structsEncountered) { + codeGeneratedStruct += `export type ${structName} = {\n`; + for (const field of structFields) { + codeGeneratedStruct += ` ${field.name}: ${abiTypeToTs(field.type, primitiveTypeMap)};\n`; + } + codeGeneratedStruct += `};\n\n`; } - return [result, getTsFunctionSignature(abiObj, primitiveTypeMap)]; + return codeGeneratedStruct; } function getTsFunctionSignature( diff --git a/tooling/noir_codegen/test/assert_lt/src/main.nr b/tooling/noir_codegen/test/assert_lt/src/main.nr index 3b3e04ddece..32d5ff84722 100644 --- a/tooling/noir_codegen/test/assert_lt/src/main.nr +++ b/tooling/noir_codegen/test/assert_lt/src/main.nr @@ -3,17 +3,23 @@ struct MyStruct { bar: [str<5>; 3], } +struct NestedStruct { + foo: MyStruct, + bar: [MyStruct; 3], + baz: u64 +} + fn main( x: u64, y: pub u64, array: [u8; 5], - my_struct: MyStruct, + my_struct: NestedStruct, string: str<5> ) -> pub (u64, u64, MyStruct) { assert(array.len() == 5); - assert(my_struct.foo); + assert(my_struct.foo.foo); assert(string == "12345"); assert(x < y); - (x + y, 3, my_struct) + (x + y, 3, my_struct.foo) } diff --git a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json index a1ab87a99fe..b1865ca5f86 100644 --- a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json +++ b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json @@ -1 +1 @@ -{"noir_version":"0.19.4+55670ff82c270534a4bdb999ab0de5cea7017093","hash":11505576107297330043,"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"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":24}],"string":[{"start":24,"end":29}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[31,32,33,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/81XbU/CMBDu5hv4gopvvGw49JOJH1q2wfaN+E+AddFEgzGL/H250Go5dInumnhJ0z2jXJ9er7s+t4yxe7YyZ9lc1Y8N7CK8tWw1A28jvIPwLsJ7Cus5mfIPxquZqBlzmX5DPowiORpIEYoJH6TTJOZRPB0mIhFxEmeDJAxlEiWjdJqOeCqiUIo8TsNcOa7RceQ6DnUUl32EDxA+RPgI4QbCxwifIHyKcBPhM4TPEb5A+BLhK4RbCLcR7iDcRdhjX3mjzUb+jIlyxibPFgFPmYNlVnm2yXjOcps8O3Q8pU2eXTqemU2eHh3PGdQbl22aS8zZYXRn3/07L4FffLN0Mt9mXH3V99iqhuu80GOgzj+wzZxxjGdXjXFLxjg/+Kkb7/T/G8bvVRe/EQxzciqfvgok9QXEp+P4eQHpGT61bRHHw9ahqurrhjCeZfH7JU+OeAqfcM09wn2tEL/SD9x/Pjdl+8yr2do54dVMUJ6Ta0b/3TF92tr3gI53aJNnn3DfuwZHyE8o2FDIQYBr0Q1FFoQmiEsQlCAiociCWASBCKIQhCCIPxB8IPJA2IGYA9EBF3q4LMNcHlsv/E31XGUOyI1g2fpsvfDfqd5T/aQo5MtrERTzYJJlweKpeAzm7/Itf54vPgBYg2KL1RAAAA=="} \ No newline at end of file +{"noir_version":"0.22.0+528d7c9fa244611cd54636493c730e6ce0734ece","hash":9387426530776910287,"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":73}],"string":[{"start":73,"end":78}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[80,81,82,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/82Y6W/TQBDFNy5HylGgXAEKmHKF2xvbic3VUM62OaDwCYkPSeMIJFAQiui/j59iw+YFIoFnJVaKnF+OyXhmN7vvvVNKfVCTUUofTnZtGuwQL6SPssF7iPcS7yPen3H+myqLj+EVG7ps/JYZ1/fqQZA0aon2dc+rxf0o9IKwX490pMMoHNQi30+iIGrE/bjhxTrwEz0MY3+YBS7L5ejldVikuhwgPkh8iPgw8RLxEeKjxMeIl4mPE58gPkl8ivi0xT5X0hgVC32uKPk+n6G6nCU+R7xCfJ74AvFFYpf4EvEq8WXiK8RXia8RX7fY52oao2qhz1Ul3+cbVJebxLeIbxPfIb5LfI/YI9bENWKfOCAOievEDYt9jtIYkYU+R0q+zzHV5T7xA+KHxI+IHxOvETeJnxCvEz8lfkb8nPgF8UviV2p6/9+g9zeJt4hbxG31ax7lw8Y5oCk0h2zmuSGQZzLEGFjNc1Msz52hzTy35PJMbObZkstzYDPPtlyeO9ANjpodjnDOJSW39p1/z0vzC7+5dbHYZl072bWrJlosnxf5Z6DX1tXsnCkZz/N9xZnzmdIf4iwar+XfXzLeL3rzM8Uwf1wqZicrpPSBpCOX488DSdeImY8F4XrYWlRFY70VrOe8+v1lnh7lqTuC99wV7GuB+s39g/uf1828PnvFxtQ68YoNLblOXiv5/x0zpq2+v5HL27eZ57Zg31tGjpif2LCxkcNIzc1TbLIwDGESwhiEGYhNFqYfjD6YezD0YOLBuINZB4MOphxMLphSMKJgPsFwgskEYwlmkqsmptGqmphDMIRgAsH4gdkD8wRmBwwOmBowMmBewLCASYEFhk0ZBgSKDqMB5gIMBZgIEOUQ0RDOEMsQyBDFEMJrWR0hcnG4gJiFgIVohVCFOIUghXCCKMGBH/Vqq+nDy3L2vEidML8x/7bV9OHlfXZdya698Tj58nXsjkdubzBwdz+NP7qj78m34efR7g+ltqXnYRcAAA=="} \ No newline at end of file diff --git a/tooling/noir_codegen/test/index.test.ts b/tooling/noir_codegen/test/index.test.ts index 48199c13a67..70f3d5bbf89 100644 --- a/tooling/noir_codegen/test/index.test.ts +++ b/tooling/noir_codegen/test/index.test.ts @@ -2,11 +2,17 @@ import { expect } from 'chai'; import { assert_lt, MyStruct, u64 } from './codegen/index.js'; it('codegens a callable function', async () => { + const my_struct = { foo: true, bar: ['12345', '12345', '12345'] }; + const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt( '2', '3', [0, 0, 0, 0, 0], - { foo: true, bar: ['12345', '12345', '12345'] }, + { + foo: my_struct, + bar: [my_struct, my_struct, my_struct], + baz: '64', + }, '12345', ); From 8f5cd6c0b641b3970bf626e8910b2a4c7cc8c310 Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:09:02 +0100 Subject: [PATCH 086/137] feat(lsp): re-add code lens feature with improved performance (#3829) # Description ## Problem\* Code Lens part of protocol previously supported, attempted to do to many things at once. ## Summary\* By introducing statfullnes into LSP client we benefit from not repeating preparation procedure on each editor code lens requst. By reducing scope of interest when resolving code lens we gain speed - only single source file needs to get prepared at a time to provide code lenses to client. By introducing `enableCodeLens` initialization option (a2943b1: feat(lsp): accept option to disable code lens ) we are able to control if code lens feature is enabled. This will require plugin setting this value, while by default it is turned on. ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 9 +- tooling/lsp/Cargo.toml | 1 + tooling/lsp/src/lib.rs | 81 +++++- tooling/lsp/src/notifications/mod.rs | 85 ++++--- tooling/lsp/src/requests/code_lens_request.rs | 236 ++++++++++++++++++ tooling/lsp/src/requests/mod.rs | 44 +++- tooling/lsp/src/types.rs | 17 +- 7 files changed, 427 insertions(+), 46 deletions(-) create mode 100644 tooling/lsp/src/requests/code_lens_request.rs diff --git a/Cargo.lock b/Cargo.lock index 122a685ba61..26945d4ab8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1130,9 +1130,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1174,9 +1174,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ "cfg-if", ] @@ -2596,6 +2596,7 @@ dependencies = [ "serde", "serde_json", "serde_with", + "thiserror", "tokio", "tower", "wasm-bindgen", diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 5f5e701da67..6371bcbac19 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -23,6 +23,7 @@ serde_json.workspace = true tower.workspace = true async-lsp = { workspace = true, features = ["omni-trait"] } serde_with = "3.2.0" +thiserror.workspace = true fm.workspace = true [target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 2ad8096a13f..9887e5b8e96 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -7,7 +7,7 @@ use std::{ collections::HashMap, future::Future, ops::{self, ControlFlow}, - path::PathBuf, + path::{Path, PathBuf}, pin::Pin, task::{self, Poll}, }; @@ -18,19 +18,27 @@ use async_lsp::{ ResponseError, }; use fm::codespan_files as files; +use lsp_types::CodeLens; +use nargo::workspace::Workspace; +use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::{Context, FunctionNameMatch}, }; + +use fm::FileManager; + use notifications::{ on_did_change_configuration, on_did_change_text_document, on_did_close_text_document, on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized, }; use requests::{ - on_formatting, on_goto_definition_request, on_initialize, on_profile_run_request, on_shutdown, - on_test_run_request, on_tests_request, + on_code_lens_request, on_formatting, on_goto_definition_request, on_initialize, + on_profile_run_request, on_shutdown, on_test_run_request, on_tests_request, }; use serde_json::Value as JsonValue; +use thiserror::Error; use tower::Service; mod notifications; @@ -41,12 +49,20 @@ mod types; use solver::WrapperSolver; use types::{notification, request, NargoTest, NargoTestId, Position, Range, Url}; +#[derive(Debug, Error)] +pub enum LspError { + /// Error while Resolving Workspace. + #[error("Failed to Resolve Workspace - {0}")] + WorkspaceResolutionError(String), +} + // 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, input_files: HashMap, + cached_lenses: HashMap>, } impl LspState { @@ -56,6 +72,7 @@ impl LspState { root_path: None, solver: WrapperSolver(Box::new(solver)), input_files: HashMap::new(), + cached_lenses: HashMap::new(), } } } @@ -72,6 +89,7 @@ impl NargoLspService { .request::(on_initialize) .request::(on_formatting) .request::(on_shutdown) + .request::(on_code_lens_request) .request::(on_tests_request) .request::(on_test_run_request) .request::(on_profile_run_request) @@ -175,3 +193,60 @@ fn byte_span_to_range<'a, F: files::Files<'a> + ?Sized>( None } } + +pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result { + let package_root = find_file_manifest(file_path); + + let toml_path = package_root.ok_or_else(|| { + LspError::WorkspaceResolutionError(format!( + "Nargo.toml not found for file: {:?}", + file_path + )) + })?; + + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) + .map_err(|err| LspError::WorkspaceResolutionError(err.to_string()))?; + + Ok(workspace) +} + +/// Prepares a package from a source string +/// This is useful for situations when we don't need dependencies +/// and just need to operate on single file. +/// +/// Use case for this is the LSP server and code lenses +/// which operate on single file and need to understand this file +/// in order to offer code lenses to the user +fn prepare_source(source: String) -> (Context<'static>, CrateId) { + let root = Path::new(""); + let mut file_manager = FileManager::new(root); + let root_file_id = file_manager.add_file_with_source(Path::new("main.nr"), source).expect( + "Adding source buffer to file manager should never fail when file manager is empty", + ); + + let mut context = Context::new(file_manager); + + let root_crate_id = context.crate_graph.add_crate_root(root_file_id); + + (context, root_crate_id) +} + +#[test] +fn prepare_package_from_source_string() { + let source = r#" + fn main() { + let x = 1; + let y = 2; + let z = x + y; + } + "#; + + let (mut context, crate_id) = crate::prepare_source(source.to_string()); + let _check_result = noirc_driver::check_crate(&mut context, crate_id, false, false); + let main_func_id = context.get_main_function(&crate_id); + assert!(main_func_id.is_some()); +} diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index d0ca8679e7e..6cefaa134ce 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -2,18 +2,20 @@ use std::ops::ControlFlow; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use nargo::{insert_all_files_for_workspace_into_file_manager, prepare_package}; -use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{check_crate, file_manager_with_stdlib}; use noirc_errors::{DiagnosticKind, FileDiagnostic}; +use crate::requests::collect_lenses_for_package; use crate::types::{ notification, Diagnostic, DiagnosticSeverity, DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, - DidSaveTextDocumentParams, InitializedParams, LogMessageParams, MessageType, NargoPackageTests, - PublishDiagnosticsParams, + DidSaveTextDocumentParams, InitializedParams, NargoPackageTests, PublishDiagnosticsParams, }; -use crate::{byte_span_to_range, get_package_tests_in_crate, LspState}; +use crate::{ + byte_span_to_range, get_package_tests_in_crate, prepare_source, + resolve_workspace_for_source_path, LspState, +}; pub(super) fn on_initialized( _state: &mut LspState, @@ -42,7 +44,38 @@ pub(super) fn on_did_change_text_document( params: DidChangeTextDocumentParams, ) -> ControlFlow> { let text = params.content_changes.into_iter().next().unwrap().text; - state.input_files.insert(params.text_document.uri.to_string(), text); + state.input_files.insert(params.text_document.uri.to_string(), text.clone()); + + let (mut context, crate_id) = prepare_source(text); + let _ = check_crate(&mut context, crate_id, false, false); + + let workspace = match resolve_workspace_for_source_path( + params.text_document.uri.to_file_path().unwrap().as_path(), + ) { + Ok(workspace) => workspace, + Err(lsp_error) => { + return ControlFlow::Break(Err(ResponseError::new( + ErrorCode::REQUEST_FAILED, + lsp_error.to_string(), + ) + .into())) + } + }; + let package = match workspace.members.first() { + Some(package) => package, + None => { + return ControlFlow::Break(Err(ResponseError::new( + ErrorCode::REQUEST_FAILED, + "Selected workspace has no members", + ) + .into())) + } + }; + + let lenses = collect_lenses_for_package(&context, crate_id, &workspace, package, None); + + state.cached_lenses.insert(params.text_document.uri.to_string(), lenses); + ControlFlow::Continue(()) } @@ -51,6 +84,7 @@ pub(super) fn on_did_close_text_document( params: DidCloseTextDocumentParams, ) -> ControlFlow> { state.input_files.remove(¶ms.text_document.uri.to_string()); + state.cached_lenses.remove(¶ms.text_document.uri.to_string()); ControlFlow::Continue(()) } @@ -69,34 +103,14 @@ pub(super) fn on_did_save_text_document( } }; - let package_root = find_file_manifest(file_path.as_path()); - - let toml_path = match package_root { - Some(toml_path) => toml_path, - None => { - // If we cannot find a manifest, we log a warning but return no diagnostics - // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps - let _ = state.client.log_message(LogMessageParams { - typ: MessageType::WARNING, - message: format!("Nargo.toml not found for file: {:}", file_path.display()), - }); - return ControlFlow::Continue(()); - } - }; - - let workspace = match resolve_workspace_from_toml( - &toml_path, - PackageSelection::All, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - ) { - Ok(workspace) => workspace, - Err(err) => { - // If we found a manifest, but the workspace is invalid, we raise an error about it + let workspace = match resolve_workspace_for_source_path(&file_path) { + Ok(value) => value, + Err(lsp_error) => { return ControlFlow::Break(Err(ResponseError::new( ErrorCode::REQUEST_FAILED, - format!("{err}"), + lsp_error.to_string(), ) - .into())); + .into())) } }; @@ -121,6 +135,15 @@ pub(super) fn on_did_save_text_document( }); } + let collected_lenses = crate::requests::collect_lenses_for_package( + &context, + crate_id, + &workspace, + package, + Some(&file_path), + ); + state.cached_lenses.insert(params.text_document.uri.to_string(), collected_lenses); + let fm = &context.file_manager; let files = fm.as_file_map(); diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs new file mode 100644 index 00000000000..4b1d38a137e --- /dev/null +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -0,0 +1,236 @@ +use std::future::{self, Future}; + +use async_lsp::{ErrorCode, ResponseError}; + +use nargo::{package::Package, workspace::Workspace}; +use noirc_driver::check_crate; +use noirc_frontend::hir::FunctionNameMatch; + +use crate::{ + byte_span_to_range, prepare_source, resolve_workspace_for_source_path, + types::{CodeLens, CodeLensParams, CodeLensResult, Command}, + LspState, +}; + +const ARROW: &str = "▶\u{fe0e}"; +const TEST_COMMAND: &str = "nargo.test"; +const TEST_CODELENS_TITLE: &str = "Run Test"; +const COMPILE_COMMAND: &str = "nargo.compile"; +const COMPILE_CODELENS_TITLE: &str = "Compile"; +const INFO_COMMAND: &str = "nargo.info"; +const INFO_CODELENS_TITLE: &str = "Info"; +const EXECUTE_COMMAND: &str = "nargo.execute"; +const EXECUTE_CODELENS_TITLE: &str = "Execute"; + +const PROFILE_COMMAND: &str = "nargo.profile"; +const PROFILE_CODELENS_TITLE: &str = "Profile"; + +fn with_arrow(title: &str) -> String { + format!("{ARROW} {title}") +} + +fn package_selection_args(workspace: &Workspace, package: &Package) -> Vec { + vec![ + "--program-dir".into(), + workspace.root_dir.display().to_string().into(), + "--package".into(), + package.name.to_string().into(), + ] +} + +pub(crate) fn on_code_lens_request( + state: &mut LspState, + params: CodeLensParams, +) -> impl Future> { + future::ready(on_code_lens_request_inner(state, params)) +} + +fn on_code_lens_request_inner( + state: &mut LspState, + params: CodeLensParams, +) -> Result { + let file_path = params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + if let Some(collected_lenses) = state.cached_lenses.get(¶ms.text_document.uri.to_string()) { + return Ok(Some(collected_lenses.clone())); + } + + let source_string = std::fs::read_to_string(&file_path).map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not read file from disk") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = workspace.members.first().unwrap(); + + let (mut context, crate_id) = prepare_source(source_string); + // We ignore the warnings and errors produced by compilation for producing code lenses + // because we can still get the test functions even if compilation fails + let _ = check_crate(&mut context, crate_id, false, false); + + let collected_lenses = + collect_lenses_for_package(&context, crate_id, &workspace, package, None); + + if collected_lenses.is_empty() { + state.cached_lenses.remove(¶ms.text_document.uri.to_string()); + Ok(None) + } else { + state + .cached_lenses + .insert(params.text_document.uri.to_string().clone(), collected_lenses.clone()); + Ok(Some(collected_lenses)) + } +} + +pub(crate) fn collect_lenses_for_package( + context: &noirc_frontend::macros_api::HirContext, + crate_id: noirc_frontend::macros_api::CrateId, + workspace: &Workspace, + package: &Package, + file_path: Option<&std::path::PathBuf>, +) -> Vec { + let mut lenses: Vec = vec![]; + let fm = &context.file_manager; + let files = fm.as_file_map(); + let tests = + context.get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Anything); + for (func_name, test_function) in tests { + let location = context.function_meta(&test_function.get_id()).name.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id) != *file_path { + continue; + } + } + + let range = byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let test_command = Command { + title: with_arrow(TEST_CODELENS_TITLE), + command: TEST_COMMAND.into(), + arguments: Some( + [ + package_selection_args(workspace, package), + vec!["--exact".into(), func_name.into()], + ] + .concat(), + ), + }; + + let test_lens = CodeLens { range, command: Some(test_command), data: None }; + + lenses.push(test_lens); + } + if package.is_binary() { + if let Some(main_func_id) = context.get_main_function(&crate_id) { + let location = context.function_meta(&main_func_id).name.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id) != *file_path { + return lenses; + } + } + + let range = + byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let compile_command = Command { + title: with_arrow(COMPILE_CODELENS_TITLE), + command: COMPILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + + let info_command = Command { + title: INFO_CODELENS_TITLE.to_string(), + command: INFO_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let info_lens = CodeLens { range, command: Some(info_command), data: None }; + + lenses.push(info_lens); + + let execute_command = Command { + title: EXECUTE_CODELENS_TITLE.to_string(), + command: EXECUTE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let execute_lens = CodeLens { range, command: Some(execute_command), data: None }; + + lenses.push(execute_lens); + + let profile_command = Command { + title: PROFILE_CODELENS_TITLE.to_string(), + command: PROFILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; + + lenses.push(profile_lens); + } + } + + if package.is_contract() { + // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying + for contract in context.get_all_contracts(&crate_id) { + let location = contract.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id) != *file_path { + continue; + } + } + + let range = + byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let compile_command = Command { + title: with_arrow(COMPILE_CODELENS_TITLE), + command: COMPILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + + let info_command = Command { + title: INFO_CODELENS_TITLE.to_string(), + command: INFO_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let info_lens = CodeLens { range, command: Some(info_command), data: None }; + + lenses.push(info_lens); + + let profile_command = Command { + title: PROFILE_CODELENS_TITLE.to_string(), + command: PROFILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; + + lenses.push(profile_lens); + } + } + + lenses +} diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index e2fdcdf08da..2711c597bcf 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -1,9 +1,10 @@ use std::future::Future; -use crate::types::InitializeParams; +use crate::types::{CodeLensOptions, InitializeParams}; use async_lsp::ResponseError; use lsp_types::{Position, TextDocumentSyncCapability, TextDocumentSyncKind}; use nargo_fmt::Config; +use serde::{Deserialize, Serialize}; use crate::{ types::{InitializeResult, NargoCapability, NargoTestsOptions, ServerCapabilities}, @@ -20,25 +21,58 @@ use crate::{ // They are not attached to the `NargoLspService` struct so they can be unit tested with only `LspState` // and params passed in. +mod code_lens_request; mod goto_definition; mod profile_run; mod test_run; mod tests; pub(crate) use { + code_lens_request::collect_lenses_for_package, code_lens_request::on_code_lens_request, goto_definition::on_goto_definition_request, profile_run::on_profile_run_request, test_run::on_test_run_request, tests::on_tests_request, }; +/// LSP client will send initialization request after the server has started. +/// [InitializeParams].`initialization_options` will contain the options sent from the client. +#[derive(Debug, Deserialize, Serialize)] +struct LspInitializationOptions { + /// Controls whether code lens is enabled by the server + /// By default this will be set to true (enabled). + #[serde(rename = "enableCodeLens", default = "default_enable_code_lens")] + enable_code_lens: bool, +} + +fn default_enable_code_lens() -> bool { + true +} + +impl Default for LspInitializationOptions { + fn default() -> Self { + Self { enable_code_lens: default_enable_code_lens() } + } +} + pub(crate) fn on_initialize( state: &mut LspState, params: InitializeParams, ) -> impl Future> { state.root_path = params.root_uri.and_then(|root_uri| root_uri.to_file_path().ok()); - async { + let initialization_options: LspInitializationOptions = params + .initialization_options + .and_then(|value| serde_json::from_value(value).ok()) + .unwrap_or_default(); + + async move { let text_document_sync = TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL); + let code_lens = if initialization_options.enable_code_lens { + Some(CodeLensOptions { resolve_provider: Some(false) }) + } else { + None + }; + let nargo = NargoCapability { tests: Some(NargoTestsOptions { fetch: Some(true), @@ -50,6 +84,7 @@ pub(crate) fn on_initialize( Ok(InitializeResult { capabilities: ServerCapabilities { text_document_sync: Some(text_document_sync), + code_lens_provider: code_lens, document_formatting_provider: true, nargo: Some(nargo), definition_provider: Some(lsp_types::OneOf::Left(true)), @@ -105,7 +140,9 @@ pub(crate) fn on_shutdown( #[cfg(test)] mod initialization { use async_lsp::ClientSocket; - use lsp_types::{InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind}; + use lsp_types::{ + CodeLensOptions, InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind, + }; use tokio::test; use crate::{ @@ -125,6 +162,7 @@ mod initialization { text_document_sync: Some(TextDocumentSyncCapability::Kind( TextDocumentSyncKind::FULL )), + code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(false) }), document_formatting_provider: true, .. } diff --git a/tooling/lsp/src/types.rs b/tooling/lsp/src/types.rs index 48c412eb5ad..b2960964e7c 100644 --- a/tooling/lsp/src/types.rs +++ b/tooling/lsp/src/types.rs @@ -9,10 +9,10 @@ use std::collections::{BTreeMap, HashMap}; // Re-providing lsp_types that we don't need to override pub(crate) use lsp_types::{ - Diagnostic, DiagnosticSeverity, DidChangeConfigurationParams, DidChangeTextDocumentParams, - DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, - InitializeParams, InitializedParams, LogMessageParams, MessageType, Position, - PublishDiagnosticsParams, Range, ServerInfo, TextDocumentSyncCapability, Url, + CodeLens, CodeLensOptions, CodeLensParams, Command, Diagnostic, DiagnosticSeverity, + DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, + DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializedParams, + Position, PublishDiagnosticsParams, Range, ServerInfo, TextDocumentSyncCapability, Url, }; pub(crate) mod request { @@ -24,7 +24,9 @@ pub(crate) mod request { }; // Re-providing lsp_types that we don't need to override - pub(crate) use lsp_types::request::{Formatting, GotoDefinition, Shutdown}; + pub(crate) use lsp_types::request::{ + CodeLensRequest as CodeLens, Formatting, GotoDefinition, Shutdown, + }; #[derive(Debug)] pub(crate) struct Initialize; @@ -112,6 +114,10 @@ pub(crate) struct ServerCapabilities { #[serde(skip_serializing_if = "Option::is_none")] pub(crate) definition_provider: Option>, + /// The server provides code lens. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) code_lens_provider: Option, + /// The server provides document formatting. pub(crate) document_formatting_provider: bool, @@ -214,4 +220,5 @@ pub(crate) struct NargoProfileRunResult { pub(crate) opcodes_counts: HashMap, } +pub(crate) type CodeLensResult = Option>; pub(crate) type GotoDefinitionResult = Option; From 836f17145c2901060706294461c2d282dd121b3e Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 19 Dec 2023 16:31:10 +0000 Subject: [PATCH 087/137] chore!: Rename Arithmetic opcode to AssertZero (#3840) # Description When this opcode is given to a backend, they assert that the expression inside of the opcode is zero, so this changes the naming to more align with that. This is breaking as it does change the serialization that backends use ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- acvm-repo/acir/acir_docs.md | 14 ++++----- acvm-repo/acir/codegen/acir.cpp | 24 +++++++-------- acvm-repo/acir/src/circuit/mod.rs | 2 +- acvm-repo/acir/src/circuit/opcodes.rs | 4 +-- .../acir/src/native_types/expression/mod.rs | 14 ++++++--- .../acir/tests/test_program_serialization.rs | 2 +- acvm-repo/acvm/src/compiler/optimizers/mod.rs | 4 +-- .../compiler/optimizers/redundant_range.rs | 12 ++++---- .../acvm/src/compiler/transformers/csat.rs | 14 ++++----- .../acvm/src/compiler/transformers/mod.rs | 6 ++-- acvm-repo/acvm/src/pwg/arithmetic.rs | 30 +++++++++---------- acvm-repo/acvm/src/pwg/memory_op.rs | 4 +-- acvm-repo/acvm/src/pwg/mod.rs | 10 +++---- acvm-repo/acvm/tests/solver.rs | 22 +++++++------- .../test/browser/execute_circuit.test.ts | 4 +-- .../acvm_js/test/node/execute_circuit.test.ts | 4 +-- .../ssa/acir_gen/acir_ir/generated_acir.rs | 4 +-- .../backend_interface/src/smart_contract.rs | 2 +- tooling/debugger/src/context.rs | 2 +- 19 files changed, 92 insertions(+), 86 deletions(-) diff --git a/acvm-repo/acir/acir_docs.md b/acvm-repo/acir/acir_docs.md index eb532c9ae0c..fd89b3f292b 100644 --- a/acvm-repo/acir/acir_docs.md +++ b/acvm-repo/acir/acir_docs.md @@ -55,14 +55,14 @@ Some opcodes are not constrained, which mean they will not be used by the provin Finally, some opcodes will have a predicate, whose value is 0 or 1. Its purpose is to nullify the opcode when the value is 0, so that it has no effect. Note that removing the opcode is not a solution because this modifies the circuit (the circuit being mainly the list of the opcodes). -*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on Arithmetic expressions of witnesses. We call an arithmetic expression a linear combination of witnesses and/or products of two witnesses (and also a constant term). A single witness is a (simple) arithmetic expression, and conversly, an arithmetic expression can be turned into a single witness using an arithmetic opcode (see below). So basically, using witnesses or arithmetic expressions is equivalent, but the latter can avoid the creation of witness in some cases. +*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on expressions of witnesses. We call an expression a linear combination of witnesses and/or products of two witnesses (and also a constant term). A single witness is a (simple) expression, and conversely, an expression can be turned into a single witness using an assert-zero opcode (see below). So basically, using witnesses or expressions is equivalent, but the latter can avoid the creation of witness in some cases. -### Arithmetic opcode -An arithmetic opcode adds the constraint that P(w) = 0, where w=(w_1,..w_n) is a tuple of n witnesses, and P is a multi-variate polynomial of total degree at most 2. +### AssertZero opcode +An AssertZero opcode adds the constraint that P(w) = 0, where w=(w_1,..w_n) is a tuple of n witnesses, and P is a multi-variate polynomial of total degree at most 2. The coefficients ${q_M}_{i,j}, q_i,q_c$ of the polynomial are known values which define the opcode. -A general expression of arithmetic opcode is the following: $\sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0$ +A general expression of assert-zero opcode is the following: $\sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0$ -An arithmetic opcode can be used to: +An assert-zero opcode can be used to: - **express a constraint** on witnesses; for instance to express that a witness $w$ is a boolean, you can add the opcode: $w*w-w=0$ - or, to **compute the value** of an arithmetic operation of some inputs. For instance, to multiply two witnesses $x$ and $y$, you would use the opcode $z-x*y=0$, which would constraint $z$ to be $x*y$. @@ -70,7 +70,7 @@ An arithmetic opcode can be used to: The solver expects that at most one witness is not known when executing the opcode. ### BlackBoxFuncCall opcode -These opcodes represent a specific computation. Even if any computation can be done using only arithmetic opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. +These opcodes represent a specific computation. Even if any computation can be done using only assert-zero opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. All black box functions takes as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. Some more advanced computations assume that the proving system has an 'embedded curve'. It is a curve that cycle with the main curve of the proving system, i.e the scalar field of the embedded curve is the base field of the main one, and vice-versa. The curves used by the proving system are dependent on the proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the embedded curve. @@ -180,7 +180,7 @@ This opcode is used as a hint for the solver when executing (solving) the circui - predicate: an arithmetic expression that disable the opcode when it is null. Let's see an example with euclidian division. -The normal way to compute a/b, where a and b are 8-bits integers, is to implement Euclid algorithm which computes in a loop (or recursively) modulos of the kind 'a mod b'. Doing this computation requires a lot of steps to be properly implemented in ACIR, especially the loop with a condition. However, euclidian division can be easily constrained with one arithmetic opcode: a = bq+r, assuming q is 8 bits and r bincodeSerialize() const; - static Arithmetic bincodeDeserialize(std::vector); + static AssertZero bincodeDeserialize(std::vector); }; struct BlackBoxFuncCall { @@ -818,7 +818,7 @@ namespace Circuit { static MemoryInit bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -4268,20 +4268,20 @@ Circuit::Opcode serde::Deserializable::deserialize(Deserializer namespace Circuit { - inline bool operator==(const Opcode::Arithmetic &lhs, const Opcode::Arithmetic &rhs) { + inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Opcode::Arithmetic::bincodeSerialize() const { + inline std::vector Opcode::AssertZero::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::Arithmetic Opcode::Arithmetic::bincodeDeserialize(std::vector input) { + inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -4292,14 +4292,14 @@ namespace Circuit { template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Arithmetic &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::AssertZero &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Arithmetic serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Arithmetic obj; +Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 99ab389e31e..df58b949b85 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -277,7 +277,7 @@ mod tests { let circuit = Circuit { current_witness_index: 0, opcodes: vec![ - Opcode::Arithmetic(crate::native_types::Expression { + Opcode::AssertZero(crate::native_types::Expression { mul_terms: vec![], linear_combinations: vec![], q_c: FieldElement::from(8u128), diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 0e15fe3757c..ac5ea0b8a69 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -13,7 +13,7 @@ pub use memory_operation::{BlockId, MemOp}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum Opcode { - Arithmetic(Expression), + AssertZero(Expression), /// Calls to "gadgets" which rely on backends implementing support for specialized constraints. /// /// Often used for exposing more efficient implementations of SNARK-unfriendly computations. @@ -36,7 +36,7 @@ pub enum Opcode { impl std::fmt::Display for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Opcode::Arithmetic(expr) => { + Opcode::AssertZero(expr) => { write!(f, "EXPR [ ")?; for i in &expr.mul_terms { write!(f, "({}, _{}, _{}) ", i.0, i.1.witness_index(), i.2.witness_index())?; diff --git a/acvm-repo/acir/src/native_types/expression/mod.rs b/acvm-repo/acir/src/native_types/expression/mod.rs index fe729720663..402aa3eb3a6 100644 --- a/acvm-repo/acir/src/native_types/expression/mod.rs +++ b/acvm-repo/acir/src/native_types/expression/mod.rs @@ -8,7 +8,7 @@ mod ordering; // In the addition polynomial // We can have arbitrary fan-in/out, so we need more than wL,wR and wO -// When looking at the arithmetic opcode for the quotient polynomial in standard plonk +// When looking at the assert-zero opcode for the quotient polynomial in standard plonk // You can think of it as fan-in 2 and fan out-1 , or you can think of it as fan-in 1 and fan-out 2 // // In the multiplication polynomial @@ -16,7 +16,7 @@ mod ordering; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct Expression { // To avoid having to create intermediate variables pre-optimization - // We collect all of the multiplication terms in the arithmetic opcode + // We collect all of the multiplication terms in the assert-zero opcode // A multiplication term if of the form q_M * wL * wR // Hence this vector represents the following sum: q_M1 * wL1 * wR1 + q_M2 * wL2 * wR2 + .. + pub mul_terms: Vec<(FieldElement, Witness, Witness)>, @@ -42,7 +42,7 @@ impl std::fmt::Display for Expression { if let Some(witness) = self.to_witness() { write!(f, "x{}", witness.witness_index()) } else { - write!(f, "%{:?}%", crate::circuit::opcodes::Opcode::Arithmetic(self.clone())) + write!(f, "%{:?}%", crate::circuit::opcodes::Opcode::AssertZero(self.clone())) } } } @@ -178,7 +178,13 @@ impl Expression { self.linear_combinations.sort_by(|a, b| a.1.cmp(&b.1)); } - /// Checks if this polynomial can fit into one arithmetic identity + /// Checks if this expression can fit into one arithmetic identity + /// TODO: This needs to be reworded, arithmetic identity only makes sense in the context + /// TODO of PLONK, whereas we want expressions to be generic. + /// TODO: We just need to reword it to say exactly what its doing and + /// TODO then reference the fact that this is what plonk will accept. + /// TODO alternatively, we can define arithmetic identity in the context of expressions + /// TODO and then reference that. pub fn fits_in_one_identity(&self, width: usize) -> bool { // A Polynomial with more than one mul term cannot fit into one opcode if self.mul_terms.len() > 1 { diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index ff69ba34437..1f25b665573 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -24,7 +24,7 @@ use brillig::{HeapArray, RegisterIndex, RegisterOrMemory}; #[test] fn addition_circuit() { - let addition = Opcode::Arithmetic(Expression { + let addition = Opcode::AssertZero(Expression { mul_terms: Vec::new(), linear_combinations: vec![ (FieldElement::one(), Witness(1)), diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index 85a97c2c7dc..dd27c0bb937 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -31,8 +31,8 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { .opcodes .into_iter() .map(|opcode| { - if let Opcode::Arithmetic(arith_expr) = opcode { - Opcode::Arithmetic(GeneralOptimizer::optimize(arith_expr)) + if let Opcode::AssertZero(arith_expr) = opcode { + Opcode::AssertZero(GeneralOptimizer::optimize(arith_expr)) } else { opcode } diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 766d3674113..7b40c35960a 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -132,7 +132,7 @@ fn extract_range_opcode(opcode: &Opcode) -> Option<(Witness, u32)> { fn optimized_range_opcode(witness: Witness, num_bits: u32) -> Opcode { if num_bits == 1 { - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![(FieldElement::one(), witness, witness)], linear_combinations: vec![(-FieldElement::one(), witness)], q_c: FieldElement::zero(), @@ -234,13 +234,13 @@ mod tests { #[test] fn non_range_opcodes() { // The optimizer should not remove or change non-range opcodes - // The four Arithmetic opcodes should remain unchanged. + // The four AssertZero opcodes should remain unchanged. let mut circuit = test_circuit(vec![(Witness(1), 16), (Witness(1), 16)]); - circuit.opcodes.push(Opcode::Arithmetic(Expression::default())); - circuit.opcodes.push(Opcode::Arithmetic(Expression::default())); - circuit.opcodes.push(Opcode::Arithmetic(Expression::default())); - circuit.opcodes.push(Opcode::Arithmetic(Expression::default())); + circuit.opcodes.push(Opcode::AssertZero(Expression::default())); + circuit.opcodes.push(Opcode::AssertZero(Expression::default())); + circuit.opcodes.push(Opcode::AssertZero(Expression::default())); + circuit.opcodes.push(Opcode::AssertZero(Expression::default())); let acir_opcode_positions = circuit.opcodes.iter().enumerate().map(|(i, _)| i).collect(); let optimizer = RangeOptimizer::new(circuit); let (optimized_circuit, _) = optimizer.replace_redundant_ranges(acir_opcode_positions); diff --git a/acvm-repo/acvm/src/compiler/transformers/csat.rs b/acvm-repo/acvm/src/compiler/transformers/csat.rs index 0d1ab87aae5..9e2e3091c74 100644 --- a/acvm-repo/acvm/src/compiler/transformers/csat.rs +++ b/acvm-repo/acvm/src/compiler/transformers/csat.rs @@ -62,7 +62,7 @@ impl CSatTransformer { } // Still missing dead witness optimization. - // To do this, we will need the whole set of arithmetic opcodes + // To do this, we will need the whole set of assert-zero opcodes // I think it can also be done before the local optimization seen here, as dead variables will come from the user pub(crate) fn transform( &mut self, @@ -84,7 +84,7 @@ impl CSatTransformer { opcode } - // This optimization will search for combinations of terms which can be represented in a single arithmetic opcode + // This optimization will search for combinations of terms which can be represented in a single assert-zero opcode // Case 1 : qM * wL * wR + qL * wL + qR * wR + qO * wO + qC // This polynomial does not require any further optimizations, it can be safely represented in one opcode // ie a polynomial with 1 mul(bi-variate) term and 3 (univariate) terms where 2 of those terms match the bivariate term @@ -93,13 +93,13 @@ impl CSatTransformer { // // // Case 2: qM * wL * wR + qL * wL + qR * wR + qO * wO + qC + qM2 * wL2 * wR2 + qL * wL2 + qR * wR2 + qO * wO2 + qC2 - // This polynomial cannot be represented using one arithmetic opcode. + // This polynomial cannot be represented using one assert-zero opcode. // // This algorithm will first extract the first full opcode(if possible): // t = qM * wL * wR + qL * wL + qR * wR + qO * wO + qC // // The polynomial now looks like so t + qM2 * wL2 * wR2 + qL * wL2 + qR * wR2 + qO * wO2 + qC2 - // This polynomial cannot be represented using one arithmetic opcode. + // This polynomial cannot be represented using one assert-zero opcode. // // This algorithm will then extract the second full opcode(if possible): // t2 = qM2 * wL2 * wR2 + qL * wL2 + qR * wR2 + qO * wO2 + qC2 @@ -121,7 +121,7 @@ impl CSatTransformer { // If the opcode only has one mul term, then this algorithm cannot optimize it any further // Either it can be represented in a single arithmetic equation or it's fan-in is too large and we need intermediate variables for those // large-fan-in optimization is not this algorithms purpose. - // If the opcode has 0 mul terms, then it is an add opcode and similarly it can either fit into a single arithmetic opcode or it has a large fan-in + // If the opcode has 0 mul terms, then it is an add opcode and similarly it can either fit into a single assert-zero opcode or it has a large fan-in if opcode.mul_terms.len() <= 1 { return opcode; } @@ -194,7 +194,7 @@ impl CSatTransformer { } } - // Now we have used up 2 spaces in our arithmetic opcode. The width now dictates, how many more we can add + // Now we have used up 2 spaces in our assert-zero opcode. The width now dictates, how many more we can add let mut remaining_space = self.width - 2 - 1; // We minus 1 because we need an extra space to contain the intermediate variable // Keep adding terms until we have no more left, or we reach the width let mut remaining_linear_terms = @@ -325,7 +325,7 @@ impl CSatTransformer { // Then use intermediate variables again to squash the fan-in, so that it can fit into the appropriate width // First check if this polynomial actually needs a partial opcode optimization - // There is the chance that it fits perfectly within the arithmetic opcode + // There is the chance that it fits perfectly within the assert-zero opcode if opcode.fits_in_one_identity(self.width) { return opcode; } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index 2a3e28c536a..eef8d7bee44 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -63,7 +63,7 @@ pub(super) fn transform_internal( // TODO or at the very least, we could put all of it inside of CSatOptimizer pass let mut new_acir_opcode_positions: Vec = Vec::with_capacity(acir_opcode_positions.len()); - // Optimize the arithmetic gates by reducing them into the correct width and + // Optimize the assert-zero gates by reducing them into the correct width and // creating intermediate variables when necessary let mut transformed_opcodes = Vec::new(); @@ -73,7 +73,7 @@ pub(super) fn transform_internal( let mut intermediate_variables: IndexMap = IndexMap::new(); for (index, opcode) in acir.opcodes.into_iter().enumerate() { match opcode { - Opcode::Arithmetic(arith_expr) => { + Opcode::AssertZero(arith_expr) => { let len = intermediate_variables.len(); let arith_expr = transformer.transform( @@ -96,7 +96,7 @@ pub(super) fn transform_internal( new_opcodes.push(arith_expr); for opcode in new_opcodes { new_acir_opcode_positions.push(acir_opcode_positions[index]); - transformed_opcodes.push(Opcode::Arithmetic(opcode)); + transformed_opcodes.push(Opcode::AssertZero(opcode)); } } Opcode::BlackBoxFuncCall(ref func) => { diff --git a/acvm-repo/acvm/src/pwg/arithmetic.rs b/acvm-repo/acvm/src/pwg/arithmetic.rs index 93a39fb249c..81462ea495e 100644 --- a/acvm-repo/acvm/src/pwg/arithmetic.rs +++ b/acvm-repo/acvm/src/pwg/arithmetic.rs @@ -5,9 +5,9 @@ use acir::{ use super::{insert_value, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError}; -/// An Arithmetic solver will take a Circuit's arithmetic opcodes with witness assignments +/// An Expression solver will take a Circuit's assert-zero opcodes with witness assignments /// and create the other witness variables -pub(super) struct ArithmeticSolver; +pub(super) struct ExpressionSolver; #[allow(clippy::enum_variant_names)] pub(super) enum OpcodeStatus { @@ -22,17 +22,17 @@ pub(crate) enum MulTerm { Solved(FieldElement), } -impl ArithmeticSolver { +impl ExpressionSolver { /// Derives the rest of the witness based on the initial low level variables pub(super) fn solve( initial_witness: &mut WitnessMap, opcode: &Expression, ) -> Result<(), OpcodeResolutionError> { - let opcode = &ArithmeticSolver::evaluate(opcode, initial_witness); + let opcode = &ExpressionSolver::evaluate(opcode, initial_witness); // Evaluate multiplication term - let mul_result = ArithmeticSolver::solve_mul_term(opcode, initial_witness); + let mul_result = ExpressionSolver::solve_mul_term(opcode, initial_witness); // Evaluate the fan-in terms - let opcode_status = ArithmeticSolver::solve_fan_in_term(opcode, initial_witness); + let opcode_status = ExpressionSolver::solve_fan_in_term(opcode, initial_witness); match (mul_result, opcode_status) { (MulTerm::TooManyUnknowns, _) | (_, OpcodeStatus::OpcodeUnsolvable) => { @@ -126,7 +126,7 @@ impl ArithmeticSolver { } } - /// Returns the evaluation of the multiplication term in the arithmetic opcode + /// Returns the evaluation of the multiplication term in the expression /// If the witness values are not known, then the function returns a None /// XXX: Do we need to account for the case where 5xy + 6x = 0 ? We do not know y, but it can be solved given x . But I believe x can be solved with another opcode /// XXX: What about making a mul opcode = a constant 5xy + 7 = 0 ? This is the same as the above. @@ -135,11 +135,11 @@ impl ArithmeticSolver { // We are assuming it has been optimized. match arith_opcode.mul_terms.len() { 0 => MulTerm::Solved(FieldElement::zero()), - 1 => ArithmeticSolver::solve_mul_term_helper( + 1 => ExpressionSolver::solve_mul_term_helper( &arith_opcode.mul_terms[0], witness_assignments, ), - _ => panic!("Mul term in the arithmetic opcode must contain either zero or one term"), + _ => panic!("Mul term in the assert-zero opcode must contain either zero or one term"), } } @@ -186,7 +186,7 @@ impl ArithmeticSolver { let mut result = FieldElement::zero(); for term in arith_opcode.linear_combinations.iter() { - let value = ArithmeticSolver::solve_fan_in_term_helper(term, witness_assignments); + let value = ExpressionSolver::solve_fan_in_term_helper(term, witness_assignments); match value { Some(a) => result += a, None => { @@ -212,7 +212,7 @@ impl ArithmeticSolver { pub(super) fn evaluate(expr: &Expression, initial_witness: &WitnessMap) -> Expression { let mut result = Expression::default(); for &(c, w1, w2) in &expr.mul_terms { - let mul_result = ArithmeticSolver::solve_mul_term_helper(&(c, w1, w2), initial_witness); + let mul_result = ExpressionSolver::solve_mul_term_helper(&(c, w1, w2), initial_witness); match mul_result { MulTerm::OneUnknown(v, w) => { if !v.is_zero() { @@ -228,7 +228,7 @@ impl ArithmeticSolver { } } for &(c, w) in &expr.linear_combinations { - if let Some(f) = ArithmeticSolver::solve_fan_in_term_helper(&(c, w), initial_witness) { + if let Some(f) = ExpressionSolver::solve_fan_in_term_helper(&(c, w), initial_witness) { result.q_c += f; } else if !c.is_zero() { result.linear_combinations.push((c, w)); @@ -240,7 +240,7 @@ impl ArithmeticSolver { } #[test] -fn arithmetic_smoke_test() { +fn expression_solver_smoke_test() { let a = Witness(0); let b = Witness(1); let c = Witness(2); @@ -274,8 +274,8 @@ fn arithmetic_smoke_test() { values.insert(c, FieldElement::from(1_i128)); values.insert(d, FieldElement::from(1_i128)); - assert_eq!(ArithmeticSolver::solve(&mut values, &opcode_a), Ok(())); - assert_eq!(ArithmeticSolver::solve(&mut values, &opcode_b), Ok(())); + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_a), Ok(())); + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_b), Ok(())); assert_eq!(values.get(&a).unwrap(), &FieldElement::from(4_i128)); } diff --git a/acvm-repo/acvm/src/pwg/memory_op.rs b/acvm-repo/acvm/src/pwg/memory_op.rs index 42951dfa3c1..c1da2cd95cf 100644 --- a/acvm-repo/acvm/src/pwg/memory_op.rs +++ b/acvm-repo/acvm/src/pwg/memory_op.rs @@ -6,7 +6,7 @@ use acir::{ FieldElement, }; -use super::{arithmetic::ArithmeticSolver, get_value, insert_value, witness_to_value}; +use super::{arithmetic::ExpressionSolver, get_value, insert_value, witness_to_value}; use super::{ErrorLocation, OpcodeResolutionError}; type MemoryIndex = u32; @@ -75,7 +75,7 @@ impl MemoryOpSolver { // // In read operations, this corresponds to the witness index at which the value from memory will be written. // In write operations, this corresponds to the expression which will be written to memory. - let value = ArithmeticSolver::evaluate(&op.value, initial_witness); + let value = ExpressionSolver::evaluate(&op.value, initial_witness); // `operation == 0` implies a read operation. (`operation == 1` implies write operation). let is_read_operation = operation.is_zero(); diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index 859ad010dcd..41b96572658 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -10,7 +10,7 @@ use acir::{ }; use acvm_blackbox_solver::BlackBoxResolutionError; -use self::{arithmetic::ArithmeticSolver, directives::solve_directives, memory_op::MemoryOpSolver}; +use self::{arithmetic::ExpressionSolver, directives::solve_directives, memory_op::MemoryOpSolver}; use crate::BlackBoxFunctionSolver; use thiserror::Error; @@ -69,8 +69,8 @@ pub enum StepResult<'a, B: BlackBoxFunctionSolver> { // The most common being that one of its input has not been // assigned a value. // -// TODO: ExpressionHasTooManyUnknowns is specific for arithmetic expressions -// TODO: we could have a error enum for arithmetic failure cases in that module +// TODO: ExpressionHasTooManyUnknowns is specific for expression solver +// TODO: we could have a error enum for expression solver failure cases in that module // TODO that can be converted into an OpcodeNotSolvable or OpcodeResolutionError enum #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum OpcodeNotSolvable { @@ -253,7 +253,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let opcode = &self.opcodes[self.instruction_pointer]; let resolution = match opcode { - Opcode::Arithmetic(expr) => ArithmeticSolver::solve(&mut self.witness_map, expr), + Opcode::AssertZero(expr) => ExpressionSolver::solve(&mut self.witness_map, expr), Opcode::BlackBoxFuncCall(bb_func) => { blackbox::solve(self.backend, &mut self.witness_map, bb_func) } @@ -397,7 +397,7 @@ pub fn get_value( expr: &Expression, initial_witness: &WitnessMap, ) -> Result { - let expr = ArithmeticSolver::evaluate(expr, initial_witness); + let expr = ExpressionSolver::evaluate(expr, initial_witness); match expr.to_const() { Some(value) => Ok(value), None => Err(OpcodeResolutionError::OpcodeNotSolvable( diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index d578555c5dc..b4011a994a5 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -111,18 +111,18 @@ fn inversion_brillig_oracle_equivalence() { let opcodes = vec![ Opcode::Brillig(brillig_data), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], q_c: fe_0, }), // Opcode::Directive(Directive::Invert { x: w_z, result: w_z_inverse }), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![(fe_1, w_z, w_z_inverse)], linear_combinations: vec![], q_c: -fe_1, }), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(-fe_1, w_oracle), (fe_1, w_z_inverse)], q_c: fe_0, @@ -238,18 +238,18 @@ fn double_inversion_brillig_oracle() { let opcodes = vec![ Opcode::Brillig(brillig_data), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], q_c: fe_0, }), // Opcode::Directive(Directive::Invert { x: w_z, result: w_z_inverse }), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![(fe_1, w_z, w_z_inverse)], linear_combinations: vec![], q_c: -fe_1, }), - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(-fe_1, w_oracle), (fe_1, w_z_inverse)], q_c: fe_0, @@ -377,9 +377,9 @@ fn oracle_dependent_execution() { }; let opcodes = vec![ - Opcode::Arithmetic(equality_check), + Opcode::AssertZero(equality_check), Opcode::Brillig(brillig_data), - Opcode::Arithmetic(inverse_equality_check), + Opcode::AssertZero(inverse_equality_check), ]; let witness_assignments = @@ -516,7 +516,7 @@ fn unsatisfied_opcode_resolved() { values.insert(c, FieldElement::from(1_i128)); values.insert(d, FieldElement::from(2_i128)); - let opcodes = vec![Opcode::Arithmetic(opcode_a)]; + let opcodes = vec![Opcode::AssertZero(opcode_a)]; let mut acvm = ACVM::new(&StubbedBackend, &opcodes, values); let solver_status = acvm.solve(); assert_eq!( @@ -595,7 +595,7 @@ fn unsatisfied_opcode_resolved_brillig() { values.insert(w_y, FieldElement::from(1_i128)); values.insert(w_result, FieldElement::from(0_i128)); - let opcodes = vec![brillig_opcode, Opcode::Arithmetic(opcode_a)]; + let opcodes = vec![brillig_opcode, Opcode::AssertZero(opcode_a)]; let mut acvm = ACVM::new(&StubbedBackend, &opcodes, values); let solver_status = acvm.solve(); @@ -630,7 +630,7 @@ fn memory_operations() { predicate: None, }; - let expression = Opcode::Arithmetic(Expression { + let expression = Opcode::AssertZero(Expression { mul_terms: Vec::new(), linear_combinations: vec![ (FieldElement::one(), Witness(7)), diff --git a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts index 925c1a07eb8..259c51ed1c6 100644 --- a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts @@ -53,7 +53,7 @@ it('successfully processes simple brillig foreign call opcodes', async () => { expect(observedInputs).to.be.deep.eq(oracleCallInputs); // If incorrect value is written into circuit then execution should halt due to unsatisfied constraint in - // arithmetic opcode. Nevertheless, check that returned value was inserted correctly. + // assert-zero opcode. Nevertheless, check that returned value was inserted correctly. expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); @@ -79,7 +79,7 @@ it('successfully processes complex brillig foreign call opcodes', async () => { expect(observedInputs).to.be.deep.eq(oracleCallInputs); // If incorrect value is written into circuit then execution should halt due to unsatisfied constraint in - // arithmetic opcode. Nevertheless, check that returned value was inserted correctly. + // assert-zero opcode. Nevertheless, check that returned value was inserted correctly. expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); diff --git a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts index b28b9e72591..adee3c15312 100644 --- a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts @@ -46,7 +46,7 @@ it('successfully processes simple brillig foreign call opcodes', async () => { expect(observedInputs).to.be.deep.eq(oracleCallInputs); // If incorrect value is written into circuit then execution should halt due to unsatisfied constraint in - // arithmetic opcode. Nevertheless, check that returned value was inserted correctly. + // assert-zero opcode. Nevertheless, check that returned value was inserted correctly. expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); @@ -72,7 +72,7 @@ it('successfully processes complex brillig foreign call opcodes', async () => { expect(observedInputs).to.be.deep.eq(oracleCallInputs); // If incorrect value is written into circuit then execution should halt due to unsatisfied constraint in - // arithmetic opcode. Nevertheless, check that returned value was inserted correctly. + // assert-zero opcode. Nevertheless, check that returned value was inserted correctly. expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index f29d3c9ec05..0ea4d99123c 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -372,7 +372,7 @@ impl GeneratedAcir { /// If `expr` is not zero, then the constraint system will /// fail upon verification. pub(crate) fn assert_is_zero(&mut self, expr: Expression) { - self.push_opcode(AcirOpcode::Arithmetic(expr)); + self.push_opcode(AcirOpcode::AssertZero(expr)); } /// Returns a `Witness` that is constrained to be: @@ -552,7 +552,7 @@ impl GeneratedAcir { // Constrain the network output to out_expr for (b, o) in b.iter().zip(out_expr) { - self.push_opcode(AcirOpcode::Arithmetic(b - o)); + self.push_opcode(AcirOpcode::AssertZero(b - o)); } Ok(()) } diff --git a/tooling/backend_interface/src/smart_contract.rs b/tooling/backend_interface/src/smart_contract.rs index 5dac57c4072..2548079f8e3 100644 --- a/tooling/backend_interface/src/smart_contract.rs +++ b/tooling/backend_interface/src/smart_contract.rs @@ -47,7 +47,7 @@ mod tests { #[test] fn test_smart_contract() -> Result<(), BackendError> { let expression = &(Witness(1) + Witness(2)) - &Expression::from(Witness(3)); - let constraint = Opcode::Arithmetic(expression); + let constraint = Opcode::AssertZero(expression); let circuit = Circuit { current_witness_index: 4, diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 1475827fbea..a033d846ae7 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -492,7 +492,7 @@ mod tests { // z = x + y Opcode::Brillig(brillig_opcodes), // x + y - z = 0 - Opcode::Arithmetic(Expression { + Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], q_c: fe_0, From 96a71382e988aaf8f63bc2c2596bddbfc67040bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Tue, 19 Dec 2023 17:20:02 +0000 Subject: [PATCH 088/137] chore: making docs always deploy on master (#3877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR makes docs deploy on every merge to master. ## Problem\* Right now docs are only deployed when the "Publish Docs" workflow runs, which is everytime a release PR is merged. There's a workflow dispatch so we can go and manually deploy it (like @kevaundray is doing here](https://github.com/noir-lang/noir/actions/runs/7251799715) We don't like manual so we're deploying it every merge to master 😄 ## Summary\* - Makes `publish_docs` run on every merge - Removes `publish_docs` from the release-please workflow ## Additional Context This doesn't touch the new versioning system @TomAFrench cleverly put together. Versions are still generated each time release-please adds a new commit to its PR (I think). This is mostly _when_ to deploy --- .github/workflows/publish-docs.yml | 13 ++++--------- .github/workflows/release.yml | 15 --------------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 4ef7dd89777..9ea2f1e1491 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -1,12 +1,10 @@ name: Publish documentation on: - workflow_dispatch: - inputs: - noir-ref: - description: The noir reference to checkout - required: false - default: 'master' + push: + branches: + - master + paths: [docs/**] jobs: publish-docs: @@ -16,9 +14,6 @@ jobs: steps: - name: Checkout release branch uses: actions/checkout@v4 - with: - ref: ${{ inputs.noir-ref }} - token: ${{ secrets.NOIR_RELEASES_TOKEN }} - name: Setup Node.js uses: actions/setup-node@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b2393eaa8f..f9f6fe2fc54 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -120,21 +120,6 @@ jobs: token: ${{ secrets.NOIR_REPO_TOKEN }} inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}", "npm-tag": "latest" }' - publish-docs: - name: Publish docs - needs: [release-please] - if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest - - steps: - - name: Dispatch to publish-docs - uses: benc-uk/workflow-dispatch@v1 - with: - workflow: publish-docs.yml - ref: master - token: ${{ secrets.NOIR_REPO_TOKEN }} - inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}" }' - publish-acvm: name: Publish acvm needs: [release-please] From e1d1708f7c26777c9b81451754c2ae5528ae8a11 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:55:31 +0000 Subject: [PATCH 089/137] chore: fix spelling issues (#3880) # Description ## Problem\* Resolves ## Summary\* Fixes a bunch of spelling issues that github keeps complaining about. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acir/acir_docs.md | 16 ++++++++-------- cspell.json | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/acvm-repo/acir/acir_docs.md b/acvm-repo/acir/acir_docs.md index fd89b3f292b..1215ea22330 100644 --- a/acvm-repo/acir/acir_docs.md +++ b/acvm-repo/acir/acir_docs.md @@ -43,7 +43,7 @@ The values of the witnesses lie in the scalar field of the proving system. We wi *Remark*: The value of a partial witness is unique and fixed throughout a program execution, although in some rare cases, multiple values are possible for a same execution and witness (when there are several valid solutions to the constraints). Having multiple possible values for a witness may indicate that the circuit is not safe. -*Remark*: Why do we use the term partial witnesses? It is because the proving system may create other constraints and witnesses (especially with BlackBoxFuncCall, see below). A proof refers to a full witness assignements and their constraints. ACIR opcodes and their partial witnesses are still an intermediate representation before getting the full list of constraints and witnesses. For the sake of simplicity, we will refer to witness instead of partial witness from now on. +*Remark*: Why do we use the term partial witnesses? It is because the proving system may create other constraints and witnesses (especially with BlackBoxFuncCall, see below). A proof refers to a full witness assignments and their constraints. ACIR opcodes and their partial witnesses are still an intermediate representation before getting the full list of constraints and witnesses. For the sake of simplicity, we will refer to witness instead of partial witness from now on. ## ACIR Reference @@ -91,11 +91,11 @@ input: (witness, bit_size) **SHA256**: computes sha256 of the inputs - inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), constrainted to be the sha256 of the inputs. +- output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), constrained to be the sha256 of the inputs. **Blake2s**: computes the Blake2s hash of the inputs, as specified in https://tools.ietf.org/html/rfc7693 - inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of length 32, i.e a vector of 32 (FieldElement, 8), constrainted to be the blake2s of the inputs. +- output is a byte array of length 32, i.e a vector of 32 (FieldElement, 8), constrained to be the blake2s of the inputs. **SchnorrVerify**: Verify a Schnorr signature over the embedded curve @@ -114,7 +114,7 @@ The proving system decides how the message is to be hashed. Barretenberg uses Bl - output: 2 witnesses representing the x,y coordinates of the resulting Grumpkin point - domain separator: a constant public value (a field element) that you can use so that the commitment also depends on the domain separator. Noir uses 0 as domain separator. -The backend should handle proper conversion between the inputs being ACIR field elements and the scalar field of the embedded curve. In the case of Aztec's Barretenberg, the latter is bigger than the ACIR field so it is straightforward. The Peredersen generators are managed by the proving system. +The backend should handle proper conversion between the inputs being ACIR field elements and the scalar field of the embedded curve. In the case of Aztec's Barretenberg, the latter is bigger than the ACIR field so it is straightforward. The Pedersen generators are managed by the proving system. **PedersenHash**: Computes a Pedersen commitments of the inputs and their number, using generators of the embedded curve @@ -163,7 +163,7 @@ $a=low+high*2^{128},$ with $low, high < 2^{128}$ - verification_key: Vector of (FieldElement, 254) representing the verification key of the circuit being verified - public_inputs: Vector of (FieldElement, 254) representing the public inputs corresponding to the proof being verified - key_hash: one (FieldElement, 254). It should be the hash of the verification key. Barretenberg expects the Pedersen hash of the verification key -- input_aggregation_object: an optional vector of (FieldElement, 254). It is a blob of data specific to the proving sytem. +- input_aggregation_object: an optional vector of (FieldElement, 254). It is a blob of data specific to the proving system. - output_aggregation_object: Some witnesses returned by the function, representing some data internal to the proving system. This black box function does not fully verify a proof, what it does is verifying that the key_hash is indeed a hash of verification_key, allowing the user to use the verification key as private inputs and only have the key_hash as public input, which is more performant. @@ -179,8 +179,8 @@ This opcode is used as a hint for the solver when executing (solving) the circui - bytecode: assembly code representing the computation to perform within this opcode. The noir assembly specification is not part of this document. - predicate: an arithmetic expression that disable the opcode when it is null. -Let's see an example with euclidian division. -The normal way to compute a/b, where a and b are 8-bits integers, is to implement Euclid algorithm which computes in a loop (or recursively) modulos of the kind 'a mod b'. Doing this computation requires a lot of steps to be properly implemented in ACIR, especially the loop with a condition. However, euclidian division can be easily constrained with one assert-zero opcode: a = bq+r, assuming q is 8 bits and r Date: Tue, 19 Dec 2023 18:56:57 +0000 Subject: [PATCH 090/137] chore: delete source-resolver artifacts (#3881) # Description ## Problem\* Resolves ## Summary\* We've got some `source-resolver` artifacts clinging on to the repo which this PR deletes. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/source-resolver/lib-node/index.js | 32 ------------------- .../source-resolver/lib-node/index.js.map | 1 - .../source-resolver/lib-node/index_node.js | 20 ------------ .../lib-node/index_node.js.map | 1 - compiler/source-resolver/lib/index.js | 27 ---------------- compiler/source-resolver/lib/index.js.map | 1 - 6 files changed, 82 deletions(-) delete mode 100644 compiler/source-resolver/lib-node/index.js delete mode 100644 compiler/source-resolver/lib-node/index.js.map delete mode 100644 compiler/source-resolver/lib-node/index_node.js delete mode 100644 compiler/source-resolver/lib-node/index_node.js.map delete mode 100644 compiler/source-resolver/lib/index.js delete mode 100644 compiler/source-resolver/lib/index.js.map diff --git a/compiler/source-resolver/lib-node/index.js b/compiler/source-resolver/lib-node/index.js deleted file mode 100644 index 7de637b6853..00000000000 --- a/compiler/source-resolver/lib-node/index.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.initializeResolver = exports.read_file = void 0; -let resolveFunction = null; -const read_file = function (source_id) { - if (resolveFunction) { - const result = resolveFunction(source_id); - if (typeof result === 'string') { - return result; - } - else { - throw new Error('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)'); - } -}; -exports.read_file = read_file; -function initialize(noir_resolver) { - 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'); - } -} -function initializeResolver(resolver) { - resolveFunction = initialize(resolver); -} -exports.initializeResolver = initializeResolver; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index.js.map b/compiler/source-resolver/lib-node/index.js.map deleted file mode 100644 index 4ac7301ddc9..00000000000 --- a/compiler/source-resolver/lib-node/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,IAAI,eAAe,GAA2C,IAAI,CAAC;AAE5D,MAAM,SAAS,GAAG,UAAU,SAAiB;IAClD,IAAI,eAAe,EAAE;QACnB,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;YAC9B,OAAO,MAAM,CAAC;SACf;aAAM;YACL,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;SACH;KACF;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAC9E;AACH,CAAC,CAAC;AAdW,QAAA,SAAS,aAcpB;AAEF,SAAS,UAAU,CAAC,aAA4C;IAC9D,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;QACvC,OAAO,aAAa,CAAC;KACtB;SAAM;QACL,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;KACH;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,QAAuC;IACxE,eAAe,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC;AAFD,gDAEC"} \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index_node.js b/compiler/source-resolver/lib-node/index_node.js deleted file mode 100644 index 7d54737ce49..00000000000 --- a/compiler/source-resolver/lib-node/index_node.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -/// -Object.defineProperty(exports, "__esModule", { value: true }); -exports.read_file = exports.initializeResolver = void 0; -const index_js_1 = require("./index.js"); -Object.defineProperty(exports, "initializeResolver", { enumerable: true, get: function () { return index_js_1.initializeResolver; } }); -Object.defineProperty(exports, "read_file", { enumerable: true, get: function () { return index_js_1.read_file; } }); -(0, index_js_1.initializeResolver)((source_id) => { - let fileContent = ''; - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require('fs'); - fileContent = fs.readFileSync(source_id, { encoding: 'utf8' }); - } - catch (e) { - console.log(e); - } - return fileContent; -}); -//# sourceMappingURL=index_node.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib-node/index_node.js.map b/compiler/source-resolver/lib-node/index_node.js.map deleted file mode 100644 index 920818232c3..00000000000 --- a/compiler/source-resolver/lib-node/index_node.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index_node.js","sourceRoot":"","sources":["../src/index_node.ts"],"names":[],"mappings":";AAAA,8BAA8B;;;AAE9B,yCAA2D;AAclD,mGAdA,6BAAkB,OAcA;AAAE,0FAdA,oBAAS,OAcA;AAZtC,IAAA,6BAAkB,EAAC,CAAC,SAAiB,EAAE,EAAE;IACvC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI;QACF,8DAA8D;QAC9D,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAW,CAAC;KAC1E;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAChB;IACD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/compiler/source-resolver/lib/index.js b/compiler/source-resolver/lib/index.js deleted file mode 100644 index 079b4460592..00000000000 --- a/compiler/source-resolver/lib/index.js +++ /dev/null @@ -1,27 +0,0 @@ -let resolveFunction = null; -export const read_file = function (source_id) { - if (resolveFunction) { - const result = resolveFunction(source_id); - if (typeof result === 'string') { - return result; - } - else { - throw new Error('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)'); - } -}; -function initialize(noir_resolver) { - 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'); - } -} -export function initializeResolver(resolver) { - resolveFunction = initialize(resolver); -} -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/compiler/source-resolver/lib/index.js.map b/compiler/source-resolver/lib/index.js.map deleted file mode 100644 index e62ae1e4c8a..00000000000 --- a/compiler/source-resolver/lib/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,IAAI,eAAe,GAA2C,IAAI,CAAC;AAEnE,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,SAAiB;IAClD,IAAI,eAAe,EAAE;QACnB,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;YAC9B,OAAO,MAAM,CAAC;SACf;aAAM;YACL,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;SACH;KACF;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAC9E;AACH,CAAC,CAAC;AAEF,SAAS,UAAU,CAAC,aAA4C;IAC9D,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;QACvC,OAAO,aAAa,CAAC;KACtB;SAAM;QACL,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;KACH;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAuC;IACxE,eAAe,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC"} \ No newline at end of file From 13834d43bd876909cb50494a41b42297f7e6375b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 19 Dec 2023 17:28:37 -0300 Subject: [PATCH 091/137] feat: Implement DAP protocol in Nargo (#3627) # Description Implements the DAP protocol to allow a tool such as VS.Code to drive the debugger in a Noir binary project. A separate PR for the [VS.Code Noir extension](https://github.com/noir-lang/vscode-noir) will be submitted later. ## Problem Part of #3015 The beginning of this implementation was heavily inspired by @dmvict [implementation](https://github.com/noir-lang/noir/issues/3094) of an alternative debugger for Noir programs. ## Summary This PR implements a new `nargo` subcommand `dap`. This starts a DAP server in single session mode through stdin/stdout and waits for a launch request. Using the arguments in the launch request (`projectFolder`, and optionally `package` and `proverName`) it compiles the Noir binary package and starts it in debug mode. Through DAP requests, a tool can then step through the program, set breakpoints and list the generated opcodes using a disassemble request. ## Additional Context ## Documentation Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [X] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- Cargo.lock | 16 + Cargo.toml | 2 + tooling/debugger/Cargo.toml | 4 + tooling/debugger/src/context.rs | 224 ++++++++++- tooling/debugger/src/dap.rs | 568 +++++++++++++++++++++++++++ tooling/debugger/src/lib.rs | 15 + tooling/nargo_cli/Cargo.toml | 1 + tooling/nargo_cli/src/cli/dap_cmd.rs | 180 +++++++++ tooling/nargo_cli/src/cli/mod.rs | 5 + tooling/nargo_cli/src/errors.rs | 3 + 10 files changed, 1017 insertions(+), 1 deletion(-) create mode 100644 tooling/debugger/src/dap.rs create mode 100644 tooling/nargo_cli/src/cli/dap_cmd.rs diff --git a/Cargo.lock b/Cargo.lock index 26945d4ab8f..223f7eb2152 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1224,6 +1224,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "dap" +version = "0.4.1-alpha1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c7fc89d334ab745ba679f94c7314c9b17ecdcd923c111df6206e9fd7729fa9" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "darling" version = "0.20.3" @@ -2466,6 +2477,7 @@ dependencies = [ "color-eyre", "const_format", "criterion", + "dap", "dirs", "env_logger", "fm", @@ -2570,11 +2582,15 @@ version = "0.22.0" dependencies = [ "acvm", "codespan-reporting", + "dap", "easy-repl", + "fm", "nargo", + "noirc_driver", "noirc_errors", "noirc_printable_type", "owo-colors", + "serde_json", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index bec16277a9e..59d2af2fab3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,8 @@ gloo-utils = { version = "0.1", features = ["serde"] } js-sys = "0.3.62" getrandom = "0.2" +# Debugger +dap = "0.4.1-alpha1" cfg-if = "1.0.0" clap = { version = "4.3.19", features = ["derive", "env"] } diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index 53c71754da4..fba4d028d05 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -13,7 +13,11 @@ acvm.workspace = true nargo.workspace = true noirc_printable_type.workspace = true noirc_errors.workspace = true +noirc_driver.workspace = true +fm.workspace = true thiserror.workspace = true codespan-reporting.workspace = true +dap.workspace = true easy-repl = "0.2.1" owo-colors = "3" +serde_json.workspace = true \ No newline at end of file diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index a033d846ae7..06855e75c97 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -87,6 +87,109 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { .and_then(|location| self.debug_artifact.debug_symbols[0].opcode_location(location)) } + fn get_opcodes_sizes(&self) -> Vec { + self.get_opcodes() + .iter() + .map(|opcode| match opcode { + Opcode::Brillig(brillig_block) => brillig_block.bytecode.len(), + _ => 1, + }) + .collect() + } + + /// Offsets the given location by the given number of opcodes (including + /// Brillig opcodes). If the offset would move the location outside of a + /// valid circuit location, returns None and the number of remaining + /// opcodes/instructions left which span outside the valid range in the + /// second element of the returned tuple. + pub(super) fn offset_opcode_location( + &self, + location: &Option, + mut offset: i64, + ) -> (Option, i64) { + if offset == 0 { + return (*location, 0); + } + let Some(location) = location else { + return (None, offset); + }; + + let (mut acir_index, mut brillig_index) = match location { + OpcodeLocation::Acir(acir_index) => (*acir_index, 0), + OpcodeLocation::Brillig { acir_index, brillig_index } => (*acir_index, *brillig_index), + }; + let opcode_sizes = self.get_opcodes_sizes(); + if offset > 0 { + while offset > 0 { + let opcode_size = opcode_sizes[acir_index] as i64 - brillig_index as i64; + if offset >= opcode_size { + acir_index += 1; + offset -= opcode_size; + brillig_index = 0; + } else { + brillig_index += offset as usize; + offset = 0; + } + if acir_index >= opcode_sizes.len() { + return (None, offset); + } + } + } else { + while offset < 0 { + if brillig_index > 0 { + if brillig_index > (-offset) as usize { + brillig_index -= (-offset) as usize; + offset = 0; + } else { + offset += brillig_index as i64; + brillig_index = 0; + } + } else { + if acir_index == 0 { + return (None, offset); + } + acir_index -= 1; + let opcode_size = opcode_sizes[acir_index] as i64; + if opcode_size <= -offset { + offset += opcode_size; + } else { + brillig_index = (opcode_size + offset) as usize; + offset = 0; + } + } + } + } + if brillig_index > 0 { + (Some(OpcodeLocation::Brillig { acir_index, brillig_index }), 0) + } else { + (Some(OpcodeLocation::Acir(acir_index)), 0) + } + } + + pub(super) fn render_opcode_at_location(&self, location: &Option) -> String { + let opcodes = self.get_opcodes(); + match location { + None => String::from("invalid"), + Some(OpcodeLocation::Acir(acir_index)) => { + let opcode = &opcodes[*acir_index]; + if let Opcode::Brillig(ref brillig) = opcode { + let first_opcode = &brillig.bytecode[0]; + format!("BRILLIG {first_opcode:?}") + } else { + format!("{opcode:?}") + } + } + Some(OpcodeLocation::Brillig { acir_index, brillig_index }) => { + if let Opcode::Brillig(ref brillig) = opcodes[*acir_index] { + let opcode = &brillig.bytecode[*brillig_index]; + format!(" | {opcode:?}") + } else { + String::from(" | invalid") + } + } + } + } + fn step_brillig_opcode(&mut self) -> DebugCommandResult { let Some(mut solver) = self.brillig_solver.take() else { unreachable!("Missing Brillig solver"); @@ -311,6 +414,10 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.breakpoints.iter() } + pub(super) fn clear_breakpoints(&mut self) { + self.breakpoints.clear(); + } + pub(super) fn is_solved(&self) -> bool { matches!(self.acvm.get_status(), ACVMStatus::Solved) } @@ -327,7 +434,10 @@ mod tests { use acvm::{ acir::{ - circuit::brillig::{Brillig, BrilligInputs, BrilligOutputs}, + circuit::{ + brillig::{Brillig, BrilligInputs, BrilligOutputs}, + opcodes::BlockId, + }, native_types::Expression, }, brillig_vm::brillig::{ @@ -535,4 +645,116 @@ mod tests { assert!(matches!(result, DebugCommandResult::Done)); assert_eq!(context.get_current_opcode_location(), None); } + + #[test] + fn test_offset_opcode_location() { + let blackbox_solver = &StubbedSolver; + let opcodes = vec![ + Opcode::Brillig(Brillig { + inputs: vec![], + outputs: vec![], + bytecode: vec![BrilligOpcode::Stop, BrilligOpcode::Stop, BrilligOpcode::Stop], + predicate: None, + }), + Opcode::MemoryInit { block_id: BlockId(0), init: vec![] }, + Opcode::Brillig(Brillig { + inputs: vec![], + outputs: vec![], + bytecode: vec![BrilligOpcode::Stop, BrilligOpcode::Stop, BrilligOpcode::Stop], + predicate: None, + }), + Opcode::AssertZero(Expression::default()), + ]; + let circuit = Circuit { opcodes, ..Circuit::default() }; + let debug_artifact = + DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new(), warnings: vec![] }; + let context = DebugContext::new( + blackbox_solver, + &circuit, + &debug_artifact, + WitnessMap::new(), + Box::new(DefaultForeignCallExecutor::new(true)), + ); + + assert_eq!(context.offset_opcode_location(&None, 0), (None, 0)); + assert_eq!(context.offset_opcode_location(&None, 2), (None, 2)); + assert_eq!(context.offset_opcode_location(&None, -2), (None, -2)); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 0), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 1), + (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 2), + (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 3), + (Some(OpcodeLocation::Acir(1)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 4), + (Some(OpcodeLocation::Acir(2)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 5), + (Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 7), + (Some(OpcodeLocation::Acir(3)), 0) + ); + assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 8), (None, 0)); + assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 20), (None, 12)); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(1)), 2), + (Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), 0) + ); + assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), -1), (None, -1)); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), -10), + (None, -10) + ); + + assert_eq!( + context.offset_opcode_location( + &Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }), + -1 + ), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location( + &Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), + -2 + ), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(1)), -3), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(2)), -4), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location( + &Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), + -5 + ), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(3)), -7), + (Some(OpcodeLocation::Acir(0)), 0) + ); + assert_eq!( + context.offset_opcode_location(&Some(OpcodeLocation::Acir(2)), -2), + (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), 0) + ); + } } diff --git a/tooling/debugger/src/dap.rs b/tooling/debugger/src/dap.rs new file mode 100644 index 00000000000..1cc05e28a6b --- /dev/null +++ b/tooling/debugger/src/dap.rs @@ -0,0 +1,568 @@ +use std::collections::BTreeMap; +use std::io::{Read, Write}; +use std::str::FromStr; + +use acvm::acir::circuit::{Circuit, OpcodeLocation}; +use acvm::acir::native_types::WitnessMap; +use acvm::BlackBoxFunctionSolver; +use codespan_reporting::files::{Files, SimpleFile}; + +use crate::context::DebugCommandResult; +use crate::context::DebugContext; + +use dap::errors::ServerError; +use dap::events::StoppedEventBody; +use dap::prelude::Event; +use dap::requests::{Command, Request, SetBreakpointsArguments}; +use dap::responses::{ + ContinueResponse, DisassembleResponse, ResponseBody, ScopesResponse, SetBreakpointsResponse, + SetExceptionBreakpointsResponse, SetInstructionBreakpointsResponse, StackTraceResponse, + ThreadsResponse, +}; +use dap::server::Server; +use dap::types::{ + Breakpoint, DisassembledInstruction, Source, StackFrame, SteppingGranularity, + StoppedEventReason, Thread, +}; +use nargo::artifacts::debug::DebugArtifact; +use nargo::ops::DefaultForeignCallExecutor; + +use fm::FileId; +use noirc_driver::CompiledProgram; + +pub struct DapSession<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> { + server: Server, + context: DebugContext<'a, B>, + debug_artifact: &'a DebugArtifact, + running: bool, + source_to_opcodes: BTreeMap>, + next_breakpoint_id: i64, + instruction_breakpoints: Vec<(OpcodeLocation, i64)>, + source_breakpoints: BTreeMap>, +} + +// BTreeMap + +impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { + pub fn new( + server: Server, + solver: &'a B, + circuit: &'a Circuit, + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + ) -> Self { + let source_to_opcodes = Self::build_source_to_opcode_debug_mappings(debug_artifact); + let context = DebugContext::new( + solver, + circuit, + debug_artifact, + initial_witness, + Box::new(DefaultForeignCallExecutor::new(true)), + ); + Self { + server, + context, + debug_artifact, + source_to_opcodes, + running: false, + next_breakpoint_id: 1, + instruction_breakpoints: vec![], + source_breakpoints: BTreeMap::new(), + } + } + + /// Builds a map from FileId to an ordered vector of tuples with line + /// numbers and opcode locations corresponding to those line numbers + fn build_source_to_opcode_debug_mappings( + debug_artifact: &'a DebugArtifact, + ) -> BTreeMap> { + if debug_artifact.debug_symbols.is_empty() { + return BTreeMap::new(); + } + let locations = &debug_artifact.debug_symbols[0].locations; + let simple_files: BTreeMap<_, _> = debug_artifact + .file_map + .iter() + .map(|(file_id, debug_file)| { + ( + file_id, + SimpleFile::new(debug_file.path.to_str().unwrap(), debug_file.source.as_str()), + ) + }) + .collect(); + + let mut result: BTreeMap> = BTreeMap::new(); + locations.iter().for_each(|(opcode_location, source_locations)| { + if source_locations.is_empty() { + return; + } + let source_location = source_locations[0]; + let span = source_location.span; + let file_id = source_location.file; + let Ok(line_index) = &simple_files[&file_id].line_index((), span.start() as usize) else { + return; + }; + let line_number = line_index + 1; + + result.entry(file_id).or_default().push((line_number, *opcode_location)); + }); + result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| x.0)); + result + } + + fn send_stopped_event(&mut self, reason: StoppedEventReason) -> Result<(), ServerError> { + let description = format!("{:?}", &reason); + self.server.send_event(Event::Stopped(StoppedEventBody { + reason, + description: Some(description), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + Ok(()) + } + + pub fn run_loop(&mut self) -> Result<(), ServerError> { + self.running = true; + + if matches!(self.context.get_current_source_location(), None) { + // TODO: remove this? This is to ensure that the tool has a proper + // source location to show when first starting the debugger, but + // maybe the default behavior should be to start executing until the + // first breakpoint set. + _ = self.context.next(); + } + + self.server.send_event(Event::Initialized)?; + self.send_stopped_event(StoppedEventReason::Entry)?; + + while self.running { + let req = match self.server.poll_request()? { + Some(req) => req, + None => break, + }; + match req.command { + Command::Disconnect(_) => { + eprintln!("INFO: ending debugging session"); + self.server.respond(req.ack()?)?; + break; + } + Command::SetBreakpoints(_) => { + self.handle_set_source_breakpoints(req)?; + } + Command::SetExceptionBreakpoints(_) => { + self.server.respond(req.success(ResponseBody::SetExceptionBreakpoints( + SetExceptionBreakpointsResponse { breakpoints: None }, + )))?; + } + Command::SetInstructionBreakpoints(_) => { + self.handle_set_instruction_breakpoints(req)?; + } + Command::Threads => { + self.server.respond(req.success(ResponseBody::Threads(ThreadsResponse { + threads: vec![Thread { id: 0, name: "main".to_string() }], + })))?; + } + Command::StackTrace(_) => { + self.handle_stack_trace(req)?; + } + Command::Disassemble(_) => { + self.handle_disassemble(req)?; + } + Command::StepIn(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next(req)?, + } + } + Command::StepOut(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next(req)?, + } + } + Command::Next(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next(req)?, + } + } + Command::Continue(_) => { + self.handle_continue(req)?; + } + Command::Scopes(_) => { + // FIXME: this needs a proper implementation when we can + // show the parameters and variables + self.server.respond( + req.success(ResponseBody::Scopes(ScopesResponse { scopes: vec![] })), + )?; + } + _ => { + eprintln!("ERROR: unhandled command: {:?}", req.command); + } + } + } + Ok(()) + } + + fn handle_stack_trace(&mut self, req: Request) -> Result<(), ServerError> { + let opcode_location = self.context.get_current_opcode_location(); + let source_location = self.context.get_current_source_location(); + let frames = match source_location { + None => vec![], + Some(locations) => locations + .iter() + .enumerate() + .map(|(index, location)| { + let line_number = self.debug_artifact.location_line_number(*location).unwrap(); + let column_number = + self.debug_artifact.location_column_number(*location).unwrap(); + let ip_reference = opcode_location.map(|location| location.to_string()); + StackFrame { + id: index as i64, + name: format!("frame #{index}"), + source: Some(Source { + path: self.debug_artifact.file_map[&location.file] + .path + .to_str() + .map(String::from), + ..Source::default() + }), + line: line_number as i64, + column: column_number as i64, + instruction_pointer_reference: ip_reference, + ..StackFrame::default() + } + }) + .collect(), + }; + let total_frames = Some(frames.len() as i64); + self.server.respond(req.success(ResponseBody::StackTrace(StackTraceResponse { + stack_frames: frames, + total_frames, + })))?; + Ok(()) + } + + fn handle_disassemble(&mut self, req: Request) -> Result<(), ServerError> { + let Command::Disassemble(ref args) = req.command else { + unreachable!("handle_disassemble called on a non disassemble request"); + }; + let starting_ip = OpcodeLocation::from_str(args.memory_reference.as_str()).ok(); + let instruction_offset = args.instruction_offset.unwrap_or(0); + let (mut opcode_location, mut invalid_count) = + self.context.offset_opcode_location(&starting_ip, instruction_offset); + let mut count = args.instruction_count; + + let mut instructions: Vec = vec![]; + + // leading invalid locations (when the request goes back + // beyond the start of the program) + if invalid_count < 0 { + while invalid_count < 0 { + instructions.push(DisassembledInstruction { + address: String::from("---"), + instruction: String::from("---"), + ..DisassembledInstruction::default() + }); + invalid_count += 1; + count -= 1; + } + if count > 0 { + opcode_location = Some(OpcodeLocation::Acir(0)); + } + } + // the actual opcodes + while count > 0 && !matches!(opcode_location, None) { + instructions.push(DisassembledInstruction { + address: format!("{}", opcode_location.unwrap()), + instruction: self.context.render_opcode_at_location(&opcode_location), + ..DisassembledInstruction::default() + }); + (opcode_location, _) = self.context.offset_opcode_location(&opcode_location, 1); + count -= 1; + } + // any remaining instruction count is beyond the valid opcode + // vector so return invalid placeholders + while count > 0 { + instructions.push(DisassembledInstruction { + address: String::from("---"), + instruction: String::from("---"), + ..DisassembledInstruction::default() + }); + invalid_count -= 1; + count -= 1; + } + + self.server.respond( + req.success(ResponseBody::Disassemble(DisassembleResponse { instructions })), + )?; + Ok(()) + } + + fn handle_step(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.step_into_opcode(); + eprintln!("INFO: stepped by instruction with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_next(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.next(); + eprintln!("INFO: stepped by statement with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_continue(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.cont(); + eprintln!("INFO: continue with result {result:?}"); + self.server.respond(req.success(ResponseBody::Continue(ContinueResponse { + all_threads_continued: Some(true), + })))?; + self.handle_execution_result(result) + } + + fn find_breakpoints_at_location(&self, opcode_location: &OpcodeLocation) -> Vec { + let mut result = vec![]; + for (location, id) in &self.instruction_breakpoints { + if opcode_location == location { + result.push(*id); + } + } + for breakpoints in self.source_breakpoints.values() { + for (location, id) in breakpoints { + if opcode_location == location { + result.push(*id); + } + } + } + result + } + + fn handle_execution_result(&mut self, result: DebugCommandResult) -> Result<(), ServerError> { + match result { + DebugCommandResult::Done => { + self.running = false; + } + DebugCommandResult::Ok => { + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Pause, + description: None, + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + } + DebugCommandResult::BreakpointReached(location) => { + let breakpoint_ids = self.find_breakpoints_at_location(&location); + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Breakpoint, + description: Some(String::from("Paused at breakpoint")), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: Some(breakpoint_ids), + }))?; + } + DebugCommandResult::Error(err) => { + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Exception, + description: Some(format!("{err:?}")), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + } + } + Ok(()) + } + + fn get_next_breakpoint_id(&mut self) -> i64 { + let id = self.next_breakpoint_id; + self.next_breakpoint_id += 1; + id + } + + fn reinstall_breakpoints(&mut self) { + self.context.clear_breakpoints(); + for (location, _) in &self.instruction_breakpoints { + self.context.add_breakpoint(*location); + } + for breakpoints in self.source_breakpoints.values() { + for (location, _) in breakpoints { + self.context.add_breakpoint(*location); + } + } + } + + fn handle_set_instruction_breakpoints(&mut self, req: Request) -> Result<(), ServerError> { + let Command::SetInstructionBreakpoints(ref args) = req.command else { + unreachable!("handle_set_instruction_breakpoints called on a different request"); + }; + + // compute breakpoints to set and return + let mut breakpoints_to_set: Vec<(OpcodeLocation, i64)> = vec![]; + let breakpoints: Vec = args.breakpoints.iter().map(|breakpoint| { + let Ok(location) = OpcodeLocation::from_str(breakpoint.instruction_reference.as_str()) else { + return Breakpoint { + verified: false, + message: Some(String::from("Missing instruction reference")), + ..Breakpoint::default() + }; + }; + if !self.context.is_valid_opcode_location(&location) { + return Breakpoint { + verified: false, + message: Some(String::from("Invalid opcode location")), + ..Breakpoint::default() + }; + } + let id = self.get_next_breakpoint_id(); + breakpoints_to_set.push((location, id)); + Breakpoint { + id: Some(id), + verified: true, + ..Breakpoint::default() + } + }).collect(); + + // actually set the computed breakpoints + self.instruction_breakpoints = breakpoints_to_set; + self.reinstall_breakpoints(); + + // response to request + self.server.respond(req.success(ResponseBody::SetInstructionBreakpoints( + SetInstructionBreakpointsResponse { breakpoints }, + )))?; + Ok(()) + } + + fn find_file_id(&self, source_path: &str) -> Option { + let file_map = &self.debug_artifact.file_map; + let found = file_map.iter().find(|(_, debug_file)| match debug_file.path.to_str() { + Some(debug_file_path) => debug_file_path == source_path, + None => false, + }); + found.map(|iter| *iter.0) + } + + // TODO: there are four possibilities for the return value of this function: + // 1. the source location is not found -> None + // 2. an exact unique location is found -> Some(opcode_location) + // 3. an exact but not unique location is found (ie. a source location may + // be mapped to multiple opcodes, and those may be disjoint, for example for + // functions called multiple times throughout the program) + // 4. exact location is not found, so an opcode for a nearby source location + // is returned (this again could actually be more than one opcodes) + // Case 3 is not supported yet, and 4 is not correctly handled. + fn find_opcode_for_source_location( + &self, + file_id: &FileId, + line: i64, + ) -> Option { + let line = line as usize; + let Some(line_to_opcodes) = self.source_to_opcodes.get(file_id) else { + return None; + }; + let found_index = match line_to_opcodes.binary_search_by(|x| x.0.cmp(&line)) { + Ok(index) => line_to_opcodes[index].1, + Err(index) => line_to_opcodes[index].1, + }; + Some(found_index) + } + + fn map_source_breakpoints(&mut self, args: &SetBreakpointsArguments) -> Vec { + let Some(ref source) = &args.source.path else { + return vec![]; + }; + let Some(file_id) = self.find_file_id(source) else { + eprintln!("WARN: file ID for source {source} not found"); + return vec![]; + }; + let Some(ref breakpoints) = &args.breakpoints else { + return vec![]; + }; + let mut breakpoints_to_set: Vec<(OpcodeLocation, i64)> = vec![]; + let breakpoints = breakpoints + .iter() + .map(|breakpoint| { + let line = breakpoint.line; + let Some(location) = self.find_opcode_for_source_location(&file_id, line) else { + return Breakpoint { + verified: false, + message: Some(String::from("Source location cannot be matched to opcode location")), + ..Breakpoint::default() + }; + }; + // TODO: line will not necessarily be the one requested; we + // should do the reverse mapping and retrieve the actual source + // code line number + if !self.context.is_valid_opcode_location(&location) { + return Breakpoint { + verified: false, + message: Some(String::from("Invalid opcode location")), + ..Breakpoint::default() + }; + } + let instruction_reference = format!("{}", location); + let breakpoint_id = self.get_next_breakpoint_id(); + breakpoints_to_set.push((location, breakpoint_id)); + Breakpoint { + id: Some(breakpoint_id), + verified: true, + source: Some(args.source.clone()), + instruction_reference: Some(instruction_reference), + line: Some(line), + ..Breakpoint::default() + } + }) + .collect(); + + self.source_breakpoints.insert(file_id, breakpoints_to_set); + + breakpoints + } + + fn handle_set_source_breakpoints(&mut self, req: Request) -> Result<(), ServerError> { + let Command::SetBreakpoints(ref args) = req.command else { + unreachable!("handle_set_source_breakpoints called on a different request"); + }; + let breakpoints = self.map_source_breakpoints(args); + self.reinstall_breakpoints(); + self.server.respond( + req.success(ResponseBody::SetBreakpoints(SetBreakpointsResponse { breakpoints })), + )?; + Ok(()) + } +} + +pub fn run_session( + server: Server, + solver: &B, + program: CompiledProgram, + initial_witness: WitnessMap, +) -> Result<(), ServerError> { + let debug_artifact = DebugArtifact { + debug_symbols: vec![program.debug], + file_map: program.file_map, + warnings: program.warnings, + }; + let mut session = + DapSession::new(server, solver, &program.circuit, &debug_artifact, initial_witness); + + session.run_loop() +} diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 7c6a9e9f618..7e0c1605e0a 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -1,12 +1,18 @@ mod context; +mod dap; mod repl; +use std::io::{Read, Write}; + +use ::dap::errors::ServerError; +use ::dap::server::Server; use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use nargo::artifacts::debug::DebugArtifact; use nargo::NargoError; +use noirc_driver::CompiledProgram; pub fn debug_circuit( blackbox_solver: &B, @@ -16,3 +22,12 @@ pub fn debug_circuit( ) -> Result, NargoError> { repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness) } + +pub fn run_dap_loop( + server: Server, + solver: &B, + program: CompiledProgram, + initial_witness: WitnessMap, +) -> Result<(), ServerError> { + dap::run_session(server, solver, program, initial_witness) +} diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 839b81460ac..65d3599bf35 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -48,6 +48,7 @@ termcolor = "1.1.2" color-eyre = "0.6.2" env_logger = "0.9.0" tokio = { version = "1.0", features = ["io-std"] } +dap.workspace = true # Backends backend-interface = { path = "../backend_interface" } diff --git a/tooling/nargo_cli/src/cli/dap_cmd.rs b/tooling/nargo_cli/src/cli/dap_cmd.rs new file mode 100644 index 00000000000..29e696ea608 --- /dev/null +++ b/tooling/nargo_cli/src/cli/dap_cmd.rs @@ -0,0 +1,180 @@ +use acvm::acir::native_types::WitnessMap; +use backend_interface::Backend; +use clap::Args; +use nargo::constants::PROVER_INPUT_FILE; +use nargo::insert_all_files_for_workspace_into_file_manager; +use nargo::workspace::Workspace; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_abi::input_parser::Format; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; +use noirc_frontend::graph::CrateName; + +use std::io::{BufReader, BufWriter, Read, Write}; +use std::path::Path; + +use dap::errors::ServerError; +use dap::requests::Command; +use dap::responses::ResponseBody; +use dap::server::Server; +use dap::types::Capabilities; +use serde_json::Value; + +use super::compile_cmd::compile_bin_package; +use super::fs::inputs::read_inputs_from_file; +use crate::errors::CliError; + +use super::NargoConfig; + +#[derive(Debug, Clone, Args)] +pub(crate) struct DapCommand; + +struct LoadError(&'static str); + +fn find_workspace(project_folder: &str, package: Option<&str>) -> Option { + let Ok(toml_path) = get_package_manifest(Path::new(project_folder)) else { + eprintln!("ERROR: Failed to get package manifest"); + return None; + }; + let package = package.and_then(|p| serde_json::from_str::(p).ok()); + let selection = package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); + match resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) { + Ok(workspace) => Some(workspace), + Err(err) => { + eprintln!("ERROR: Failed to resolve workspace: {err}"); + None + } + } +} + +fn load_and_compile_project( + backend: &Backend, + project_folder: &str, + package: Option<&str>, + prover_name: &str, +) -> Result<(CompiledProgram, WitnessMap), LoadError> { + let workspace = + find_workspace(project_folder, package).ok_or(LoadError("Cannot open workspace"))?; + + let expression_width = + backend.get_backend_info().map_err(|_| LoadError("Failed to get backend info"))?; + let package = workspace + .into_iter() + .find(|p| p.is_binary()) + .ok_or(LoadError("No matching binary packages found in workspace"))?; + + let mut workspace_file_manager = file_manager_with_stdlib(std::path::Path::new("")); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + + let compiled_program = compile_bin_package( + &workspace_file_manager, + &workspace, + package, + &CompileOptions::default(), + expression_width, + ) + .map_err(|_| LoadError("Failed to compile project"))?; + + let (inputs_map, _) = + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi) + .map_err(|_| LoadError("Failed to read program inputs"))?; + let initial_witness = compiled_program + .abi + .encode(&inputs_map, None) + .map_err(|_| LoadError("Failed to encode inputs"))?; + + Ok((compiled_program, initial_witness)) +} + +fn loop_uninitialized_dap( + mut server: Server, + backend: &Backend, +) -> Result<(), ServerError> { + loop { + let req = match server.poll_request()? { + Some(req) => req, + None => break, + }; + + match req.command { + Command::Initialize(_) => { + let rsp = req.success(ResponseBody::Initialize(Capabilities { + supports_disassemble_request: Some(true), + supports_instruction_breakpoints: Some(true), + supports_stepping_granularity: Some(true), + ..Default::default() + })); + server.respond(rsp)?; + } + + Command::Launch(ref arguments) => { + let Some(Value::Object(ref additional_data)) = arguments.additional_data else { + server.respond(req.error("Missing launch arguments"))?; + continue; + }; + let Some(Value::String(ref project_folder)) = additional_data.get("projectFolder") else { + server.respond(req.error("Missing project folder argument"))?; + continue; + }; + + let project_folder = project_folder.as_str(); + let package = additional_data.get("package").and_then(|v| v.as_str()); + let prover_name = additional_data + .get("proverName") + .and_then(|v| v.as_str()) + .unwrap_or(PROVER_INPUT_FILE); + + eprintln!("Project folder: {}", project_folder); + eprintln!("Package: {}", package.unwrap_or("(default)")); + eprintln!("Prover name: {}", prover_name); + + match load_and_compile_project(backend, project_folder, package, prover_name) { + Ok((compiled_program, initial_witness)) => { + server.respond(req.ack()?)?; + + let blackbox_solver = bn254_blackbox_solver::Bn254BlackBoxSolver::new(); + + noir_debugger::run_dap_loop( + server, + &blackbox_solver, + compiled_program, + initial_witness, + )?; + break; + } + Err(LoadError(message)) => { + server.respond(req.error(message))?; + } + } + } + + Command::Disconnect(_) => { + server.respond(req.ack()?)?; + break; + } + + _ => { + let command = req.command; + eprintln!("ERROR: unhandled command: {command:?}"); + } + } + } + Ok(()) +} + +pub(crate) fn run( + backend: &Backend, + _args: DapCommand, + _config: NargoConfig, +) -> Result<(), CliError> { + let output = BufWriter::new(std::io::stdout()); + let input = BufReader::new(std::io::stdin()); + let server = Server::new(input, output); + + loop_uninitialized_dap(server, backend).map_err(CliError::DapError) +} diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 448e28fb6a7..cbed65593a1 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -14,6 +14,7 @@ mod backend_cmd; mod check_cmd; mod codegen_verifier_cmd; mod compile_cmd; +mod dap_cmd; mod debug_cmd; mod execute_cmd; mod fmt_cmd; @@ -74,6 +75,8 @@ enum NargoCommand { Test(test_cmd::TestCommand), Info(info_cmd::InfoCommand), Lsp(lsp_cmd::LspCommand), + #[command(hide = true)] + Dap(dap_cmd::DapCommand), } pub(crate) fn start_cli() -> eyre::Result<()> { @@ -91,6 +94,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { | NargoCommand::Init(_) | NargoCommand::Lsp(_) | NargoCommand::Backend(_) + | NargoCommand::Dap(_) ) { config.program_dir = find_package_root(&config.program_dir)?; } @@ -112,6 +116,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { NargoCommand::CodegenVerifier(args) => codegen_verifier_cmd::run(&backend, args, config), NargoCommand::Backend(args) => backend_cmd::run(args), NargoCommand::Lsp(args) => lsp_cmd::run(&backend, args, config), + NargoCommand::Dap(args) => dap_cmd::run(&backend, args, config), NargoCommand::Fmt(args) => fmt_cmd::run(args, config), }?; diff --git a/tooling/nargo_cli/src/errors.rs b/tooling/nargo_cli/src/errors.rs index 92da74c71d4..4636772231b 100644 --- a/tooling/nargo_cli/src/errors.rs +++ b/tooling/nargo_cli/src/errors.rs @@ -53,6 +53,9 @@ pub(crate) enum CliError { #[error(transparent)] LspError(#[from] async_lsp::Error), + #[error(transparent)] + DapError(#[from] dap::errors::ServerError), + /// Error from Nargo #[error(transparent)] NargoError(#[from] NargoError), From 57eae42080d6a928e8010c6bc77489964a5777ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Tue, 19 Dec 2023 21:43:47 +0000 Subject: [PATCH 092/137] fix: fixing dark mode background on the CTA button (#3882) # Description As usual I got a little bit carried away, but the whole point was to just remove the white background in the CTA box with dark mode. Ended up making some other color changes. ## Problem\* A picture worth a thousand words: ![Screenshot 2023-12-19 at 18 01 19](https://github.com/noir-lang/noir/assets/20129824/3fd2938b-6d26-4d98-bab5-6bbc642306c5) ## Summary\* - Fixes the CTA box - Changes primary colors to match Aztec's color sheet, not much since we're gonna have a restyling later on anyway - Makes docs respect system theme instead of defaulting to white --- docs/docusaurus.config.ts | 4 ++++ docs/src/css/custom.css | 50 +++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 7516d35c6d9..043c6cba72e 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ import type { Config } from '@docusaurus/types'; const { themes } = require('prism-react-renderer'); @@ -47,6 +48,9 @@ export default { ], themeConfig: { + colorMode: { + respectPrefersColorScheme: true, + }, navbar: { logo: { alt: 'Noir Logo', diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 53dec741513..c96e9df9832 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -6,45 +6,47 @@ /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #9f3fff; - --ifm-color-primary-dark: #2f1f49; - --ifm-color-primary-darker: #2f1f49; - --ifm-color-primary-darkest: #2f1f49; - --ifm-color-primary-light: #9f3fff; - --ifm-color-primary-lighter: #9f3fff; - --ifm-color-primary-lightest: #9f3fff; + --ifm-color-primary: #514167; + --ifm-color-primary-dark: #493a5d; + --ifm-color-primary-darker: #453758; + --ifm-color-primary-darkest: #392d48; + --ifm-color-primary-light: #594871; + --ifm-color-primary-lighter: #5d4b76; + --ifm-color-primary-lightest: #695486; --search-local-highlight-color: #2f1f49; --ifm-menu-color-background-active: #f6f8fa; --ifm-code-font-size: 95%; - --ifm-breadcrumb-color-active: white; - --ifm-breadcrumb-item-background-active: #2f1f49; + --ifm-breadcrumb-color-active: #F6FBFC; + --ifm-breadcrumb-item-background-active: #2f1f49; --ifm-heading-color: #2f1f49; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + --ifm-link-color: #B68BE4; } /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme='dark'] { - --ifm-color-primary: #f5bda9; - --ifm-color-primary-dark: #f5bda9; - --ifm-color-primary-darker: #f5bda9; - --ifm-color-primary-darkest: #f5bda9; - --ifm-color-primary-light: #f5bda9; - --ifm-color-primary-lighter: #f5bda9; - --ifm-color-primary-lightest: #f5bda9; - - --ifm-heading-color: white; + --ifm-color-primary: #fbc0b4; + --ifm-color-primary-dark: #f99e8b; + --ifm-color-primary-darker: #f88c77; + --ifm-color-primary-darkest: #f45939; + --ifm-color-primary-light: #fde2dd; + --ifm-color-primary-lighter: #fef4f1; + --ifm-color-primary-lightest: #ffffff; + + --ifm-heading-color: #F6FBFC; --ifm-menu-color-background-active: #282a36; --ifm-breadcrumb-color-active: #2f1f49; --ifm-breadcrumb-item-background-active: #f5bda9; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + --ifm-link-color: var(--ifm-color-primary); } html[data-theme='dark'] { --search-local-highlight-color: #f5bda9; - --search-local-muted-color: white; + --search-local-muted-color: #F6FBFC; --search-local-hit-active-color: #1b1b1d; - --search-local-hit-color: white; + --search-local-hit-color: #F6FBFC; } [data-theme='dark'] .footer { @@ -65,6 +67,13 @@ html[data-theme='dark'] { --ifm-footer-title-color: #2f1f49; } +[data-theme='light'] #__docusaurus { + background-color: #F6FBFC; +} +[data-theme='dark'] #__docusaurus { + background-color: #161717; +} + .katex-html { display: none; } @@ -91,7 +100,6 @@ html[data-theme='dark'] { justify-content: center; margin: 0 auto; text-align: center; - background: white; border: none; width: 50%; } From a3dfca81eee222608c2df8ef38e3a676044464f3 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Wed, 20 Dec 2023 10:34:03 +0100 Subject: [PATCH 093/137] chore(debugger): Add guide on how to test unmerged experimental features (#3853) # Description There's a number of debugger features that are in active development and that can't yet be merged to the main branch for different reasons. This changeset adds a summary of what those features are and how to try them out. ## Problem Part of #3015. ## Summary Adds instructions on how to test experimental debugger features to the debugger's README.md file. ## Documentation Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/debugger/README.md | 98 ++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/tooling/debugger/README.md b/tooling/debugger/README.md index 964784cb730..0ec3b6f0cd4 100644 --- a/tooling/debugger/README.md +++ b/tooling/debugger/README.md @@ -315,25 +315,105 @@ Finished execution Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. -## VS Code extension -We're working on extending Noir's official VS Code extension so it uses the editor's debugger facilities to debug Noir programs. +# Testing experimental features -This section will soon show how to load the extension from sources, in order to test the debugger. +There's a number of features that are in active development and that can't yet be merged to the main branch for different reasons. In this section we detail what those features are and how to try them out. +## Build from experimental branch at fork -## Variable value inspection (unstable) +Build Nargo by pulling the source version from https://github.com/manastech/noir/tree/dap-with-vars. -To enable the inspection of variable values at runtime from the debugger, we're in the process of instrumenting the compiler to track and collect the necessary mappings between source code level variable names and ACIR/Brillig state. +This will result in a Nargo binary being written to `PROJECT_ROOT/target/debug/nargo`. We will use this path later, so keep it at hand or export it to a an env var. For example: -At the time of writing, there are still some parts of the language that haven't been fully instrumented, which means certain programs will crash when compiled with this. +`export NARGO_EXP=PROJECT_ROOT/target/debug/nargo` -It is however possible to try out this feature, both from the REPL and VS Code, by building Nargo from branch https://github.com/manastech/noir/tree/dap-with-vars. +## About the experimental features -We'll soon expand this section with details on how to do so for the adventurous. +There are currently 2 experimental features in the debugger: +- Variables inspection +- Stacktrace inspection -## Towards debugging contracts +NOTE: Supporting variables inspection requires extensive instrumentation of the compiler, handling all cases of variable creation, types, and value assignment. At the time of writing this README, some cases are still not supported. For example, if your program uses slices or references, this compiler version might panic when trying to compile them, or at some point during the debugger step-by-step execution. This is the main reason why this feature has not yet been merged into master. + +## Trying out REPL experimental features + +To try out these features, go through the same steps as described at the REPL Debugger section above, but instead of using `nargo debug` use `$NARGO_EXP debug` (assuming you exported your custom built Nargo binary to NARGO_EXP). + +When entering `help` on this version, you'll find two new commands: + +``` +... +stacktrace display the current stack trace +... +vars show variable values available at this point + in execution +``` + +Running `vars` will print the current variables in scope, and its current values: + +``` +At /mul_1/src/main.nr:6:5 + 1 // Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 + 2 // The circuit should handle properly the growth of the bit size + 3 fn main(mut x: u32, y: u32, z: u32) { + 4 x *= y; + 5 x *= x; //144 + 6 -> x *= x; //20736 + 7 x *= x; //429 981 696 + 8 assert(x == z); + 9 } +> vars +y:UnsignedInteger { width: 32 }=Field(4), z:UnsignedInteger { width: 32 }=Field(2¹⁶×6561), x:UnsignedInteger { width: 32 }=Field(2⁴×9) +> +``` + +Running `stacktrace` will print information about the current frame in the stacktrace: + +``` +> stacktrace +Frame #0, opcode 12: EXPR [ (1, _5, _5) (-1, _6) 0 ] +At /1_mul/src/main.nr:6:5 + 1 // Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 + 2 // The circuit should handle properly the growth of the bit size + 3 fn main(mut x: u32, y: u32, z: u32) { + 4 x *= y; + 5 x *= x; //144 + 6 -> x *= x; //20736 + 7 x *= x; //429 981 696 + 8 assert(x == z); + 9 } +> +``` + +## Testing the VS Code extension (experimental) + +There is a fork of the official Noir Visual Studio extension which enables the debugger in VS Code. This fork is at: https://github.com/manastech/vscode-noir/tree/dap-support. + +In this section, we'll explain how to test the VS Code Noir debugger combining that extension fork with the experimental features branch discussed above. + +1. First, get a copy of the extension source code from https://github.com/manastech/vscode-noir/tree/dap-support. + +2. Package the extension by running `npm run package`. + +3. Open the root folder of the extension on VS Code. + +4. From VS Code, press fn+F5. This will open a new VS Code window with the extension loaded from source. + +5. Go to Code -> Settings -> Extensions -> Noir Language Server. Look for the property `Nargo Path` and enter the path to the experimental build you got as a result of following the steps at [Trying out REPL experimental features](#trying-out-repl-experimental-features). + +6. At the VS Code sidebar, go to the debugger section (see screenshot). Click "Add configuration". Overwrite the `projectFolder` property with the absolute path to the Nargo project you want to debug. + +Screenshot 2023-12-18 at 14 37 38 + +7. Go to a Noir file you want to debug. Navigate again to the debug section of VS Code, and click the "play" icon. + +The debugger should now have started. Current features exposed to the debugger include different kinds of stepping interactions, variable inspection and stacktraces. At the time of writing, Brillig registers and memory are not being exposed, but they will soon be. + +![Screen Recording 2023-12-18 at 14 14 28](https://github.com/manastech/noir/assets/651693/36b4becb-953a-4158-9c5a-7a185673f54f) + +## Towards debugging contracts ### Contracts Runtime From 194939c1fb40228be865d0f16d19d706c65f32ae Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 20 Dec 2023 11:22:12 +0000 Subject: [PATCH 094/137] chore(docs): fix spelling issues in docs (#3887) # Description ## Problem\* Resolves ## Summary\* I heard there's airdrops for typo fixes now so I've addressed all of the typos in the docs. On an unrelated note this will prevent #3886 from causing issues from existing spelling errors. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/CHANGELOG.md | 8 +++---- acvm-repo/acir/CHANGELOG.md | 8 +++---- acvm-repo/acvm/CHANGELOG.md | 8 +++---- cspell.json | 22 ++++++++++++++++++- docs/docs/explainers/explainer-recursion.md | 2 +- .../installation/other_install_methods.md | 6 ++--- .../docs/getting_started/project_breakdown.md | 2 +- docs/docs/getting_started/tooling/testing.md | 2 +- docs/docs/how_to/how-to-recursion.md | 8 +++---- docs/docs/index.md | 4 ++-- .../modules_packages_crates/dependencies.md | 8 +++---- .../noir/modules_packages_crates/modules.md | 2 +- docs/docs/noir/syntax/data_types/index.md | 2 +- docs/docs/noir/syntax/mutability.md | 4 ++-- docs/docs/noir/syntax/ops.md | 2 +- docs/docs/noir/syntax/unconstrained.md | 2 +- .../getting_started/00_nargo_installation.md | 4 ++-- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.17.0/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.17.0/nargo/02_testing.md | 2 +- .../noir_js/reference/01_noirjs.md | 2 +- .../noir_js/reference/02_bb_backend.md | 2 +- .../getting_started/00_nargo_installation.md | 6 ++--- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.19.0/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.19.0/nargo/02_testing.md | 2 +- .../noir_js/reference/01_noirjs.md | 2 +- .../noir_js/reference/02_bb_backend.md | 2 +- .../noir_js/reference/noir_js/classes/Noir.md | 2 +- .../getting_started/00_nargo_installation.md | 6 ++--- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.19.1/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.19.1/nargo/02_testing.md | 2 +- .../noir_js/reference/noir_js/classes/Noir.md | 2 +- .../getting_started/00_nargo_installation.md | 6 ++--- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.19.2/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.19.2/nargo/02_testing.md | 2 +- .../noir_js/reference/noir_js/classes/Noir.md | 2 +- .../getting_started/00_nargo_installation.md | 6 ++--- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.19.3/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.19.3/nargo/02_testing.md | 2 +- .../noir_js/reference/noir_js/classes/Noir.md | 2 +- .../getting_started/00_nargo_installation.md | 6 ++--- .../getting_started/02_breakdown.md | 2 +- docs/versioned_docs/version-v0.19.4/index.md | 4 ++-- .../language_concepts/03_ops.md | 2 +- .../language_concepts/05_unconstrained.md | 2 +- .../language_concepts/07_mutability.md | 4 ++-- .../language_concepts/data_types.md | 2 +- .../modules_packages_crates/dependencies.md | 8 +++---- .../modules_packages_crates/modules.md | 2 +- .../version-v0.19.4/nargo/02_testing.md | 2 +- .../noir_js/reference/noir_js/classes/Noir.md | 2 +- .../explainers/explainer-recursion.md | 2 +- .../installation/other_install_methods.md | 6 ++--- .../getting_started/project_breakdown.md | 2 +- .../getting_started/tooling/testing.md | 2 +- .../how_to/how-to-recursion.md | 8 +++---- docs/versioned_docs/version-v0.22.0/index.md | 4 ++-- .../modules_packages_crates/dependencies.md | 8 +++---- .../noir/modules_packages_crates/modules.md | 2 +- .../noir/syntax/data_types/index.md | 2 +- .../version-v0.22.0/noir/syntax/mutability.md | 4 ++-- .../version-v0.22.0/noir/syntax/ops.md | 2 +- .../noir/syntax/unconstrained.md | 2 +- .../global_consts/src/main.nr | 16 +++++++------- .../execution_success/submodules/src/main.nr | 6 ++--- 99 files changed, 198 insertions(+), 178 deletions(-) diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index 0bd38fd3307..4dc900d87a8 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -977,7 +977,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * require `Backend` to implement `Default` trait ([#223](https://github.com/noir-lang/acvm/issues/223)) * Make GeneralOptimizer crate visible ([#220](https://github.com/noir-lang/acvm/issues/220)) * return `PartialWitnessGeneratorStatus` from `PartialWitnessGenerator.solve` ([#213](https://github.com/noir-lang/acvm/issues/213)) -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ### Features @@ -1000,7 +1000,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Chores * Make GeneralOptimizer crate visible ([#220](https://github.com/noir-lang/acvm/issues/220)) ([64bb346](https://github.com/noir-lang/acvm/commit/64bb346524428a0ce196826ea1e5ccde08ad6201)) -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) ## [0.9.0](https://github.com/noir-lang/acvm/compare/root-v0.8.1...root-v0.9.0) (2023-04-07) @@ -1114,7 +1114,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **acir:** make PublicInputs use a BTreeSet rather than Vec ([#99](https://github.com/noir-lang/acvm/issues/99)) * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) * **acir:** Add keccak256 Opcode ([#91](https://github.com/noir-lang/acvm/issues/91)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ### Features @@ -1138,7 +1138,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Miscellaneous Chores * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) ([2427a27](https://github.com/noir-lang/acvm/commit/2427a275048e598c6d651cce8348a4c55148f235)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) ## [0.4.1] - 2023-02-08 diff --git a/acvm-repo/acir/CHANGELOG.md b/acvm-repo/acir/CHANGELOG.md index e31ee66379a..6551fc85262 100644 --- a/acvm-repo/acir/CHANGELOG.md +++ b/acvm-repo/acir/CHANGELOG.md @@ -404,7 +404,7 @@ * replace `MerkleMembership` opcode with `ComputeMerkleRoot` ([#233](https://github.com/noir-lang/acvm/issues/233)) * return `PartialWitnessGeneratorStatus` from `PartialWitnessGenerator.solve` ([#213](https://github.com/noir-lang/acvm/issues/213)) -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ### Features @@ -415,7 +415,7 @@ ### Miscellaneous Chores -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) ## [0.9.0](https://github.com/noir-lang/acvm/compare/acir-v0.8.1...acir-v0.9.0) (2023-04-07) @@ -507,7 +507,7 @@ * **acir:** make PublicInputs use a BTreeSet rather than Vec ([#99](https://github.com/noir-lang/acvm/issues/99)) * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) * **acir:** Add keccak256 Opcode ([#91](https://github.com/noir-lang/acvm/issues/91)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ### Features @@ -518,4 +518,4 @@ ### Miscellaneous Chores * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) ([2427a27](https://github.com/noir-lang/acvm/commit/2427a275048e598c6d651cce8348a4c55148f235)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) diff --git a/acvm-repo/acvm/CHANGELOG.md b/acvm-repo/acvm/CHANGELOG.md index 29a4aa93adc..2a340f649f5 100644 --- a/acvm-repo/acvm/CHANGELOG.md +++ b/acvm-repo/acvm/CHANGELOG.md @@ -537,7 +537,7 @@ * require `Backend` to implement `Default` trait ([#223](https://github.com/noir-lang/acvm/issues/223)) * Make GeneralOptimizer crate visible ([#220](https://github.com/noir-lang/acvm/issues/220)) * return `PartialWitnessGeneratorStatus` from `PartialWitnessGenerator.solve` ([#213](https://github.com/noir-lang/acvm/issues/213)) -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ### Features @@ -557,7 +557,7 @@ ### Miscellaneous Chores * Make GeneralOptimizer crate visible ([#220](https://github.com/noir-lang/acvm/issues/220)) ([64bb346](https://github.com/noir-lang/acvm/commit/64bb346524428a0ce196826ea1e5ccde08ad6201)) -* organise operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) +* organize operator implementations for Expression ([#190](https://github.com/noir-lang/acvm/issues/190)) ([a619df6](https://github.com/noir-lang/acvm/commit/a619df614bbb9b2518b788b42a7553b069823a0f)) ## [0.9.0](https://github.com/noir-lang/acvm/compare/acvm-v0.8.1...acvm-v0.9.0) (2023-04-07) @@ -641,7 +641,7 @@ * update `ProofSystemCompiler` to not take ownership of keys ([#111](https://github.com/noir-lang/acvm/issues/111)) * update `ProofSystemCompiler` methods to take `&Circuit` ([#108](https://github.com/noir-lang/acvm/issues/108)) * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ### Features @@ -659,4 +659,4 @@ ### Miscellaneous Chores * refactor ToRadix to ToRadixLe and ToRadixBe ([#58](https://github.com/noir-lang/acvm/issues/58)) ([2427a27](https://github.com/noir-lang/acvm/commit/2427a275048e598c6d651cce8348a4c55148f235)) -* reorganise compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) +* reorganize compiler in terms of optimisers and transformers ([#88](https://github.com/noir-lang/acvm/issues/88)) ([9329307](https://github.com/noir-lang/acvm/commit/9329307e054de202cfc55207162ad952b70d515e)) diff --git a/cspell.json b/cspell.json index 5bdb04cb4b2..d8f04ed6069 100644 --- a/cspell.json +++ b/cspell.json @@ -6,6 +6,7 @@ "acvm", "aeiou", "appender", + "Arbitrum", "arithmetization", "arity", "arkworks", @@ -15,21 +16,26 @@ "bindgen", "bitand", "blackbox", + "bridgekeeper", "brillig", "cachix", "callsite", "callsites", "canonicalize", "castable", + "Celo", "chumsky", "clippy", "codegen", "codegens", + "Codespaces", "codespan", "coeff", "combinators", "comptime", + "cpus", "cranelift", + "curvegroup", "deflatten", "deflattened", "deflattening", @@ -40,12 +46,14 @@ "desugared", "direnv", "eddsa", + "Elligator", "endianness", "envrc", "Flamegraph", "flate", "fmtstr", "foldl", + "foos", "forall", "foralls", "formatcp", @@ -69,9 +77,11 @@ "jmpif", "jmpifs", "jmps", + "Jubjub", "keccak", "krate", "lvalue", + "mathbb", "merkle", "metas", "monomorphization", @@ -79,22 +89,27 @@ "monomorphized", "monomorphizer", "monomorphizes", + "montcurve", "nand", "nargo", "newtype", + "nightlies", "nixpkgs", "noirc", + "noirjs", "noirup", "nomicfoundation", "pedersen", "peekable", "plonkc", + "PLONKish", "pprof", "preprocess", "prettytable", "println", "printstd", "pseudocode", + "pubkey", "quantile", "rustc", "rustup", @@ -112,6 +127,8 @@ "subexpression", "subshell", "subtyping", + "swcurve", + "tecurve", "tempdir", "tempfile", "termcolor", @@ -126,7 +143,10 @@ "unnormalized", "unoptimized", "urem", + "USERPROFILE", "vecmap", - "wasi" + "wasi", + "Weierstraß", + "zshell" ] } diff --git a/docs/docs/explainers/explainer-recursion.md b/docs/docs/explainers/explainer-recursion.md index cc431a878dc..9357d3c7341 100644 --- a/docs/docs/explainers/explainer-recursion.md +++ b/docs/docs/explainers/explainer-recursion.md @@ -149,7 +149,7 @@ In such a situation, and assuming Alice is first, she would skip the first part ### Aggregating proofs -In some one-way interaction situations, recursiveness would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: diff --git a/docs/docs/getting_started/installation/other_install_methods.md b/docs/docs/getting_started/installation/other_install_methods.md index 36f05657277..a532f83750e 100644 --- a/docs/docs/getting_started/installation/other_install_methods.md +++ b/docs/docs/getting_started/installation/other_install_methods.md @@ -83,9 +83,9 @@ Check if the installation was successful by running `nargo --version`. You shoul ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -163,7 +163,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/docs/getting_started/project_breakdown.md b/docs/docs/getting_started/project_breakdown.md index 5a214804f7b..c4e2a9ae003 100644 --- a/docs/docs/getting_started/project_breakdown.md +++ b/docs/docs/getting_started/project_breakdown.md @@ -40,7 +40,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/docs/getting_started/tooling/testing.md b/docs/docs/getting_started/tooling/testing.md index 868a061200d..5febd44e96b 100644 --- a/docs/docs/getting_started/tooling/testing.md +++ b/docs/docs/getting_started/tooling/testing.md @@ -25,7 +25,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/docs/how_to/how-to-recursion.md b/docs/docs/how_to/how-to-recursion.md index 226f7e6e73d..db9ad0e99f8 100644 --- a/docs/docs/how_to/how-to-recursion.md +++ b/docs/docs/how_to/how-to-recursion.md @@ -53,7 +53,7 @@ For a full example on how recursive proofs work, please refer to the [noir-examp In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. -For recursiveness, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: @@ -159,7 +159,7 @@ const backends = { main: new BarretenbergBackend(circuits.main), recursive: new BarretenbergBackend(circuits.recursive) } -const noirs = { +const noir_programs = { main: new Noir(circuits.main, backends.main), recursive: new Noir(circuits.recursive, backends.recursive) } @@ -169,7 +169,7 @@ This allows you to neatly call exactly the method you want without conflicting n ```js // Alice runs this 👇 -const { witness: mainWitness } = await noirs.main.execute(input) +const { witness: mainWitness } = await noir_programs.main.execute(input) const proof = await backends.main.generateIntermediateProof(mainWitness) // Bob runs this 👇 @@ -178,7 +178,7 @@ const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateInterm proof, numPublicInputs, ); -const recursiveProof = await noirs.recursive.generateFinalProof(recursiveInputs) +const recursiveProof = await noir_programs.recursive.generateFinalProof(recursiveInputs) ``` ::: diff --git a/docs/docs/index.md b/docs/docs/index.md index e1ec3362c1f..eaf8c59f935 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -26,7 +26,7 @@ Noir, a domain-specific language crafted for SNARK proving systems, stands out w and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's -barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin +barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkworks' Marlin backend, among others. This innovative design introduces unique challenges, yet it strategically separates the programming language from the @@ -43,7 +43,7 @@ contracts efficiently. While the current alpha version offers this as a direct f to modularize this process for even greater ease of use. Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be -modularised in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. +modularized in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. ### Protocol Developers diff --git a/docs/docs/noir/modules_packages_crates/dependencies.md b/docs/docs/noir/modules_packages_crates/dependencies.md index 57f0f9fd420..1e93b30781a 100644 --- a/docs/docs/noir/modules_packages_crates/dependencies.md +++ b/docs/docs/noir/modules_packages_crates/dependencies.md @@ -49,7 +49,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -61,17 +61,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/docs/noir/modules_packages_crates/modules.md b/docs/docs/noir/modules_packages_crates/modules.md index f9f15aee8be..ae822a1cff4 100644 --- a/docs/docs/noir/modules_packages_crates/modules.md +++ b/docs/docs/noir/modules_packages_crates/modules.md @@ -11,7 +11,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/docs/noir/syntax/data_types/index.md b/docs/docs/noir/syntax/data_types/index.md index 52e568e9b7e..01cd0431a68 100644 --- a/docs/docs/noir/syntax/data_types/index.md +++ b/docs/docs/noir/syntax/data_types/index.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/docs/noir/syntax/mutability.md b/docs/docs/noir/syntax/mutability.md index 58e9c1cecfb..6abfae3cfa7 100644 --- a/docs/docs/noir/syntax/mutability.md +++ b/docs/docs/noir/syntax/mutability.md @@ -70,11 +70,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/docs/noir/syntax/ops.md b/docs/docs/noir/syntax/ops.md index 977c8ba1203..60425cb8994 100644 --- a/docs/docs/noir/syntax/ops.md +++ b/docs/docs/noir/syntax/ops.md @@ -63,7 +63,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/docs/noir/syntax/unconstrained.md b/docs/docs/noir/syntax/unconstrained.md index 7a61d3953ef..6b3424f7993 100644 --- a/docs/docs/noir/syntax/unconstrained.md +++ b/docs/docs/noir/syntax/unconstrained.md @@ -6,7 +6,7 @@ keywords: [Noir programming language, unconstrained, open] sidebar_position: 5 --- -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md index f4ca361d3c4..0de5597c213 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment diff --git a/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md index bc0e742fb4e..e7b1f33b339 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md index ddbee58f6e4..4eeeb6f1346 100644 --- a/docs/versioned_docs/version-v0.17.0/index.md +++ b/docs/versioned_docs/version-v0.17.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md index 11fef2bf8b5..3480fbfedad 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md @@ -90,7 +90,7 @@ This async method generates a witness and a proof given an object as input. ### Syntax ```js -async generateFinalproof(input) +async generateFinalProof(input) ``` ### Parameters diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md index f444eab1772..958cabd6289 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md @@ -41,7 +41,7 @@ constructor(acirCircuit, (numberOfThreads = 1)); | Parameter | Type | Description | | ----------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode Tipically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | +| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode typically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | | `numberOfThreads` | Number (optional) | The number of threads to be used by the backend. Defaults to 1. | ### Usage diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md index 349756d60c0..7d3c88c7693 100644 --- a/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -220,7 +220,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md index 9a17f5d6360..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.19.0/index.md b/docs/versioned_docs/version-v0.19.0/index.md index 4e2f4043892..93944f92bf5 100644 --- a/docs/versioned_docs/version-v0.19.0/index.md +++ b/docs/versioned_docs/version-v0.19.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md index ccdd53f2bcc..2e90779ceab 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md @@ -94,7 +94,7 @@ This async method generates a witness and a proof given an object as input. ### Syntax ```js -async generateFinalproof(input) +async generateFinalProof(input) ``` ### Parameters diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md index f444eab1772..958cabd6289 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md @@ -41,7 +41,7 @@ constructor(acirCircuit, (numberOfThreads = 1)); | Parameter | Type | Description | | ----------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode Tipically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | +| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode typically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | | `numberOfThreads` | Number (optional) | The number of threads to be used by the backend. Defaults to 1. | ### Usage diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md index a8a0bb451c1..1d7b54a9dca 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md @@ -95,7 +95,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md index 349756d60c0..7d3c88c7693 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -220,7 +220,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md index 9a17f5d6360..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.19.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md index 4e2f4043892..93944f92bf5 100644 --- a/docs/versioned_docs/version-v0.19.1/index.md +++ b/docs/versioned_docs/version-v0.19.1/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md index a8a0bb451c1..1d7b54a9dca 100644 --- a/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md +++ b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md @@ -95,7 +95,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md index 349756d60c0..7d3c88c7693 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -220,7 +220,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md index 9a17f5d6360..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.19.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md index 4e2f4043892..93944f92bf5 100644 --- a/docs/versioned_docs/version-v0.19.2/index.md +++ b/docs/versioned_docs/version-v0.19.2/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md index a8a0bb451c1..1d7b54a9dca 100644 --- a/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md +++ b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md @@ -95,7 +95,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md index 349756d60c0..7d3c88c7693 100644 --- a/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -220,7 +220,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md index 9a17f5d6360..7a7fb876c35 100644 --- a/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter'" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.19.3/index.md b/docs/versioned_docs/version-v0.19.3/index.md index 4e2f4043892..93944f92bf5 100644 --- a/docs/versioned_docs/version-v0.19.3/index.md +++ b/docs/versioned_docs/version-v0.19.3/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md index a8a0bb451c1..1d7b54a9dca 100644 --- a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md @@ -95,7 +95,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md index 349756d60c0..7d3c88c7693 100644 --- a/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md @@ -140,9 +140,9 @@ Commands: ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -220,7 +220,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md index 9a17f5d6360..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md +++ b/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md @@ -39,7 +39,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.19.4/index.md b/docs/versioned_docs/version-v0.19.4/index.md index 4e2f4043892..93944f92bf5 100644 --- a/docs/versioned_docs/version-v0.19.4/index.md +++ b/docs/versioned_docs/version-v0.19.4/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -55,7 +55,7 @@ must be implemented for it. Noir is simple and flexible in its design, as it does not compile immediately to a fixed NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkworks' Marlin backend, or others). This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md index d5caa463765..0e35ef5e584 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md @@ -62,7 +62,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md index 6b621eda3eb..097d6ee9894 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md @@ -7,7 +7,7 @@ keywords: [Noir programming language, unconstrained, open] -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md index ad902c42c9b..ed3fed820ec 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md @@ -69,11 +69,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md index d546cc463a8..74f573f7d3f 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md index 75f95aaa305..2c188992616 100644 --- a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md @@ -48,7 +48,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -60,17 +60,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md index 147c9b284e8..11e60cbf35e 100644 --- a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md @@ -10,7 +10,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md index da767274efd..917c9415126 100644 --- a/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md @@ -24,7 +24,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md index e54116fb1d8..c54468891af 100644 --- a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md @@ -95,7 +95,7 @@ Generates a witness and a proof given an object as input. #### Example ```typescript -async generateFinalproof(input) +async generateFinalProof(input) ``` *** diff --git a/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md index cc431a878dc..9357d3c7341 100644 --- a/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md +++ b/docs/versioned_docs/version-v0.22.0/explainers/explainer-recursion.md @@ -149,7 +149,7 @@ In such a situation, and assuming Alice is first, she would skip the first part ### Aggregating proofs -In some one-way interaction situations, recursiveness would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: diff --git a/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md index 36f05657277..a532f83750e 100644 --- a/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md +++ b/docs/versioned_docs/version-v0.22.0/getting_started/installation/other_install_methods.md @@ -83,9 +83,9 @@ Check if the installation was successful by running `nargo --version`. You shoul ### Option 3: Compile from Source -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. #### Setting up your environment @@ -163,7 +163,7 @@ Advanced: If you aren't using direnv nor launching your editor within the subshe ### Option 4: WSL (for Windows) -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. diff --git a/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md b/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md index 5a214804f7b..c4e2a9ae003 100644 --- a/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md +++ b/docs/versioned_docs/version-v0.22.0/getting_started/project_breakdown.md @@ -40,7 +40,7 @@ Example Nargo.toml: ```toml [package] -name = "noirstarter" +name = "noir_starter" type = "bin" authors = ["Alice"] compiler_version = "0.9.0" diff --git a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md index 868a061200d..5febd44e96b 100644 --- a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md +++ b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md @@ -25,7 +25,7 @@ fn test_add() { ``` Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't +the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. ### Test fail diff --git a/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md index 226f7e6e73d..db9ad0e99f8 100644 --- a/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md +++ b/docs/versioned_docs/version-v0.22.0/how_to/how-to-recursion.md @@ -53,7 +53,7 @@ For a full example on how recursive proofs work, please refer to the [noir-examp In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. -For recursiveness, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: @@ -159,7 +159,7 @@ const backends = { main: new BarretenbergBackend(circuits.main), recursive: new BarretenbergBackend(circuits.recursive) } -const noirs = { +const noir_programs = { main: new Noir(circuits.main, backends.main), recursive: new Noir(circuits.recursive, backends.recursive) } @@ -169,7 +169,7 @@ This allows you to neatly call exactly the method you want without conflicting n ```js // Alice runs this 👇 -const { witness: mainWitness } = await noirs.main.execute(input) +const { witness: mainWitness } = await noir_programs.main.execute(input) const proof = await backends.main.generateIntermediateProof(mainWitness) // Bob runs this 👇 @@ -178,7 +178,7 @@ const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateInterm proof, numPublicInputs, ); -const recursiveProof = await noirs.recursive.generateFinalProof(recursiveInputs) +const recursiveProof = await noir_programs.recursive.generateFinalProof(recursiveInputs) ``` ::: diff --git a/docs/versioned_docs/version-v0.22.0/index.md b/docs/versioned_docs/version-v0.22.0/index.md index e1ec3362c1f..eaf8c59f935 100644 --- a/docs/versioned_docs/version-v0.22.0/index.md +++ b/docs/versioned_docs/version-v0.22.0/index.md @@ -26,7 +26,7 @@ Noir, a domain-specific language crafted for SNARK proving systems, stands out w and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's -barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin +barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkworks' Marlin backend, among others. This innovative design introduces unique challenges, yet it strategically separates the programming language from the @@ -43,7 +43,7 @@ contracts efficiently. While the current alpha version offers this as a direct f to modularize this process for even greater ease of use. Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be -modularised in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. +modularized in the future; however, as of the alpha, you can use the `nargo codegen-verifier` command to create a verifier contract. ### Protocol Developers diff --git a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md index 57f0f9fd420..1e93b30781a 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md +++ b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md @@ -49,7 +49,7 @@ For example, this file structure has a library and binary crate │   ├── Nargo.toml │   └── src │   └── main.nr -└── liba +└── lib_a ├── Nargo.toml └── src └── lib.nr @@ -61,17 +61,17 @@ Inside of the binary crate, you can specify: # Nargo.toml [dependencies] -libA = { path = "../liba" } +lib_a = { path = "../lib_a" } ``` ## Importing dependencies You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: +ecrecover-noir library and local lib_a referenced above: ```rust use dep::ecrecover; -use dep::libA; +use dep::lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: diff --git a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md index f9f15aee8be..ae822a1cff4 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md +++ b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/modules.md @@ -11,7 +11,7 @@ Noir's module system follows the same convention as the _newer_ version of Rust' ## Purpose of Modules -Modules are used to organise files. Without modules all of your code would need to live in a single +Modules are used to organize files. Without modules all of your code would need to live in a single file. In Noir, the compiler does not automatically scan all of your files to detect modules. This must be done explicitly by the developer. diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md index 52e568e9b7e..01cd0431a68 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md @@ -93,4 +93,4 @@ fn main() { ### BigInt -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md index 58e9c1cecfb..6abfae3cfa7 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/mutability.md @@ -70,11 +70,11 @@ fn main(x : Field, y : [Field; N]) { assert(res == y[0]); - let res2 = x * mysubmodule::N; + let res2 = x * my_submodule::N; assert(res != res2); } -mod mysubmodule { +mod my_submodule { use dep::std; global N: Field = 10; diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md index 977c8ba1203..60425cb8994 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/ops.md @@ -63,7 +63,7 @@ fn main(x : Field) { Noir has no support for the logical operators `||` and `&&`. This is because encoding the short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +use the bitwise operators `|` and `&` which operate identically for booleans, just without the short-circuiting. ```rust diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md index 7a61d3953ef..6b3424f7993 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/unconstrained.md @@ -6,7 +6,7 @@ keywords: [Noir programming language, unconstrained, open] sidebar_position: 5 --- -Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. ## Why? diff --git a/test_programs/execution_success/global_consts/src/main.nr b/test_programs/execution_success/global_consts/src/main.nr index a749ec77da6..70c7a745a22 100644 --- a/test_programs/execution_success/global_consts/src/main.nr +++ b/test_programs/execution_success/global_consts/src/main.nr @@ -55,17 +55,17 @@ fn main( let t: [Field; T_LEN] = [N, M]; assert(t[1] == 32); - assert(15 == mysubmodule::my_helper()); + assert(15 == my_submodule::my_helper()); - let add_submodules_N = mysubmodule::N + foo::bar::N; + let add_submodules_N = my_submodule::N + foo::bar::N; assert(15 == add_submodules_N); - let add_from_bar_N = mysubmodule::N + foo::bar::from_bar(1); + let add_from_bar_N = my_submodule::N + foo::bar::from_bar(1); assert(15 == add_from_bar_N); - // Example showing an array filled with (mysubmodule::N + 2) 0's - let sugared = [0; mysubmodule::N + 2]; - assert(sugared[mysubmodule::N + 1] == 0); + // Example showing an array filled with (my_submodule::N + 2) 0's + let sugared = [0; my_submodule::N + 2]; + assert(sugared[my_submodule::N + 1] == 0); - let arr: [Field; mysubmodule::N] = [N; 10]; + let arr: [Field; my_submodule::N] = [N; 10]; assert((arr[0] == 5) & (arr[9] == 5)); foo::from_foo(d); @@ -80,7 +80,7 @@ fn arrays_neq(a: [Field; M], b: [Field; M]) { assert(a != b); } -mod mysubmodule { +mod my_submodule { global N: Field = 10; global L: Field = 50; diff --git a/test_programs/execution_success/submodules/src/main.nr b/test_programs/execution_success/submodules/src/main.nr index 813f3a26a20..f937af74627 100644 --- a/test_programs/execution_success/submodules/src/main.nr +++ b/test_programs/execution_success/submodules/src/main.nr @@ -1,11 +1,11 @@ -use mysubmodule::my_helper; +use my_submodule::my_helper; fn main(x: u1, y: u1) { my_helper(); - mysubmodule::my_bool_or(x, y); + my_submodule::my_bool_or(x, y); } -mod mysubmodule { +mod my_submodule { pub fn my_bool_or(x: u1, y: u1) { assert(x | y == 1); } From b5949195631be6b9e2eafdafeaa744632ae172c8 Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Wed, 20 Dec 2023 17:08:36 +0100 Subject: [PATCH 095/137] chore: replace `env-logger` with `tracing` (#3878) # Description ## Problem\* While env-logger concerns itself with logging, tracing is drop in replacement to support logging case but also provides more features for profiling. ## Summary\* ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- Cargo.lock | 120 ++++++++---------- Cargo.toml | 3 +- acvm-repo/acvm/Cargo.toml | 2 +- acvm-repo/acvm/src/compiler/optimizers/mod.rs | 5 +- .../acvm/src/compiler/transformers/mod.rs | 5 +- acvm-repo/acvm_js/Cargo.toml | 7 +- acvm-repo/acvm_js/src/lib.rs | 2 +- acvm-repo/acvm_js/src/logging.rs | 31 ++--- compiler/noirc_driver/Cargo.toml | 2 +- compiler/noirc_driver/src/lib.rs | 8 +- compiler/noirc_errors/Cargo.toml | 2 +- compiler/noirc_errors/src/debug_info.rs | 3 +- compiler/noirc_evaluator/Cargo.toml | 2 +- compiler/noirc_evaluator/src/ssa.rs | 17 +-- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 1 + compiler/noirc_frontend/Cargo.toml | 2 +- .../src/monomorphization/mod.rs | 3 +- compiler/wasm/Cargo.toml | 5 +- compiler/wasm/src/lib.rs | 21 ++- tooling/backend_interface/Cargo.toml | 2 +- tooling/backend_interface/src/lib.rs | 5 +- tooling/backend_interface/src/proof_system.rs | 3 +- tooling/nargo/Cargo.toml | 2 +- tooling/nargo/src/ops/execute.rs | 7 +- tooling/nargo_cli/Cargo.toml | 4 +- tooling/nargo_cli/src/main.rs | 15 ++- 26 files changed, 128 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 223f7eb2152..0c4638f4001 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,13 +43,13 @@ dependencies = [ "acvm_blackbox_solver", "brillig_vm", "indexmap 1.9.3", - "log", "num-bigint", "num-traits", "paste", "proptest", "rand", "thiserror", + "tracing", ] [[package]] @@ -77,13 +77,14 @@ dependencies = [ "const-str", "gloo-utils", "js-sys", - "log", "pkg-config", "serde", + "tracing", + "tracing-subscriber", + "tracing-web", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test", - "wasm-logger", ] [[package]] @@ -400,17 +401,6 @@ dependencies = [ "waitpid-any", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -435,7 +425,6 @@ dependencies = [ "const_format", "dirs", "flate2", - "log", "reqwest", "serde", "serde_json", @@ -443,6 +432,7 @@ dependencies = [ "tempfile", "test-binary", "thiserror", + "tracing", ] [[package]] @@ -1507,19 +1497,6 @@ dependencies = [ "syn 2.0.26", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1945,15 +1922,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.2" @@ -2009,12 +1977,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.27" @@ -2212,7 +2174,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "rustix", "windows-sys 0.48.0", ] @@ -2356,6 +2318,15 @@ dependencies = [ "libc", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.5.0" @@ -2447,7 +2418,6 @@ dependencies = [ "codespan-reporting", "fm", "iter-extended", - "log", "noirc_abi", "noirc_driver", "noirc_errors", @@ -2459,6 +2429,7 @@ dependencies = [ "serde", "tempfile", "thiserror", + "tracing", ] [[package]] @@ -2479,7 +2450,6 @@ dependencies = [ "criterion", "dap", "dirs", - "env_logger", "fm", "hex", "iai", @@ -2510,7 +2480,6 @@ dependencies = [ "tokio-util", "toml", "tower", - "tracing", "tracing-appender", "tracing-subscriber", ] @@ -2629,14 +2598,14 @@ dependencies = [ "getrandom", "gloo-utils", "js-sys", - "log", "nargo", "noirc_driver", "noirc_errors", "noirc_frontend", "serde", + "tracing-subscriber", + "tracing-web", "wasm-bindgen", - "wasm-logger", ] [[package]] @@ -2684,13 +2653,13 @@ dependencies = [ "fm", "fxhash", "iter-extended", - "log", "noirc_abi", "noirc_errors", "noirc_evaluator", "noirc_frontend", "rust-embed", "serde", + "tracing", ] [[package]] @@ -2702,9 +2671,9 @@ dependencies = [ "codespan", "codespan-reporting", "fm", - "log", "serde", "serde_with", + "tracing", ] [[package]] @@ -2715,12 +2684,12 @@ dependencies = [ "fxhash", "im", "iter-extended", - "log", "noirc_errors", "noirc_frontend", "num-bigint", "serde", "thiserror", + "tracing", ] [[package]] @@ -2732,7 +2701,6 @@ dependencies = [ "chumsky", "fm", "iter-extended", - "log", "noirc_errors", "noirc_printable_type", "regex", @@ -2745,6 +2713,7 @@ dependencies = [ "strum_macros", "tempfile", "thiserror", + "tracing", ] [[package]] @@ -2822,7 +2791,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", ] @@ -3142,7 +3111,7 @@ dependencies = [ "rand", "rand_chacha", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.7.4", "rusty-fork", "tempfile", "unarray", @@ -3326,7 +3295,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata 0.3.3", - "regex-syntax", + "regex-syntax 0.7.4", ] [[package]] @@ -3334,6 +3303,9 @@ name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] [[package]] name = "regex-automata" @@ -3343,9 +3315,15 @@ checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.4", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.4" @@ -4522,14 +4500,31 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] +[[package]] +name = "tracing-web" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e6a141feebd51f8d91ebfd785af50fca223c570b86852166caa3b141defe7c" +dependencies = [ + "js-sys", + "tracing-core", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "trie-rs" version = "0.1.1" @@ -4812,17 +4807,6 @@ dependencies = [ "leb128", ] -[[package]] -name = "wasm-logger" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718" -dependencies = [ - "log", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasmer" version = "4.2.3" diff --git a/Cargo.toml b/Cargo.toml index 59d2af2fab3..7dda111c1a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,10 +121,11 @@ const_format = "0.2.30" num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" -log = "0.4.17" tempfile = "3.6.0" tracing = "0.1.40" +tracing-web = "0.1.3" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } [profile.dev] # This is required to be able to run `cargo test` in acvm_js due to the `locals exceeds maximum` error. diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 5fdf44cbd5e..f5819d6fa34 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -16,7 +16,7 @@ repository.workspace = true num-bigint.workspace = true num-traits.workspace = true thiserror.workspace = true -log.workspace = true +tracing.workspace = true acir.workspace = true brillig_vm.workspace = true diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index dd27c0bb937..952bec2f7af 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -23,9 +23,8 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. +#[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir))] pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { - log::trace!("Start circuit optimization"); - // General optimizer pass let opcodes: Vec = acir .opcodes @@ -54,7 +53,5 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { let (acir, acir_opcode_positions) = range_optimizer.replace_redundant_ranges(acir_opcode_positions); - log::trace!("Finish circuit optimization"); - (acir, acir_opcode_positions) } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index eef8d7bee44..c9bc91b02c7 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -37,13 +37,12 @@ pub fn transform( /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. /// /// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations. +#[tracing::instrument(level = "trace", name = "transform_acir", skip(acir, acir_opcode_positions))] pub(super) fn transform_internal( acir: Circuit, expression_width: ExpressionWidth, acir_opcode_positions: Vec, ) -> (Circuit, Vec) { - log::trace!("Start circuit transformation"); - let mut transformer = match &expression_width { crate::ExpressionWidth::Unbounded => { let transformer = R1CSTransformer::new(acir); @@ -209,7 +208,5 @@ pub(super) fn transform_internal( ..acir }; - log::trace!("Finish circuit transformation"); - (acir, new_acir_opcode_positions) } diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index 06903fec3f5..987006f8e2b 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -25,11 +25,12 @@ wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true -js-sys.workspace = true -log.workspace = true +js-sys.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +tracing-web.workspace = true serde = { version = "1.0.136", features = ["derive"] } -wasm-logger = "0.2.0" const-str = "0.5.5" [build-dependencies] diff --git a/acvm-repo/acvm_js/src/lib.rs b/acvm-repo/acvm_js/src/lib.rs index ba2a37bf984..88afd1767c9 100644 --- a/acvm-repo/acvm_js/src/lib.rs +++ b/acvm-repo/acvm_js/src/lib.rs @@ -24,7 +24,7 @@ cfg_if::cfg_if! { pub use compression::{compress_witness, decompress_witness}; pub use execute::{execute_circuit, execute_circuit_with_black_box_solver, create_black_box_solver}; pub use js_witness_map::JsWitnessMap; - pub use logging::{init_log_level, LogLevel}; + pub use logging::init_log_level; pub use public_witness::{get_public_parameters_witness, get_public_witness, get_return_witness}; pub use js_execution_error::JsExecutionError; } diff --git a/acvm-repo/acvm_js/src/logging.rs b/acvm-repo/acvm_js/src/logging.rs index d939c5f8367..f5d71fae067 100644 --- a/acvm-repo/acvm_js/src/logging.rs +++ b/acvm-repo/acvm_js/src/logging.rs @@ -1,31 +1,26 @@ -use js_sys::JsString; -use log::Level; -use std::str::FromStr; +use tracing_subscriber::prelude::*; +use tracing_subscriber::EnvFilter; +use tracing_web::MakeWebConsoleWriter; use wasm_bindgen::prelude::*; -#[wasm_bindgen(typescript_custom_section)] -const LOG_LEVEL: &'static str = r#" -export type LogLevel = "OFF" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE"; -"#; - -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(extends = JsString, typescript_type = "LogLevel")] - pub type LogLevel; -} - /// Sets the package's logging level. /// /// @param {LogLevel} level - The maximum level of logging to be emitted. #[wasm_bindgen(js_name = initLogLevel, skip_jsdoc)] -pub fn init_log_level(level: LogLevel) { +pub fn init_log_level(filter: String) { // Set the static variable from Rust use std::sync::Once; - let log_level = level.as_string().unwrap(); - let log_level = Level::from_str(&log_level).unwrap_or(Level::Error); + let filter: EnvFilter = + filter.parse().expect("Could not parse log filter while initializing logger"); + static SET_HOOK: Once = Once::new(); SET_HOOK.call_once(|| { - wasm_logger::init(wasm_logger::Config::new(log_level)); + let fmt_layer = tracing_subscriber::fmt::layer() + .with_ansi(false) + .without_time() + .with_writer(MakeWebConsoleWriter::new()); + + tracing_subscriber::registry().with(fmt_layer.with_filter(filter)).init(); }); } diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index 7f431db4398..32c418b0adb 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -22,6 +22,6 @@ fm.workspace = true serde.workspace = true fxhash.workspace = true rust-embed = "6.6.0" -log.workspace = true +tracing.workspace = true aztec_macros = { path = "../../aztec_macros" } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 926e541c2f3..3908d16e01d 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -18,6 +18,7 @@ use noirc_frontend::monomorphization::monomorphize; use noirc_frontend::node_interner::FuncId; use serde::{Deserialize, Serialize}; use std::path::Path; +use tracing::info; mod abi_gen; mod contract; @@ -160,14 +161,13 @@ pub fn add_dep( /// /// This returns a (possibly empty) vector of any warnings found on success. /// On error, this returns a non-empty vector of warnings and error messages, with at least one error. +#[tracing::instrument(level = "trace", skip(context))] pub fn check_crate( context: &mut Context, crate_id: CrateId, deny_warnings: bool, disable_macros: bool, ) -> CompilationResult<()> { - log::trace!("Start checking crate"); - let macros: Vec<&dyn MacroProcessor> = if disable_macros { vec![] } else { @@ -181,8 +181,6 @@ pub fn check_crate( diagnostic.in_file(file_id) })); - log::trace!("Finish checking crate"); - if has_errors(&errors, deny_warnings) { Err(errors) } else { @@ -395,7 +393,7 @@ pub fn compile_no_check( force_compile || options.print_acir || options.show_brillig || options.show_ssa; if !force_compile && hashes_match { - log::info!("Program matches existing artifact, returning early"); + info!("Program matches existing artifact, returning early"); return Ok(cached_program.expect("cache must exist for hashes to match")); } let visibility = program.return_visibility; diff --git a/compiler/noirc_errors/Cargo.toml b/compiler/noirc_errors/Cargo.toml index 812a507550c..02e97b2c670 100644 --- a/compiler/noirc_errors/Cargo.toml +++ b/compiler/noirc_errors/Cargo.toml @@ -15,4 +15,4 @@ fm.workspace = true chumsky.workspace = true serde.workspace = true serde_with = "3.2.0" -log.workspace = true +tracing.workspace = true \ No newline at end of file diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 3ae5c193e39..ee40ced19bf 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -38,8 +38,8 @@ impl DebugInfo { /// The [`OpcodeLocation`]s are generated with the ACIR, but passing the ACIR through a transformation step /// renders the old `OpcodeLocation`s invalid. The AcirTransformationMap is able to map the old `OpcodeLocation` to the new ones. /// Note: One old `OpcodeLocation` might have transformed into more than one new `OpcodeLocation`. + #[tracing::instrument(level = "trace", skip(self, update_map))] pub fn update_acir(&mut self, update_map: AcirTransformationMap) { - log::trace!("Start debug info update"); let old_locations = mem::take(&mut self.locations); for (old_opcode_location, source_locations) in old_locations { @@ -47,7 +47,6 @@ impl DebugInfo { self.locations.insert(new_opcode_location, source_locations.clone()); }); } - log::trace!("Finish debug info update"); } pub fn opcode_location(&self, loc: &OpcodeLocation) -> Option> { diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index 6e7152c6d71..a8f0e8d83a9 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -17,4 +17,4 @@ thiserror.workspace = true num-bigint = "0.4" im = { version = "15.1", features = ["serde"] } serde.workspace = true -log.workspace = true +tracing.workspace = true \ No newline at end of file diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 6a02a5f6edc..3c814c04eb2 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -23,6 +23,7 @@ use noirc_errors::debug_info::DebugInfo; use noirc_frontend::{ hir_def::function::FunctionSignature, monomorphization::ast::Program, Visibility, }; +use tracing::{span, Level}; use self::{acir_gen::GeneratedAcir, ssa_gen::Ssa}; @@ -42,7 +43,8 @@ pub(crate) fn optimize_into_acir( ) -> Result { let abi_distinctness = program.return_distinctness; - log::trace!("Start SSA generation"); + let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); + let ssa_gen_span_guard = ssa_gen_span.enter(); let ssa_builder = SsaBuilder::new(program, print_ssa_passes)? .run_pass(Ssa::defunctionalize, "After Defunctionalization:") .run_pass(Ssa::inline_functions, "After Inlining:") @@ -70,28 +72,23 @@ pub(crate) fn optimize_into_acir( let ssa = ssa_builder .run_pass(Ssa::fill_internal_slices, "After Fill Internal Slice Dummy Data:") .finish(); - log::trace!("Finish SSA generation"); + drop(ssa_gen_span_guard); let last_array_uses = ssa.find_last_array_uses(); - log::trace!("Start ACIR generation"); - let acir = ssa.into_acir(brillig, abi_distinctness, &last_array_uses); - log::trace!("Finish ACIR generation"); - - acir + ssa.into_acir(brillig, abi_distinctness, &last_array_uses) } /// Compiles the [`Program`] into [`ACIR`][acvm::acir::circuit::Circuit]. /// /// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. #[allow(clippy::type_complexity)] +#[tracing::instrument(level = "trace", skip(program))] pub fn create_circuit( program: Program, enable_ssa_logging: bool, enable_brillig_logging: bool, ) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { - log::trace!("Start circuit generation"); - let func_sig = program.main_function_signature.clone(); let mut generated_acir = optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?; @@ -133,8 +130,6 @@ pub fn create_circuit( let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); debug_info.update_acir(transformation_map); - log::trace!("Finish circuit generation"); - Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 01056355915..6a48dadaf30 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -156,6 +156,7 @@ impl AcirValue { } impl Ssa { + #[tracing::instrument(level = "trace", skip_all)] pub(crate) fn into_acir( self, brillig: Brillig, diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index aa3a8e9f6b8..80d767f7f2c 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -22,7 +22,7 @@ serde.workspace = true rustc-hash = "1.1.0" small-ord-set = "0.1.3" regex = "1.9.1" -log.workspace = true +tracing.workspace = true [dev-dependencies] strum = "0.24" diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 52b8d5bfd79..39b05dcd5ac 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -91,8 +91,8 @@ type HirType = crate::Type; /// Note that there is no requirement on the `main` function that can be passed into /// this function. Typically, this is the function named "main" in the source project, /// but it can also be, for example, an arbitrary test function for running `nargo test`. +#[tracing::instrument(level = "trace", skip(main, interner))] pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Program { - log::trace!("Start monomorphization"); let mut monomorphizer = Monomorphizer::new(interner); let function_sig = monomorphizer.compile_main(main); @@ -108,7 +108,6 @@ pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Pro let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); let FuncMeta { return_distinctness, return_visibility, .. } = interner.function_meta(&main); - log::trace!("Finish monomorphization"); Program::new( functions, function_sig, diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index 58ad7764fdc..7ea138b60a4 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -23,9 +23,8 @@ serde.workspace = true js-sys.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true -log.workspace = true - -wasm-logger = "0.2.0" +tracing-subscriber.workspace = true +tracing-web.workspace = true # This is an unused dependency, we are adding it # so that we can enable the js feature in getrandom. diff --git a/compiler/wasm/src/lib.rs b/compiler/wasm/src/lib.rs index d0394589578..e10b992a00e 100644 --- a/compiler/wasm/src/lib.rs +++ b/compiler/wasm/src/lib.rs @@ -6,11 +6,12 @@ use getrandom as _; use gloo_utils::format::JsValueSerdeExt; -use log::Level; + use noirc_driver::{GIT_COMMIT, GIT_DIRTY, NOIRC_VERSION}; use serde::{Deserialize, Serialize}; -use std::str::FromStr; -use wasm_bindgen::prelude::*; +use tracing_subscriber::prelude::*; +use tracing_subscriber::EnvFilter; +use tracing_web::MakeWebConsoleWriter; mod compile; mod compile_new; @@ -20,6 +21,7 @@ pub use compile::compile; // Expose the new Context-Centric API pub use compile_new::{compile_, CompilerContext, CrateIDWrapper}; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; #[derive(Serialize, Deserialize)] pub struct BuildInfo { @@ -29,14 +31,21 @@ pub struct BuildInfo { } #[wasm_bindgen] -pub fn init_log_level(level: String) { +pub fn init_log_level(filter: String) { // Set the static variable from Rust use std::sync::Once; - let log_level = Level::from_str(&level).unwrap_or(Level::Error); + let filter: EnvFilter = + filter.parse().expect("Could not parse log filter while initializing logger"); + static SET_HOOK: Once = Once::new(); SET_HOOK.call_once(|| { - wasm_logger::init(wasm_logger::Config::new(log_level)); + let fmt_layer = tracing_subscriber::fmt::layer() + .with_ansi(false) + .without_time() + .with_writer(MakeWebConsoleWriter::new()); + + tracing_subscriber::registry().with(fmt_layer.with_filter(filter)).init(); }); } diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml index 32c5d28e3b0..2d991f9ae6c 100644 --- a/tooling/backend_interface/Cargo.toml +++ b/tooling/backend_interface/Cargo.toml @@ -16,7 +16,7 @@ thiserror.workspace = true serde.workspace = true serde_json.workspace = true bb_abstraction_leaks.workspace = true -log.workspace = true +tracing.workspace = true tempfile.workspace = true diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index 8ed164fc217..c15383086eb 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -12,6 +12,7 @@ pub use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use bb_abstraction_leaks::BB_VERSION; use cli::VersionCommand; pub use download::download_backend; +use tracing::warn; const BACKENDS_DIR: &str = ".nargo/backends"; @@ -115,7 +116,7 @@ impl Backend { // If version doesn't match then download the correct version. Ok(version_string) => { - log::warn!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); + warn!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; @@ -123,7 +124,7 @@ impl Backend { // If `bb` fails to report its version, then attempt to fix it by re-downloading the binary. Err(_) => { - log::warn!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); + warn!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index 01842a81da9..6eee7c890c8 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -6,6 +6,7 @@ use acvm::acir::{circuit::Circuit, native_types::WitnessMap}; use acvm::ExpressionWidth; use acvm::FieldElement; use tempfile::tempdir; +use tracing::warn; use crate::cli::{ GatesCommand, InfoCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand, @@ -42,7 +43,7 @@ impl Backend { if let Ok(expression_width) = self.get_backend_info() { expression_width } else { - log::warn!( + warn!( "No valid backend found, ExpressionWidth defaulting to Bounded with a width of 3" ); ExpressionWidth::Bounded { width: 3 } diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index f0733d7ad44..d60f9d3ea28 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -24,7 +24,7 @@ iter-extended.workspace = true serde.workspace = true thiserror.workspace = true codespan-reporting.workspace = true -log.workspace = true +tracing.workspace = true rayon = "1.8.0" [dev-dependencies] diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs index 2ac85781410..4fc7f7b599f 100644 --- a/tooling/nargo/src/ops/execute.rs +++ b/tooling/nargo/src/ops/execute.rs @@ -7,13 +7,13 @@ use crate::NargoError; use super::foreign_calls::ForeignCallExecutor; +#[tracing::instrument(level = "trace", skip_all)] pub fn execute_circuit( circuit: &Circuit, initial_witness: WitnessMap, blackbox_solver: &B, foreign_call_executor: &mut F, ) -> Result { - log::trace!("Start circuit execution"); let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); loop { @@ -55,8 +55,5 @@ pub fn execute_circuit( } } - let solved_witness = acvm.finalize(); - - log::trace!("Finish circuit execution"); - Ok(solved_witness) + Ok(acvm.finalize()) } diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 65d3599bf35..f280682e15c 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -46,7 +46,6 @@ hex.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" color-eyre = "0.6.2" -env_logger = "0.9.0" tokio = { version = "1.0", features = ["io-std"] } dap.workspace = true @@ -55,8 +54,7 @@ backend-interface = { path = "../backend_interface" } bb_abstraction_leaks.workspace = true # Logs -tracing.workspace = true -tracing-subscriber = "0.3.18" +tracing-subscriber.workspace = true tracing-appender = "0.2.3" [target.'cfg(not(unix))'.dependencies] diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs index 7eeca2ab2b0..3f797b0bf0c 100644 --- a/tooling/nargo_cli/src/main.rs +++ b/tooling/nargo_cli/src/main.rs @@ -14,22 +14,27 @@ mod errors; use std::env; use color_eyre::config::HookBuilder; -use env_logger::{Builder, Env}; + use tracing_appender::rolling; +use tracing_subscriber::{fmt::format::FmtSpan, EnvFilter}; const PANIC_MESSAGE: &str = "This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.\nIf there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml"; fn main() { - let env = Env::default().filter_or("NOIR_LOG", "error"); // Default to 'error' if NOIR_LOG is not set - Builder::from_env(env).init(); - // Setup tracing if let Ok(log_dir) = env::var("NARGO_LOG_DIR") { let debug_file = rolling::daily(log_dir, "nargo-log"); tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) .with_writer(debug_file) .with_ansi(false) - .with_max_level(tracing::Level::TRACE) + .with_env_filter(EnvFilter::from_default_env()) + .init(); + } else { + tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) + .with_ansi(true) + .with_env_filter(EnvFilter::from_env("NOIR_LOG")) .init(); } From 6ddd98ab7d3fefde491cf12b785f76bf0585609e Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Wed, 20 Dec 2023 19:16:00 +0100 Subject: [PATCH 096/137] fix: bit-shifts for signed integers (#3890) # Description ## Problem\* Resolves #1479 ## Summary\* Add support for bit shifts with signed integers. We use Rust behaviour for overflows. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/function_builder/mod.rs | 25 ++++----- .../src/ssa/ssa_gen/context.rs | 56 ++++++++++++++----- .../noirc_frontend/src/hir/type_check/expr.rs | 10 +--- .../bit_shifts_runtime/src/main.nr | 11 ++++ 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 56a22fd4107..b972afa2990 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -266,15 +266,6 @@ impl FunctionBuilder { self.insert_instruction(Instruction::Call { func, arguments }, Some(result_types)).results() } - /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs - pub(crate) fn insert_shift_left(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { - let base = self.field_constant(FieldElement::from(2_u128)); - let pow = self.pow(base, rhs); - let typ = self.current_function.dfg.type_of_value(lhs); - let pow = self.insert_cast(pow, typ); - self.insert_binary(lhs, BinaryOp::Mul, pow) - } - /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs /// and truncate the result to bit_size pub(crate) fn insert_wrapping_shift_left( @@ -308,8 +299,9 @@ impl FunctionBuilder { let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1)); let predicate = self.insert_binary(overflow, BinaryOp::Eq, one); let predicate = self.insert_cast(predicate, typ.clone()); - - let pow = self.pow(base, rhs); + // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value + let rhs_unsigned = self.insert_cast(rhs, Type::unsigned(bit_size)); + let pow = self.pow(base, rhs_unsigned); let pow = self.insert_cast(pow, typ); (FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow)) }; @@ -323,9 +315,16 @@ impl FunctionBuilder { } /// Insert ssa instructions which computes lhs >> rhs by doing lhs/2^rhs - pub(crate) fn insert_shift_right(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { + pub(crate) fn insert_shift_right( + &mut self, + lhs: ValueId, + rhs: ValueId, + bit_size: u32, + ) -> ValueId { let base = self.field_constant(FieldElement::from(2_u128)); - let pow = self.pow(base, rhs); + // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value + let rhs_unsigned = self.insert_cast(rhs, Type::unsigned(bit_size)); + let pow = self.pow(base, rhs_unsigned); self.insert_binary(lhs, BinaryOp::Div, pow) } diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 501a03bcb5c..5724bf56e8e 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -326,8 +326,8 @@ impl<'a> FunctionContext<'a> { self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); self.builder.insert_cast(result, result_type) } - BinaryOpKind::ShiftLeft => { - unreachable!("shift is not supported for signed integer") + BinaryOpKind::ShiftLeft | BinaryOpKind::ShiftRight => { + self.check_shift_overflow(result, rhs, bit_size, location, true) } _ => unreachable!("operator {} should not overflow", operator), } @@ -343,8 +343,10 @@ impl<'a> FunctionContext<'a> { if operator == BinaryOpKind::Multiply && bit_size == 1 { result - } else if operator == BinaryOpKind::ShiftLeft { - self.check_left_shift_overflow(result, rhs, bit_size, location) + } else if operator == BinaryOpKind::ShiftLeft + || operator == BinaryOpKind::ShiftRight + { + self.check_shift_overflow(result, rhs, bit_size, location, false) } else { let message = format!("attempt to {} with overflow", op_name); let range_constraint = Instruction::RangeCheck { @@ -360,26 +362,44 @@ impl<'a> FunctionContext<'a> { } } - /// Overflow checks for shift-left - /// We use Rust behavior for shift left: + /// Overflow checks for bit-shift + /// We use Rust behavior for bit-shift: /// If rhs is more or equal than the bit size, then we overflow - /// If not, we do not overflow and shift left with 0 when bits are falling out of the bit size - fn check_left_shift_overflow( + /// If not, we do not overflow and shift with 0 when bits are falling out of the bit size + fn check_shift_overflow( &mut self, result: ValueId, rhs: ValueId, bit_size: u32, location: Location, + is_signed: bool, ) -> ValueId { + let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); + let rhs = + if is_signed { self.builder.insert_cast(rhs, Type::unsigned(bit_size)) } else { rhs }; + // Bit-shift with a negative number is an overflow + if is_signed { + // We compute the sign of rhs. + let half_width = self.builder.numeric_constant( + FieldElement::from(2_i128.pow(bit_size - 1)), + Type::unsigned(bit_size), + ); + let sign = self.builder.insert_binary(rhs, BinaryOp::Lt, half_width); + self.builder.set_location(location).insert_constrain( + sign, + one, + Some("attempt to bit-shift with overflow".to_string()), + ); + } + let max = self .builder .numeric_constant(FieldElement::from(bit_size as i128), Type::unsigned(bit_size)); let overflow = self.builder.insert_binary(rhs, BinaryOp::Lt, max); - let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); self.builder.set_location(location).insert_constrain( overflow, one, - Some("attempt to left shift with overflow".to_owned()), + Some("attempt to bit-shift with overflow".to_owned()), ); self.builder.insert_truncate(result, bit_size, bit_size + 1) } @@ -466,7 +486,6 @@ impl<'a> FunctionContext<'a> { Some(message), ); } - BinaryOpKind::ShiftLeft => unreachable!("shift is not supported for signed integer"), _ => unreachable!("operator {} should not overflow", operator), } } @@ -482,19 +501,26 @@ impl<'a> FunctionContext<'a> { mut rhs: ValueId, location: Location, ) -> Values { + let result_type = self.builder.type_of_value(lhs); let mut result = match operator { BinaryOpKind::ShiftLeft => { - let result_type = self.builder.current_function.dfg.type_of_value(lhs); let bit_size = match result_type { Type::Numeric(NumericType::Signed { bit_size }) | Type::Numeric(NumericType::Unsigned { bit_size }) => bit_size, - _ => unreachable!("ICE: Truncation attempted on non-integer"), + _ => unreachable!("ICE: left-shift attempted on non-integer"), }; self.builder.insert_wrapping_shift_left(lhs, rhs, bit_size) } - BinaryOpKind::ShiftRight => self.builder.insert_shift_right(lhs, rhs), + BinaryOpKind::ShiftRight => { + let bit_size = match result_type { + Type::Numeric(NumericType::Signed { bit_size }) + | Type::Numeric(NumericType::Unsigned { bit_size }) => bit_size, + _ => unreachable!("ICE: right-shift attempted on non-integer"), + }; + self.builder.insert_shift_right(lhs, rhs, bit_size) + } BinaryOpKind::Equal | BinaryOpKind::NotEqual - if matches!(self.builder.type_of_value(lhs), Type::Array(..)) => + if matches!(result_type, Type::Array(..)) => { return self.insert_array_equality(lhs, operator, rhs, location) } diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index f7154895150..e8f9f23d378 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -11,7 +11,7 @@ use crate::{ types::Type, }, node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId}, - BinaryOpKind, Signedness, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, + BinaryOpKind, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, }; use super::{errors::TypeCheckError, TypeChecker}; @@ -1121,13 +1121,7 @@ impl<'interner> TypeChecker<'interner> { span, }); } - if op.is_bit_shift() - && (*sign_x == Signedness::Signed || *sign_y == Signedness::Signed) - { - Err(TypeCheckError::InvalidInfixOp { kind: "Signed integer", span }) - } else { - Ok(Integer(*sign_x, *bit_width_x)) - } + Ok(Integer(*sign_x, *bit_width_x)) } (Integer(..), FieldElement) | (FieldElement, Integer(..)) => { Err(TypeCheckError::IntegerAndFieldBinaryOperation { span }) diff --git a/test_programs/execution_success/bit_shifts_runtime/src/main.nr b/test_programs/execution_success/bit_shifts_runtime/src/main.nr index a2c873a7e7f..33d68765598 100644 --- a/test_programs/execution_success/bit_shifts_runtime/src/main.nr +++ b/test_programs/execution_success/bit_shifts_runtime/src/main.nr @@ -5,4 +5,15 @@ fn main(x: u64, y: u64) { // runtime shifts on runtime values assert(x << y == 128); assert(x >> y == 32); + + // Bit-shift with signed integers + let mut a :i8 = y as i8; + let mut b: i8 = x as i8; + assert(b << 1 == -128); + assert(b >> 2 == 16); + assert(b >> a == 32); + a = -a; + assert(a << 7 == -128); + assert(a << -a == -2); + } From b8c7078810e174ba2385f467467afd16bd211d16 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 20 Dec 2023 18:33:34 +0000 Subject: [PATCH 097/137] chore: improve tracing of compiler execution (#3893) # Description ## Problem\* Resolves ## Summary\* This PR adds more comprehensive tracing through the compiler as well as allowing us to monitor how long proving/verification takes. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acvm/src/compiler/optimizers/mod.rs | 5 +++++ compiler/noirc_driver/src/lib.rs | 1 + compiler/noirc_evaluator/src/ssa.rs | 2 +- compiler/noirc_evaluator/src/ssa/opt/array_use.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/die.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/inlining.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs | 1 + compiler/noirc_evaluator/src/ssa/opt/unrolling.rs | 1 + tooling/backend_interface/src/cli/write_vk.rs | 1 + tooling/backend_interface/src/proof_system.rs | 2 ++ 16 files changed, 21 insertions(+), 1 deletion(-) diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index 952bec2f7af..923756580b3 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -6,6 +6,7 @@ mod unused_memory; pub(crate) use general::GeneralOptimizer; pub(crate) use redundant_range::RangeOptimizer; +use tracing::info; use self::unused_memory::UnusedMemoryOptimizer; @@ -25,6 +26,8 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. #[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir))] pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { + info!("Number of opcodes before: {}", acir.opcodes.len()); + // General optimizer pass let opcodes: Vec = acir .opcodes @@ -53,5 +56,7 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { let (acir, acir_opcode_positions) = range_optimizer.replace_redundant_ranges(acir_opcode_positions); + info!("Number of opcodes after: {}", acir.opcodes.len()); + (acir, acir_opcode_positions) } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 3908d16e01d..7136580b770 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -375,6 +375,7 @@ fn compile_contract_inner( /// Compile the current crate using `main_function` as the entrypoint. /// /// This function assumes [`check_crate`] is called beforehand. +#[tracing::instrument(level = "trace", skip_all, fields(function_name = context.function_name(&main_function)))] pub fn compile_no_check( context: &Context, options: &CompileOptions, diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 3c814c04eb2..deffe84baea 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -83,7 +83,7 @@ pub(crate) fn optimize_into_acir( /// /// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. #[allow(clippy::type_complexity)] -#[tracing::instrument(level = "trace", skip(program))] +#[tracing::instrument(level = "trace", skip_all)] pub fn create_circuit( program: Program, enable_ssa_logging: bool, diff --git a/compiler/noirc_evaluator/src/ssa/opt/array_use.rs b/compiler/noirc_evaluator/src/ssa/opt/array_use.rs index cfa97cee551..0bb8b0112b6 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/array_use.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/array_use.rs @@ -14,6 +14,7 @@ impl Ssa { /// Map arrays with the last instruction that uses it /// For this we simply process all the instructions in execution order /// and update the map whenever there is a match + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn find_last_array_uses(&self) -> HashMap { let mut array_use = HashMap::default(); for func in self.functions.values() { diff --git a/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs b/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs index cd3a509a62e..a3608f89612 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs @@ -21,6 +21,7 @@ impl Ssa { /// seen by loop unrolling. Furthermore, this pass cannot be a part of loop unrolling /// since we must go through every instruction to find all references to `assert_constant` /// while loop unrolling only touches blocks with loops in them. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn evaluate_assert_constant(mut self) -> Result { for function in self.functions.values_mut() { for block in function.reachable_blocks() { diff --git a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index f48e6f2a129..e944d7d99d8 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -40,6 +40,7 @@ impl Ssa { /// Performs constant folding on each instruction. /// /// See [`constant_folding`][self] module for more information. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn fold_constants(mut self) -> Ssa { for function in self.functions.values_mut() { constant_fold(function); diff --git a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index 62b335be1e2..b7f154397a6 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -52,6 +52,7 @@ struct DefunctionalizationContext { } impl Ssa { + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn defunctionalize(mut self) -> Ssa { // Find all functions used as value that share the same signature let variants = find_variants(&self); diff --git a/compiler/noirc_evaluator/src/ssa/opt/die.rs b/compiler/noirc_evaluator/src/ssa/opt/die.rs index 492e96dc08c..029adb10054 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -17,6 +17,7 @@ use crate::ssa::{ impl Ssa { /// Performs Dead Instruction Elimination (DIE) to remove any instructions with /// unused results. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn dead_instruction_elimination(mut self) -> Ssa { for function in self.functions.values_mut() { dead_instruction_elimination(function); diff --git a/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs index f5e9598114c..5ee8e42fe3a 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs @@ -60,6 +60,7 @@ use acvm::FieldElement; use fxhash::FxHashMap as HashMap; impl Ssa { + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn fill_internal_slices(mut self) -> Ssa { for function in self.functions.values_mut() { // This pass is only necessary for generating ACIR and thus we should not diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index f0ad610948c..0e7bfff7b6b 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -163,6 +163,7 @@ impl Ssa { /// This pass will modify any instructions with side effects in particular, often multiplying /// them by jump conditions to maintain correctness even when all branches of a jmpif are inlined. /// For more information, see the module-level comment at the top of this file. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn flatten_cfg(mut self) -> Ssa { flatten_function_cfg(self.main_mut()); self diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index b4f12b2f897..776f22b2877 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -36,6 +36,7 @@ impl Ssa { /// changes. This is because if the function's id later becomes known by a later /// pass, we would need to re-run all of inlining anyway to inline it, so we might /// as well save the work for later instead of performing it twice. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn inline_functions(mut self) -> Ssa { self.functions = btree_map(get_entry_point_functions(&self), |entry_point| { let new_function = InlineContext::new(&self, entry_point).inline_all(&self); diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index ce205c8d883..0a49ca4ecca 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -86,6 +86,7 @@ use self::block::{Block, Expression}; impl Ssa { /// Attempts to remove any load instructions that recover values that are already available in /// scope, and attempts to remove stores that are subsequently redundant. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn mem2reg(mut self) -> Ssa { for function in self.functions.values_mut() { let mut context = PerFunctionContext::new(function); diff --git a/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs index d491afc3d26..a31def8fd98 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs @@ -29,6 +29,7 @@ impl Ssa { /// only 1 successor then (2) also will be applied. /// /// Currently, 1 and 4 are unimplemented. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn simplify_cfg(mut self) -> Self { for function in self.functions.values_mut() { simplify_function(function); diff --git a/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index 50c2f5b1524..2fe9ea13cec 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -36,6 +36,7 @@ use fxhash::FxHashMap as HashMap; impl Ssa { /// Unroll all loops in each SSA function. /// If any loop cannot be unrolled, it is left as-is or in a partially unrolled state. + #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn unroll_loops(mut self) -> Result { for function in self.functions.values_mut() { // Loop unrolling in brillig can lead to a code explosion currently. This can diff --git a/tooling/backend_interface/src/cli/write_vk.rs b/tooling/backend_interface/src/cli/write_vk.rs index 8d4aa9cc7e3..da9fc04cbef 100644 --- a/tooling/backend_interface/src/cli/write_vk.rs +++ b/tooling/backend_interface/src/cli/write_vk.rs @@ -12,6 +12,7 @@ pub(crate) struct WriteVkCommand { } impl WriteVkCommand { + #[tracing::instrument(level = "trace", name = "vk_generation", skip_all)] pub(crate) fn run(self, binary_path: &Path) -> Result<(), BackendError> { let mut command = std::process::Command::new(binary_path); diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index 6eee7c890c8..595cd7e2020 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -50,6 +50,7 @@ impl Backend { } } + #[tracing::instrument(level = "trace", skip_all)] pub fn prove( &self, circuit: &Circuit, @@ -90,6 +91,7 @@ impl Backend { Ok(proof) } + #[tracing::instrument(level = "trace", skip_all)] pub fn verify( &self, proof: &[u8], From d0257318fee0683d4b9e026f6e7606b8912eded4 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 20 Dec 2023 23:21:49 +0000 Subject: [PATCH 098/137] chore: error on cspell issues in docs (#3886) # Description ## Problem\* Resolves ## Summary\* This PR updates the spellcheck workflow to run a separate pass over the docs which will error rather than raising a warning. This is as it's more important to catch spelling issues in the docs rather than in the code (plus the docs is going to use fewer non-standard-english library names, etc. so false positives will be rarer. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .github/workflows/spellcheck.yml | 32 +++++++++++++++++++++++++++++--- cspell.json | 4 ++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 89fcdd12d12..83d67325775 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -8,6 +8,32 @@ concurrency: cancel-in-progress: true jobs: - spellcheck: - name: Spellcheck - uses: noir-lang/.github/.github/workflows/spellcheck.yml@main + code: + name: Code + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check spelling + uses: streetsidesoftware/cspell-action@v2 + with: + strict: false # Do not fail, if a spelling mistake is found (This can be annoying for contributors) + incremental_files_only: true # Run this action on files which have changed in PR + files: | + **/*.{md,rs} + + docs: + name: Documentation + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check spelling + uses: streetsidesoftware/cspell-action@v2 + with: + strict: true # Documentation has higher standards for correctness. + incremental_files_only: true # Run this action on files which have changed in PR + files: | + ./docs/**/*.md diff --git a/cspell.json b/cspell.json index d8f04ed6069..9b6ea53f9b2 100644 --- a/cspell.json +++ b/cspell.json @@ -124,6 +124,7 @@ "srem", "stdlib", "struct", + "structs", "subexpression", "subshell", "subtyping", @@ -148,5 +149,8 @@ "wasi", "Weierstraß", "zshell" + ], + "ignorePaths": [ + "./**/node_modules/**" ] } From f7fa1811ad2591020c914976f26e2f11a91cd177 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:52:32 +0000 Subject: [PATCH 099/137] fix: allow abi encoding tuples from JS (#3894) # Description ## Problem\* Resolves ## Summary\* We currently disallow abi encoding tuples which contain a mix of primitive types, arrays and structs due to the types which have been applied. This PR loosens the types so that we can pass a mix of these types as a tuple. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- cspell.json | 1 + tooling/noirc_abi_wasm/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index 9b6ea53f9b2..51e49c78e59 100644 --- a/cspell.json +++ b/cspell.json @@ -36,6 +36,7 @@ "cpus", "cranelift", "curvegroup", + "databus", "deflatten", "deflattened", "deflattening", diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs index 281ec712c39..5557cc917bf 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -27,7 +27,7 @@ use js_witness_map::JsWitnessMap; #[wasm_bindgen(typescript_custom_section)] const INPUT_MAP: &'static str = r#" export type Field = string | number | boolean; -export type InputValue = Field | Field[] | InputMap | InputMap[]; +export type InputValue = Field | InputMap | (Field | InputMap)[]; export type InputMap = { [key: string]: InputValue }; "#; From 926460a0c70e21e2f4720148cf424e44ab9b0678 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:52:59 +0000 Subject: [PATCH 100/137] feat: optimize logic gate ACIR-gen (#3897) # Description ## Problem\* Resolves ## Summary\* We're performing a number of unnecessary logic operations due to the new signed integer behaviour. This PR adds acir-gen logic to remove these. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 05a22ab6aad..c9eed69e77c 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -368,6 +368,21 @@ impl AcirContext { rhs: AcirVar, typ: AcirType, ) -> Result { + let lhs_expr = self.var_to_expression(lhs)?; + let rhs_expr = self.var_to_expression(rhs)?; + + if lhs_expr == rhs_expr { + // x ^ x == 0 + let zero = self.add_constant(FieldElement::zero()); + return Ok(zero); + } else if lhs_expr.is_zero() { + // 0 ^ x == x + return Ok(rhs); + } else if rhs_expr.is_zero() { + // x ^ 0 == x + return Ok(lhs); + } + let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; Ok(outputs[0]) @@ -380,6 +395,18 @@ impl AcirContext { rhs: AcirVar, typ: AcirType, ) -> Result { + let lhs_expr = self.var_to_expression(lhs)?; + let rhs_expr = self.var_to_expression(rhs)?; + + if lhs_expr == rhs_expr { + // x & x == x + return Ok(lhs); + } else if lhs_expr.is_zero() || rhs_expr.is_zero() { + // x & 0 == 0 and 0 & x == 0 + let zero = self.add_constant(FieldElement::zero()); + return Ok(zero); + } + let bit_size = typ.bit_size(); if bit_size == 1 { // Operands are booleans. @@ -398,6 +425,16 @@ impl AcirContext { rhs: AcirVar, typ: AcirType, ) -> Result { + let lhs_expr = self.var_to_expression(lhs)?; + let rhs_expr = self.var_to_expression(rhs)?; + if lhs_expr.is_zero() { + // 0 | x == x + return Ok(rhs); + } else if rhs_expr.is_zero() { + // x | 0 == x + return Ok(lhs); + } + let bit_size = typ.bit_size(); if bit_size == 1 { // Operands are booleans From 0ec39b8396084ed1e7f20609c8ad8a5844a86674 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:51:17 +0000 Subject: [PATCH 101/137] feat: prefer `AcirContext`-native methods for performing logic operations (#3898) # Description ## Problem\* Resolves ## Summary\* This PR remove some duplicate implementations or too-low-level calls to logic operations in `AcirContext`. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index c9eed69e77c..db2e24af142 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -383,9 +383,19 @@ impl AcirContext { return Ok(lhs); } - let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; - let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; - Ok(outputs[0]) + let bit_size = typ.bit_size(); + if bit_size == 1 { + // Operands are booleans. + // + // a ^ b == a + b - 2*a*b + let sum = self.add_var(lhs, rhs)?; + let prod = self.mul_var(lhs, rhs)?; + self.add_mul_var(sum, -FieldElement::from(2_i128), prod) + } else { + let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; + let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; + Ok(outputs[0]) + } } /// Returns an `AcirVar` that is the AND result of `lhs` & `rhs`. @@ -450,9 +460,8 @@ impl AcirContext { let max = self.add_constant((1_u128 << bit_size) - 1); let a = self.sub_var(max, lhs)?; let b = self.sub_var(max, rhs)?; - let inputs = vec![AcirValue::Var(a, typ.clone()), AcirValue::Var(b, typ)]; - let outputs = self.black_box_function(BlackBoxFunc::AND, inputs, 1)?; - self.sub_var(max, outputs[0]) + let a_and_b = self.and_var(a, b, typ)?; + self.sub_var(max, a_and_b) } } @@ -889,9 +898,7 @@ impl AcirContext { // Unsigned to signed: derive q and r from q1,r1 and the signs of lhs and rhs // Quotient sign is lhs sign * rhs sign, whose resulting sign bit is the XOR of the sign bits - let sign_sum = self.add_var(lhs_leading, rhs_leading)?; - let sign_prod = self.mul_var(lhs_leading, rhs_leading)?; - let q_sign = self.add_mul_var(sign_sum, -FieldElement::from(2_i128), sign_prod)?; + let q_sign = self.xor_var(lhs_leading, rhs_leading, AcirType::unsigned(1))?; let quotient = self.two_complement(q1, q_sign, bit_size)?; let remainder = self.two_complement(r1, lhs_leading, bit_size)?; From 0a36fdf20dd5b07bd9efc1414f7f52ca71800aba Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:51:24 +0000 Subject: [PATCH 102/137] chore: improve package.json metadata (#3900) # Description ## Problem\* Resolves ## Summary\* Socket is complaining about our releases: https://socket.dev/npm/package/@noir-lang/noir_js/issues/0.22.0-d025731.nightly This PR adds various metadata to improve out package quality score. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acvm_js/package.json | 15 ++++++++++----- compiler/wasm/package.json | 11 ++++++++--- tooling/noir_codegen/package.json | 11 ++++++++++- tooling/noir_js/package.json | 11 ++++++++++- tooling/noir_js_backend_barretenberg/package.json | 11 ++++++++++- tooling/noir_js_types/package.json | 11 ++++++++++- tooling/noirc_abi_wasm/package.json | 15 ++++++++++----- 7 files changed, 68 insertions(+), 17 deletions(-) diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index 9f265dd676a..2d878e961da 100644 --- a/acvm-repo/acvm_js/package.json +++ b/acvm-repo/acvm_js/package.json @@ -1,16 +1,21 @@ { "name": "@noir-lang/acvm_js", "version": "0.38.0", - "repository": { - "type": "git", - "url": "https://github.com/noir-lang/acvm.git" - }, "publishConfig": { "access": "public" }, - "collaborators": [ + "contributors": [ "The Noir Team " ], + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "acvm_repo/acvm_js", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "license": "MIT", "main": "./nodejs/acvm_js.js", "types": "./web/acvm_js.d.ts", diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index 352142eb3e3..38fd118f189 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/noir_wasm", - "collaborators": [ + "contributors": [ "The Noir Team " ], "version": "0.22.0", @@ -14,9 +14,14 @@ "package.json" ], "sideEffects": false, + "homepage": "https://noir-lang.org/", "repository": { - "type": "git", - "url": "https://github.com/noir-lang/noir.git" + "url": "https://github.com/noir-lang/noir.git", + "directory": "compiler/wasm", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" }, "scripts": { "build": "bash ./build.sh", diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json index 3ae31d9834f..a10855ed63d 100644 --- a/tooling/noir_codegen/package.json +++ b/tooling/noir_codegen/package.json @@ -1,12 +1,21 @@ { "name": "@noir-lang/noir_codegen", - "collaborators": [ + "contributors": [ "The Noir Team " ], "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "compiler/wasm", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "dependencies": { "@noir-lang/types": "workspace:*", "glob": "^10.3.10", diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index d5ea4b4ad5d..ed2fd225810 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -1,12 +1,21 @@ { "name": "@noir-lang/noir_js", - "collaborators": [ + "contributors": [ "The Noir Team " ], "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noir_js", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "dependencies": { "@noir-lang/acvm_js": "workspace:*", "@noir-lang/noirc_abi": "workspace:*", diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index c34b8dfc825..93fdc856338 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -1,12 +1,21 @@ { "name": "@noir-lang/backend_barretenberg", - "collaborators": [ + "contributors": [ "The Noir Team " ], "version": "0.22.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noir_js_backend_barretenberg", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "source": "src/index.ts", "main": "lib/cjs/index.js", "module": "lib/esm/index.js", diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index 51856cfe465..0276b8d087c 100644 --- a/tooling/noir_js_types/package.json +++ b/tooling/noir_js_types/package.json @@ -1,11 +1,20 @@ { "name": "@noir-lang/types", - "collaborators": [ + "contributors": [ "The Noir Team " ], "packageManager": "yarn@3.5.1", "version": "0.22.0", "license": "(MIT OR Apache-2.0)", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noir_js_types", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "files": [ "lib", "package.json" diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index 5b2cd344eab..d023e1e4391 100644 --- a/tooling/noirc_abi_wasm/package.json +++ b/tooling/noirc_abi_wasm/package.json @@ -1,10 +1,19 @@ { "name": "@noir-lang/noirc_abi", - "collaborators": [ + "contributors": [ "The Noir Team " ], "version": "0.22.0", "license": "(MIT OR Apache-2.0)", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noirc_abi_wasm", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, "files": [ "nodejs", "web", @@ -17,10 +26,6 @@ "types": "./web/noirc_abi_wasm.d.ts", "module": "./web/noirc_abi_wasm.js", "sideEffects": false, - "repository": { - "type": "git", - "url": "https://github.com/noir-lang/noir.git" - }, "scripts": { "build": "bash ./build.sh", "test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha", From 278b404981557f3f1fe1b96d23ba64be0dbd5605 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:11:39 +0000 Subject: [PATCH 103/137] chore: remove unnecessary dependency (#3901) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 1 - acvm-repo/acvm_js/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c4638f4001..dec9609c76f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,7 +79,6 @@ dependencies = [ "js-sys", "pkg-config", "serde", - "tracing", "tracing-subscriber", "tracing-web", "wasm-bindgen", diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index 987006f8e2b..e8d46b9717e 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -26,7 +26,6 @@ wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true js-sys.workspace = true -tracing.workspace = true tracing-subscriber.workspace = true tracing-web.workspace = true From 2fcbef565f27defad5d309e6cbb4b8f952da0257 Mon Sep 17 00:00:00 2001 From: brunny-eth <96834997+brunny-eth@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:24:58 -0500 Subject: [PATCH 104/137] chore: Update explainer-recursion.md (#3906) Made some simple readability changes # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/explainers/explainer-recursion.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/docs/explainers/explainer-recursion.md b/docs/docs/explainers/explainer-recursion.md index 9357d3c7341..8f992ec29fd 100644 --- a/docs/docs/explainers/explainer-recursion.md +++ b/docs/docs/explainers/explainer-recursion.md @@ -64,7 +64,9 @@ So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob w This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. -So, Alice started thinking: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". She can then generate a proof that she verified his proof, and so on. +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. ```md Did you fail? <-------------------------- @@ -86,7 +88,7 @@ Generate proof of that / Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! -So, the tallier puts all the votes in a merkle tree, and everyone can also prove the verification of two proofs within one proof, as such: +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: ```md abcd @@ -104,7 +106,7 @@ Doing this recursively allows us to arrive on a final proof `abcd` which if true Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. -He could find it more efficient to generate a proof for that setup phase separately, and verifying it in his actual business logic section of the circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. ## What params do I need From cc4461392e795376a744419de5e43ae8d901fe4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 08:30:50 +0000 Subject: [PATCH 105/137] feat: Resolve oracle calls via JSON-RPC (#3902) # Description This adds a JSON-RPC client to the DefaultForeignCallExecutor. This allows it to solve unknown oracle calls. The URL to the foreign call executor is an optional argument to nargo execute, nargo test and nargo prove. ## Problem\* Resolves #1052 ## Summary\* ## Additional Context An example echo server in typescript ```typescript import { JSONRPCServer, TypedJSONRPCServer, } from "json-rpc-2.0"; import express from "express"; import bodyParser from "body-parser"; type Methods = { echo(params: ForeignCallParam[]): ForeignCallResult; }; const server: TypedJSONRPCServer = new JSONRPCServer(/* ... */); interface Value { inner: string, } interface SingleForeignCallParam { Single: Value, } interface ArrayForeignCallParam { Array: Value[], } type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; interface ForeignCallResult { values: ForeignCallParam[], } server.addMethod("echo", (params) => { return {values: params}; }); const app = express(); app.use(bodyParser.json()); app.post("/", (req, res) => { const jsonRPCRequest = req.body; console.log(jsonRPCRequest); // server.receive takes a JSON-RPC request and returns a promise of a JSON-RPC response. // It can also receive an array of requests, in which case it may return an array of responses. // Alternatively, you can use server.receiveJSON, which takes JSON string as is (in this case req.body). server.receive(jsonRPCRequest).then((jsonRPCResponse) => { if (jsonRPCResponse) { res.json(jsonRPCResponse); } else { // If response is absent, it was a JSON-RPC notification method. // Respond with no content status (204). res.sendStatus(204); } }); }); app.listen(5555); ``` And the corresponding main.nr ```rust #[oracle(echo)] fn echo_oracle(_x: Field) -> Field {} unconstrained fn echo(x: Field) -> Field { echo_oracle(x) } fn main(x: Field, y: pub Field) { assert(echo(x) == y); } ``` ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. (We can document this when we evaluate if this solution is enough) # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: thunkar --- Cargo.lock | 565 +++++++++++++++++++---- Cargo.toml | 1 + acvm-repo/acir_field/src/generic_ark.rs | 5 +- compiler/noirc_printable_type/Cargo.toml | 1 + compiler/noirc_printable_type/src/lib.rs | 3 + deny.toml | 1 + tooling/debugger/src/context.rs | 6 +- tooling/debugger/src/dap.rs | 2 +- tooling/debugger/src/repl.rs | 4 +- tooling/lsp/src/requests/test_run.rs | 10 +- tooling/nargo/Cargo.toml | 8 +- tooling/nargo/src/ops/foreign_calls.rs | 153 +++++- tooling/nargo/src/ops/test.rs | 3 +- tooling/nargo_cli/src/cli/execute_cmd.rs | 18 +- tooling/nargo_cli/src/cli/prove_cmd.rs | 10 +- tooling/nargo_cli/src/cli/test_cmd.rs | 15 +- 16 files changed, 687 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dec9609c76f..1750f5d284e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "acir" version = "0.38.0" dependencies = [ "acir_field", - "base64", + "base64 0.21.2", "bincode", "brillig", "flate2", @@ -28,7 +28,7 @@ dependencies = [ "ark-bls12-381", "ark-bn254", "ark-ff", - "cfg-if", + "cfg-if 1.0.0", "hex", "num-bigint", "num-traits", @@ -47,7 +47,7 @@ dependencies = [ "num-traits", "paste", "proptest", - "rand", + "rand 0.8.5", "thiserror", "tracing", ] @@ -72,7 +72,7 @@ dependencies = [ "acvm", "bn254_blackbox_solver", "build-data", - "cfg-if", + "cfg-if 1.0.0", "console_error_panic_hook", "const-str", "gloo-utils", @@ -107,7 +107,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom", + "getrandom 0.2.10", "once_cell", "version_check", ] @@ -118,8 +118,8 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ - "cfg-if", - "getrandom", + "cfg-if 1.0.0", + "getrandom 0.2.10", "once_cell", "version_check", ] @@ -341,7 +341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -386,7 +386,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures", + "futures 0.3.28", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -442,7 +442,7 @@ checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -455,6 +455,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.2" @@ -560,7 +566,7 @@ dependencies = [ "ark-ec", "ark-ff", "flate2", - "getrandom", + "getrandom 0.2.10", "grumpkin", "js-sys", "num-bigint", @@ -726,6 +732,12 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -851,7 +863,7 @@ checksum = "fc4159b76af02757139baf42c0c971c6dc155330999fbfd8eddb29b97fb2db68" dependencies = [ "codespan-reporting", "lsp-types 0.88.0", - "url", + "url 2.4.0", ] [[package]] @@ -916,7 +928,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen", ] @@ -952,6 +964,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -965,7 +983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", "libc", "scopeguard", "windows-sys 0.33.0", @@ -977,7 +995,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee34052ee3d93d6d8f3e6f81d85c47921f6653a19a7b70e939e3e602d893a674" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1078,7 +1096,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1123,7 +1141,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -1133,7 +1151,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] @@ -1145,7 +1163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", "memoffset 0.9.0", "scopeguard", @@ -1157,7 +1175,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -1167,7 +1185,7 @@ version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1177,7 +1195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -1265,11 +1283,11 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "hashbrown 0.14.0", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.8", ] [[package]] @@ -1311,6 +1329,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "difflib" version = "0.4.0" @@ -1343,7 +1374,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "dirs-sys-next", ] @@ -1422,7 +1453,7 @@ dependencies = [ "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1446,7 +1477,7 @@ version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1550,7 +1581,7 @@ version = "3.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "rustix", "windows-sys 0.48.0", ] @@ -1561,7 +1592,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1580,7 +1611,7 @@ version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.3.5", "windows-sys 0.48.0", @@ -1639,7 +1670,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ - "percent-encoding", + "percent-encoding 2.3.0", ] [[package]] @@ -1648,6 +1679,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + [[package]] name = "futures" version = "0.3.28" @@ -1656,6 +1693,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1678,6 +1716,18 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + [[package]] name = "futures-io" version = "0.3.28" @@ -1713,6 +1763,7 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures 0.1.31", "futures-channel", "futures-core", "futures-io", @@ -1740,7 +1791,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1753,16 +1804,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1833,7 +1895,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1863,7 +1925,7 @@ dependencies = [ "indexmap 1.9.3", "slab", "tokio", - "tokio-util", + "tokio-util 0.7.8", "tracing", ] @@ -2049,6 +2111,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.4.0" @@ -2083,7 +2156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core", + "rand_core 0.6.4", "rand_xoshiro", "serde", "sized-chunks", @@ -2161,6 +2234,15 @@ dependencies = [ "str_stack", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "ipnet" version = "2.8.0" @@ -2206,13 +2288,127 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpc" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efde8d2422fb79ed56db1d3aea8fa5b583351d15a26770cdee2f88813dd702" +dependencies = [ + "base64 0.13.1", + "minreq", + "serde", + "serde_json", +] + +[[package]] +name = "jsonrpc-client-transports" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" +dependencies = [ + "derive_more", + "futures 0.3.28", + "jsonrpc-core", + "jsonrpc-pubsub", + "log", + "serde", + "serde_json", + "url 1.7.2", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures 0.3.28", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "jsonrpc-core-client" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" +dependencies = [ + "futures 0.3.28", + "jsonrpc-client-transports", +] + +[[package]] +name = "jsonrpc-derive" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "jsonrpc-http-server" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" +dependencies = [ + "futures 0.3.28", + "hyper", + "jsonrpc-core", + "jsonrpc-server-utils", + "log", + "net2", + "parking_lot 0.11.2", + "unicase", +] + +[[package]] +name = "jsonrpc-pubsub" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" +dependencies = [ + "futures 0.3.28", + "jsonrpc-core", + "lazy_static", + "log", + "parking_lot 0.11.2", + "rand 0.7.3", + "serde", +] + +[[package]] +name = "jsonrpc-server-utils" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" +dependencies = [ + "bytes", + "futures 0.3.28", + "globset", + "jsonrpc-core", + "lazy_static", + "log", + "tokio", + "tokio-stream", + "tokio-util 0.6.10", + "unicase", +] + [[package]] name = "k256" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "ecdsa", "elliptic-curve", "sha2", @@ -2292,7 +2488,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url", + "url 2.4.0", ] [[package]] @@ -2305,7 +2501,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url", + "url 2.4.0", ] [[package]] @@ -2326,6 +2522,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + [[package]] name = "memchr" version = "2.5.0" @@ -2392,6 +2594,17 @@ dependencies = [ "adler", ] +[[package]] +name = "minreq" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3371dfc7b772c540da1380123674a8e20583aca99907087d990ca58cf44203" +dependencies = [ + "log", + "serde", + "serde_json", +] + [[package]] name = "mio" version = "0.8.8" @@ -2399,7 +2612,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2417,6 +2630,11 @@ dependencies = [ "codespan-reporting", "fm", "iter-extended", + "jsonrpc", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "jsonrpc-http-server", "noirc_abi", "noirc_driver", "noirc_errors", @@ -2426,6 +2644,7 @@ dependencies = [ "rayon", "rustc_version", "serde", + "serial_test", "tempfile", "thiserror", "tracing", @@ -2476,8 +2695,8 @@ dependencies = [ "test-binary", "thiserror", "tokio", - "tokio-util", - "toml", + "tokio-util 0.7.8", + "toml 0.7.6", "tower", "tracing-appender", "tracing-subscriber", @@ -2492,7 +2711,7 @@ dependencies = [ "serde", "similar-asserts", "thiserror", - "toml", + "toml 0.7.6", ] [[package]] @@ -2506,8 +2725,19 @@ dependencies = [ "semver", "serde", "thiserror", - "toml", - "url", + "toml 0.7.6", + "url 2.4.0", +] + +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi", ] [[package]] @@ -2527,7 +2757,7 @@ checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags 1.3.2", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.6.5", ] @@ -2539,7 +2769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "static_assertions", ] @@ -2594,7 +2824,7 @@ dependencies = [ "build-data", "console_error_panic_hook", "fm", - "getrandom", + "getrandom 0.2.10", "gloo-utils", "js-sys", "nargo", @@ -2621,7 +2851,7 @@ dependencies = [ "strum", "strum_macros", "thiserror", - "toml", + "toml 0.7.6", ] [[package]] @@ -2631,7 +2861,7 @@ dependencies = [ "acvm", "build-data", "console_error_panic_hook", - "getrandom", + "getrandom 0.2.10", "gloo-utils", "iter-extended", "js-sys", @@ -2721,6 +2951,7 @@ version = "0.22.0" dependencies = [ "acvm", "iter-extended", + "jsonrpc", "regex", "serde", "serde_json", @@ -2838,6 +3069,17 @@ dependencies = [ "sha2", ] +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -2845,7 +3087,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -2854,7 +3110,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.3.5", "smallvec", @@ -2867,6 +3123,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + [[package]] name = "percent-encoding" version = "2.3.0" @@ -2891,7 +3153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -2980,7 +3242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978385d59daf9269189d052ca8a84c1acfd0715c0599a5d5188d4acc078ca46a" dependencies = [ "backtrace", - "cfg-if", + "cfg-if 1.0.0", "criterion", "findshlibs", "inferno", @@ -2988,7 +3250,7 @@ dependencies = [ "log", "nix 0.26.2", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "smallvec", "symbolic-demangle", "tempfile", @@ -3057,6 +3319,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3107,8 +3378,8 @@ dependencies = [ "bitflags 2.3.3", "lazy_static", "num-traits", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_xorshift", "regex-syntax 0.7.4", "rusty-fork", @@ -3176,6 +3447,19 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -3183,8 +3467,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -3194,7 +3488,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -3203,7 +3506,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -3212,7 +3524,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3221,7 +3533,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3268,7 +3580,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.10", "redox_syscall 0.2.16", "thiserror", ] @@ -3356,7 +3668,7 @@ version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -3371,7 +3683,7 @@ dependencies = [ "log", "mime", "once_cell", - "percent-encoding", + "percent-encoding 2.3.0", "pin-project-lite", "rustls", "rustls-pemfile", @@ -3381,7 +3693,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "url", + "url 2.4.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3541,7 +3853,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64", + "base64 0.21.2", ] [[package]] @@ -3579,7 +3891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "clipboard-win", "dirs-next", "fd-lock", @@ -3836,7 +4148,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" dependencies = [ - "base64", + "base64 0.21.2", "chrono", "hex", "indexmap 1.9.3", @@ -3859,13 +4171,38 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "serial_test" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +dependencies = [ + "dashmap", + "futures 0.3.28", + "lazy_static", + "log", + "parking_lot 0.12.1", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "sha2" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -3921,7 +4258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4166,7 +4503,7 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", "rustix", @@ -4259,7 +4596,7 @@ version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -4355,6 +4692,31 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -4370,6 +4732,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.7.6" @@ -4551,6 +4922,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -4602,6 +4982,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + [[package]] name = "url" version = "2.4.0" @@ -4609,8 +5000,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", - "idna", - "percent-encoding", + "idna 0.4.0", + "percent-encoding 2.3.0", "serde", ] @@ -4676,6 +5067,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4688,7 +5085,7 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "serde", "serde_json", "wasm-bindgen-macro", @@ -4738,7 +5135,7 @@ version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -4813,7 +5210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50cb1ae2956aac1fbbcf334c543c1143cdf7d5b0a5fb6c3d23a17bf37dd1f47b" dependencies = [ "bytes", - "cfg-if", + "cfg-if 1.0.0", "derivative", "indexmap 1.9.3", "js-sys", @@ -4845,7 +5242,7 @@ checksum = "12fd9aeef339095798d1e04957d5657d97490b1112f145cbf08b98f6393b4a0a" dependencies = [ "backtrace", "bytes", - "cfg-if", + "cfg-if 1.0.0", "enum-iterator", "enumset", "lazy_static", @@ -4919,7 +5316,7 @@ checksum = "60c3513477bc0097250f6e34a640e2a903bb0ee57e6bb518c427f72c06ac7728" dependencies = [ "backtrace", "cc", - "cfg-if", + "cfg-if 1.0.0", "corosensei", "crossbeam-queue", "dashmap", @@ -4952,7 +5349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" dependencies = [ "indexmap 1.9.3", - "url", + "url 2.4.0", ] [[package]] @@ -5222,7 +5619,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index 7dda111c1a5..5469a63f3dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -122,6 +122,7 @@ num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" tempfile = "3.6.0" +jsonrpc = { version = "0.16.0", features = ["minreq_http"] } tracing = "0.1.40" tracing-web = "0.1.3" diff --git a/acvm-repo/acir_field/src/generic_ark.rs b/acvm-repo/acir_field/src/generic_ark.rs index 5c70d3cda37..542e291982b 100644 --- a/acvm-repo/acir_field/src/generic_ark.rs +++ b/acvm-repo/acir_field/src/generic_ark.rs @@ -2,6 +2,7 @@ use ark_ff::PrimeField; use ark_ff::Zero; use num_bigint::BigUint; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; // XXX: Switch out for a trait and proper implementations // This implementation is in-efficient, can definitely remove hex usage and Iterator instances for trivial functionality @@ -125,8 +126,8 @@ impl<'de, T: ark_ff::PrimeField> Deserialize<'de> for FieldElement { where D: serde::Deserializer<'de>, { - let s = <&str>::deserialize(deserializer)?; - match Self::from_hex(s) { + let s: Cow<'de, str> = Deserialize::deserialize(deserializer)?; + match Self::from_hex(&s) { Some(value) => Ok(value), None => Err(serde::de::Error::custom(format!("Invalid hex for FieldElement: {s}",))), } diff --git a/compiler/noirc_printable_type/Cargo.toml b/compiler/noirc_printable_type/Cargo.toml index 5f2eea92257..fbbe778e561 100644 --- a/compiler/noirc_printable_type/Cargo.toml +++ b/compiler/noirc_printable_type/Cargo.toml @@ -14,5 +14,6 @@ regex = "1.9.1" serde.workspace = true serde_json.workspace = true thiserror.workspace = true +jsonrpc.workspace = true [dev-dependencies] diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index e10e400b0db..273e2d512ea 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -73,6 +73,9 @@ pub enum ForeignCallError { #[error("Could not parse PrintableType argument. {0}")] ParsingError(#[from] serde_json::Error), + + #[error("Failed calling external resolver. {0}")] + ExternalResolverError(#[from] jsonrpc::Error), } impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay { diff --git a/deny.toml b/deny.toml index d9ffd4d37f0..5edce08fb70 100644 --- a/deny.toml +++ b/deny.toml @@ -67,6 +67,7 @@ exceptions = [ # so we prefer to not have dependencies using it # https://tldrlegal.com/license/creative-commons-cc0-1.0-universal { allow = ["CC0-1.0"], name = "more-asserts" }, + { allow = ["CC0-1.0"], name = "jsonrpc" }, { allow = ["MPL-2.0"], name = "sized-chunks" }, { allow = ["MPL-2.0"], name = "webpki-roots" }, diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 06855e75c97..74224ce3795 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -529,7 +529,7 @@ mod tests { circuit, debug_artifact, initial_witness, - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); @@ -623,7 +623,7 @@ mod tests { circuit, debug_artifact, initial_witness, - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); // set breakpoint @@ -673,7 +673,7 @@ mod tests { &circuit, &debug_artifact, WitnessMap::new(), - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); assert_eq!(context.offset_opcode_location(&None, 0), (None, 0)); diff --git a/tooling/debugger/src/dap.rs b/tooling/debugger/src/dap.rs index 1cc05e28a6b..803f9f108db 100644 --- a/tooling/debugger/src/dap.rs +++ b/tooling/debugger/src/dap.rs @@ -57,7 +57,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { circuit, debug_artifact, initial_witness, - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); Self { server, diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index cb6539cbdb1..16dc206e303 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -37,7 +37,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { circuit, debug_artifact, initial_witness.clone(), - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); Self { context, @@ -278,7 +278,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.circuit, self.debug_artifact, self.initial_witness.clone(), - Box::new(DefaultForeignCallExecutor::new(true)), + Box::new(DefaultForeignCallExecutor::new(true, None)), ); for opcode_location in breakpoints { self.context.add_breakpoint(opcode_location); diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 2a040a2e3e9..c2181d7839d 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -78,8 +78,14 @@ fn on_test_run_request_inner( ) })?; - let test_result = - run_test(&state.solver, &context, test_function, false, &CompileOptions::default()); + let test_result = run_test( + &state.solver, + &context, + test_function, + false, + None, + &CompileOptions::default(), + ); let result = match test_result { TestStatus::Pass => NargoTestRunResult { id: params.id.clone(), diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index d60f9d3ea28..cd97980b9e0 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -26,8 +26,14 @@ thiserror.workspace = true codespan-reporting.workspace = true tracing.workspace = true rayon = "1.8.0" +jsonrpc.workspace = true [dev-dependencies] # TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` # TODO: once that method is moved to nargo_cli, we can move this dependency to nargo_cli -tempfile.workspace = true \ No newline at end of file +tempfile.workspace = true +jsonrpc-http-server = "18.0" +jsonrpc-core-client = "18.0" +jsonrpc-derive = "18.0" +jsonrpc-core = "18.0" +serial_test = "2.0" diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs index bc1e19cdcf4..cbe40c92b4e 100644 --- a/tooling/nargo/src/ops/foreign_calls.rs +++ b/tooling/nargo/src/ops/foreign_calls.rs @@ -2,6 +2,7 @@ use acvm::{ acir::brillig::{ForeignCallParam, ForeignCallResult, Value}, pwg::ForeignCallWaitInfo, }; +use jsonrpc::{arg as build_json_rpc_arg, minreq_http::Builder, Client}; use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValueDisplay}; pub trait ForeignCallExecutor { @@ -94,11 +95,22 @@ pub struct DefaultForeignCallExecutor { mocked_responses: Vec, /// Whether to print [`ForeignCall::Print`] output. show_output: bool, + /// JSON RPC client to resolve foreign calls + external_resolver: Option, } impl DefaultForeignCallExecutor { - pub fn new(show_output: bool) -> Self { - DefaultForeignCallExecutor { show_output, ..DefaultForeignCallExecutor::default() } + pub fn new(show_output: bool, resolver_url: Option<&str>) -> Self { + let oracle_resolver = resolver_url.map(|resolver_url| { + let transport_builder = + Builder::new().url(resolver_url).expect("Invalid oracle resolver URL"); + Client::with_transport(transport_builder.build()) + }); + DefaultForeignCallExecutor { + show_output, + external_resolver: oracle_resolver, + ..DefaultForeignCallExecutor::default() + } } } @@ -190,27 +202,136 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor { Ok(ForeignCallResult { values: vec![] }) } None => { - let response_position = self + let mock_response_position = self .mocked_responses .iter() - .position(|response| response.matches(foreign_call_name, &foreign_call.inputs)) - .unwrap_or_else(|| panic!("Unknown foreign call {}", foreign_call_name)); + .position(|response| response.matches(foreign_call_name, &foreign_call.inputs)); - let mock = self - .mocked_responses - .get_mut(response_position) - .expect("Invalid position of mocked response"); - let result = mock.result.values.clone(); - - if let Some(times_left) = &mut mock.times_left { - *times_left -= 1; - if *times_left == 0 { - self.mocked_responses.remove(response_position); + match (mock_response_position, &self.external_resolver) { + (Some(response_position), _) => { + let mock = self + .mocked_responses + .get_mut(response_position) + .expect("Invalid position of mocked response"); + let result = mock.result.values.clone(); + + if let Some(times_left) = &mut mock.times_left { + *times_left -= 1; + if *times_left == 0 { + self.mocked_responses.remove(response_position); + } + } + + Ok(ForeignCallResult { values: result }) + } + (None, Some(external_resolver)) => { + let encoded_params: Vec<_> = + foreign_call.inputs.iter().map(build_json_rpc_arg).collect(); + + let req = + external_resolver.build_request(foreign_call_name, &encoded_params); + + let response = external_resolver.send_request(req)?; + + let parsed_response: ForeignCallResult = response.result()?; + + Ok(parsed_response) } + (None, None) => panic!("Unknown foreign call {}", foreign_call_name), } + } + } + } +} + +#[cfg(test)] +mod tests { + use acvm::{ + acir::brillig::ForeignCallParam, + brillig_vm::brillig::{ForeignCallResult, Value}, + pwg::ForeignCallWaitInfo, + FieldElement, + }; + use jsonrpc_core::Result as RpcResult; + use jsonrpc_derive::rpc; + use jsonrpc_http_server::{Server, ServerBuilder}; + use serial_test::serial; + + use crate::ops::{DefaultForeignCallExecutor, ForeignCallExecutor}; - Ok(ForeignCallResult { values: result }) + #[allow(unreachable_pub)] + #[rpc] + pub trait OracleResolver { + #[rpc(name = "echo")] + fn echo(&self, param: ForeignCallParam) -> RpcResult; + + #[rpc(name = "sum")] + fn sum(&self, array: ForeignCallParam) -> RpcResult; + } + + struct OracleResolverImpl; + + impl OracleResolver for OracleResolverImpl { + fn echo(&self, param: ForeignCallParam) -> RpcResult { + Ok(vec![param].into()) + } + + fn sum(&self, array: ForeignCallParam) -> RpcResult { + let mut res: FieldElement = 0_usize.into(); + + for value in array.values() { + res += value.to_field(); } + + Ok(Value::from(res).into()) } } + + fn build_oracle_server() -> (Server, String) { + let mut io = jsonrpc_core::IoHandler::new(); + io.extend_with(OracleResolverImpl.to_delegate()); + + let server = ServerBuilder::new(io) + .start_http(&"127.0.0.1:5555".parse().expect("Invalid address")) + .expect("Could not start server"); + + let url = format!("http://{}", server.address()); + (server, url) + } + + #[serial] + #[test] + fn test_oracle_resolver_echo() { + let (server, url) = build_oracle_server(); + + let mut executor = DefaultForeignCallExecutor::new(false, Some(&url)); + + let foreign_call = ForeignCallWaitInfo { + function: "echo".to_string(), + inputs: vec![ForeignCallParam::Single(1_u128.into())], + }; + + let result = executor.execute(&foreign_call); + assert_eq!(result.unwrap(), ForeignCallResult { values: foreign_call.inputs }); + + server.close(); + } + + #[serial] + #[test] + fn test_oracle_resolver_sum() { + let (server, url) = build_oracle_server(); + + let mut executor = DefaultForeignCallExecutor::new(false, Some(&url)); + + let foreign_call = ForeignCallWaitInfo { + function: "sum".to_string(), + inputs: vec![ForeignCallParam::Array(vec![1_usize.into(), 2_usize.into()])], + }; + + let result = executor.execute(&foreign_call); + assert_eq!(result.unwrap(), Value::from(3_usize).into()); + + server.close(); + } } diff --git a/tooling/nargo/src/ops/test.rs b/tooling/nargo/src/ops/test.rs index 5bfdd6d15d0..f38dcad0c2f 100644 --- a/tooling/nargo/src/ops/test.rs +++ b/tooling/nargo/src/ops/test.rs @@ -19,6 +19,7 @@ pub fn run_test( context: &Context, test_function: TestFunction, show_output: bool, + foreign_call_resolver_url: Option<&str>, config: &CompileOptions, ) -> TestStatus { let program = compile_no_check(context, config, test_function.get_id(), None, false); @@ -30,7 +31,7 @@ pub fn run_test( &program.circuit, WitnessMap::new(), blackbox_solver, - &mut DefaultForeignCallExecutor::new(show_output), + &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); test_status_program_compile_pass(test_function, program.debug, circuit_execution) } diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index f2d5bce5524..7f695c42fa4 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -42,6 +42,10 @@ pub(crate) struct ExecuteCommand { #[clap(flatten)] compile_options: CompileOptions, + + /// JSON RPC url to solve oracle calls + #[clap(long)] + oracle_resolver: Option, } pub(crate) fn run( @@ -73,8 +77,12 @@ pub(crate) fn run( expression_width, )?; - let (return_value, solved_witness) = - execute_program_and_decode(compiled_program, package, &args.prover_name)?; + let (return_value, solved_witness) = execute_program_and_decode( + compiled_program, + package, + &args.prover_name, + args.oracle_resolver.as_deref(), + )?; println!("[{}] Circuit witness successfully solved", package.name); if let Some(return_value) = return_value { @@ -93,11 +101,12 @@ fn execute_program_and_decode( program: CompiledProgram, package: &Package, prover_name: &str, + foreign_call_resolver_url: Option<&str>, ) -> Result<(Option, WitnessMap), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; - let solved_witness = execute_program(&program, &inputs_map)?; + let solved_witness = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; let public_abi = program.abi.public_abi(); let (_, return_value) = public_abi.decode(&solved_witness)?; @@ -107,6 +116,7 @@ fn execute_program_and_decode( pub(crate) fn execute_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, + foreign_call_resolver_url: Option<&str>, ) -> Result { let blackbox_solver = Bn254BlackBoxSolver::new(); @@ -116,7 +126,7 @@ pub(crate) fn execute_program( &compiled_program.circuit, initial_witness, &blackbox_solver, - &mut DefaultForeignCallExecutor::new(true), + &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ); match solved_witness_err { Ok(solved_witness) => Ok(solved_witness), diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index 2b1dd8c65f3..167ab541bc5 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -43,6 +43,10 @@ pub(crate) struct ProveCommand { #[clap(flatten)] compile_options: CompileOptions, + + /// JSON RPC url to solve oracle calls + #[clap(long)] + oracle_resolver: Option, } pub(crate) fn run( @@ -81,12 +85,14 @@ pub(crate) fn run( &args.prover_name, &args.verifier_name, args.verify, + args.oracle_resolver.as_deref(), )?; } Ok(()) } +#[allow(clippy::too_many_arguments)] pub(crate) fn prove_package( backend: &Backend, workspace: &Workspace, @@ -95,12 +101,14 @@ pub(crate) fn prove_package( prover_name: &str, verifier_name: &str, check_proof: bool, + foreign_call_resolver_url: Option<&str>, ) -> Result<(), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)?; - let solved_witness = execute_program(&compiled_program, &inputs_map)?; + let solved_witness = + execute_program(&compiled_program, &inputs_map, foreign_call_resolver_url)?; // Write public inputs into Verifier.toml let public_abi = compiled_program.abi.public_abi(); diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 575af9938b6..32893baa157 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -43,6 +43,10 @@ pub(crate) struct TestCommand { #[clap(flatten)] compile_options: CompileOptions, + + /// JSON RPC url to solve oracle calls + #[clap(long)] + oracle_resolver: Option, } pub(crate) fn run( @@ -84,6 +88,7 @@ pub(crate) fn run( package, pattern, args.show_output, + args.oracle_resolver.as_deref(), &args.compile_options, )?; } @@ -97,6 +102,7 @@ fn run_tests( package: &Package, fn_name: FunctionNameMatch, show_output: bool, + foreign_call_resolver_url: Option<&str>, compile_options: &CompileOptions, ) -> Result<(), CliError> { let (mut context, crate_id) = prepare_package(file_manager, package); @@ -141,7 +147,14 @@ fn run_tests( .expect("Failed to write to stdout"); writer.flush().expect("Failed to flush writer"); - match run_test(blackbox_solver, &context, test_function, show_output, compile_options) { + match run_test( + blackbox_solver, + &context, + test_function, + show_output, + foreign_call_resolver_url, + compile_options, + ) { TestStatus::Pass { .. } => { writer .set_color(ColorSpec::new().set_fg(Some(Color::Green))) From 8570a04c04b3b6b43cd2c9da8b193297d89b47a1 Mon Sep 17 00:00:00 2001 From: brunny-eth <96834997+brunny-eth@users.noreply.github.com> Date: Fri, 22 Dec 2023 04:36:22 -0500 Subject: [PATCH 106/137] chore: Update how-to-recursion.md (#3912) Last typo changes # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/how_to/how-to-recursion.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/how_to/how-to-recursion.md b/docs/docs/how_to/how-to-recursion.md index db9ad0e99f8..f60aa3ff2d9 100644 --- a/docs/docs/how_to/how-to-recursion.md +++ b/docs/docs/how_to/how-to-recursion.md @@ -31,9 +31,9 @@ It is also assumed that you're not using `noir_wasm` for compilation, and instea :::info -As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. Meaning it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. -While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. Which means these proofs need to be created by using the backend directly. +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. In short: @@ -82,11 +82,11 @@ const { proof, publicInputs } = await backend.generateIntermediateProof(witness) :::warning -Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit are we actually running and why! +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. -With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*. So it is Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. ::: From 93d07249bfcd3ec9ff467b7d6a2e64a15e818a92 Mon Sep 17 00:00:00 2001 From: brunny-eth <96834997+brunny-eth@users.noreply.github.com> Date: Fri, 22 Dec 2023 06:01:46 -0500 Subject: [PATCH 107/137] chore: Update index.md (#3910) # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/index.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/docs/index.md b/docs/docs/index.md index eaf8c59f935..ab8c2f8acd2 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -24,12 +24,13 @@ sidebar_position: 0 Noir, a domain-specific language crafted for SNARK proving systems, stands out with its simplicity, flexibility, and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, -Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, -depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's -barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkworks' Marlin -backend, among others. +Noir takes a two-pronged path. First, Noir compiles to an adaptable intermediate language known as ACIR. -This innovative design introduces unique challenges, yet it strategically separates the programming language from the +From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's +barretenberg backend, or transformed into a rank-1 constraint system suitable for R1CS backends like Arkworks' Marlin +backend (among others). + +This innovative design introduces unique challenges; however, this approach also strategically separates the programming language from the backend. Noir's approach echoes the modular philosophy of LLVM, offering developers a versatile toolkit for cryptographic programming. @@ -61,7 +62,7 @@ within your projects. ## Libraries -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the +Noir does not currently have an official package manager. You can find a list of some of the available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). Some libraries that are available today include: From 65cbb3df63155d6b54163828290f9ef4b1441b94 Mon Sep 17 00:00:00 2001 From: brunny-eth <96834997+brunny-eth@users.noreply.github.com> Date: Fri, 22 Dec 2023 06:02:06 -0500 Subject: [PATCH 108/137] chore: Update index.md (#3911) Making a few small typo changes. # Description ## Problem\* Resolves ## Summary\* ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/getting_started/installation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/getting_started/installation/index.md b/docs/docs/getting_started/installation/index.md index ddb8a250eb4..0c341c83ffb 100644 --- a/docs/docs/getting_started/installation/index.md +++ b/docs/docs/getting_started/installation/index.md @@ -41,5 +41,5 @@ noirup Done. That's it. You should have the latest version working. You can check with `nargo --version`. You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more information. From 66af0e7a14f50b090b36f7cfdf815faa797cc55a Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Fri, 22 Dec 2023 16:16:03 +0100 Subject: [PATCH 109/137] chore: Optimize goto_definitions for workspace case (#3914) # Description ## Problem\* Resolves Slow performance on bigger workspace with goto-definitions #3915 ## Summary\* Optimises performance of a request from ~16 seconds to ~1s on sample workspace [noir-protocol-circuits](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-protocol-circuits) ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- tooling/lsp/src/requests/goto_definition.rs | 106 ++++++++------------ 1 file changed, 40 insertions(+), 66 deletions(-) diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index a23bde2e210..d2b66682d89 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -1,13 +1,13 @@ use std::future::{self, Future}; +use crate::resolve_workspace_for_source_path; use crate::{types::GotoDefinitionResult, LspState}; -use async_lsp::{ErrorCode, LanguageClient, ResponseError}; +use async_lsp::{ErrorCode, ResponseError}; use fm::codespan_files::Error; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Location}; use lsp_types::{Position, Url}; use nargo::insert_all_files_for_workspace_into_file_manager; -use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::file_manager_with_stdlib; pub(crate) fn on_goto_definition_request( state: &mut LspState, @@ -18,81 +18,55 @@ pub(crate) fn on_goto_definition_request( } fn on_goto_definition_inner( - state: &mut LspState, + _state: &mut LspState, params: GotoDefinitionParams, ) -> Result { - let root_path = state.root_path.as_deref().ok_or_else(|| { - ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") - })?; - let file_path = params.text_document_position_params.text_document.uri.to_file_path().map_err(|_| { ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") })?; - let toml_path = match find_package_manifest(root_path, &file_path) { - Ok(toml_path) => toml_path, - Err(err) => { - let _ = state.client.log_message(lsp_types::LogMessageParams { - typ: lsp_types::MessageType::WARNING, - message: err.to_string(), - }); - return Ok(None); - } - }; - let workspace = resolve_workspace_from_toml( - &toml_path, - PackageSelection::All, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - ) - .map_err(|err| { - // If we found a manifest, but the workspace is invalid, we raise an error about it - ResponseError::new(ErrorCode::REQUEST_FAILED, err) - })?; - - let mut definition_position = None; + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = workspace.members.first().unwrap(); let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - for package in &workspace { - let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, package); - - // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); - - let files = context.file_manager.as_file_map(); - let file_id = context.file_manager.name_to_id(file_path.clone()); - - if let Some(file_id) = file_id { - let byte_index = position_to_byte_index( - files, - file_id, - ¶ms.text_document_position_params.position, - ); - - if let Ok(byte_index) = byte_index { - let search_for_location = noirc_errors::Location { - file: file_id, - span: noirc_errors::Span::single_char(byte_index as u32), - }; - let found_location = context.get_definition_location_from(search_for_location); - - if let Some(found_location) = found_location { - let file_id = found_location.file; - definition_position = to_lsp_location(files, file_id, found_location.span); - } - } - } - } + let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, package); + + // We ignore the warnings and errors produced by compilation while resolving the definition + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); + + let files = context.file_manager.as_file_map(); + let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not find file in file manager. File path: {:?}", file_path), + ))?; + + let byte_index = + position_to_byte_index(files, file_id, ¶ms.text_document_position_params.position) + .map_err(|err| { + ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not convert position to byte index. Error: {:?}", err), + ) + })?; + + let search_for_location = noirc_errors::Location { + file: file_id, + span: noirc_errors::Span::single_char(byte_index as u32), + }; - if let Some(definition_position) = definition_position { - let response: GotoDefinitionResponse = - GotoDefinitionResponse::from(definition_position).to_owned(); - Ok(Some(response)) - } else { - Ok(None) - } + let goto_definition_response = + context.get_definition_location_from(search_for_location).and_then(|found_location| { + let file_id = found_location.file; + let definition_position = to_lsp_location(files, file_id, found_location.span)?; + let response: GotoDefinitionResponse = + GotoDefinitionResponse::from(definition_position).to_owned(); + Some(response) + }); + + Ok(goto_definition_response) } fn to_lsp_location<'a, F>( From aabe5c15bc9d509e6953e689a5f479b26b972384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Tue, 2 Jan 2024 12:20:41 +0000 Subject: [PATCH 110/137] chore: Update CONTRIBUTING.md (#3921) # Description This PR makes changes to the contribution guide in order to make clear the usage of PRs as a metric is not encouraged ## Problem\* We have been getting a lot of PRs opened for typos and other small fixes that, despite being valuable, would not be relevant enough to be included in separate PRs --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9cbbeeb677f..d2553b003f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,6 +92,10 @@ This strategy avoids scenarios where pull requests grow too large/out-of-scope a The easiest way to do this is to have multiple Conventional Commits while you work and then you can cherry-pick the smaller changes into separate branches for pull requesting. +### Typos and other small changes + +Significant changes, like new features or important bug fixes, typically have a more pronounced impact on the project’s overall development. For smaller fixes, such as typos, we encourage you to report them instead of opening PRs. This approach helps us manage our resources effectively and ensures that every change contributes meaningfully to the project. PRs involving such smaller fixes will likely be closed and incorporated in PRs authored by the core team. + ### Reviews For any repository in the noir-lang organization, we require code review & approval by __one__ Noir team member before the changes are merged, as enforced by GitHub branch protection. Non-breaking pull requests may be merged at any time. Breaking pull requests should only be merged when the team has general agreement of the changes and is preparing a breaking release. From 64dd78b940ffe308634aa4849adccccca83f811a Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:27:31 +0000 Subject: [PATCH 111/137] chore: bump dependency versions (#3925) # Description ## Problem\* Resolves ## Summary\* This pr bumps a few versions of deps to reduce dependency tree. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 72 ++++++++++++------------------------------------------ 1 file changed, 16 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1750f5d284e..bd9f186c3b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2561,15 +2561,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.9.0" @@ -2764,14 +2755,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "static_assertions", ] [[package]] @@ -3248,7 +3238,7 @@ dependencies = [ "inferno", "libc", "log", - "nix 0.26.2", + "nix 0.26.4", "once_cell", "parking_lot 0.12.1", "smallvec", @@ -4380,12 +4370,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "str-buf" version = "1.0.6" @@ -5106,29 +5090,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-downcast" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" -dependencies = [ - "js-sys", - "once_cell", - "wasm-bindgen", - "wasm-bindgen-downcast-macros", -] - -[[package]] -name = "wasm-bindgen-downcast-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "wasm-bindgen-futures" version = "0.4.36" @@ -5205,9 +5166,9 @@ dependencies = [ [[package]] name = "wasmer" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cb1ae2956aac1fbbcf334c543c1143cdf7d5b0a5fb6c3d23a17bf37dd1f47b" +checksum = "ce45cc009177ca345a6d041f9062305ad467d15e7d41494f5b81ab46d62d7a58" dependencies = [ "bytes", "cfg-if 1.0.0", @@ -5222,7 +5183,6 @@ dependencies = [ "target-lexicon", "thiserror", "wasm-bindgen", - "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", @@ -5236,9 +5196,9 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fd9aeef339095798d1e04957d5657d97490b1112f145cbf08b98f6393b4a0a" +checksum = "e044f6140c844602b920deb4526aea3cc9c0d7cf23f00730bb9b2034669f522a" dependencies = [ "backtrace", "bytes", @@ -5263,9 +5223,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "344f5f1186c122756232fe7f156cc8d2e7bf333d5a658e81e25efa3415c26d07" +checksum = "32ce02358eb44a149d791c1d6648fb7f8b2f99cd55e3c4eef0474653ec8cc889" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -5282,9 +5242,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac8c1f2dc0ed3c7412a5546e468365184a461f8ce7dfe2a707b621724339f91" +checksum = "c782d80401edb08e1eba206733f7859db6c997fc5a7f5fb44edc3ecd801468f6" dependencies = [ "proc-macro-error", "proc-macro2", @@ -5294,9 +5254,9 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a57ecbf218c0a9348d4dfbdac0f9d42d9201ae276dffb13e61ea4ff939ecce7" +checksum = "fd09e80d4d74bb9fd0ce6c3c106b1ceba1a050f9948db9d9b78ae53c172d6157" dependencies = [ "bytecheck", "enum-iterator", @@ -5310,9 +5270,9 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "4.2.3" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60c3513477bc0097250f6e34a640e2a903bb0ee57e6bb518c427f72c06ac7728" +checksum = "bdcd8a4fd36414a7b6a003dbfbd32393bce3e155d715dd877c05c1b7a41d224d" dependencies = [ "backtrace", "cc", @@ -5327,7 +5287,7 @@ dependencies = [ "lazy_static", "libc", "mach", - "memoffset 0.8.0", + "memoffset 0.9.0", "more-asserts", "region", "scopeguard", From e58844daf9f040626a3a7595f8c4f831e48a4037 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:28:38 +0000 Subject: [PATCH 112/137] feat: simplify multiplications by `0` or `1` in ACIR gen (#3924) # Description ## Problem\* Resolves ## Summary\* This PR avoids churn on `AcirVar`s when we perform trivial multiplications. This avoids some situations where we were codegenning expressions with zero-coefficient terms. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index db2e24af142..f42d3deaa91 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -533,8 +533,19 @@ impl AcirContext { let lhs_data = self.vars[&lhs].clone(); let rhs_data = self.vars[&rhs].clone(); let result = match (lhs_data, rhs_data) { + // (x * 1) == (1 * x) == x + (AcirVarData::Const(constant), _) if constant.is_one() => rhs, + (_, AcirVarData::Const(constant)) if constant.is_one() => lhs, + + // (x * 0) == (0 * x) == 0 + (AcirVarData::Const(constant), _) | (_, AcirVarData::Const(constant)) + if constant.is_zero() => + { + self.add_constant(FieldElement::zero()) + } + (AcirVarData::Const(lhs_constant), AcirVarData::Const(rhs_constant)) => { - self.add_data(AcirVarData::Const(lhs_constant * rhs_constant)) + self.add_constant(lhs_constant * rhs_constant) } (AcirVarData::Witness(witness), AcirVarData::Const(constant)) | (AcirVarData::Const(constant), AcirVarData::Witness(witness)) => { From a63433fb8747722ec3cf2c6eb85d34e5b04bc15c Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:59:05 +0000 Subject: [PATCH 113/137] feat: remove unnecessary predicate from `Lt` instruction (#3922) # Description ## Problem\* Resolves ## Summary\* This PR removes the predicate from the ACIR codegened from `Instruction::Lt`. I think this predicate got added as a knee-jerk reaction to there being divisions involved however all these divisions are done with a known non-zero constant divisor so we can always perform the division safely. This fixes a discrepancy as we're applying `current_side_effects_enabled_var` despite https://github.com/noir-lang/noir/blob/aabe5c15bc9d509e6953e689a5f479b26b972384/compiler/noirc_evaluator/src/ssa/ir/instruction.rs#L263-L273 stating that `Lt` not having side effects. As a bonus we can benefit from optimisations in acir gen. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x ] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 29 +++++++++--------- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 30 +++++-------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index f42d3deaa91..616b3438349 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1002,23 +1002,25 @@ impl AcirContext { lhs: AcirVar, rhs: AcirVar, bit_count: u32, - predicate: AcirVar, ) -> Result { let pow_last = self.add_constant(FieldElement::from(1_u128 << (bit_count - 1))); let pow = self.add_constant(FieldElement::from(1_u128 << (bit_count))); // We check whether the inputs have same sign or not by computing the XOR of their bit sign + + // Predicate is always active as `pow_last` is known to be non-zero. + let one = self.add_constant(1_u128); let lhs_sign = self.div_var( lhs, pow_last, AcirType::NumericType(NumericType::Unsigned { bit_size: bit_count }), - predicate, + one, )?; let rhs_sign = self.div_var( rhs, pow_last, AcirType::NumericType(NumericType::Unsigned { bit_size: bit_count }), - predicate, + one, )?; let same_sign = self.xor_var( lhs_sign, @@ -1031,7 +1033,7 @@ impl AcirContext { let diff = self.sub_var(no_underflow, rhs)?; // We check the 'bit sign' of the difference - let diff_sign = self.less_than_var(diff, pow, bit_count + 1, predicate)?; + let diff_sign = self.less_than_var(diff, pow, bit_count + 1)?; // Then the result is simply diff_sign XOR same_sign (can be checked with a truth table) self.xor_var( @@ -1048,7 +1050,6 @@ impl AcirContext { lhs: AcirVar, rhs: AcirVar, max_bits: u32, - predicate: AcirVar, ) -> Result { // Returns a `Witness` that is constrained to be: // - `1` if lhs >= rhs @@ -1073,6 +1074,7 @@ impl AcirContext { // // TODO: perhaps this should be a user error, instead of an assert assert!(max_bits + 1 < FieldElement::max_num_bits()); + let two_max_bits = self .add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(max_bits as i128))); let diff = self.sub_var(lhs, rhs)?; @@ -1102,13 +1104,11 @@ impl AcirContext { // let k = b - a // - 2^{max_bits} - k == q * 2^{max_bits} + r // - This is only the case when q == 0 and r == 2^{max_bits} - k - // - let (q, _) = self.euclidean_division_var( - comparison_evaluation, - two_max_bits, - max_bits + 1, - predicate, - )?; + + // Predicate is always active as we know `two_max_bits` is always non-zero. + let one = self.add_constant(1_u128); + let (q, _) = + self.euclidean_division_var(comparison_evaluation, two_max_bits, max_bits + 1, one)?; Ok(q) } @@ -1119,11 +1119,10 @@ impl AcirContext { lhs: AcirVar, rhs: AcirVar, bit_size: u32, - predicate: AcirVar, ) -> Result { // Flip the result of calling more than equal method to // compute less than. - let comparison = self.more_than_eq_var(lhs, rhs, bit_size, predicate)?; + let comparison = self.more_than_eq_var(lhs, rhs, bit_size)?; let one = self.add_constant(FieldElement::one()); self.sub_var(one, comparison) // comparison_negated @@ -1519,7 +1518,7 @@ impl AcirContext { bit_size: u32, predicate: AcirVar, ) -> Result<(), RuntimeError> { - let lhs_less_than_rhs = self.more_than_eq_var(rhs, lhs, bit_size, predicate)?; + let lhs_less_than_rhs = self.more_than_eq_var(rhs, lhs, bit_size)?; self.maybe_eq_predicate(lhs_less_than_rhs, predicate) } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 6a48dadaf30..e5f5d23d547 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1571,15 +1571,10 @@ impl Context { // this Eq instruction is being used for a constrain statement BinaryOp::Eq => self.acir_context.eq_var(lhs, rhs), BinaryOp::Lt => match binary_type { - AcirType::NumericType(NumericType::Signed { .. }) => self - .acir_context - .less_than_signed(lhs, rhs, bit_count, self.current_side_effects_enabled_var), - _ => self.acir_context.less_than_var( - lhs, - rhs, - bit_count, - self.current_side_effects_enabled_var, - ), + AcirType::NumericType(NumericType::Signed { .. }) => { + self.acir_context.less_than_signed(lhs, rhs, bit_count) + } + _ => self.acir_context.less_than_var(lhs, rhs, bit_count), }, BinaryOp::Xor => self.acir_context.xor_var(lhs, rhs, binary_type), BinaryOp::And => self.acir_context.and_var(lhs, rhs, binary_type), @@ -2141,19 +2136,11 @@ impl Context { let current_index = self.acir_context.add_constant(i); // Check that we are above the lower bound of the insertion index - let greater_eq_than_idx = self.acir_context.more_than_eq_var( - current_index, - flat_user_index, - 64, - self.current_side_effects_enabled_var, - )?; + let greater_eq_than_idx = + self.acir_context.more_than_eq_var(current_index, flat_user_index, 64)?; // Check that we are below the upper bound of the insertion index - let less_than_idx = self.acir_context.less_than_var( - current_index, - max_flat_user_index, - 64, - self.current_side_effects_enabled_var, - )?; + let less_than_idx = + self.acir_context.less_than_var(current_index, max_flat_user_index, 64)?; // Read from the original slice the value we want to insert into our new slice. // We need to make sure that we read the previous element when our current index is greater than insertion index. @@ -2328,7 +2315,6 @@ impl Context { current_index, flat_user_index, 64, - self.current_side_effects_enabled_var, )?; let shifted_value_pred = From 467948f9ee9ae65b4e2badaa1d15835fced3e835 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:38:37 +0000 Subject: [PATCH 114/137] fix: prevent `Instruction::Constrain`s for non-primitive types (#3916) # Description ## Problem\* Followup to #3740 ## Summary\* #3740 fixed an issue where array equalities were making their way into SSA and not having side effect predicates applied correctly by applying the predicate to each of the array elements. We actually state that we do not want array equalities in SSA (in `insert_array_equality`) so the fundamental issue of array equalities in SSA still exists. We were allowing an implicit array equality to sneak into SSA by performing an optimization of `Constrain(Eq(x, y), 1)` into `Constrain(x, y)` during codegen. This meant that if `x` and `y` were arrays then we bypass the `insert_array_equality` function which the `Eq` instruction would call, which would have calculated a primitive predicate value for the constrain statement to act on. This PR removes the extra logic from the `flatten_cfg` pass (while adding an assert that we're only constraining primitive values) and removes the faulty optimization from SSA codegen. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/opt/flatten_cfg.rs | 105 ++++-------------- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 24 +--- 2 files changed, 24 insertions(+), 105 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 0e7bfff7b6b..fdd7c66684c 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -641,8 +641,25 @@ impl<'f> Context<'f> { match instruction { Instruction::Constrain(lhs, rhs, message) => { // Replace constraint `lhs == rhs` with `condition * lhs == condition * rhs`. - let lhs = self.handle_constrain_arg_side_effects(lhs, condition, &call_stack); - let rhs = self.handle_constrain_arg_side_effects(rhs, condition, &call_stack); + + // Condition needs to be cast to argument type in order to multiply them together. + let argument_type = self.inserter.function.dfg.type_of_value(lhs); + // Sanity check that we're not constraining non-primitive types + assert!(matches!(argument_type, Type::Numeric(_))); + + let casted_condition = self.insert_instruction( + Instruction::Cast(condition, argument_type), + call_stack.clone(), + ); + + let lhs = self.insert_instruction( + Instruction::binary(BinaryOp::Mul, lhs, casted_condition), + call_stack.clone(), + ); + let rhs = self.insert_instruction( + Instruction::binary(BinaryOp::Mul, rhs, casted_condition), + call_stack, + ); Instruction::Constrain(lhs, rhs, message) } @@ -673,90 +690,6 @@ impl<'f> Context<'f> { } } - /// Given the arguments of a constrain instruction, multiplying them by the branch's condition - /// requires special handling in the case of complex types. - fn handle_constrain_arg_side_effects( - &mut self, - argument: ValueId, - condition: ValueId, - call_stack: &CallStack, - ) -> ValueId { - let argument_type = self.inserter.function.dfg.type_of_value(argument); - - match &argument_type { - Type::Numeric(_) => { - // Condition needs to be cast to argument type in order to multiply them together. - let casted_condition = self.insert_instruction( - Instruction::Cast(condition, argument_type), - call_stack.clone(), - ); - - self.insert_instruction( - Instruction::binary(BinaryOp::Mul, argument, casted_condition), - call_stack.clone(), - ) - } - Type::Array(_, _) => { - self.handle_array_constrain_arg(argument_type, argument, condition, call_stack) - } - Type::Slice(_) => { - panic!("Cannot use slices directly in a constrain statement") - } - Type::Reference(_) => { - panic!("Cannot use references directly in a constrain statement") - } - Type::Function => { - panic!("Cannot use functions directly in a constrain statement") - } - } - } - - fn handle_array_constrain_arg( - &mut self, - typ: Type, - argument: ValueId, - condition: ValueId, - call_stack: &CallStack, - ) -> ValueId { - let mut new_array = im::Vector::new(); - - let (element_types, len) = match &typ { - Type::Array(elements, len) => (elements, *len), - _ => panic!("Expected array type"), - }; - - for i in 0..len { - for (element_index, element_type) in element_types.iter().enumerate() { - let index = ((i * element_types.len() + element_index) as u128).into(); - let index = self.inserter.function.dfg.make_constant(index, Type::field()); - - let typevars = Some(vec![element_type.clone()]); - - let mut get_element = |array, typevars| { - let get = Instruction::ArrayGet { array, index }; - self.inserter - .function - .dfg - .insert_instruction_and_results( - get, - self.inserter.function.entry_block(), - typevars, - CallStack::new(), - ) - .first() - }; - - let element = get_element(argument, typevars); - - new_array.push_back( - self.handle_constrain_arg_side_effects(element, condition, call_stack), - ); - } - } - - self.inserter.function.dfg.make_array(new_array, typ) - } - fn undo_stores_in_then_branch(&mut self, then_branch: &Branch) { for (address, store) in &then_branch.store_values { let address = *address; diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index d7e6b8b0a3d..c00fbbbcb40 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -8,8 +8,8 @@ use context::SharedContext; use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; use noirc_frontend::{ - monomorphization::ast::{self, Binary, Expression, Program}, - BinaryOpKind, Visibility, + monomorphization::ast::{self, Expression, Program}, + Visibility, }; use crate::{ @@ -653,24 +653,10 @@ impl<'a> FunctionContext<'a> { location: Location, assert_message: Option, ) -> Result { - match expr { - // If we're constraining an equality to be true then constrain the two sides directly. - Expression::Binary(Binary { lhs, operator: BinaryOpKind::Equal, rhs, .. }) => { - let lhs = self.codegen_non_tuple_expression(lhs)?; - let rhs = self.codegen_non_tuple_expression(rhs)?; - self.builder.set_location(location).insert_constrain(lhs, rhs, assert_message); - } + let expr = self.codegen_non_tuple_expression(expr)?; + let true_literal = self.builder.numeric_constant(true, Type::bool()); + self.builder.set_location(location).insert_constrain(expr, true_literal, assert_message); - _ => { - let expr = self.codegen_non_tuple_expression(expr)?; - let true_literal = self.builder.numeric_constant(true, Type::bool()); - self.builder.set_location(location).insert_constrain( - expr, - true_literal, - assert_message, - ); - } - } Ok(Self::unit_value()) } From 664cbe3745315ce0563c9156cd87641b1afc005e Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:54:53 +0000 Subject: [PATCH 115/137] chore: fix `should_fail_mismatch` test to use correct pedersen return type (#3927) # Description ## Problem\* Resolves ## Summary\* This PR updates the `should_fail_mismatch` test to use the correct return type from the `pedersen_commitment` function. Previously the test was failing due to this type error and not from the fact that the assertion was failing. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../noir_test_failure/should_fail_mismatch/src/main.nr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr b/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr index a677b10b0cd..253e999ce07 100644 --- a/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr +++ b/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr @@ -10,5 +10,6 @@ fn test_with_extra_space() { // The assert message has a space #[test(should_fail_with = "Not equal")] fn test_runtime_mismatch() { - assert_eq(dep::std::hash::pedersen_commitment([27])[0], 0, "Not equal "); + // We use a pedersen commitment here so that the assertion failure is only known at runtime. + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal "); } From f9bfed6737c8971b7c1862e0a70d6e2a9101ea14 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:21:31 +0000 Subject: [PATCH 116/137] chore: abstract away subtractions from `OR` implementation (#3923) # Description ## Problem\* Resolves ## Summary\* This is just a small cleanup so that we can think in terms of logic operators rather than subtractions here. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 616b3438349..3bc99b4d054 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -454,14 +454,11 @@ impl AcirContext { self.sub_var(sum, mul) } else { // Implement OR in terms of AND - // max - ((max - a) AND (max -b)) - // Subtracting from max flips the bits, so this is effectively: - // (NOT a) NAND (NOT b) - let max = self.add_constant((1_u128 << bit_size) - 1); - let a = self.sub_var(max, lhs)?; - let b = self.sub_var(max, rhs)?; - let a_and_b = self.and_var(a, b, typ)?; - self.sub_var(max, a_and_b) + // (NOT a) NAND (NOT b) => a OR b + let a = self.not_var(lhs, typ.clone())?; + let b = self.not_var(rhs, typ.clone())?; + let a_and_b = self.and_var(a, b, typ.clone())?; + self.not_var(a_and_b, typ) } } From 223e860975c2698bd5043340b937de74552ec15b Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Tue, 2 Jan 2024 18:25:28 +0100 Subject: [PATCH 117/137] fix(debugger): crash when stepping through locations spanning multiple lines (#3920) # Description The debugger REPL was failing under certain scenarios when a stepped location spanned multiple lines. We tracked down the failure to a missing bounds check. This PR fixes the issue, introduces a refactor to make the relevant code testable, and adds regression tests to prevent reoccurrence. This PR is best reviewed as a whole instead of commit-by-commit. ## Summary - Moves source code printing logic from the main debugger REPL module, to a new source_code_printer module. - Decouples actual printing from rendering logic to improve testability. - Adds regression tests ## Documentation Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 1 + tooling/debugger/Cargo.toml | 5 +- tooling/debugger/src/lib.rs | 1 + tooling/debugger/src/repl.rs | 83 +---- tooling/debugger/src/source_code_printer.rs | 317 ++++++++++++++++++++ tooling/nargo/src/artifacts/debug.rs | 89 ++++++ 6 files changed, 414 insertions(+), 82 deletions(-) create mode 100644 tooling/debugger/src/source_code_printer.rs diff --git a/Cargo.lock b/Cargo.lock index bd9f186c3b6..5c507c8c5f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2779,6 +2779,7 @@ dependencies = [ "noirc_printable_type", "owo-colors", "serde_json", + "tempfile", "thiserror", ] diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index fba4d028d05..0afe28727d1 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -20,4 +20,7 @@ codespan-reporting.workspace = true dap.workspace = true easy-repl = "0.2.1" owo-colors = "3" -serde_json.workspace = true \ No newline at end of file +serde_json.workspace = true + +[dev_dependencies] +tempfile.workspace = true \ No newline at end of file diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 7e0c1605e0a..21834e44f93 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -1,6 +1,7 @@ mod context; mod dap; mod repl; +mod source_code_printer; use std::io::{Read, Write}; diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index 16dc206e303..8fbd10d8db6 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -9,12 +9,7 @@ use nargo::{artifacts::debug::DebugArtifact, ops::DefaultForeignCallExecutor, Na use easy_repl::{command, CommandStatus, Repl}; use std::cell::RefCell; -use codespan_reporting::files::Files; -use noirc_errors::Location; - -use owo_colors::OwoColorize; - -use std::ops::Range; +use crate::source_code_printer::print_source_code_location; pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { context: DebugContext<'a, B>, @@ -70,73 +65,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { ); } } - self.show_source_code_location(&location); - } - } - } - - fn print_location_path(&self, loc: Location) { - let line_number = self.debug_artifact.location_line_number(loc).unwrap(); - let column_number = self.debug_artifact.location_column_number(loc).unwrap(); - - println!( - "At {}:{line_number}:{column_number}", - self.debug_artifact.name(loc.file).unwrap() - ); - } - - fn show_source_code_location(&self, location: &OpcodeLocation) { - let locations = self.debug_artifact.debug_symbols[0].opcode_location(location); - let Some(locations) = locations else { return }; - for loc in locations { - self.print_location_path(loc); - - let loc_line_index = self.debug_artifact.location_line_index(loc).unwrap(); - - // How many lines before or after the location's line we - // print - let context_lines = 5; - - let first_line_to_print = - if loc_line_index < context_lines { 0 } else { loc_line_index - context_lines }; - - let last_line_index = self.debug_artifact.last_line_index(loc).unwrap(); - let last_line_to_print = std::cmp::min(loc_line_index + context_lines, last_line_index); - - let source = self.debug_artifact.location_source_code(loc).unwrap(); - for (current_line_index, line) in source.lines().enumerate() { - let current_line_number = current_line_index + 1; - - if current_line_index < first_line_to_print { - // Ignore lines before range starts - continue; - } else if current_line_index == first_line_to_print && current_line_index > 0 { - // Denote that there's more lines before but we're not showing them - print_line_of_ellipsis(current_line_index); - } - - if current_line_index > last_line_to_print { - // Denote that there's more lines after but we're not showing them, - // and stop printing - print_line_of_ellipsis(current_line_number); - break; - } - - if current_line_index == loc_line_index { - // Highlight current location - let Range { start: loc_start, end: loc_end } = - self.debug_artifact.location_in_line(loc).unwrap(); - println!( - "{:>3} {:2} {}{}{}", - current_line_number, - "->", - &line[0..loc_start].to_string().dimmed(), - &line[loc_start..loc_end], - &line[loc_end..].to_string().dimmed() - ); - } else { - print_dimmed_line(current_line_number, line); - } + print_source_code_location(self.debug_artifact, &location); } } } @@ -384,14 +313,6 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } } -fn print_line_of_ellipsis(line_number: usize) { - println!("{}", format!("{:>3} {}", line_number, "...").dimmed()); -} - -fn print_dimmed_line(line_number: usize, line: &str) { - println!("{}", format!("{:>3} {:2} {}", line_number, "", line).dimmed()); -} - pub fn run( blackbox_solver: &B, circuit: &Circuit, diff --git a/tooling/debugger/src/source_code_printer.rs b/tooling/debugger/src/source_code_printer.rs new file mode 100644 index 00000000000..1707f9066b7 --- /dev/null +++ b/tooling/debugger/src/source_code_printer.rs @@ -0,0 +1,317 @@ +use acvm::acir::circuit::OpcodeLocation; +use codespan_reporting::files::Files; +use nargo::artifacts::debug::DebugArtifact; +use noirc_errors::Location; +use owo_colors::OwoColorize; +use std::ops::Range; + +#[derive(Debug, PartialEq)] +enum PrintedLine<'a> { + Skip, + Ellipsis { + line_number: usize, + }, + Content { + line_number: usize, + cursor: &'a str, + content: &'a str, + highlight: Option>, + }, +} + +#[derive(Clone, Debug)] +struct LocationPrintContext { + file_lines: Range, + printed_lines: Range, + location_lines: Range, + location_offset_in_first_line: Range, + location_offset_in_last_line: Range, +} + +// Given a DebugArtifact and an OpcodeLocation, prints all the source code +// locations the OpcodeLocation maps to, with some surrounding context and +// visual aids to highlight the location itself. +pub(crate) fn print_source_code_location( + debug_artifact: &DebugArtifact, + location: &OpcodeLocation, +) { + let locations = debug_artifact.debug_symbols[0].opcode_location(location); + let Some(locations) = locations else { return; }; + + let locations = locations.iter(); + + for loc in locations { + print_location_path(debug_artifact, *loc); + + let lines = render_location(debug_artifact, loc); + + for line in lines { + match line { + PrintedLine::Skip => {} + PrintedLine::Ellipsis { line_number } => print_ellipsis(line_number), + PrintedLine::Content { line_number, cursor, content, highlight } => { + print_content(line_number, cursor, content, highlight) + } + } + } + } +} + +fn print_location_path(debug_artifact: &DebugArtifact, loc: Location) { + let line_number = debug_artifact.location_line_number(loc).unwrap(); + let column_number = debug_artifact.location_column_number(loc).unwrap(); + + println!("At {}:{line_number}:{column_number}", debug_artifact.name(loc.file).unwrap()); +} + +fn print_ellipsis(line_number: usize) { + println!("{:>3} {:2} {}", line_number.dimmed(), "", "...".dimmed()); +} + +fn print_content(line_number: usize, cursor: &str, content: &str, highlight: Option>) { + match highlight { + Some(highlight) => { + println!( + "{:>3} {:2} {}{}{}", + line_number, + cursor, + content[0..highlight.start].to_string().dimmed(), + &content[highlight.start..highlight.end], + content[highlight.end..].to_string().dimmed(), + ); + } + None => { + println!( + "{:>3} {:2} {}", + line_number.dimmed(), + cursor.dimmed(), + content.to_string().dimmed(), + ); + } + } +} + +fn render_line( + current: usize, + content: &str, + loc_context: LocationPrintContext, +) -> PrintedLine<'_> { + let file_lines = loc_context.file_lines; + let printed_lines = loc_context.printed_lines; + let location_lines = loc_context.location_lines; + let line_number = current + 1; + + if current < printed_lines.start { + // Ignore lines before the context window we choose to show + PrintedLine::Skip + } else if 0 < current && current == printed_lines.start && current < location_lines.start { + // Denote that there's more lines before but we're not showing them + PrintedLine::Ellipsis { line_number } + } else if current < location_lines.start { + // Print lines before the location start without highlighting + PrintedLine::Content { line_number, cursor: "", content, highlight: None } + } else if current == location_lines.start { + // Highlight current location from where it starts to the end of the current line + PrintedLine::Content { + line_number, + cursor: "->", + content, + highlight: Some(loc_context.location_offset_in_first_line), + } + } else if current < location_lines.end { + // Highlight current line if it's contained by the current location + PrintedLine::Content { + line_number, + cursor: "", + content, + highlight: Some(Range { start: 0, end: content.len() }), + } + } else if current == location_lines.end { + // Highlight current location from the beginning of the line until the location's own end + PrintedLine::Content { + line_number, + cursor: "", + content, + highlight: Some(loc_context.location_offset_in_last_line), + } + } else if current < printed_lines.end || printed_lines.end == file_lines.end { + // Print lines after the location end without highlighting + PrintedLine::Content { line_number, cursor: "", content, highlight: None } + } else if current == printed_lines.end && printed_lines.end < file_lines.end { + // Denote that there's more lines after but we're not showing them + PrintedLine::Ellipsis { line_number } + } else { + PrintedLine::Skip + } +} + +// Given a Location in a DebugArtifact, returns a line iterator that specifies how to +// print the location's file. +// +// Consider for example the file (line numbers added to facilitate this doc): +// ``` +// 1 use dep::std::hash::poseidon; +// 2 +// 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { +// 4 let hash1 = poseidon::bn254::hash_2(x1); +// 5 assert(hash1 == y1); +// 6 +// 7 let hash2 = poseidon::bn254::hash_4(x2); +// 8 assert(hash2 == y2); +// 9 } +// 10 +// ``` +// +// If the location to render is `poseidon::bn254::hash_2(x1)`, we'll render the file as: +// ``` +// 1 use dep::std::hash::poseidon; +// 2 +// 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { +// 4 let hash1 = poseidon::bn254::hash_2(x1); +// 5 -> assert(hash1 == y1); +// 6 +// 7 let hash2 = poseidon::bn254::hash_4(x2); +// 8 assert(hash2 == y2); +// 9 } +// 10 ... +// ``` +// +// This is the result of: +// 1. Limiting the amount of printed lines to 5 before and 5 after the location. +// 2. Using ellipsis (...) to denote when some file lines have been left out of the render. +// 3. Using an arrow cursor (->) to denote where the rendered location starts. +// 4. Highlighting the location (here expressed as a block for the sake of the explanation). +// +// Note that locations may span multiple lines, so this function deals with that too. +fn render_location<'a>( + debug_artifact: &'a DebugArtifact, + loc: &'a Location, +) -> impl Iterator> { + let loc = *loc; + + let file_lines = Range { start: 0, end: debug_artifact.last_line_index(loc).unwrap() }; + + // Sub-range of file lines that this location spans + let location_lines = Range { + start: debug_artifact.location_line_index(loc).unwrap(), + end: debug_artifact.location_end_line_index(loc).unwrap(), + }; + + // How many lines before or after the location's lines we print + let context_lines = 5; + + // Sub-range of lines that we'll print, which includes location + context lines + let first_line_to_print = + if location_lines.start < context_lines { 0 } else { location_lines.start - context_lines }; + let last_line_to_print = std::cmp::min(location_lines.end + context_lines, file_lines.end); + let printed_lines = Range { start: first_line_to_print, end: last_line_to_print }; + + // Range of the location relative to its starting and ending lines + let location_offset_in_first_line = debug_artifact.location_in_line(loc).unwrap(); + let location_offset_in_last_line = debug_artifact.location_in_end_line(loc).unwrap(); + + let context = LocationPrintContext { + file_lines, + printed_lines, + location_lines, + location_offset_in_first_line, + location_offset_in_last_line, + }; + + let source = debug_artifact.location_source_code(loc).unwrap(); + source + .lines() + .enumerate() + .map(move |(index, content)| render_line(index, content, context.clone())) +} + +#[cfg(test)] +mod tests { + use crate::source_code_printer::render_location; + use crate::source_code_printer::PrintedLine::Content; + use acvm::acir::circuit::OpcodeLocation; + use fm::FileManager; + use nargo::artifacts::debug::DebugArtifact; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::collections::BTreeMap; + use std::ops::Range; + use std::path::Path; + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { + let file_path = dir.path().join(file_name); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path + } + + #[test] + fn render_multiple_line_location() { + let source_code = r##"pub fn main(mut state: [Field; 2]) -> [Field; 2] { + state = permute( + consts::x5_2_config(), + state); + + state +}"##; + + let dir = tempdir().unwrap(); + let file_name = Path::new("main.nr"); + create_dummy_file(&dir, file_name); + + let mut fm = FileManager::new(dir.path()); + let file_id = fm.add_file_with_source(file_name, source_code.to_string()).unwrap(); + + // Location of + // ``` + // permute( + // consts::x5_2_config(), + // state) + // ``` + let loc = Location::new(Span::inclusive(63, 116), file_id); + + // We don't care about opcodes in this context, + // we just use a dummy to construct debug_symbols + let mut opcode_locations = BTreeMap::>::new(); + opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); + + let debug_symbols = vec![DebugInfo::new(opcode_locations)]; + let debug_artifact = DebugArtifact::new(debug_symbols, &fm); + + let location_rendered: Vec<_> = render_location(&debug_artifact, &loc).collect(); + + assert_eq!( + location_rendered, + vec![ + Content { + line_number: 1, + cursor: "", + content: "pub fn main(mut state: [Field; 2]) -> [Field; 2] {", + highlight: None, + }, + Content { + line_number: 2, + cursor: "->", + content: " state = permute(", + highlight: Some(Range { start: 12, end: 20 }), + }, + Content { + line_number: 3, + cursor: "", + content: " consts::x5_2_config(),", + highlight: Some(Range { start: 0, end: 30 }), + }, + Content { + line_number: 4, + cursor: "", + content: " state);", + highlight: Some(Range { start: 0, end: 14 }), + }, + Content { line_number: 5, cursor: "", content: "", highlight: None }, + Content { line_number: 6, cursor: "", content: " state", highlight: None }, + Content { line_number: 7, cursor: "", content: "}", highlight: None }, + ] + ); + } +} diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index 324c476d13d..633fc7a8ded 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -59,6 +59,12 @@ impl DebugArtifact { self.line_index(location.file, location_start) } + /// Given a location, returns the index of the line it ends at + pub fn location_end_line_index(&self, location: Location) -> Result { + let location_end = location.span.end() as usize; + self.line_index(location.file, location_end) + } + /// Given a location, returns the line number it starts at pub fn location_line_number(&self, location: Location) -> Result { let location_start = location.span.start() as usize; @@ -82,12 +88,28 @@ impl DebugArtifact { let line_index = self.line_index(location.file, location_start)?; let line_span = self.line_range(location.file, line_index)?; + let line_length = line_span.end - (line_span.start + 1); let start_in_line = location_start - line_span.start; + + // The location might continue beyond the line, + // so we need a bounds check let end_in_line = location_end - line_span.start; + let end_in_line = std::cmp::min(end_in_line, line_length); Ok(Range { start: start_in_line, end: end_in_line }) } + /// Given a location, returns a Span relative to its last line's + /// position in the file. This is useful when processing a file's + /// contents on a per-line-basis. + pub fn location_in_end_line(&self, location: Location) -> Result, Error> { + let end_line_index = self.location_end_line_index(location)?; + let line_span = self.line_range(location.file, end_line_index)?; + let location_end = location.span.end() as usize; + let end_in_line = location_end - line_span.start; + Ok(Range { start: 0, end: end_in_line }) + } + /// Given a location, returns the last line index /// of its file pub fn last_line_index(&self, location: Location) -> Result { @@ -149,3 +171,70 @@ impl<'a> Files<'a> for DebugArtifact { }) } } + +#[cfg(test)] +mod tests { + use crate::artifacts::debug::DebugArtifact; + use acvm::acir::circuit::OpcodeLocation; + use fm::FileManager; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::collections::BTreeMap; + use std::ops::Range; + use std::path::Path; + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { + let file_path = dir.path().join(file_name); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path + } + + // Tests that location_in_line correctly handles + // locations spanning multiple lines. + // For example, given the snippet: + // ``` + // permute( + // consts::x5_2_config(), + // state); + // ``` + // We want location_in_line to return the range + // containing `permute(` + #[test] + fn location_in_line_stops_at_end_of_line() { + let source_code = r##"pub fn main(mut state: [Field; 2]) -> [Field; 2] { + state = permute( + consts::x5_2_config(), + state); + + state +}"##; + + let dir = tempdir().unwrap(); + let file_name = Path::new("main.nr"); + create_dummy_file(&dir, file_name); + + let mut fm = FileManager::new(dir.path()); + let file_id = fm.add_file_with_source(file_name, source_code.to_string()).unwrap(); + + // Location of + // ``` + // permute( + // consts::x5_2_config(), + // state) + // ``` + let loc = Location::new(Span::inclusive(63, 116), file_id); + + // We don't care about opcodes in this context, + // we just use a dummy to construct debug_symbols + let mut opcode_locations = BTreeMap::>::new(); + opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); + + let debug_symbols = vec![DebugInfo::new(opcode_locations)]; + let debug_artifact = DebugArtifact::new(debug_symbols, &fm); + + let location_in_line = debug_artifact.location_in_line(loc).expect("Expected a range"); + assert_eq!(location_in_line, Range { start: 12, end: 20 }); + } +} From 642011ab6ebbe8f012eda1da1abbf8660500723d Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:14:38 +0100 Subject: [PATCH 118/137] fix: checks for cyclic dependencies (#3699) # Description ## Problem\* Resolves #2295 ## Summary\* Keep track of the processed packages and check against this list before processing a new one. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- .../compile_failure/cyclic_dep/Nargo.toml | 7 +++ .../compile_failure/cyclic_dep/Prover.toml | 0 .../cyclic_dep/dep1/Nargo.toml | 7 +++ .../cyclic_dep/dep1/src/lib.nr | 3 + .../cyclic_dep/dep2/Nargo.toml | 7 +++ .../cyclic_dep/dep2/src/lib.nr | 3 + .../compile_failure/cyclic_dep/src/main.nr | 7 +++ tooling/nargo_toml/src/errors.rs | 3 + tooling/nargo_toml/src/lib.rs | 57 +++++++++++++++---- 9 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 test_programs/compile_failure/cyclic_dep/Nargo.toml create mode 100644 test_programs/compile_failure/cyclic_dep/Prover.toml create mode 100644 test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml create mode 100644 test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr create mode 100644 test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml create mode 100644 test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr create mode 100644 test_programs/compile_failure/cyclic_dep/src/main.nr diff --git a/test_programs/compile_failure/cyclic_dep/Nargo.toml b/test_programs/compile_failure/cyclic_dep/Nargo.toml new file mode 100644 index 00000000000..6a5a9b7db73 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cyclic_dep" +type = "bin" +authors = [""] + +[dependencies] +dep1 = { path= "./dep1"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/Prover.toml b/test_programs/compile_failure/cyclic_dep/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml b/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml new file mode 100644 index 00000000000..4782bbd5cda --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "dep1" +type = "lib" +authors = [""] + +[dependencies] +dep1 = { path= "../dep2"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr b/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr new file mode 100644 index 00000000000..02b68c56bd2 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr @@ -0,0 +1,3 @@ +fn bar() { + +} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml b/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml new file mode 100644 index 00000000000..5e2a0f304b0 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "dep2" +type = "lib" +authors = [""] + +[dependencies] +dep1 = { path= "../dep1"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr b/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr new file mode 100644 index 00000000000..298a0f3c7ca --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr @@ -0,0 +1,3 @@ +fn foo() { + +} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/src/main.nr b/test_programs/compile_failure/cyclic_dep/src/main.nr new file mode 100644 index 00000000000..c55ca748334 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/src/main.nr @@ -0,0 +1,7 @@ +use dep1::foo; +use dep2::bar; + +fn main() { + dep1::foo(); + dep2::bar(); +} diff --git a/tooling/nargo_toml/src/errors.rs b/tooling/nargo_toml/src/errors.rs index da976e1b185..440895056c3 100644 --- a/tooling/nargo_toml/src/errors.rs +++ b/tooling/nargo_toml/src/errors.rs @@ -69,6 +69,9 @@ pub enum ManifestError { #[error(transparent)] SemverError(SemverError), + + #[error("Cyclic package dependency found when processing {cycle}")] + CyclicDependency { cycle: String }, } #[allow(clippy::enum_variant_names)] diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 6c77fe85f2b..cecc3f7e26a 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -120,7 +120,11 @@ struct PackageConfig { } impl PackageConfig { - fn resolve_to_package(&self, root_dir: &Path) -> Result { + fn resolve_to_package( + &self, + root_dir: &Path, + processed: &mut Vec, + ) -> Result { let name: CrateName = if let Some(name) = &self.package.name { name.parse().map_err(|_| ManifestError::InvalidPackageName { toml: root_dir.join("Nargo.toml"), @@ -136,7 +140,7 @@ impl PackageConfig { toml: root_dir.join("Nargo.toml"), name: name.into(), })?; - let resolved_dep = dep_config.resolve_to_dependency(root_dir)?; + let resolved_dep = dep_config.resolve_to_dependency(root_dir, processed)?; dependencies.insert(name, resolved_dep); } @@ -283,7 +287,11 @@ enum DependencyConfig { } impl DependencyConfig { - fn resolve_to_dependency(&self, pkg_root: &Path) -> Result { + fn resolve_to_dependency( + &self, + pkg_root: &Path, + processed: &mut Vec, + ) -> Result { let dep = match self { Self::Github { git, tag, directory } => { let dir_path = clone_git_repo(git, tag).map_err(ManifestError::GitError)?; @@ -300,13 +308,13 @@ impl DependencyConfig { dir_path }; let toml_path = project_path.join("Nargo.toml"); - let package = resolve_package_from_toml(&toml_path)?; + let package = resolve_package_from_toml(&toml_path, processed)?; Dependency::Remote { package } } Self::Path { path } => { let dir_path = pkg_root.join(path); let toml_path = dir_path.join("Nargo.toml"); - let package = resolve_package_from_toml(&toml_path)?; + let package = resolve_package_from_toml(&toml_path, processed)?; Dependency::Local { package } } }; @@ -325,9 +333,10 @@ fn toml_to_workspace( nargo_toml: NargoToml, package_selection: PackageSelection, ) -> Result { + let mut resolved = Vec::new(); let workspace = match nargo_toml.config { Config::Package { package_config } => { - let member = package_config.resolve_to_package(&nargo_toml.root_dir)?; + let member = package_config.resolve_to_package(&nargo_toml.root_dir, &mut resolved)?; match &package_selection { PackageSelection::Selected(selected_name) if selected_name != &member.name => { return Err(ManifestError::MissingSelectedPackage(member.name)) @@ -345,7 +354,7 @@ fn toml_to_workspace( for (index, member_path) in workspace_config.members.into_iter().enumerate() { let package_root_dir = nargo_toml.root_dir.join(&member_path); let package_toml_path = package_root_dir.join("Nargo.toml"); - let member = resolve_package_from_toml(&package_toml_path)?; + let member = resolve_package_from_toml(&package_toml_path, &mut resolved)?; match &package_selection { PackageSelection::Selected(selected_name) => { @@ -402,17 +411,43 @@ fn read_toml(toml_path: &Path) -> Result { } /// Resolves a Nargo.toml file into a `Package` struct as defined by our `nargo` core. -fn resolve_package_from_toml(toml_path: &Path) -> Result { +fn resolve_package_from_toml( + toml_path: &Path, + processed: &mut Vec, +) -> Result { + // Checks for cyclic dependencies + let str_path = toml_path.to_str().expect("ICE - path is empty"); + if processed.contains(&str_path.to_string()) { + let mut cycle = false; + let mut message = String::new(); + for toml in processed { + cycle = cycle || toml == str_path; + if cycle { + message += &format!("{} referencing ", toml); + } + } + message += str_path; + return Err(ManifestError::CyclicDependency { cycle: message }); + } + // Adds the package to the set of resolved packages + if let Some(str) = toml_path.to_str() { + processed.push(str.to_string()); + } + let nargo_toml = read_toml(toml_path)?; - match nargo_toml.config { + let result = match nargo_toml.config { Config::Package { package_config } => { - package_config.resolve_to_package(&nargo_toml.root_dir) + package_config.resolve_to_package(&nargo_toml.root_dir, processed) } Config::Workspace { .. } => { Err(ManifestError::UnexpectedWorkspace(toml_path.to_path_buf())) } - } + }; + let pos = + processed.iter().position(|toml| toml == str_path).expect("added package must be here"); + processed.remove(pos); + result } #[derive(Debug, PartialEq, Eq)] From a93098dcd9252be61489c574c54f9fcc8185f475 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:54:23 +0000 Subject: [PATCH 119/137] chore: rename "syntax" chapter in docs to "concepts" (#3934) # Description ## Problem\* Resolves ## Summary\* Pulls out docs changes from #3931 ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- docs/docs/noir/{syntax => concepts}/_category_.json | 2 +- docs/docs/noir/{syntax => concepts}/assert.md | 0 docs/docs/noir/{syntax => concepts}/comments.md | 0 docs/docs/noir/{syntax => concepts}/control_flow.md | 0 docs/docs/noir/{syntax => concepts}/data_bus.md | 0 docs/docs/noir/{syntax => concepts}/data_types/_category_.json | 0 docs/docs/noir/{syntax => concepts}/data_types/arrays.md | 0 docs/docs/noir/{syntax => concepts}/data_types/booleans.md | 0 docs/docs/noir/{syntax => concepts}/data_types/fields.md | 0 .../docs/noir/{syntax => concepts}/data_types/function_types.md | 0 docs/docs/noir/{syntax => concepts}/data_types/index.md | 0 docs/docs/noir/{syntax => concepts}/data_types/integers.md | 0 docs/docs/noir/{syntax => concepts}/data_types/references.md | 0 docs/docs/noir/{syntax => concepts}/data_types/slices.mdx | 0 docs/docs/noir/{syntax => concepts}/data_types/strings.md | 0 docs/docs/noir/{syntax => concepts}/data_types/structs.md | 0 docs/docs/noir/{syntax => concepts}/data_types/tuples.md | 0 docs/docs/noir/{syntax => concepts}/data_types/vectors.mdx | 0 docs/docs/noir/{syntax => concepts}/distinct.md | 0 docs/docs/noir/{syntax => concepts}/functions.md | 0 docs/docs/noir/{syntax => concepts}/generics.md | 0 docs/docs/noir/{syntax => concepts}/lambdas.md | 0 docs/docs/noir/{syntax => concepts}/mutability.md | 0 docs/docs/noir/{syntax => concepts}/ops.md | 0 docs/docs/noir/{syntax => concepts}/shadowing.md | 0 docs/docs/noir/{syntax => concepts}/unconstrained.md | 0 26 files changed, 1 insertion(+), 1 deletion(-) rename docs/docs/noir/{syntax => concepts}/_category_.json (73%) rename docs/docs/noir/{syntax => concepts}/assert.md (100%) rename docs/docs/noir/{syntax => concepts}/comments.md (100%) rename docs/docs/noir/{syntax => concepts}/control_flow.md (100%) rename docs/docs/noir/{syntax => concepts}/data_bus.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/_category_.json (100%) rename docs/docs/noir/{syntax => concepts}/data_types/arrays.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/booleans.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/fields.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/function_types.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/index.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/integers.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/references.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/slices.mdx (100%) rename docs/docs/noir/{syntax => concepts}/data_types/strings.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/structs.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/tuples.md (100%) rename docs/docs/noir/{syntax => concepts}/data_types/vectors.mdx (100%) rename docs/docs/noir/{syntax => concepts}/distinct.md (100%) rename docs/docs/noir/{syntax => concepts}/functions.md (100%) rename docs/docs/noir/{syntax => concepts}/generics.md (100%) rename docs/docs/noir/{syntax => concepts}/lambdas.md (100%) rename docs/docs/noir/{syntax => concepts}/mutability.md (100%) rename docs/docs/noir/{syntax => concepts}/ops.md (100%) rename docs/docs/noir/{syntax => concepts}/shadowing.md (100%) rename docs/docs/noir/{syntax => concepts}/unconstrained.md (100%) diff --git a/docs/docs/noir/syntax/_category_.json b/docs/docs/noir/concepts/_category_.json similarity index 73% rename from docs/docs/noir/syntax/_category_.json rename to docs/docs/noir/concepts/_category_.json index 666b691ae91..78dd943647f 100644 --- a/docs/docs/noir/syntax/_category_.json +++ b/docs/docs/noir/concepts/_category_.json @@ -1,5 +1,5 @@ { - "label": "Syntax", + "label": "Concepts", "position": 0, "collapsible": true, "collapsed": true diff --git a/docs/docs/noir/syntax/assert.md b/docs/docs/noir/concepts/assert.md similarity index 100% rename from docs/docs/noir/syntax/assert.md rename to docs/docs/noir/concepts/assert.md diff --git a/docs/docs/noir/syntax/comments.md b/docs/docs/noir/concepts/comments.md similarity index 100% rename from docs/docs/noir/syntax/comments.md rename to docs/docs/noir/concepts/comments.md diff --git a/docs/docs/noir/syntax/control_flow.md b/docs/docs/noir/concepts/control_flow.md similarity index 100% rename from docs/docs/noir/syntax/control_flow.md rename to docs/docs/noir/concepts/control_flow.md diff --git a/docs/docs/noir/syntax/data_bus.md b/docs/docs/noir/concepts/data_bus.md similarity index 100% rename from docs/docs/noir/syntax/data_bus.md rename to docs/docs/noir/concepts/data_bus.md diff --git a/docs/docs/noir/syntax/data_types/_category_.json b/docs/docs/noir/concepts/data_types/_category_.json similarity index 100% rename from docs/docs/noir/syntax/data_types/_category_.json rename to docs/docs/noir/concepts/data_types/_category_.json diff --git a/docs/docs/noir/syntax/data_types/arrays.md b/docs/docs/noir/concepts/data_types/arrays.md similarity index 100% rename from docs/docs/noir/syntax/data_types/arrays.md rename to docs/docs/noir/concepts/data_types/arrays.md diff --git a/docs/docs/noir/syntax/data_types/booleans.md b/docs/docs/noir/concepts/data_types/booleans.md similarity index 100% rename from docs/docs/noir/syntax/data_types/booleans.md rename to docs/docs/noir/concepts/data_types/booleans.md diff --git a/docs/docs/noir/syntax/data_types/fields.md b/docs/docs/noir/concepts/data_types/fields.md similarity index 100% rename from docs/docs/noir/syntax/data_types/fields.md rename to docs/docs/noir/concepts/data_types/fields.md diff --git a/docs/docs/noir/syntax/data_types/function_types.md b/docs/docs/noir/concepts/data_types/function_types.md similarity index 100% rename from docs/docs/noir/syntax/data_types/function_types.md rename to docs/docs/noir/concepts/data_types/function_types.md diff --git a/docs/docs/noir/syntax/data_types/index.md b/docs/docs/noir/concepts/data_types/index.md similarity index 100% rename from docs/docs/noir/syntax/data_types/index.md rename to docs/docs/noir/concepts/data_types/index.md diff --git a/docs/docs/noir/syntax/data_types/integers.md b/docs/docs/noir/concepts/data_types/integers.md similarity index 100% rename from docs/docs/noir/syntax/data_types/integers.md rename to docs/docs/noir/concepts/data_types/integers.md diff --git a/docs/docs/noir/syntax/data_types/references.md b/docs/docs/noir/concepts/data_types/references.md similarity index 100% rename from docs/docs/noir/syntax/data_types/references.md rename to docs/docs/noir/concepts/data_types/references.md diff --git a/docs/docs/noir/syntax/data_types/slices.mdx b/docs/docs/noir/concepts/data_types/slices.mdx similarity index 100% rename from docs/docs/noir/syntax/data_types/slices.mdx rename to docs/docs/noir/concepts/data_types/slices.mdx diff --git a/docs/docs/noir/syntax/data_types/strings.md b/docs/docs/noir/concepts/data_types/strings.md similarity index 100% rename from docs/docs/noir/syntax/data_types/strings.md rename to docs/docs/noir/concepts/data_types/strings.md diff --git a/docs/docs/noir/syntax/data_types/structs.md b/docs/docs/noir/concepts/data_types/structs.md similarity index 100% rename from docs/docs/noir/syntax/data_types/structs.md rename to docs/docs/noir/concepts/data_types/structs.md diff --git a/docs/docs/noir/syntax/data_types/tuples.md b/docs/docs/noir/concepts/data_types/tuples.md similarity index 100% rename from docs/docs/noir/syntax/data_types/tuples.md rename to docs/docs/noir/concepts/data_types/tuples.md diff --git a/docs/docs/noir/syntax/data_types/vectors.mdx b/docs/docs/noir/concepts/data_types/vectors.mdx similarity index 100% rename from docs/docs/noir/syntax/data_types/vectors.mdx rename to docs/docs/noir/concepts/data_types/vectors.mdx diff --git a/docs/docs/noir/syntax/distinct.md b/docs/docs/noir/concepts/distinct.md similarity index 100% rename from docs/docs/noir/syntax/distinct.md rename to docs/docs/noir/concepts/distinct.md diff --git a/docs/docs/noir/syntax/functions.md b/docs/docs/noir/concepts/functions.md similarity index 100% rename from docs/docs/noir/syntax/functions.md rename to docs/docs/noir/concepts/functions.md diff --git a/docs/docs/noir/syntax/generics.md b/docs/docs/noir/concepts/generics.md similarity index 100% rename from docs/docs/noir/syntax/generics.md rename to docs/docs/noir/concepts/generics.md diff --git a/docs/docs/noir/syntax/lambdas.md b/docs/docs/noir/concepts/lambdas.md similarity index 100% rename from docs/docs/noir/syntax/lambdas.md rename to docs/docs/noir/concepts/lambdas.md diff --git a/docs/docs/noir/syntax/mutability.md b/docs/docs/noir/concepts/mutability.md similarity index 100% rename from docs/docs/noir/syntax/mutability.md rename to docs/docs/noir/concepts/mutability.md diff --git a/docs/docs/noir/syntax/ops.md b/docs/docs/noir/concepts/ops.md similarity index 100% rename from docs/docs/noir/syntax/ops.md rename to docs/docs/noir/concepts/ops.md diff --git a/docs/docs/noir/syntax/shadowing.md b/docs/docs/noir/concepts/shadowing.md similarity index 100% rename from docs/docs/noir/syntax/shadowing.md rename to docs/docs/noir/concepts/shadowing.md diff --git a/docs/docs/noir/syntax/unconstrained.md b/docs/docs/noir/concepts/unconstrained.md similarity index 100% rename from docs/docs/noir/syntax/unconstrained.md rename to docs/docs/noir/concepts/unconstrained.md From e48106ed44314ad7a50d280e3126d4fad4a1334d Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:59:09 +0000 Subject: [PATCH 120/137] chore: updated ACIR documentation and other docs (#3932) # Description ## Problem\* Resolves ## Summary\* Replay of #3919 PR ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- acvm-repo/acir/acir_docs.md | 12 ++++++------ cspell.json | 1 + docs/docs/getting_started/installation/index.md | 2 +- docs/docs/getting_started/tooling/testing.md | 2 +- docs/docs/migration_notes.md | 4 ++-- docs/docs/noir/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.17.0/index.md | 2 +- .../version-v0.17.0/migration_notes.md | 4 ++-- .../version-v0.17.0/nargo/02_testing.md | 2 +- .../version-v0.17.0/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.19.0/index.md | 2 +- .../version-v0.19.0/migration_notes.md | 4 ++-- .../version-v0.19.0/nargo/02_testing.md | 2 +- .../version-v0.19.0/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.19.1/index.md | 2 +- .../version-v0.19.1/migration_notes.md | 4 ++-- .../version-v0.19.1/nargo/02_testing.md | 2 +- .../version-v0.19.1/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.19.2/index.md | 2 +- .../version-v0.19.2/migration_notes.md | 4 ++-- .../version-v0.19.2/nargo/02_testing.md | 2 +- .../version-v0.19.2/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.19.3/index.md | 2 +- .../version-v0.19.3/migration_notes.md | 4 ++-- .../version-v0.19.3/nargo/02_testing.md | 2 +- .../version-v0.19.3/standard_library/logging.md | 2 +- docs/versioned_docs/version-v0.19.4/index.md | 2 +- .../version-v0.19.4/migration_notes.md | 4 ++-- .../version-v0.19.4/nargo/02_testing.md | 2 +- .../version-v0.19.4/standard_library/logging.md | 2 +- .../getting_started/tooling/testing.md | 2 +- .../version-v0.22.0/migration_notes.md | 4 ++-- .../version-v0.22.0/noir/standard_library/logging.md | 2 +- 33 files changed, 46 insertions(+), 45 deletions(-) diff --git a/acvm-repo/acir/acir_docs.md b/acvm-repo/acir/acir_docs.md index 1215ea22330..a124bfbc37f 100644 --- a/acvm-repo/acir/acir_docs.md +++ b/acvm-repo/acir/acir_docs.md @@ -6,14 +6,14 @@ This document describes the purpose of ACIR, what it is and how ACIR programs ca ## Introduction The purpose of ACIR is to make the link between a generic proving system, such as Aztec's Barretenberg, and a frontend, such as Noir, which describes user-specific computations. -More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) which allows users to write programs in an intuitive way using a high-level language close to Rust syntax. Noir is able to generate a proof of execution of a Noir program, using an external proving system. However, proving systems uses specific low-level constrain-based languages. Similarly, frontends have their own internal representation in order to represent user programs. +More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) which allows users to write programs in an intuitive way using a high-level language close to Rust syntax. Noir is able to generate a proof of execution of a Noir program, using an external proving system. However, proving systems use specific low-level constrain-based languages. Similarly, frontends have their own internal representation in order to represent user programs. The goal of ACIR is to provide a generic open-source intermediate representation close to proving system 'languages', but agnostic to a specific proving system, that can be used both by proving system as well as a target for frontends. So, at the end of the day, an ACIR program is just another representation of a program, dedicated to proving systems. ## Abstract Circuit Intermediate Representation ACIR stands for abstract circuit intermediate representation: - **abstract circuit**: circuits are a simple computation model where basic computation units, named gates, are connected with wires. Data flows through the wires while gates compute output wires based on their input. More formally, they are directed acyclic graphs (DAG) where the vertices are the gates and the edges are the wires. Due to the immutability nature of the wires (their value does not change during an execution), they are well suited for describing computations for ZKPs. Furthermore, we do not lose any expressiveness when using a circuit as it is well known that any bounded computation can be translated into an arithmetic circuit (i.e a circuit with only addition and multiplication gates). -The term abstract here simply mean that we do not refer to an actual physical circuit (such as an electronic circuit). Furthermore, we will not exactly use the circuit model, but another model even better suited to ZKPs, the constraint model (see below). +The term abstract here simply means that we do not refer to an actual physical circuit (such as an electronic circuit). Furthermore, we will not exactly use the circuit model, but another model even better suited to ZKPs, the constraint model (see below). - **intermediate representation**: The ACIR representation is intermediate because it lies between a frontend and its proving system. ACIR bytecode makes the link between noir compiler output and the proving system backend input. ## The constraint model @@ -32,13 +32,13 @@ For instance, if input_wire_1 and input_wire_2 values are supplied as 3 and 8, t In summary, the workflow is the following: 1. user program -> (compilation) ACIR, a list of opcodes which constrain (partial) witnesses 2. user inputs + ACIR -> (execution/solving) assign values to all the (partial) witnesses -3. witness assignement + ACIR -> (proving system) proof +3. witness assignment + ACIR -> (proving system) proof Although the ordering of opcode does not matter in theory, since a system of equations is not dependent on its ordering, in practice it matters a lot for the solving (i.e the performance of the execution). ACIR opcodes **must be ordered** so that each opcode can be resolved one after the other. -The values of the witnesses lie in the scalar field of the proving system. We will refer to it as FieldElement or ACIR field. The proving system need the values of all the partial witnesses and all the constraints in order to generate a proof. +The values of the witnesses lie in the scalar field of the proving system. We will refer to it as FieldElement or ACIR field. The proving system needs the values of all the partial witnesses and all the constraints in order to generate a proof. *Remark*: The value of a partial witness is unique and fixed throughout a program execution, although in some rare cases, multiple values are possible for a same execution and witness (when there are several valid solutions to the constraints). Having multiple possible values for a witness may indicate that the circuit is not safe. @@ -51,7 +51,7 @@ We assume here that the proving system is Barretenberg. Some parameters may slig Some opcodes have inputs and outputs, which means that the output is constrained to be the result of the opcode computation from the inputs. The solver expects that all inputs are known when solving such opcodes. -Some opcodes are not constrained, which mean they will not be used by the proving system and are only used by the solver. +Some opcodes are not constrained, which means they will not be used by the proving system and are only used by the solver. Finally, some opcodes will have a predicate, whose value is 0 or 1. Its purpose is to nullify the opcode when the value is 0, so that it has no effect. Note that removing the opcode is not a solution because this modifies the circuit (the circuit being mainly the list of the opcodes). @@ -71,7 +71,7 @@ The solver expects that at most one witness is not known when executing the opco ### BlackBoxFuncCall opcode These opcodes represent a specific computation. Even if any computation can be done using only assert-zero opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. -All black box functions takes as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. +All black box functions take as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. Some more advanced computations assume that the proving system has an 'embedded curve'. It is a curve that cycle with the main curve of the proving system, i.e the scalar field of the embedded curve is the base field of the main one, and vice-versa. The curves used by the proving system are dependent on the proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the embedded curve. The black box functions supported by ACIR are: diff --git a/cspell.json b/cspell.json index 51e49c78e59..4ba51240c19 100644 --- a/cspell.json +++ b/cspell.json @@ -64,6 +64,7 @@ "gloo", "grumpkin", "Guillaume", + "gzipped", "hasher", "hexdigit", "higher-kinded", diff --git a/docs/docs/getting_started/installation/index.md b/docs/docs/getting_started/installation/index.md index 0c341c83ffb..27eeeca88ed 100644 --- a/docs/docs/getting_started/installation/index.md +++ b/docs/docs/getting_started/installation/index.md @@ -1,7 +1,7 @@ --- title: Nargo Installation description: - nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo though the most common and easy method, noirup + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup keywords: [ Nargo Noir diff --git a/docs/docs/getting_started/tooling/testing.md b/docs/docs/getting_started/tooling/testing.md index 5febd44e96b..d3e0c522473 100644 --- a/docs/docs/getting_started/tooling/testing.md +++ b/docs/docs/getting_started/tooling/testing.md @@ -24,7 +24,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index d5d0682cf0c..184ca283539 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/docs/noir/standard_library/logging.md b/docs/docs/noir/standard_library/logging.md index 16daf922e15..2e163b52ab3 100644 --- a/docs/docs/noir/standard_library/logging.md +++ b/docs/docs/noir/standard_library/logging.md @@ -22,7 +22,7 @@ The standard library provides two familiar statements you can use: `println` and You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md index 4eeeb6f1346..2d5e6f4454f 100644 --- a/docs/versioned_docs/version-v0.17.0/index.md +++ b/docs/versioned_docs/version-v0.17.0/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.17.0/migration_notes.md b/docs/versioned_docs/version-v0.17.0/migration_notes.md index 69782cba388..1a81af04b3a 100644 --- a/docs/versioned_docs/version-v0.17.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.17.0/migration_notes.md @@ -42,7 +42,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -70,7 +70,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.17.0/standard_library/logging.md b/docs/versioned_docs/version-v0.17.0/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.17.0/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.17.0/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.19.0/index.md b/docs/versioned_docs/version-v0.19.0/index.md index 93944f92bf5..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.0/index.md +++ b/docs/versioned_docs/version-v0.19.0/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.19.0/migration_notes.md b/docs/versioned_docs/version-v0.19.0/migration_notes.md index 0d7e0af0efd..905bca3d30c 100644 --- a/docs/versioned_docs/version-v0.19.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.0/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.19.0/standard_library/logging.md b/docs/versioned_docs/version-v0.19.0/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.19.0/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.19.0/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.19.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md index 93944f92bf5..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.1/index.md +++ b/docs/versioned_docs/version-v0.19.1/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.19.1/migration_notes.md b/docs/versioned_docs/version-v0.19.1/migration_notes.md index 0d7e0af0efd..905bca3d30c 100644 --- a/docs/versioned_docs/version-v0.19.1/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.1/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.19.1/standard_library/logging.md b/docs/versioned_docs/version-v0.19.1/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.19.1/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.19.1/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.19.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md index 93944f92bf5..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.2/index.md +++ b/docs/versioned_docs/version-v0.19.2/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.19.2/migration_notes.md b/docs/versioned_docs/version-v0.19.2/migration_notes.md index 0d7e0af0efd..905bca3d30c 100644 --- a/docs/versioned_docs/version-v0.19.2/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.2/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.19.2/standard_library/logging.md b/docs/versioned_docs/version-v0.19.2/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.19.2/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.19.2/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.19.3/index.md b/docs/versioned_docs/version-v0.19.3/index.md index 93944f92bf5..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.3/index.md +++ b/docs/versioned_docs/version-v0.19.3/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.19.3/migration_notes.md b/docs/versioned_docs/version-v0.19.3/migration_notes.md index 0d7e0af0efd..905bca3d30c 100644 --- a/docs/versioned_docs/version-v0.19.3/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.3/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/logging.md b/docs/versioned_docs/version-v0.19.3/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.19.3/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.19.3/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.19.4/index.md b/docs/versioned_docs/version-v0.19.4/index.md index 93944f92bf5..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.4/index.md +++ b/docs/versioned_docs/version-v0.19.4/index.md @@ -25,7 +25,7 @@ slug: / Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +Its design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. ## Who is Noir for? diff --git a/docs/versioned_docs/version-v0.19.4/migration_notes.md b/docs/versioned_docs/version-v0.19.4/migration_notes.md index 0d7e0af0efd..905bca3d30c 100644 --- a/docs/versioned_docs/version-v0.19.4/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.4/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md index 917c9415126..5c57ef92705 100644 --- a/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md +++ b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md @@ -23,7 +23,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/logging.md b/docs/versioned_docs/version-v0.19.4/standard_library/logging.md index 7e2fd9b9aff..4ba0fe0e656 100644 --- a/docs/versioned_docs/version-v0.19.4/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.19.4/standard_library/logging.md @@ -22,7 +22,7 @@ implementation of rust's `println!` macro, this construct can be useful for debu You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: diff --git a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md index 5febd44e96b..d3e0c522473 100644 --- a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md +++ b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/testing.md @@ -24,7 +24,7 @@ fn test_add() { } ``` -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +Running `nargo test` will test that the `test_add` function can be executed while satisfying all the constraints which allows you to test that add returns the expected values. Test functions can't have any arguments currently. diff --git a/docs/versioned_docs/version-v0.22.0/migration_notes.md b/docs/versioned_docs/version-v0.22.0/migration_notes.md index d5d0682cf0c..184ca283539 100644 --- a/docs/versioned_docs/version-v0.22.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.22.0/migration_notes.md @@ -50,7 +50,7 @@ If you are using the default barretenberg backend, simply run: nargo prove ``` -with you Noir program. +with your Noir program. This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md index 16daf922e15..2e163b52ab3 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md +++ b/docs/versioned_docs/version-v0.22.0/noir/standard_library/logging.md @@ -22,7 +22,7 @@ The standard library provides two familiar statements you can use: `println` and You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). -It is recommended to use `nargo execute` if you want to debug failing constrains with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: From 6b078b4a0078ee38bd16b1773ef107a218e302b9 Mon Sep 17 00:00:00 2001 From: kek kek kek Date: Wed, 3 Jan 2024 06:26:46 -0500 Subject: [PATCH 121/137] chore: fix broken links (#3935) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2fc47f16fef..038ce5691cd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Noir is a Domain Specific Language for SNARK proving systems. It has been design ## Quick Start -Read the installation section [here](https://noir-lang.org/getting_started/nargo_installation). +Read the installation section [here](https://noir-lang.org/docs/dev/getting_started/installation/). Once you have read through the documentation, you can visit [Awesome Noir](https://github.com/noir-lang/awesome-noir) to run some of the examples that others have created. @@ -58,7 +58,7 @@ This crate's minimum supported rustc version is 1.71.1. ## Working on this project -This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/getting_started/nargo_installation/#option-3-compile-from-source) to setup your environment for working on the project. +This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/docs/dev/getting_started/installation/other_install_methods#option-3-compile-from-source) to setup your environment for working on the project. ### Building against a different local/remote version of Barretenberg From 99c2c5a2c2c0da6bad783b60d9e3de8d9a1f4ee4 Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:33:00 +0100 Subject: [PATCH 122/137] feat(lsp): goto struct member inside Impl method (#3918) # Description ## Problem\* Resolves feat(lsp): goto struct member inside Impl method #3719 ## Summary\* ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/node_interner.rs | 31 ++++---------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 236f1e0b513..34313595271 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1295,8 +1295,6 @@ impl NodeInterner { HirExpression::Constructor(expr) => { let struct_type = &expr.r#type.borrow(); - eprintln!("\n -> Resolve Constructor {struct_type:?}\n"); - Some(struct_type.location) } HirExpression::MemberAccess(expr_member_access) => { @@ -1322,34 +1320,17 @@ impl NodeInterner { let expr_lhs = &expr_member_access.lhs; let expr_rhs = &expr_member_access.rhs; - let found_ident = self.nodes.get(expr_lhs.into())?; - - let ident = match found_ident { - Node::Expression(HirExpression::Ident(ident)) => ident, - _ => return None, - }; - - let definition_info = self.definition(ident.id); - - let local_id = match definition_info.kind { - DefinitionKind::Local(Some(local_id)) => local_id, + let lhs_self_struct = match self.id_type(expr_lhs) { + Type::Struct(struct_type, _) => struct_type, _ => return None, }; - let constructor_expression = match self.nodes.get(local_id.into()) { - Some(Node::Expression(HirExpression::Constructor(constructor_expression))) => { - constructor_expression - } - _ => return None, - }; - - let struct_type = constructor_expression.r#type.borrow(); + let struct_type = lhs_self_struct.borrow(); let field_names = struct_type.field_names(); - match field_names.iter().find(|field_name| field_name.0 == expr_rhs.0) { - Some(found) => Some(Location::new(found.span(), struct_type.location.file)), - None => None, - } + field_names.iter().find(|field_name| field_name.0 == expr_rhs.0).map(|found_field_name| { + Location::new(found_field_name.span(), struct_type.location.file) + }) } } From 64c144a3f88b2cd925cd7707d43386d966c072a6 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:44:59 +0000 Subject: [PATCH 123/137] chore: add test case for brillig array equality assertion (#3936) # Description ## Problem\* Resolves https://github.com/AztecProtocol/aztec-packages/issues/3752 ## Summary\* This PR adds a regression test for https://github.com/AztecProtocol/aztec-packages/issues/3752 which was fixed in https://github.com/noir-lang/noir/pull/3916. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- test_programs/execution_success/brillig_array_eq/Nargo.toml | 6 ++++++ .../execution_success/brillig_array_eq/Prover.toml | 2 ++ .../execution_success/brillig_array_eq/src/main.nr | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 test_programs/execution_success/brillig_array_eq/Nargo.toml create mode 100644 test_programs/execution_success/brillig_array_eq/Prover.toml create mode 100644 test_programs/execution_success/brillig_array_eq/src/main.nr diff --git a/test_programs/execution_success/brillig_array_eq/Nargo.toml b/test_programs/execution_success/brillig_array_eq/Nargo.toml new file mode 100644 index 00000000000..62ce392f96b --- /dev/null +++ b/test_programs/execution_success/brillig_array_eq/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_array_eq" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_array_eq/Prover.toml b/test_programs/execution_success/brillig_array_eq/Prover.toml new file mode 100644 index 00000000000..ecfed7de213 --- /dev/null +++ b/test_programs/execution_success/brillig_array_eq/Prover.toml @@ -0,0 +1,2 @@ +a = [77,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102] +b = [77,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102] diff --git a/test_programs/execution_success/brillig_array_eq/src/main.nr b/test_programs/execution_success/brillig_array_eq/src/main.nr new file mode 100644 index 00000000000..90f631dbed8 --- /dev/null +++ b/test_programs/execution_success/brillig_array_eq/src/main.nr @@ -0,0 +1,4 @@ +// Simple example of checking where two arrays are equal +unconstrained fn main(a: [Field; 32], b: [Field; 32]) { + assert(a == b); +} From 459700cb7425ed8a04effb68e9e5387e48023473 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:34:33 +0000 Subject: [PATCH 124/137] chore: fix casing on `InternalError::Unexpected` (#3937) # Description ## Problem\* Resolves ## Summary\* Unexpected is one word so we shouldn't have a capitial here. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_evaluator/src/errors.rs | 4 ++-- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs index 42818e8b19d..33ecc794f76 100644 --- a/compiler/noirc_evaluator/src/errors.rs +++ b/compiler/noirc_evaluator/src/errors.rs @@ -106,7 +106,7 @@ pub enum InternalError { #[error("ICE: Undeclared AcirVar")] UndeclaredAcirVar { call_stack: CallStack }, #[error("ICE: Expected {expected:?}, found {found:?}")] - UnExpected { expected: String, found: String, call_stack: CallStack }, + Unexpected { expected: String, found: String, call_stack: CallStack }, } impl RuntimeError { @@ -119,7 +119,7 @@ impl RuntimeError { | InternalError::MissingArg { call_stack, .. } | InternalError::NotAConstant { call_stack, .. } | InternalError::UndeclaredAcirVar { call_stack } - | InternalError::UnExpected { call_stack, .. }, + | InternalError::Unexpected { call_stack, .. }, ) | RuntimeError::FailedConstraint { call_stack, .. } | RuntimeError::IndexOutOfBounds { call_stack, .. } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index e5f5d23d547..33f00796c9d 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -302,7 +302,7 @@ impl Context { let len = if matches!(typ, Type::Array(_, _)) { typ.flattened_size() } else { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "Block params should be an array".to_owned(), found: format!("Instead got {:?}", typ), call_stack: self.acir_context.get_call_stack(), @@ -640,7 +640,7 @@ impl Context { Instruction::ArrayGet { array, index } => (array, index, None), Instruction::ArraySet { array, index, value, .. } => (array, index, Some(value)), _ => { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "Instruction should be an ArrayGet or ArraySet".to_owned(), found: format!("Instead got {:?}", dfg[instruction]), call_stack: self.acir_context.get_call_stack(), @@ -697,7 +697,7 @@ impl Context { match self.convert_value(array, dfg) { AcirValue::Var(acir_var, _) => { - return Err(RuntimeError::InternalError(InternalError::UnExpected { + return Err(RuntimeError::InternalError(InternalError::Unexpected { expected: "an array value".to_string(), found: format!("{acir_var:?}"), call_stack: self.acir_context.get_call_stack(), @@ -788,7 +788,7 @@ impl Context { let slice_sizes = if store_type.contains_slice_element() { self.compute_slice_sizes(store, None, dfg); self.slice_sizes.get(&store).cloned().ok_or_else(|| { - InternalError::UnExpected { + InternalError::Unexpected { expected: "Store value should have slice sizes computed".to_owned(), found: "Missing key in slice sizes map".to_owned(), call_stack: self.acir_context.get_call_stack(), @@ -1013,7 +1013,7 @@ impl Context { let array = match dfg[instruction] { Instruction::ArraySet { array, .. } => array, _ => { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "Instruction should be an ArraySet".to_owned(), found: format!("Instead got {:?}", dfg[instruction]), call_stack: self.acir_context.get_call_stack(), @@ -1235,7 +1235,7 @@ impl Context { } } _ => { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "AcirValue::DynamicArray or AcirValue::Array" .to_owned(), found: format!("{:?}", array_acir_value), @@ -1246,7 +1246,7 @@ impl Context { } } _ => { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "array or instruction".to_owned(), found: format!("{:?}", &dfg[array_id]), call_stack: self.acir_context.get_call_stack(), @@ -1256,7 +1256,7 @@ impl Context { }; } _ => { - return Err(InternalError::UnExpected { + return Err(InternalError::Unexpected { expected: "array or slice".to_owned(), found: array_typ.to_string(), call_stack: self.acir_context.get_call_stack(), @@ -1513,12 +1513,12 @@ impl Context { ) -> Result { match self.convert_value(value_id, dfg) { AcirValue::Var(acir_var, _) => Ok(acir_var), - AcirValue::Array(array) => Err(InternalError::UnExpected { + AcirValue::Array(array) => Err(InternalError::Unexpected { expected: "a numeric value".to_string(), found: format!("{array:?}"), call_stack: self.acir_context.get_call_stack(), }), - AcirValue::DynamicArray(_) => Err(InternalError::UnExpected { + AcirValue::DynamicArray(_) => Err(InternalError::Unexpected { expected: "a numeric value".to_string(), found: "an array".to_string(), call_stack: self.acir_context.get_call_stack(), From 4b16090beecd0fcdd41c9e7b8f615c4625c26a5b Mon Sep 17 00:00:00 2001 From: jfecher Date: Wed, 3 Jan 2024 13:46:27 -0500 Subject: [PATCH 125/137] feat: Implement Operator Overloading (#3931) # Description ## Problem\* Working towards https://github.com/noir-lang/noir/issues/2568 ## Summary\* This PR implements operator overloading through traits. This works for all operators in noir, including bitwise operators. The comparison operators `<`, `<=`, `>`, and `>=`, are notable in that their corresponding function `cmp` returns an `Ordering` object rather than a boolean as the operators themselves do. ## Additional Context There is a bug when using static trait function syntax `Default::default` or operator overloading when the trait has generic methods. I'm considering this a separate bug, although for the moment it prevents us from being able to use e.g. the `Eq` trait for arrays. There is a boolean in `type_check/expr.rs` that determines if we use a trait impl or primitive implementation of each operator and because of this bug I've kept the primitive implementations for string and array equality. ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Tom French Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- .../src/hir/resolution/resolver.rs | 8 +- .../src/hir/resolution/traits.rs | 7 + .../noirc_frontend/src/hir/type_check/expr.rs | 187 ++++++----- .../noirc_frontend/src/hir/type_check/mod.rs | 8 +- compiler/noirc_frontend/src/hir_def/expr.rs | 6 + .../src/monomorphization/ast.rs | 2 +- .../src/monomorphization/mod.rs | 115 ++++++- compiler/noirc_frontend/src/node_interner.rs | 105 +++++- compiler/noirc_frontend/src/tests.rs | 1 + cspell.json | 2 + .../explanations/standard_library/traits.md | 140 -------- docs/docs/getting_started/create_a_project.md | 4 +- docs/docs/migration_notes.md | 2 +- docs/docs/noir/concepts/_category_.json | 2 +- .../concepts/data_types/function_types.md | 2 +- docs/docs/noir/concepts/data_types/index.md | 2 +- .../noir => noir/concepts}/traits.md | 0 docs/docs/noir/standard_library/traits.md | 284 ++++++++++++++++ noir_stdlib/src/cmp.nr | 310 ++++++++++++++++++ noir_stdlib/src/lib.nr | 1 + noir_stdlib/src/ops.nr | 121 ++++--- noir_stdlib/src/prelude.nr | 2 + .../impl_with_where_clause/src/main.nr | 18 +- .../trait_default_implementation/src/main.nr | 11 +- .../trait_override_implementation/src/main.nr | 22 +- .../compile_success_empty/traits/src/main.nr | 10 +- .../operator_overloading/Nargo.toml | 7 + .../operator_overloading/Prover.toml | 2 + .../operator_overloading/src/main.nr | 154 +++++++++ tooling/lsp/src/lib.rs | 12 +- 30 files changed, 1219 insertions(+), 328 deletions(-) delete mode 100644 docs/docs/explanations/standard_library/traits.md rename docs/docs/{explanations/noir => noir/concepts}/traits.md (100%) create mode 100644 docs/docs/noir/standard_library/traits.md create mode 100644 noir_stdlib/src/cmp.nr create mode 100644 test_programs/execution_success/operator_overloading/Nargo.toml create mode 100644 test_programs/execution_success/operator_overloading/Prover.toml create mode 100644 test_programs/execution_success/operator_overloading/src/main.nr diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 9cd28d80784..91cfa5c6058 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1253,8 +1253,10 @@ impl<'a> Resolver<'a> { if let Some((hir_expr, object_type)) = self.resolve_trait_generic_path(&path) { let expr_id = self.interner.push_expr(hir_expr); self.interner.push_expr_location(expr_id, expr.span, self.file); - self.interner - .select_impl_for_ident(expr_id, TraitImplKind::Assumed { object_type }); + self.interner.select_impl_for_expression( + expr_id, + TraitImplKind::Assumed { object_type }, + ); return expr_id; } else { // If the Path is being used as an Expression, then it is referring to a global from a separate module @@ -1313,10 +1315,12 @@ impl<'a> Resolver<'a> { ExpressionKind::Infix(infix) => { let lhs = self.resolve_expression(infix.lhs); let rhs = self.resolve_expression(infix.rhs); + let trait_id = self.interner.get_operator_trait_method(infix.operator.contents); HirExpression::Infix(HirInfixExpression { lhs, operator: HirBinaryOp::new(infix.operator, self.file), + trait_method_id: trait_id, rhs, }) } diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index 54d2630c722..40041b0fd00 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -52,6 +52,13 @@ pub(crate) fn resolve_traits( context.def_interner.update_trait(trait_id, |trait_def| { trait_def.set_methods(methods); }); + + // This check needs to be after the trait's methods are set since + // the interner may set `interner.ordering_type` based on the result type + // of the Cmp trait, if this is it. + if crate_id.is_stdlib() { + context.def_interner.try_add_operator_trait(trait_id); + } } res } diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index e8f9f23d378..caa77852560 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -136,11 +136,21 @@ impl<'interner> TypeChecker<'interner> { let rhs_span = self.interner.expr_span(&infix_expr.rhs); let span = lhs_span.merge(rhs_span); - self.infix_operand_type_rules(&lhs_type, &infix_expr.operator, &rhs_type, span) - .unwrap_or_else(|error| { + let operator = &infix_expr.operator; + match self.infix_operand_type_rules(&lhs_type, operator, &rhs_type, span) { + Ok((typ, use_impl)) => { + if use_impl { + let id = infix_expr.trait_method_id; + self.verify_trait_constraint(&lhs_type, id.trait_id, *expr_id, span); + self.typecheck_operator_method(*expr_id, id, &lhs_type, span); + } + typ + } + Err(error) => { self.errors.push(error); Type::Error - }) + } + } } HirExpression::Index(index_expr) => self.check_index_expression(expr_id, index_expr), HirExpression::Call(call_expr) => { @@ -294,7 +304,7 @@ impl<'interner> TypeChecker<'interner> { // We must also remember to apply these substitutions to the object_type // referenced by the selected trait impl, if one has yet to be selected. - let impl_kind = self.interner.get_selected_impl_for_ident(*expr_id); + let impl_kind = self.interner.get_selected_impl_for_expression(*expr_id); if let Some(TraitImplKind::Assumed { object_type }) = impl_kind { let the_trait = self.interner.get_trait(method.trait_id); let object_type = object_type.substitute(&bindings); @@ -302,8 +312,10 @@ impl<'interner> TypeChecker<'interner> { the_trait.self_type_typevar_id, (the_trait.self_type_typevar.clone(), object_type.clone()), ); - self.interner - .select_impl_for_ident(*expr_id, TraitImplKind::Assumed { object_type }); + self.interner.select_impl_for_expression( + *expr_id, + TraitImplKind::Assumed { object_type }, + ); } self.interner.store_instantiation_bindings(*expr_id, bindings); @@ -323,7 +335,7 @@ impl<'interner> TypeChecker<'interner> { span: Span, ) { match self.interner.lookup_trait_implementation(object_type, trait_id) { - Ok(impl_kind) => self.interner.select_impl_for_ident(function_ident_id, impl_kind), + Ok(impl_kind) => self.interner.select_impl_for_expression(function_ident_id, impl_kind), Err(erroring_constraints) => { // Don't show any errors where try_get_trait returns None. // This can happen if a trait is used that was never declared. @@ -753,19 +765,22 @@ impl<'interner> TypeChecker<'interner> { None } + // Given a binary comparison operator and another type. This method will produce the output type + // and a boolean indicating whether to use the trait impl corresponding to the operator + // or not. A value of false indicates the caller to use a primitive operation for this + // operator, while a true value indicates a user-provided trait impl is required. fn comparator_operand_type_rules( &mut self, lhs_type: &Type, rhs_type: &Type, op: &HirBinaryOp, span: Span, - ) -> Result { - use crate::BinaryOpKind::{Equal, NotEqual}; + ) -> Result<(Type, bool), TypeCheckError> { use Type::*; match (lhs_type, rhs_type) { // Avoid reporting errors multiple times - (Error, _) | (_, Error) => Ok(Bool), + (Error, _) | (_, Error) => Ok((Bool, false)), // Matches on TypeVariable must be first to follow any type // bindings. @@ -791,7 +806,7 @@ impl<'interner> TypeChecker<'interner> { || other == &Type::Error { Type::apply_type_bindings(bindings); - Ok(Bool) + Ok((Bool, false)) } else { Err(TypeCheckError::TypeMismatchWithSource { expected: lhs_type.clone(), @@ -816,36 +831,23 @@ impl<'interner> TypeChecker<'interner> { span, }); } - Ok(Bool) - } - (Integer(..), FieldElement) | (FieldElement, Integer(..)) => { - Err(TypeCheckError::IntegerAndFieldBinaryOperation { span }) - } - (Integer(..), typ) | (typ, Integer(..)) => { - Err(TypeCheckError::IntegerTypeMismatch { typ: typ.clone(), span }) + Ok((Bool, false)) } (FieldElement, FieldElement) => { if op.kind.is_valid_for_field_type() { - Ok(Bool) + Ok((Bool, false)) } else { Err(TypeCheckError::FieldComparison { span }) } } // <= and friends are technically valid for booleans, just not very useful - (Bool, Bool) => Ok(Bool), + (Bool, Bool) => Ok((Bool, false)), // Special-case == and != for arrays (Array(x_size, x_type), Array(y_size, y_type)) - if matches!(op.kind, Equal | NotEqual) => + if matches!(op.kind, BinaryOpKind::Equal | BinaryOpKind::NotEqual) => { - self.unify(x_type, y_type, || TypeCheckError::TypeMismatchWithSource { - expected: lhs_type.clone(), - actual: rhs_type.clone(), - source: Source::ArrayElements, - span: op.location.span, - }); - self.unify(x_size, y_size, || TypeCheckError::TypeMismatchWithSource { expected: lhs_type.clone(), actual: rhs_type.clone(), @@ -853,19 +855,9 @@ impl<'interner> TypeChecker<'interner> { span: op.location.span, }); - Ok(Bool) - } - (lhs @ NamedGeneric(binding_a, _), rhs @ NamedGeneric(binding_b, _)) => { - if binding_a == binding_b { - return Ok(Bool); - } - Err(TypeCheckError::TypeMismatchWithSource { - expected: lhs.clone(), - actual: rhs.clone(), - source: Source::Comparison, - span, - }) + self.comparator_operand_type_rules(x_type, y_type, op, span) } + (String(x_size), String(y_size)) => { self.unify(x_size, y_size, || TypeCheckError::TypeMismatchWithSource { expected: *x_size.clone(), @@ -874,14 +866,17 @@ impl<'interner> TypeChecker<'interner> { source: Source::StringLen, }); - Ok(Bool) + Ok((Bool, false)) + } + (lhs, rhs) => { + self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { + expected: lhs.clone(), + actual: rhs.clone(), + span: op.location.span, + source: Source::Binary, + }); + Ok((Bool, true)) } - (lhs, rhs) => Err(TypeCheckError::TypeMismatchWithSource { - expected: lhs.clone(), - actual: rhs.clone(), - source: Source::Comparison, - span, - }), } } @@ -1041,13 +1036,16 @@ impl<'interner> TypeChecker<'interner> { } // Given a binary operator and another type. This method will produce the output type + // and a boolean indicating whether to use the trait impl corresponding to the operator + // or not. A value of false indicates the caller to use a primitive operation for this + // operator, while a true value indicates a user-provided trait impl is required. fn infix_operand_type_rules( &mut self, lhs_type: &Type, op: &HirBinaryOp, rhs_type: &Type, span: Span, - ) -> Result { + ) -> Result<(Type, bool), TypeCheckError> { if op.kind.is_comparator() { return self.comparator_operand_type_rules(lhs_type, rhs_type, op, span); } @@ -1055,7 +1053,7 @@ impl<'interner> TypeChecker<'interner> { use Type::*; match (lhs_type, rhs_type) { // An error type on either side will always return an error - (Error, _) | (_, Error) => Ok(Error), + (Error, _) | (_, Error) => Ok((Error, false)), // Matches on TypeVariable must be first so that we follow any type // bindings. @@ -1096,7 +1094,7 @@ impl<'interner> TypeChecker<'interner> { || other == &Type::Error { Type::apply_type_bindings(bindings); - Ok(other.clone()) + Ok((other.clone(), false)) } else { Err(TypeCheckError::TypeMismatchWithSource { expected: lhs_type.clone(), @@ -1121,25 +1119,8 @@ impl<'interner> TypeChecker<'interner> { span, }); } - Ok(Integer(*sign_x, *bit_width_x)) - } - (Integer(..), FieldElement) | (FieldElement, Integer(..)) => { - Err(TypeCheckError::IntegerAndFieldBinaryOperation { span }) + Ok((Integer(*sign_x, *bit_width_x), false)) } - (Integer(..), typ) | (typ, Integer(..)) => { - Err(TypeCheckError::IntegerTypeMismatch { typ: typ.clone(), span }) - } - // These types are not supported in binary operations - (Array(..), _) | (_, Array(..)) => { - Err(TypeCheckError::InvalidInfixOp { kind: "Arrays", span }) - } - (Struct(..), _) | (_, Struct(..)) => { - Err(TypeCheckError::InvalidInfixOp { kind: "Structs", span }) - } - (Tuple(_), _) | (_, Tuple(_)) => { - Err(TypeCheckError::InvalidInfixOp { kind: "Tuples", span }) - } - // The result of two Fields is always a witness (FieldElement, FieldElement) => { if op.is_bitwise() { @@ -1148,17 +1129,20 @@ impl<'interner> TypeChecker<'interner> { if op.is_modulo() { return Err(TypeCheckError::FieldModulo { span }); } - Ok(FieldElement) + Ok((FieldElement, false)) } - (Bool, Bool) => Ok(Bool), + (Bool, Bool) => Ok((Bool, false)), - (lhs, rhs) => Err(TypeCheckError::TypeMismatchWithSource { - expected: lhs.clone(), - actual: rhs.clone(), - source: Source::BinOp(op.kind), - span, - }), + (lhs, rhs) => { + self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { + expected: lhs.clone(), + actual: rhs.clone(), + span: op.location.span, + source: Source::Binary, + }); + Ok((lhs.clone(), true)) + } } } @@ -1210,6 +1194,57 @@ impl<'interner> TypeChecker<'interner> { } } } + + /// Prerequisite: verify_trait_constraint of the operator's trait constraint. + /// + /// Although by this point the operator is expected to already have a trait impl, + /// we still need to match the operator's type against the method's instantiated type + /// to ensure the instantiation bindings are correct and the monomorphizer can + /// re-apply the needed bindings. + fn typecheck_operator_method( + &mut self, + expr_id: ExprId, + trait_method_id: TraitMethodId, + object_type: &Type, + span: Span, + ) { + let the_trait = self.interner.get_trait(trait_method_id.trait_id); + + let method = &the_trait.methods[trait_method_id.method_index]; + let (method_type, mut bindings) = method.typ.instantiate(self.interner); + + match method_type { + Type::Function(args, _, _) => { + // We can cheat a bit and match against only the object type here since no operator + // overload uses other generic parameters or return types aside from the object type. + let expected_object_type = &args[0]; + self.unify(object_type, expected_object_type, || TypeCheckError::TypeMismatch { + expected_typ: expected_object_type.to_string(), + expr_typ: object_type.to_string(), + expr_span: span, + }); + } + other => { + unreachable!("Expected operator method to have a function type, but found {other}") + } + } + + // We must also remember to apply these substitutions to the object_type + // referenced by the selected trait impl, if one has yet to be selected. + let impl_kind = self.interner.get_selected_impl_for_expression(expr_id); + if let Some(TraitImplKind::Assumed { object_type }) = impl_kind { + let the_trait = self.interner.get_trait(trait_method_id.trait_id); + let object_type = object_type.substitute(&bindings); + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), object_type.clone()), + ); + self.interner + .select_impl_for_expression(expr_id, TraitImplKind::Assumed { object_type }); + } + + self.interner.store_instantiation_bindings(expr_id, bindings); + } } /// Taken from: https://stackoverflow.com/a/47127500 diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index 95991047091..092e8631f1b 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -241,7 +241,7 @@ mod test { function::{FuncMeta, HirFunction}, stmt::HirStatement, }; - use crate::node_interner::{DefinitionKind, FuncId, NodeInterner}; + use crate::node_interner::{DefinitionKind, FuncId, NodeInterner, TraitId, TraitMethodId}; use crate::{ hir::{ def_map::{CrateDefMap, LocalModuleId, ModuleDefId}, @@ -254,6 +254,7 @@ mod test { #[test] fn basic_let() { let mut interner = NodeInterner::default(); + interner.populate_dummy_operator_traits(); // Safety: The FileId in a location isn't used for tests let file = FileId::default(); @@ -284,7 +285,9 @@ mod test { // Create Infix let operator = HirBinaryOp { location, kind: BinaryOpKind::Add }; - let expr = HirInfixExpression { lhs: x_expr_id, operator, rhs: y_expr_id }; + let trait_id = TraitId(ModuleId::dummy_id()); + let trait_method_id = TraitMethodId { trait_id, method_index: 0 }; + let expr = HirInfixExpression { lhs: x_expr_id, operator, rhs: y_expr_id, trait_method_id }; let expr_id = interner.push_expr(HirExpression::Infix(expr)); interner.push_expr_location(expr_id, Span::single_char(0), file); @@ -469,6 +472,7 @@ mod test { ) { let (program, errors) = parse_program(src); let mut interner = NodeInterner::default(); + interner.populate_dummy_operator_traits(); assert_eq!( errors.len(), diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index ef1c3af7ac0..7c04398ca88 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -101,6 +101,12 @@ pub struct HirInfixExpression { pub lhs: ExprId, pub operator: HirBinaryOp, pub rhs: ExprId, + + /// The trait method id for the operator trait method that corresponds to this operator. + /// For derived operators like `!=`, this will lead to the method `Eq::eq`. For these + /// cases, it is up to the monomorphization pass to insert the appropriate `not` operation + /// after the call to `Eq::eq` to get the result of the `!=` operator. + pub trait_method_id: TraitMethodId, } /// This is always a struct field access `my_struct.field` diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index 5a5f07b0a38..42a618e7d77 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -352,7 +352,7 @@ impl std::fmt::Display for Type { }; write!(f, "fn({}) -> {}{}", args.join(", "), ret, closure_env_text) } - Type::Slice(element) => write!(f, "[{element}"), + Type::Slice(element) => write!(f, "[{element}]"), Type::MutableReference(element) => write!(f, "&mut {element}"), } } diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 39b05dcd5ac..5bdd41eafaa 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -26,7 +26,7 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, + ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, Visibility, }; @@ -238,6 +238,7 @@ impl<'interner> Monomorphizer<'interner> { }); let parameters = self.parameters(meta.parameters); + let body = self.expr(body_expr_id); let unconstrained = modifiers.is_unconstrained || matches!(modifiers.contract_function_type, Some(ContractFunctionType::Open)); @@ -356,11 +357,37 @@ impl<'interner> Monomorphizer<'interner> { } HirExpression::Infix(infix) => { - let lhs = Box::new(self.expr(infix.lhs)); - let rhs = Box::new(self.expr(infix.rhs)); + let lhs = self.expr(infix.lhs); + let rhs = self.expr(infix.rhs); let operator = infix.operator.kind; let location = self.interner.expr_location(&expr); - ast::Expression::Binary(ast::Binary { lhs, rhs, operator, location }) + + if self.interner.get_selected_impl_for_expression(expr).is_some() { + // If an impl was selected for this infix operator, replace it + // with a method call to the appropriate trait impl method. + let lhs_type = self.interner.id_type(infix.lhs); + let args = vec![lhs_type.clone(), lhs_type]; + + // If this is a comparison operator, the result is a boolean but + // the actual method call returns an Ordering + use crate::BinaryOpKind::*; + let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { + self.interner.ordering_type() + } else { + self.interner.id_type(expr) + }; + + let env = Box::new(Type::Unit); + let function_type = Type::Function(args, Box::new(ret.clone()), env); + + let method = infix.trait_method_id; + let func = self.resolve_trait_method_reference(expr, function_type, method); + self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location) + } else { + let lhs = Box::new(lhs); + let rhs = Box::new(rhs); + ast::Expression::Binary(ast::Binary { lhs, rhs, operator, location }) + } } HirExpression::Index(index) => self.index(expr, index), @@ -400,13 +427,8 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Lambda(lambda) => self.lambda(lambda, expr), HirExpression::TraitMethodReference(method) => { - if let Type::Function(_, _, _) = self.interner.id_type(expr) { - self.resolve_trait_method_reference(expr, method) - } else { - unreachable!( - "Calling a non-function, this should've been caught in typechecking" - ); - } + let function_type = self.interner.id_type(expr); + self.resolve_trait_method_reference(expr, function_type, method) } HirExpression::MethodCall(hir_method_call) => { @@ -826,13 +848,12 @@ impl<'interner> Monomorphizer<'interner> { fn resolve_trait_method_reference( &mut self, expr_id: node_interner::ExprId, + function_type: HirType, method: TraitMethodId, ) -> ast::Expression { - let function_type = self.interner.id_type(expr_id); - let trait_impl = self .interner - .get_selected_impl_for_ident(expr_id) + .get_selected_impl_for_expression(expr_id) .expect("ICE: missing trait impl - should be caught during type checking"); let hir_func_id = match trait_impl { @@ -1087,7 +1108,7 @@ impl<'interner> Monomorphizer<'interner> { function_type: HirType, ) -> FuncId { let new_id = self.next_function_id(); - self.define_global(id, function_type, new_id); + self.define_global(id, function_type.clone(), new_id); let bindings = self.interner.get_instantiation_bindings(expr_id); let bindings = self.follow_bindings(bindings); @@ -1417,6 +1438,70 @@ impl<'interner> Monomorphizer<'interner> { ), }) } + + /// Call an operator overloading method for the given operator. + /// This function handles the special cases some operators have which don't map + /// 1 to 1 onto their operator function. For example: != requires a negation on + /// the result of its `eq` method, and the comparison operators each require a + /// conversion from the `Ordering` result to a boolean. + fn create_operator_impl_call( + &self, + func: ast::Expression, + lhs: ast::Expression, + operator: HirBinaryOp, + rhs: ast::Expression, + ret: Type, + location: Location, + ) -> ast::Expression { + let arguments = vec![lhs, rhs]; + let func = Box::new(func); + let return_type = self.convert_type(&ret); + + let mut result = + ast::Expression::Call(ast::Call { func, arguments, return_type, location }); + + use crate::BinaryOpKind::*; + match operator.kind { + // Negate the result of the == operation + NotEqual => { + result = ast::Expression::Unary(ast::Unary { + operator: UnaryOp::Not, + rhs: Box::new(result), + result_type: ast::Type::Bool, + location, + }); + } + // All the comparison operators require special handling since their `cmp` method + // returns an `Ordering` rather than a boolean value. + // + // (a < b) => a.cmp(b) == Ordering::Less + // (a <= b) => a.cmp(b) != Ordering::Greater + // (a > b) => a.cmp(b) == Ordering::Greater + // (a >= b) => a.cmp(b) != Ordering::Less + Less | LessEqual | Greater | GreaterEqual => { + // Comparing an Ordering directly to a field value in this way takes advantage + // of the fact the Ordering struct contains a single Field type, and our SSA + // pass will automatically unpack tuple values. + let ordering_value = if matches!(operator.kind, Less | GreaterEqual) { + FieldElement::zero() // Ordering::Less + } else { + 2u128.into() // Ordering::Greater + }; + + let operator = + if matches!(operator.kind, Less | Greater) { Equal } else { NotEqual }; + + let int_value = ast::Literal::Integer(ordering_value, ast::Type::Field, location); + let rhs = Box::new(ast::Expression::Literal(int_value)); + let lhs = Box::new(ast::Expression::ExtractTupleField(Box::new(result), 0)); + + result = ast::Expression::Binary(ast::Binary { lhs, operator, rhs, location }); + } + _ => (), + } + + result + } } fn unwrap_tuple_type(typ: &HirType) -> Vec { diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 34313595271..7c42e279916 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -21,8 +21,8 @@ use crate::hir_def::{ }; use crate::token::{Attributes, SecondaryAttribute}; use crate::{ - ContractFunctionType, FunctionDefinition, FunctionVisibility, Generics, Shared, TypeAliasType, - TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, + BinaryOpKind, ContractFunctionType, FunctionDefinition, FunctionVisibility, Generics, Shared, + TypeAliasType, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, }; /// An arbitrary number to limit the recursion depth when searching for trait impls. @@ -110,6 +110,12 @@ pub struct NodeInterner { /// the context to get the concrete type of the object and select the correct impl itself. selected_trait_implementations: HashMap, + /// Holds the trait ids of the traits used for operator overloading + operator_traits: HashMap, + + /// The `Ordering` type is a semi-builtin type that is the result of the comparison traits. + ordering_type: Option, + /// Map from ExprId (referring to a Function/Method call) to its corresponding TypeBindings, /// filled out during type checking from instantiated variables. Used during monomorphization /// to map call site types back onto function parameter types, and undo this binding as needed. @@ -423,6 +429,8 @@ impl Default for NodeInterner { trait_implementations: Vec::new(), trait_implementation_map: HashMap::new(), selected_trait_implementations: HashMap::new(), + operator_traits: HashMap::new(), + ordering_type: None, instantiation_bindings: HashMap::new(), field_indices: HashMap::new(), next_type_variable_id: std::cell::Cell::new(0), @@ -1254,13 +1262,12 @@ impl NodeInterner { /// Tags the given identifier with the selected trait_impl so that monomorphization /// can later recover which impl was selected, or alternatively see if it needs to /// decide which impl to select (because the impl was Assumed). - pub fn select_impl_for_ident(&mut self, ident_id: ExprId, trait_impl: TraitImplKind) { + pub fn select_impl_for_expression(&mut self, ident_id: ExprId, trait_impl: TraitImplKind) { self.selected_trait_implementations.insert(ident_id, trait_impl); } - /// Retrieves the impl selected for a given IdentId during name resolution. - /// From type checking and on, the "ident" referred to is changed to a TraitMethodReference node. - pub fn get_selected_impl_for_ident(&self, ident_id: ExprId) -> Option { + /// Retrieves the impl selected for a given ExprId during name resolution. + pub fn get_selected_impl_for_expression(&self, ident_id: ExprId) -> Option { self.selected_trait_implementations.get(&ident_id).cloned() } @@ -1294,7 +1301,6 @@ impl NodeInterner { } HirExpression::Constructor(expr) => { let struct_type = &expr.r#type.borrow(); - Some(struct_type.location) } HirExpression::MemberAccess(expr_member_access) => { @@ -1332,6 +1338,91 @@ impl NodeInterner { Location::new(found_field_name.span(), struct_type.location.file) }) } + + /// Retrieves the trait id for a given binary operator. + /// All binary operators correspond to a trait - although multiple may correspond + /// to the same trait (such as `==` and `!=`). + /// `self.operator_traits` is expected to be filled before name resolution, + /// during definition collection. + pub fn get_operator_trait_method(&self, operator: BinaryOpKind) -> TraitMethodId { + let trait_id = self.operator_traits[&operator]; + + // Assume that the operator's method to be overloaded is the first method of the trait. + TraitMethodId { trait_id, method_index: 0 } + } + + /// Add the given trait as an operator trait if its name matches one of the + /// operator trait names (Add, Sub, ...). + pub fn try_add_operator_trait(&mut self, trait_id: TraitId) { + let the_trait = self.get_trait(trait_id); + + let operator = match the_trait.name.0.contents.as_str() { + "Add" => BinaryOpKind::Add, + "Sub" => BinaryOpKind::Subtract, + "Mul" => BinaryOpKind::Multiply, + "Div" => BinaryOpKind::Divide, + "Rem" => BinaryOpKind::Modulo, + "Eq" => BinaryOpKind::Equal, + "Ord" => BinaryOpKind::Less, + "BitAnd" => BinaryOpKind::And, + "BitOr" => BinaryOpKind::Or, + "BitXor" => BinaryOpKind::Xor, + "Shl" => BinaryOpKind::ShiftLeft, + "Shr" => BinaryOpKind::ShiftRight, + _ => return, + }; + + self.operator_traits.insert(operator, trait_id); + + // Some operators also require we insert a matching entry for related operators + match operator { + BinaryOpKind::Equal => { + self.operator_traits.insert(BinaryOpKind::NotEqual, trait_id); + } + BinaryOpKind::Less => { + self.operator_traits.insert(BinaryOpKind::LessEqual, trait_id); + self.operator_traits.insert(BinaryOpKind::Greater, trait_id); + self.operator_traits.insert(BinaryOpKind::GreaterEqual, trait_id); + + let the_trait = self.get_trait(trait_id); + self.ordering_type = match &the_trait.methods[0].typ { + Type::Forall(_, typ) => match typ.as_ref() { + Type::Function(_, return_type, _) => Some(return_type.as_ref().clone()), + other => unreachable!("Expected function type for `cmp`, found {}", other), + }, + other => unreachable!("Expected Forall type for `cmp`, found {}", other), + }; + } + _ => (), + } + } + + /// This function is needed when creating a NodeInterner for testing so that calls + /// to `get_operator_trait` do not panic when the stdlib isn't present. + #[cfg(test)] + pub fn populate_dummy_operator_traits(&mut self) { + let dummy_trait = TraitId(ModuleId::dummy_id()); + self.operator_traits.insert(BinaryOpKind::Add, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Subtract, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Multiply, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Divide, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Modulo, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Equal, dummy_trait); + self.operator_traits.insert(BinaryOpKind::NotEqual, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Less, dummy_trait); + self.operator_traits.insert(BinaryOpKind::LessEqual, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Greater, dummy_trait); + self.operator_traits.insert(BinaryOpKind::GreaterEqual, dummy_trait); + self.operator_traits.insert(BinaryOpKind::And, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Or, dummy_trait); + self.operator_traits.insert(BinaryOpKind::Xor, dummy_trait); + self.operator_traits.insert(BinaryOpKind::ShiftLeft, dummy_trait); + self.operator_traits.insert(BinaryOpKind::ShiftRight, dummy_trait); + } + + pub(crate) fn ordering_type(&self) -> Type { + self.ordering_type.clone().expect("Expected ordering_type to be set in the NodeInterner") + } } impl Methods { diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index cd0c34f7e09..063e0215a30 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -53,6 +53,7 @@ mod test { let root = std::path::Path::new("/"); let fm = FileManager::new(root); let mut context = Context::new(fm); + context.def_interner.populate_dummy_operator_traits(); let root_file_id = FileId::dummy(); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); let (program, parser_errors) = parse_program(src); diff --git a/cspell.json b/cspell.json index 4ba51240c19..94449a68a77 100644 --- a/cspell.json +++ b/cspell.json @@ -15,6 +15,8 @@ "bincode", "bindgen", "bitand", + "bitxor", + "bitor", "blackbox", "bridgekeeper", "brillig", diff --git a/docs/docs/explanations/standard_library/traits.md b/docs/docs/explanations/standard_library/traits.md deleted file mode 100644 index 63b4f3d6f0b..00000000000 --- a/docs/docs/explanations/standard_library/traits.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: Traits -description: Noir's stdlib provides a few commonly used traits. -keywords: [traits, trait, interface, protocol, default, add, eq] ---- - -## `std::default` - -### `std::default::Default` - -```rust -trait Default { - fn default() -> Self; -} -``` - -Constructs a default value of a type. - -Implementations: -```rust -impl Default for Field { .. } - -impl Default for i8 { .. } -impl Default for i16 { .. } -impl Default for i32 { .. } -impl Default for i64 { .. } - -impl Default for u8 { .. } -impl Default for u16 { .. } -impl Default for u32 { .. } -impl Default for u64 { .. } - -impl Default for () { .. } -impl Default for bool { .. } - -impl Default for [T; N] - where T: Default { .. } - -impl Default for (A, B) - where A: Default, B: Default { .. } - -impl Default for (A, B, C) - where A: Default, B: Default, C: Default { .. } - -impl Default for (A, B, C, D) - where A: Default, B: Default, C: Default, D: Default { .. } - -impl Default for (A, B, C, D, E) - where A: Default, B: Default, C: Default, D: Default, E: Default { .. } -``` - -For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. - -## `std::ops` - -### `std::ops::Eq` - -```rust -trait Eq { - fn eq(self, other: Self) -> bool; -} -``` -Returns `true` if `self` is equal to `other`. - -Implementations: -```rust -impl Eq for Field { .. } - -impl Eq for i8 { .. } -impl Eq for i16 { .. } -impl Eq for i32 { .. } -impl Eq for i64 { .. } - -impl Eq for u8 { .. } -impl Eq for u16 { .. } -impl Eq for u32 { .. } -impl Eq for u64 { .. } - -impl Eq for () { .. } -impl Eq for bool { .. } - -impl Eq for [T; N] - where T: Eq { .. } - -impl Eq for (A, B) - where A: Eq, B: Eq { .. } - -impl Eq for (A, B, C) - where A: Eq, B: Eq, C: Eq { .. } - -impl Eq for (A, B, C, D) - where A: Eq, B: Eq, C: Eq, D: Eq { .. } - -impl Eq for (A, B, C, D, E) - where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } -``` - -### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` - -These traits abstract over addition, subtraction, multiplication, and division respectively. -Although Noir does not currently have operator overloading, in the future implementing these -traits for a given type will also allow that type to be used with the corresponding operator -for that trait (`+` for Add, etc) in addition to the normal method names. - -```rust -trait Add { - fn add(self, other: Self) -> Self; -} - -trait Sub { - fn sub(self, other: Self) -> Self; -} - -trait Mul { - fn mul(self, other: Self) -> Self; -} - -trait Div { - fn div(self, other: Self) -> Self; -} -``` - -The implementations block below is given for the `Add` trait, but the same types that implement -`Add` also implement `Sub`, `Mul`, and `Div`. - -Implementations: -```rust -impl Add for Field { .. } - -impl Add for i8 { .. } -impl Add for i16 { .. } -impl Add for i32 { .. } -impl Add for i64 { .. } - -impl Add for u8 { .. } -impl Add for u16 { .. } -impl Add for u32 { .. } -impl Add for u64 { .. } -``` diff --git a/docs/docs/getting_started/create_a_project.md b/docs/docs/getting_started/create_a_project.md index f10916c39c5..26ff265c389 100644 --- a/docs/docs/getting_started/create_a_project.md +++ b/docs/docs/getting_started/create_a_project.md @@ -69,7 +69,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../noir/syntax/data_types/index.md) section. +[Data Types](../noir/concepts/data_types/index.md) section. The next line of the program specifies its body: @@ -79,7 +79,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../noir/syntax/comments.md) chapter. +For more Noir syntax, check the [Language Concepts](../noir/concepts/comments.md) chapter. ## Build In/Output Files diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 184ca283539..9f27230a1a0 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -16,7 +16,7 @@ To update, please make sure this field in `Nargo.toml` matches the output of `na ## ≥0.14 -The index of the [for loops](noir/syntax/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: +The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: ```rust for i in 0..10 { diff --git a/docs/docs/noir/concepts/_category_.json b/docs/docs/noir/concepts/_category_.json index 78dd943647f..7da08f8a8c5 100644 --- a/docs/docs/noir/concepts/_category_.json +++ b/docs/docs/noir/concepts/_category_.json @@ -3,4 +3,4 @@ "position": 0, "collapsible": true, "collapsed": true -} +} \ No newline at end of file diff --git a/docs/docs/noir/concepts/data_types/function_types.md b/docs/docs/noir/concepts/data_types/function_types.md index 61e4076adaf..e224e860d59 100644 --- a/docs/docs/noir/concepts/data_types/function_types.md +++ b/docs/docs/noir/concepts/data_types/function_types.md @@ -23,4 +23,4 @@ fn main() { ``` A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](@site/docs/noir/syntax/lambdas.md) for more details. +See [Lambdas](@site/docs/noir/concepts/lambdas.md) for more details. diff --git a/docs/docs/noir/concepts/data_types/index.md b/docs/docs/noir/concepts/data_types/index.md index 01cd0431a68..3c9cd4c2437 100644 --- a/docs/docs/noir/concepts/data_types/index.md +++ b/docs/docs/noir/concepts/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/noir/syntax/generics.md): +Type aliases can also be used with [generics](@site/docs/noir/concepts/generics.md): ```rust type Id = Size; diff --git a/docs/docs/explanations/noir/traits.md b/docs/docs/noir/concepts/traits.md similarity index 100% rename from docs/docs/explanations/noir/traits.md rename to docs/docs/noir/concepts/traits.md diff --git a/docs/docs/noir/standard_library/traits.md b/docs/docs/noir/standard_library/traits.md new file mode 100644 index 00000000000..50b0e6816ab --- /dev/null +++ b/docs/docs/noir/standard_library/traits.md @@ -0,0 +1,284 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust +trait Default { + fn default() -> Self; +} +``` + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + +## `std::cmp` + +### `std::cmp::Eq` + +```rust +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Cmp` + +```rust +trait Cmp { + fn cmp(self, other: Self) -> Ordering; +} +``` + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust +trait Add { + fn add(self, other: Self) -> Self; +} + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +trait Div { + fn div(self, other: Self) -> Self; +} +``` + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust +trait Rem { + fn rem(self, other: Self) -> Self; +} +``` + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust +trait BitOr { + fn bitor(self, other: Self) -> Self; +} + +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} + +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust +trait Shl { + fn shl(self, other: Self) -> Self; +} + +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` \ No newline at end of file diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr new file mode 100644 index 00000000000..11127494c18 --- /dev/null +++ b/noir_stdlib/src/cmp.nr @@ -0,0 +1,310 @@ +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } + +impl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } } +impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } +impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } +impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } +impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } + +impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } +impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } +impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } +impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } + +impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } +impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } + +impl Eq for [T; N] where T: Eq { + fn eq(self, other: [T; N]) -> bool { + let mut result = true; + for i in 0 .. self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + +impl Eq for str { + fn eq(self, other: str) -> bool { + let self_bytes = self.as_bytes(); + let other_bytes = other.as_bytes(); + self_bytes == other_bytes + } +} + +impl Eq for (A, B) where A: Eq, B: Eq { + fn eq(self, other: (A, B)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) + } +} + +impl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq { + fn eq(self, other: (A, B, C)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) + } +} + +impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { + fn eq(self, other: (A, B, C, D)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) + } +} + +impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { + fn eq(self, other: (A, B, C, D, E)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) + } +} + +impl Eq for Ordering { + fn eq(self, other: Ordering) -> bool { + self.result == other.result + } +} + + +// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct +// that has 3 public functions for constructing the struct. +struct Ordering { + result: Field, +} + +impl Ordering { + // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built + // into the compiler, do not change these without also updating + // the compiler itself! + pub fn less() -> Ordering { + Ordering { result: 0 } + } + + pub fn equal() -> Ordering { + Ordering { result: 1 } + } + + pub fn greater() -> Ordering { + Ordering { result: 2 } + } +} + + +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} + +// Note: Field deliberately does not implement Ord + +impl Ord for u8 { + fn cmp(self, other: u8) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u16 { + fn cmp(self, other: u16) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u32 { + fn cmp(self, other: u32) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u64 { + fn cmp(self, other: u64) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i8 { + fn cmp(self, other: i8) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i16 { + fn cmp(self, other: i16) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i32 { + fn cmp(self, other: i32) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i64 { + fn cmp(self, other: i64) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for () { + fn cmp(_self: Self, _other: ()) -> Ordering { + Ordering::equal() + } +} + +impl Ord for bool { + fn cmp(self, other: bool) -> Ordering { + if self { + if other { + Ordering::equal() + } else { + Ordering::greater() + } + } else { + if other { + Ordering::less() + } else { + Ordering::equal() + } + } + } +} + +impl Ord for [T; N] where T: Ord { + // The first non-equal element of both arrays determines + // the ordering for the whole array. + fn cmp(self, other: [T; N]) -> Ordering { + let mut result = Ordering::equal(); + for i in 0 .. self.len() { + if result == Ordering::equal() { + let result_i = self[i].cmp(other[i]); + + if result_i == Ordering::less() { + result = result_i; + } else if result_i == Ordering::greater() { + result = result_i; + } + } + } + result + } +} + +impl Ord for (A, B) where A: Ord, B: Ord { + fn cmp(self, other: (A, B)) -> Ordering { + let result = self.0.cmp(other.0); + + if result != Ordering::equal() { + result + } else { + self.1.cmp(other.1) + } + } +} + +impl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord { + fn cmp(self, other: (A, B, C)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + result + } +} + +impl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord { + fn cmp(self, other: (A, B, C, D)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + if result == Ordering::equal() { + result = self.3.cmp(other.3); + } + + result + } +} + +impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { + fn cmp(self, other: (A, B, C, D, E)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + if result == Ordering::equal() { + result = self.3.cmp(other.3); + } + + if result == Ordering::equal() { + result = self.4.cmp(other.4); + } + + result + } +} diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 70b4681b54d..9b166f6ae94 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -19,6 +19,7 @@ mod compat; mod option; mod string; mod test; +mod cmp; mod ops; mod default; mod prelude; diff --git a/noir_stdlib/src/ops.nr b/noir_stdlib/src/ops.nr index 23acc2f0e5d..3078ac11296 100644 --- a/noir_stdlib/src/ops.nr +++ b/noir_stdlib/src/ops.nr @@ -63,55 +63,94 @@ impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } -trait Eq { - fn eq(self, other: Self) -> bool; +trait Rem { + fn rem(self, other: Self) -> Self; } -impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } - -impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } -impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } -impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } -impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } - -impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } -impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } -impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } -impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } - -impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } -impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } - -impl Eq for [T; N] where T: Eq { - fn eq(self, other: [T; N]) -> bool { - let mut result = true; - for i in 0 .. self.len() { - result &= self[i].eq(other[i]); - } - result - } +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } + +trait BitOr { + fn bitor(self, other: Self) -> Self; } -impl Eq for (A, B) where A: Eq, B: Eq { - fn eq(self, other: (A, B)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) - } +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } + +trait BitAnd { + fn bitand(self, other: Self) -> Self; } -impl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq { - fn eq(self, other: (A, B, C)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) - } +impl BitAnd for bool { fn bitand(self, other: bool) -> bool { self & other } } + +impl BitAnd for u8 { fn bitand(self, other: u8) -> u8 { self & other } } +impl BitAnd for u16 { fn bitand(self, other: u16) -> u16 { self & other } } +impl BitAnd for u32 { fn bitand(self, other: u32) -> u32 { self & other } } +impl BitAnd for u64 { fn bitand(self, other: u64) -> u64 { self & other } } + +impl BitAnd for i8 { fn bitand(self, other: i8) -> i8 { self & other } } +impl BitAnd for i16 { fn bitand(self, other: i16) -> i16 { self & other } } +impl BitAnd for i32 { fn bitand(self, other: i32) -> i32 { self & other } } +impl BitAnd for i64 { fn bitand(self, other: i64) -> i64 { self & other } } + +trait BitXor { + fn bitxor(self, other: Self) -> Self; } -impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { - fn eq(self, other: (A, B, C, D)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) - } +impl BitXor for bool { fn bitxor(self, other: bool) -> bool { self ^ other } } + +impl BitXor for u8 { fn bitxor(self, other: u8) -> u8 { self ^ other } } +impl BitXor for u16 { fn bitxor(self, other: u16) -> u16 { self ^ other } } +impl BitXor for u32 { fn bitxor(self, other: u32) -> u32 { self ^ other } } +impl BitXor for u64 { fn bitxor(self, other: u64) -> u64 { self ^ other } } + +impl BitXor for i8 { fn bitxor(self, other: i8) -> i8 { self ^ other } } +impl BitXor for i16 { fn bitxor(self, other: i16) -> i16 { self ^ other } } +impl BitXor for i32 { fn bitxor(self, other: i32) -> i32 { self ^ other } } +impl BitXor for i64 { fn bitxor(self, other: i64) -> i64 { self ^ other } } + +trait Shl { + fn shl(self, other: Self) -> Self; } -impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { - fn eq(self, other: (A, B, C, D, E)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) - } +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } + +// Bit shifting is not currently supported for signed integer types +// impl Shl for i8 { fn shl(self, other: i8) -> i8 { self << other } } +// impl Shl for i16 { fn shl(self, other: i16) -> i16 { self << other } } +// impl Shl for i32 { fn shl(self, other: i32) -> i32 { self << other } } +// impl Shl for i64 { fn shl(self, other: i64) -> i64 { self << other } } + +trait Shr { + fn shr(self, other: Self) -> Self; } + +impl Shr for u8 { fn shr(self, other: u8) -> u8 { self >> other } } +impl Shr for u16 { fn shr(self, other: u16) -> u16 { self >> other } } +impl Shr for u32 { fn shr(self, other: u32) -> u32 { self >> other } } +impl Shr for u64 { fn shr(self, other: u64) -> u64 { self >> other } } + +// Bit shifting is not currently supported for signed integer types +// impl Shr for i8 { fn shr(self, other: i8) -> i8 { self >> other } } +// impl Shr for i16 { fn shr(self, other: i16) -> i16 { self >> other } } +// impl Shr for i32 { fn shr(self, other: i32) -> i32 { self >> other } } +// impl Shr for i64 { fn shr(self, other: i64) -> i64 { self >> other } } diff --git a/noir_stdlib/src/prelude.nr b/noir_stdlib/src/prelude.nr index f33a1f7e7f1..56020509122 100644 --- a/noir_stdlib/src/prelude.nr +++ b/noir_stdlib/src/prelude.nr @@ -1,3 +1,5 @@ use crate::collections::vec::Vec; use crate::option::Option; use crate::{print, println, assert_constant}; +use crate::cmp::{Eq, Ord}; +use crate::default::Default; diff --git a/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr b/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr index de3078be8ba..780512f04dc 100644 --- a/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr +++ b/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr @@ -1,27 +1,27 @@ fn main() { let array: [Field; 3] = [1, 2, 3]; - assert(array.eq(array)); + assert(array.my_eq(array)); // Ensure this still works if we have to infer the type of the integer literals let array = [1, 2, 3]; - assert(array.eq(array)); + assert(array.my_eq(array)); } -trait Eq { - fn eq(self, other: Self) -> bool; +trait MyEq { + fn my_eq(self, other: Self) -> bool; } -impl Eq for [T; 3] where T: Eq { - fn eq(self, other: Self) -> bool { +impl MyEq for [T; 3] where T: MyEq { + fn my_eq(self, other: Self) -> bool { let mut ret = true; for i in 0 .. self.len() { - ret &= self[i].eq(other[i]); + ret &= self[i].my_eq(other[i]); } ret } } -impl Eq for Field { - fn eq(self, other: Field) -> bool { +impl MyEq for Field { + fn my_eq(self, other: Field) -> bool { self == other } } diff --git a/test_programs/compile_success_empty/trait_default_implementation/src/main.nr b/test_programs/compile_success_empty/trait_default_implementation/src/main.nr index e1f29ce3f48..2f5bff8c40c 100644 --- a/test_programs/compile_success_empty/trait_default_implementation/src/main.nr +++ b/test_programs/compile_success_empty/trait_default_implementation/src/main.nr @@ -1,12 +1,11 @@ use dep::std; -trait Default { - fn default(x: Field, y: Field) -> Self; +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; fn method2(x: Field) -> Field { - x + x } - } struct Foo { @@ -14,8 +13,8 @@ struct Foo { array: [Field; 2], } -impl Default for Foo { - fn default(x: Field,y: Field) -> Self { +impl MyDefault for Foo { + fn my_default(x: Field,y: Field) -> Self { Self { bar: x, array: [x,y] } } } diff --git a/test_programs/compile_success_empty/trait_override_implementation/src/main.nr b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr index a385efc63fd..85528291870 100644 --- a/test_programs/compile_success_empty/trait_override_implementation/src/main.nr +++ b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr @@ -1,7 +1,7 @@ use dep::std; -trait Default { - fn default(x: Field, y: Field) -> Self; +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; fn method2(x: Field) -> Field { x @@ -13,8 +13,8 @@ struct Foo { array: [Field; 2], } -impl Default for Foo { - fn default(x: Field,y: Field) -> Self { +impl MyDefault for Foo { + fn my_default(x: Field,y: Field) -> Self { Self { bar: x, array: [x,y] } } @@ -25,18 +25,18 @@ impl Default for Foo { trait F { fn f1(self) -> Field; - fn f2(self) -> Field { 2 } - fn f3(self) -> Field { 3 } - fn f4(self) -> Field { 4 } - fn f5(self) -> Field { 5 } + fn f2(_self: Self) -> Field { 2 } + fn f3(_self: Self) -> Field { 3 } + fn f4(_self: Self) -> Field { 4 } + fn f5(_self: Self) -> Field { 5 } } struct Bar {} impl F for Bar { - fn f5(self) -> Field { 50 } - fn f1(self) -> Field { 10 } - fn f3(self) -> Field { 30 } + fn f5(_self: Self) -> Field { 50 } + fn f1(_self: Self) -> Field { 10 } + fn f3(_self: Self) -> Field { 30 } } // Impls on mutable references are temporarily disabled // impl F for &mut Bar { diff --git a/test_programs/compile_success_empty/traits/src/main.nr b/test_programs/compile_success_empty/traits/src/main.nr index 784ff01a883..ed804559fed 100644 --- a/test_programs/compile_success_empty/traits/src/main.nr +++ b/test_programs/compile_success_empty/traits/src/main.nr @@ -1,7 +1,7 @@ use dep::std; -trait Default { - fn default(x: Field, y: Field) -> Self; +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; } struct Foo { @@ -9,13 +9,13 @@ struct Foo { array: [Field; 2], } -impl Default for Foo { - fn default(x: Field,y: Field) -> Self { +impl MyDefault for Foo { + fn my_default(x: Field,y: Field) -> Self { Self { bar: x, array: [x,y] } } } fn main(x: Field, y: Field) { - let first = Foo::default(x, y); + let first = Foo::my_default(x, y); assert(first.bar == x); } diff --git a/test_programs/execution_success/operator_overloading/Nargo.toml b/test_programs/execution_success/operator_overloading/Nargo.toml new file mode 100644 index 00000000000..7f9f18ff567 --- /dev/null +++ b/test_programs/execution_success/operator_overloading/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "operator_overloading" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/test_programs/execution_success/operator_overloading/Prover.toml b/test_programs/execution_success/operator_overloading/Prover.toml new file mode 100644 index 00000000000..516b7b4074c --- /dev/null +++ b/test_programs/execution_success/operator_overloading/Prover.toml @@ -0,0 +1,2 @@ +x = 3 +y = 9 diff --git a/test_programs/execution_success/operator_overloading/src/main.nr b/test_programs/execution_success/operator_overloading/src/main.nr new file mode 100644 index 00000000000..3867531abca --- /dev/null +++ b/test_programs/execution_success/operator_overloading/src/main.nr @@ -0,0 +1,154 @@ +use dep::std::ops::{ Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr }; +use dep::std::cmp::Ordering; + +// x = 3, y = 9 +fn main(x: u32, y: u32) { + let wx = Wrapper::new(x); + let wy = Wrapper::new(y); + + // expected x and expected y values + let ex: u32 = 3; + let ey: u32 = 9; + + assert((wx + wy).inner == ex + ey); + assert((wy - wx).inner == ey - ex); + assert((wx * wy).inner == ex * ey); + assert((wx / wy).inner == ex / ey); + assert((wx % wy).inner == ex % ey); + + assert((wx & wy).inner == (ex & ey)); + assert((wx | wy).inner == (ex | ey)); + assert((wx ^ wy).inner == (ex ^ ey)); + + assert((wy << wx).inner == (ey << ex)); + assert((wy >> wx).inner == (ey >> ex)); + + assert((wx == wy) == (ex == ey)); + assert((wx < wy) == (ex < ey)); + assert((wx <= wy) == (ex <= ey)); + assert((wx > wy) == (ex > ey)); + assert((wx >= wy) == (ex >= ey)); + assert(wx.cmp(wy) == ex.cmp(ey)); + + // Ensure operator overloading still works with more complex types + let pair_ascending = Pair { x: wx, y: wy }; + let pair_descending = Pair { x: wy, y: wx }; + + assert(pair_ascending != pair_descending); + + assert(pair_ascending < pair_descending); + assert(pair_ascending <= pair_descending); + assert(pair_descending > pair_ascending); + assert(pair_descending >= pair_ascending); + + assert(pair_ascending.cmp(pair_descending) == Ordering::less()); +} + +struct Wrapper { + inner: u32 +} + +impl Wrapper { + fn new(inner: u32) -> Self { + Wrapper { inner } + } +} + +impl Add for Wrapper { + fn add(self, other: Self) -> Self { + Wrapper::new(self.inner + other.inner) + } +} + +impl Sub for Wrapper { + fn sub(self, other: Self) -> Self { + Wrapper::new(self.inner - other.inner) + } +} + +impl Mul for Wrapper { + fn mul(self, other: Self) -> Self { + Wrapper::new(self.inner * other.inner) + } +} + +impl Div for Wrapper { + fn div(self, other: Self) -> Self { + Wrapper::new(self.inner / other.inner) + } +} + +impl Rem for Wrapper { + fn rem(self, other: Self) -> Self { + Wrapper::new(self.inner % other.inner) + } +} + +impl BitAnd for Wrapper { + fn bitand(self, other: Self) -> Self { + Wrapper::new(self.inner & other.inner) + } +} + +impl BitOr for Wrapper { + fn bitor(self, other: Self) -> Self { + Wrapper::new(self.inner | other.inner) + } +} + +impl BitXor for Wrapper { + fn bitxor(self, other: Self) -> Self { + Wrapper::new(self.inner ^ other.inner) + } +} + +impl Shl for Wrapper { + fn shl(self, other: Self) -> Self { + Wrapper::new(self.inner << other.inner) + } +} + +impl Shr for Wrapper { + fn shr(self, other: Self) -> Self { + Wrapper::new(self.inner >> other.inner) + } +} + +impl Eq for Wrapper { + fn eq(self, other: Self) -> bool { + self.inner == other.inner + } +} + +impl Ord for Wrapper { + fn cmp(self, other: Self) -> Ordering { + self.inner.cmp(other.inner) + } +} + + + + + +struct Pair { + x: Wrapper, + y: Wrapper, +} + +impl Eq for Pair { + fn eq(self, o: Self) -> bool { + (self.x == o.x) & (self.y == o.y) + } +} + +impl Ord for Pair { + fn cmp(self, o: Self) -> Ordering { + let mut result = self.x.cmp(o.x); + + if result == Ordering::equal() { + result = self.y.cmp(o.y); + } + + result + } +} diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 9887e5b8e96..90e8e563cd3 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -21,14 +21,12 @@ use fm::codespan_files as files; use lsp_types::CodeLens; use nargo::workspace::Workspace; use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; +use noirc_driver::{file_manager_with_stdlib, prepare_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::{Context, FunctionNameMatch}, }; -use fm::FileManager; - use notifications::{ on_did_change_configuration, on_did_change_text_document, on_did_close_text_document, on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized, @@ -223,14 +221,14 @@ pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result (Context<'static>, CrateId) { let root = Path::new(""); - let mut file_manager = FileManager::new(root); - let root_file_id = file_manager.add_file_with_source(Path::new("main.nr"), source).expect( + let file_name = Path::new("main.nr"); + let mut file_manager = file_manager_with_stdlib(root); + file_manager.add_file_with_source(file_name, source).expect( "Adding source buffer to file manager should never fail when file manager is empty", ); let mut context = Context::new(file_manager); - - let root_crate_id = context.crate_graph.add_crate_root(root_file_id); + let root_crate_id = prepare_crate(&mut context, file_name); (context, root_crate_id) } From e5e52a81b31d7735b680e97a9bef89a010a99763 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:51:12 +0000 Subject: [PATCH 126/137] feat: add foreign call support to `noir_codegen` functions (#3933) # Description ## Problem\* Resolves ## Summary\* This PR exposes custom foreign call handler functionality into the functions which are codegened by `noir_codegen`. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/monomorphization/mod.rs | 2 +- tooling/noir_codegen/src/index.ts | 10 ++- .../noir_codegen/test/assert_lt/src/main.nr | 1 + .../test/assert_lt/target/assert_lt.json | 2 +- tooling/noir_codegen/test/index.test.ts | 84 ++++++++++++++++++- 5 files changed, 93 insertions(+), 6 deletions(-) diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 5bdd41eafaa..bb0972987e4 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -974,7 +974,7 @@ impl<'interner> Monomorphizer<'interner> { } /// Adds a function argument that contains type metadata that is required to tell - /// `println` how to convert values passed to an foreign call back to a human-readable string. + /// `println` how to convert values passed to an foreign call back to a human-readable string. /// The values passed to an foreign call will be a simple list of field elements, /// thus requiring extra metadata to correctly decode this list of elements. /// diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts index 7bef216097a..19829cd06ff 100644 --- a/tooling/noir_codegen/src/index.ts +++ b/tooling/noir_codegen/src/index.ts @@ -9,7 +9,9 @@ const codegenPrelude = `/* Autogenerated file, do not edit! */ /* eslint-disable */ -import { Noir, InputMap, CompiledCircuit } from "@noir-lang/noir_js" +import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js" + +export { ForeignCallHandler } from "@noir-lang/noir_js" `; const codegenFunction = ( @@ -22,10 +24,12 @@ const codegenFunction = ( return `export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)}; -export async function ${name}(${args_with_types}): Promise<${function_signature.returnValue}> { +export async function ${name}(${args_with_types}, foreignCallHandler?: ForeignCallHandler): Promise<${ + function_signature.returnValue + }> { const program = new Noir(${name}_circuit); const args: InputMap = { ${args} }; - const { returnValue } = await program.execute(args); + const { returnValue } = await program.execute(args, foreignCallHandler); return returnValue as ${function_signature.returnValue}; } `; diff --git a/tooling/noir_codegen/test/assert_lt/src/main.nr b/tooling/noir_codegen/test/assert_lt/src/main.nr index 32d5ff84722..ed370bd87c0 100644 --- a/tooling/noir_codegen/test/assert_lt/src/main.nr +++ b/tooling/noir_codegen/test/assert_lt/src/main.nr @@ -20,6 +20,7 @@ fn main( assert(my_struct.foo.foo); assert(string == "12345"); + print(x); assert(x < y); (x + y, 3, my_struct.foo) } diff --git a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json index b1865ca5f86..be1b134d642 100644 --- a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json +++ b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json @@ -1 +1 @@ -{"noir_version":"0.22.0+528d7c9fa244611cd54636493c730e6ce0734ece","hash":9387426530776910287,"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":73}],"string":[{"start":73,"end":78}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[80,81,82,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/82Y6W/TQBDFNy5HylGgXAEKmHKF2xvbic3VUM62OaDwCYkPSeMIJFAQiui/j59iw+YFIoFnJVaKnF+OyXhmN7vvvVNKfVCTUUofTnZtGuwQL6SPssF7iPcS7yPen3H+myqLj+EVG7ps/JYZ1/fqQZA0aon2dc+rxf0o9IKwX490pMMoHNQi30+iIGrE/bjhxTrwEz0MY3+YBS7L5ejldVikuhwgPkh8iPgw8RLxEeKjxMeIl4mPE58gPkl8ivi0xT5X0hgVC32uKPk+n6G6nCU+R7xCfJ74AvFFYpf4EvEq8WXiK8RXia8RX7fY52oao2qhz1Ul3+cbVJebxLeIbxPfIb5LfI/YI9bENWKfOCAOievEDYt9jtIYkYU+R0q+zzHV5T7xA+KHxI+IHxOvETeJnxCvEz8lfkb8nPgF8UviV2p6/9+g9zeJt4hbxG31ax7lw8Y5oCk0h2zmuSGQZzLEGFjNc1Msz52hzTy35PJMbObZkstzYDPPtlyeO9ANjpodjnDOJSW39p1/z0vzC7+5dbHYZl072bWrJlosnxf5Z6DX1tXsnCkZz/N9xZnzmdIf4iwar+XfXzLeL3rzM8Uwf1wqZicrpPSBpCOX488DSdeImY8F4XrYWlRFY70VrOe8+v1lnh7lqTuC99wV7GuB+s39g/uf1828PnvFxtQ68YoNLblOXiv5/x0zpq2+v5HL27eZ57Zg31tGjpif2LCxkcNIzc1TbLIwDGESwhiEGYhNFqYfjD6YezD0YOLBuINZB4MOphxMLphSMKJgPsFwgskEYwlmkqsmptGqmphDMIRgAsH4gdkD8wRmBwwOmBowMmBewLCASYEFhk0ZBgSKDqMB5gIMBZgIEOUQ0RDOEMsQyBDFEMJrWR0hcnG4gJiFgIVohVCFOIUghXCCKMGBH/Vqq+nDy3L2vEidML8x/7bV9OHlfXZdya698Tj58nXsjkdubzBwdz+NP7qj78m34efR7g+ltqXnYRcAAA=="} \ No newline at end of file +{"noir_version":"0.22.0+6f69b3f511c8b4c51404ad4c18131bdf6b7f6a94","hash":3763979860977920209,"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":73}],"string":[{"start":73,"end":78}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[98,99,100,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/+1cC3PTRhBex8SJ40cezsNxaOtSoGnpQ7Jsy+6LkFJaSFIoKVCgQGzsTJlpCWU85Zf1/9Ur6drz9pAF3jtZM9FMRvliZff7bqXV6bTeYwD4E/wtNfyZCfY7Ep4hOD38mZfwGYJnCc4QPBdg4RMC+7hZk232vORLtutYzXq979b6tmN3rFq722pY9Ua32bJbdqPV6NVajtNv1Vtuu9t2rbZdd/r2caPtHAeG5/k4WmIcsmRcFgjOEZwnuEBwkeBFgpcIXiZ4heASwasErxG8TvCGxjiXhzbKGuJcBv44b5JxqRC8RfBZgt8h+F2C3yO4SvD7BJ8j+AOCzxN8geCLBH+oMc7bQxvbGuK8Dfxx/oiMy8cEXyL4E4I/Jfgzgj8n2CLYJrhGsENwneAGwU2CXY1xbg1ttDTEuQX8cW6TcfmC4C8J/orgrwn+huDLBO8QfIXgXYK/Jfgqwd8RfI3g7wn+AUbv/9fJ5zcI3iN4n+AD+O88EpuOecAO0zkk85whPCe1fZ3R1o9s4+fYaSkmOuPEx9m/PsV2E/x5qRwz3NLBPqNBCxA/dPyKir+xOtcRnJsa7N4C3otTh+5b/DHSmkhuMNr6iU2zUzOVSPg4jyaS23CaSFiCc1uD3UOY7kSCug/5Y6Q1kewx2vqZTbPjmEokfJxHE8kdOE0kLMG5o8HuXZjuRIK67/LHSAtXnDkdAv+j/D1IRgLdZ7T1C5tmp24qgfJxHk2g9+E0gbIE574Guw9guhMo6n7AHyMtXDHR3wP+BPoQkpFADxht/cqm2WmYSqB8nEcT6CM4TaAswXmkwe5jmO4Eirof88dIC1dM9A+BP4E+mXLdGJ8nihhNqttU4ksB/w3q72CPxRYzhH9GMVbWhJuGJGrJ3MV+VuJfDH5Pa9CSYbVZa6CWM6A+j2gs5BhlAs2M+my0Ocdr0xLFTnw23S7ayEpjIsZPcM9Jn89L45VlHq+U5FPYFTirzW8N6xi84qgw/QsKHgsG9S9o89vsCo1h+nMKHjmD+nPa/Dax3sIrfgvTn1fwyBvUn9fmt9lHG4Ux+gsKHgWD+gva/DaxTsm7x4XpLyp4FA3ql/lF5ZqNmSu/X6eDNhbH6F9U8Fg0qF/mF5VrNmau/H5drPfzioLD9C8peCwZ1C/zi8o1HzNXfr8u1m56Bdth+pcVPJYN6pf5ReWai5krv98m1sl6xfRh+lcUPFYM6pf5ReWaj5krv9+mlwNLY/SXFDxKBvXL/KJyLSSIay5BXPMxc+X363rz69Ux+lcVPFYN6pf5ReW6kiCuywniGve48vt1vTWmtTH61xQ81gzql/lF5ZqNmSu/39pTtLE+Rv+6gse6Qf0yv6hcszFz5ffrenPhjTH6NxQ8Ngzql/lF5ZpLENdCgriWYubK77eJ30H0vqwcpr+s4FE2qF/mF5VrNkFcizFz5ffr4PdzvS+Xh+nfVPDYNKh/U5tfx3tuqYzRX1HwqBjUX9Hm1+2hja0x+rcUPLYM6he+8L20eH//4uWz5wNKGre09LsodEhJx1xQHDsHGivI0vD/qhGZHJcfufJl0mqdmbfnZdM/KKSz2ZbH9SjY4+ujWSnw4hg8AXal41PSPiXFZBdGTxx6TOo1duTqCvH/iStNPAoGkrvs7YiP4789FDqSTbExly9pu6gmtdVnHM+w8XtDnhbhaR8xau4wxnWC8QtNcNN83YTF2Zps4yy7tDmvky7w5x3Zpq64P+Xj7ejk2WOM+77EEc9PvGGLElXR7w1vslieJsq1cFkCb7JYWoCvrHEJHJeWcQkAl1hx6Q6XhPCRGB9fcAqP01icUmKPLOyLhb2wsP9VFfw+V+fA72d1HvzZ4kXw+1Nhvyfsz4Q9mS6B33sJ+y1hjyXsq4QXGN6UcR0YBx2fLfDdID5j4RoWPsNjHRr2+sH+PtjTB/v4YO+ey8E4XgF/coH9d66C32fnGvj9dLCHDvZ6wTYNe+D3xDmA0cmLWFafZJzw/Mbzrwejk5fnwf5ssO8MBv0/Xgyqg5Nqp9ervno2+K168lf/5fHvJ6/+ASeieLQUUAAA"} \ No newline at end of file diff --git a/tooling/noir_codegen/test/index.test.ts b/tooling/noir_codegen/test/index.test.ts index 70f3d5bbf89..822993b2f1e 100644 --- a/tooling/noir_codegen/test/index.test.ts +++ b/tooling/noir_codegen/test/index.test.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { assert_lt, MyStruct, u64 } from './codegen/index.js'; +import { assert_lt, MyStruct, u64, ForeignCallHandler } from './codegen/index.js'; it('codegens a callable function', async () => { const my_struct = { foo: true, bar: ['12345', '12345', '12345'] }; @@ -20,3 +20,85 @@ it('codegens a callable function', async () => { expect(constant).to.be.eq('0x03'); expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] }); }); + +it('allows passing a custom foreign call handler', async () => { + let observedName = ''; + let observedInputs: string[][] = []; + const foreignCallHandler: ForeignCallHandler = async (name: string, inputs: string[][]) => { + // Throwing inside the oracle callback causes a timeout so we log the observed values + // and defer the check against expected values until after the execution is complete. + observedName = name; + observedInputs = inputs; + + return []; + }; + + const my_struct = { foo: true, bar: ['12345', '12345', '12345'] }; + + const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt( + '2', + '3', + [0, 0, 0, 0, 0], + { + foo: my_struct, + bar: [my_struct, my_struct, my_struct], + baz: '64', + }, + '12345', + foreignCallHandler, + ); + + expect(observedName).to.be.eq('print'); + expect(observedInputs).to.be.deep.eq([ + // add newline? + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + // x + ['0x0000000000000000000000000000000000000000000000000000000000000002'], + // Type metadata + [ + '0x000000000000000000000000000000000000000000000000000000000000007b', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000006b', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000003a', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x0000000000000000000000000000000000000000000000000000000000000075', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000073', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x0000000000000000000000000000000000000000000000000000000000000067', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000074', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000067', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000072', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000002c', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x0000000000000000000000000000000000000000000000000000000000000077', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000074', + '0x0000000000000000000000000000000000000000000000000000000000000068', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000003a', + '0x0000000000000000000000000000000000000000000000000000000000000036', + '0x0000000000000000000000000000000000000000000000000000000000000034', + '0x000000000000000000000000000000000000000000000000000000000000007d', + ], + // format string? + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ]); + + expect(sum).to.be.eq('0x05'); + expect(constant).to.be.eq('0x03'); + expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] }); +}); From 219423eb87fa12bd8cca2a6fd2ce4c06e308783c Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:56:08 +0100 Subject: [PATCH 127/137] fix: handle multiple imports in the same file (#3903) # Description ## Problem\* Resolves #3889 ## Summary\* An import of an imported object in the same file would not work because the imports are added to the module after they are resolved. To fix this we simply process the imports one-by-one. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/hir/def_collector/dc_crate.rs | 60 +++++++++---------- .../src/hir/resolution/import.rs | 37 ++++++------ .../regression_3889/Nargo.toml | 7 +++ .../regression_3889/Prover.toml | 10 ++++ .../regression_3889/src/main.nr | 23 +++++++ 5 files changed, 85 insertions(+), 52 deletions(-) create mode 100644 test_programs/execution_success/regression_3889/Nargo.toml create mode 100644 test_programs/execution_success/regression_3889/Prover.toml create mode 100644 test_programs/execution_success/regression_3889/src/main.nr diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index ae061792125..8ada3faf756 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -4,7 +4,7 @@ use crate::graph::CrateId; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; -use crate::hir::resolution::import::{resolve_imports, ImportDirective}; +use crate::hir::resolution::import::{resolve_import, ImportDirective}; use crate::hir::resolution::resolver::Resolver; use crate::hir::resolution::{ collect_impls, collect_trait_impls, path_resolver, resolve_free_functions, resolve_globals, @@ -259,37 +259,33 @@ impl DefCollector { ); } - // Resolve unresolved imports collected from the crate - let (resolved, unresolved_imports) = - resolve_imports(crate_id, def_collector.collected_imports, &context.def_maps); - - { - let current_def_map = context.def_maps.get(&crate_id).unwrap(); - errors.extend(vecmap(unresolved_imports, |(error, module_id)| { - let file_id = current_def_map.file_id(module_id); - let error = DefCollectorErrorKind::PathResolutionError(error); - (error.into(), file_id) - })); - }; - - // Populate module namespaces according to the imports used - let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); - for resolved_import in resolved { - let name = resolved_import.name; - for ns in resolved_import.resolved_namespace.iter_defs() { - let result = current_def_map.modules[resolved_import.module_scope.0].import( - name.clone(), - ns, - resolved_import.is_prelude, - ); - - if let Err((first_def, second_def)) = result { - let err = DefCollectorErrorKind::Duplicate { - typ: DuplicateType::Import, - first_def, - second_def, - }; - errors.push((err.into(), root_file_id)); + // Resolve unresolved imports collected from the crate, one by one. + for collected_import in def_collector.collected_imports { + match resolve_import(crate_id, collected_import, &context.def_maps) { + Ok(resolved_import) => { + // Populate module namespaces according to the imports used + let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); + + let name = resolved_import.name; + for ns in resolved_import.resolved_namespace.iter_defs() { + let result = current_def_map.modules[resolved_import.module_scope.0] + .import(name.clone(), ns, resolved_import.is_prelude); + + if let Err((first_def, second_def)) = result { + let err = DefCollectorErrorKind::Duplicate { + typ: DuplicateType::Import, + first_def, + second_def, + }; + errors.push((err.into(), root_file_id)); + } + } + } + Err((error, module_id)) => { + let current_def_map = context.def_maps.get(&crate_id).unwrap(); + let file_id = current_def_map.file_id(module_id); + let error = DefCollectorErrorKind::PathResolutionError(error); + errors.push((error.into(), file_id)); } } } diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index 41fdac746bd..e6ac33053a0 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -1,4 +1,3 @@ -use iter_extended::partition_results; use noirc_errors::{CustomDiagnostic, Span}; use crate::graph::CrateId; @@ -51,29 +50,27 @@ impl From for CustomDiagnostic { } } -pub fn resolve_imports( +pub fn resolve_import( crate_id: CrateId, - imports_to_resolve: Vec, + import_directive: ImportDirective, def_maps: &BTreeMap, -) -> (Vec, Vec<(PathResolutionError, LocalModuleId)>) { +) -> Result { let def_map = &def_maps[&crate_id]; - partition_results(imports_to_resolve, |import_directive| { - let allow_contracts = - allow_referencing_contracts(def_maps, crate_id, import_directive.module_id); - - let module_scope = import_directive.module_id; - let resolved_namespace = - resolve_path_to_ns(&import_directive, def_map, def_maps, allow_contracts) - .map_err(|error| (error, module_scope))?; - - let name = resolve_path_name(&import_directive); - Ok(ResolvedImport { - name, - resolved_namespace, - module_scope, - is_prelude: import_directive.is_prelude, - }) + let allow_contracts = + allow_referencing_contracts(def_maps, crate_id, import_directive.module_id); + + let module_scope = import_directive.module_id; + let resolved_namespace = + resolve_path_to_ns(&import_directive, def_map, def_maps, allow_contracts) + .map_err(|error| (error, module_scope))?; + + let name = resolve_path_name(&import_directive); + Ok(ResolvedImport { + name, + resolved_namespace, + module_scope, + is_prelude: import_directive.is_prelude, }) } diff --git a/test_programs/execution_success/regression_3889/Nargo.toml b/test_programs/execution_success/regression_3889/Nargo.toml new file mode 100644 index 00000000000..d212d24473f --- /dev/null +++ b/test_programs/execution_success/regression_3889/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3889" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_3889/Prover.toml b/test_programs/execution_success/regression_3889/Prover.toml new file mode 100644 index 00000000000..a81ab67fe3e --- /dev/null +++ b/test_programs/execution_success/regression_3889/Prover.toml @@ -0,0 +1,10 @@ +[works] +a = "5" + +[fails] +a = "6" + + +[also_fails] +a = "7" + diff --git a/test_programs/execution_success/regression_3889/src/main.nr b/test_programs/execution_success/regression_3889/src/main.nr new file mode 100644 index 00000000000..10b8ecabee3 --- /dev/null +++ b/test_programs/execution_success/regression_3889/src/main.nr @@ -0,0 +1,23 @@ +mod Foo { + struct NewType{ + a: Field, + } +} + +mod Bar { + use crate::Foo::NewType as BarStruct; + use crate::Foo::NewType; +} + +mod Baz { + struct Works { + a: Field, + } + use crate::Bar::BarStruct; + use crate::Bar::NewType; +} + + +fn main(works: Baz::Works, fails: Baz::BarStruct, also_fails: Bar::NewType) -> pub Field { + works.a + fails.a + also_fails.a +} From a99e1f732de429b764547c0dd37e47a279c77c4f Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 4 Jan 2024 12:22:41 +0100 Subject: [PATCH 128/137] chore(debugger): Integration tests (#3938) # Description Adds integration tests for the debugger. ## Problem Related to #3015. Generates a new suite of tests that uses the examples at test_programs/execution_success to verify that the debugger can be started and stepped to completion with those examples. ## Summary We take the same approach used for the `nargo execute` cmd: generating test cases from those at test_programs/execution_success. This means future extensions to the Noir language captured in those examples will automatically be included in the debugger integration suite, and will help detect any potential divergence between the language runtime and the debugger instrumentation. ## Documentation Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- Cargo.lock | 38 +++++++++++++++++ tooling/debugger/Cargo.toml | 11 +++-- tooling/debugger/build.rs | 74 +++++++++++++++++++++++++++++++++ tooling/debugger/src/repl.rs | 1 + tooling/debugger/tests/debug.rs | 55 ++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 tooling/debugger/build.rs create mode 100644 tooling/debugger/tests/debug.rs diff --git a/Cargo.lock b/Cargo.lock index 5c507c8c5f2..3266f4e652e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -910,6 +910,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "comma" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" + [[package]] name = "console" version = "0.15.7" @@ -2753,6 +2759,20 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "libc", + "memoffset 0.6.5", + "pin-utils", +] + [[package]] name = "nix" version = "0.26.4" @@ -2769,6 +2789,8 @@ name = "noir_debugger" version = "0.22.0" dependencies = [ "acvm", + "assert_cmd", + "build-data", "codespan-reporting", "dap", "easy-repl", @@ -2778,8 +2800,11 @@ dependencies = [ "noirc_errors", "noirc_printable_type", "owo-colors", + "rexpect", + "rustc_version", "serde_json", "tempfile", + "test-binary", "thiserror", ] @@ -3692,6 +3717,19 @@ dependencies = [ "winreg", ] +[[package]] +name = "rexpect" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ff60778f96fb5a48adbe421d21bf6578ed58c0872d712e7e08593c195adff8" +dependencies = [ + "comma", + "nix 0.25.1", + "regex", + "tempfile", + "thiserror", +] + [[package]] name = "rfc6979" version = "0.3.1" diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index 0afe28727d1..4d37f801d78 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -6,7 +6,9 @@ authors.workspace = true edition.workspace = true license.workspace = true -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[build-dependencies] +rustc_version = "0.4.0" +build-data.workspace = true [dependencies] acvm.workspace = true @@ -22,5 +24,8 @@ easy-repl = "0.2.1" owo-colors = "3" serde_json.workspace = true -[dev_dependencies] -tempfile.workspace = true \ No newline at end of file +[dev-dependencies] +assert_cmd = "2.0.12" +rexpect = "0.5.0" +test-binary = "3.0.1" +tempfile.workspace = true diff --git a/tooling/debugger/build.rs b/tooling/debugger/build.rs new file mode 100644 index 00000000000..5d14ec2bae2 --- /dev/null +++ b/tooling/debugger/build.rs @@ -0,0 +1,74 @@ +use rustc_version::{version, Version}; +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +fn check_rustc_version() { + assert!( + version().unwrap() >= Version::parse("1.71.1").unwrap(), + "The minimal supported rustc version is 1.71.1." + ); +} + +const GIT_COMMIT: &&str = &"GIT_COMMIT"; + +fn main() { + // Rebuild if the tests have changed + println!("cargo:rerun-if-changed=tests"); + + check_rustc_version(); + + // Only use build_data if the environment variable isn't set + // The environment variable is always set when working via Nix + if std::env::var(GIT_COMMIT).is_err() { + build_data::set_GIT_COMMIT(); + build_data::set_GIT_DIRTY(); + build_data::no_debug_rebuilds(); + } + + let out_dir = env::var("OUT_DIR").unwrap(); + let destination = Path::new(&out_dir).join("debug.rs"); + let mut test_file = File::create(destination).unwrap(); + + // Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD + // is the root of the repository and append the crate path + let root_dir = match std::env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), + Err(_) => std::env::current_dir().unwrap(), + }; + let test_dir = root_dir.join("test_programs"); + + generate_debugger_tests(&mut test_file, &test_dir); +} + +fn generate_debugger_tests(test_file: &mut File, test_data_dir: &Path) { + let test_sub_dir = "execution_success"; + let test_data_dir = test_data_dir.join(test_sub_dir); + + let test_case_dirs = + fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); + + for test_dir in test_case_dirs { + let test_name = + test_dir.file_name().into_string().expect("Directory can't be converted to string"); + if test_name.contains('-') { + panic!( + "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" + ); + }; + let test_dir = &test_dir.path(); + + write!( + test_file, + r#" +#[test] +fn debug_{test_name}() {{ + debugger_execution_success("{test_dir}"); +}} + "#, + test_dir = test_dir.display(), + ) + .expect("Could not write templated test file."); + } +} diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index 8fbd10d8db6..b1af2bc2686 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -65,6 +65,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { ); } } + print_source_code_location(self.debug_artifact, &location); } } diff --git a/tooling/debugger/tests/debug.rs b/tooling/debugger/tests/debug.rs new file mode 100644 index 00000000000..b2f441f5606 --- /dev/null +++ b/tooling/debugger/tests/debug.rs @@ -0,0 +1,55 @@ +#[cfg(test)] +mod tests { + // Some of these imports are consumed by the injected tests + use assert_cmd::cargo::cargo_bin; + + use rexpect::spawn_bash; + + test_binary::build_test_binary_once!(mock_backend, "../backend_interface/test-binaries"); + + // include tests generated by `build.rs` + include!(concat!(env!("OUT_DIR"), "/debug.rs")); + + pub fn debugger_execution_success(test_program_dir: &str) { + let nargo_bin = + cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); + + let mock_backend_path = + path_to_mock_backend().into_string().expect("Cannot parse mock_backend path"); + + let mut dbg_session = spawn_bash(Some(10000)).expect("Could not start bash session"); + + dbg_session + .send_line(&format!("export NARGO_BACKEND_PATH={}", mock_backend_path)) + .expect("Could not export NARGO_BACKEND_PATH."); + dbg_session.wait_for_prompt().expect("Could not export NARGO_BACKEND_PATH."); + + // Start debugger and test that it loads for the given program. + dbg_session + .execute( + &format!("{} debug --program-dir {}", nargo_bin, test_program_dir), + &format!(".*\\Starting debugger.*"), + ) + .expect("Could not start debugger"); + + // While running the debugger, issue a "continue" cmd, + // which should run to the program to end given + // we haven't set any breakpoints. + // ">" is the debugger's prompt, so finding one + // after running "continue" indicates that the + // debugger has not panicked until the end of the program. + dbg_session + .send_line("c") + .expect("Debugger panicked while attempting to step through program."); + dbg_session + .exp_string(">") + .expect("Failed while waiting for debugger to step through program."); + + // Run the "quit" command, then check that the debugger confirms + // having successfully solved the circuit witness. + dbg_session.send_line("quit").expect("Failed to quit debugger"); + dbg_session + .exp_regex(&format!(".*Circuit witness successfully solved.*")) + .expect("Expected circuit witness to be successfully solved."); + } +} From 2c5eceb04ab6bc38e954492642121c7fe3da866f Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:26:29 +0000 Subject: [PATCH 129/137] fix: implement missing codegen for `BlackBoxFunc::EcdsaSecp256r1` in brillig (#3943) # Description ## Problem\* Resolves https://github.com/AztecProtocol/aztec-packages/issues/3822 ## Summary\* This PR adds codegen for the `BlackBoxFunc::EcdsaSecp256r1` in brillig and removes the catch-all branch when codegening black box functions. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../brillig/brillig_gen/brillig_black_box.rs | 35 ++++++++++++++++++- .../Nargo.toml | 2 +- .../Prover.toml | 0 .../src/main.nr | 9 +++-- .../brillig_ecdsa_secp256r1/Nargo.toml | 6 ++++ .../brillig_ecdsa_secp256r1/Prover.toml | 20 +++++++++++ .../brillig_ecdsa_secp256r1/src/main.nr | 16 +++++++++ 7 files changed, 84 insertions(+), 4 deletions(-) rename test_programs/execution_success/{brillig_ecdsa => brillig_ecdsa_secp256k1}/Nargo.toml (62%) rename test_programs/execution_success/{brillig_ecdsa => brillig_ecdsa_secp256k1}/Prover.toml (100%) rename test_programs/execution_success/{brillig_ecdsa => brillig_ecdsa_secp256k1}/src/main.nr (52%) create mode 100644 test_programs/execution_success/brillig_ecdsa_secp256r1/Nargo.toml create mode 100644 test_programs/execution_success/brillig_ecdsa_secp256r1/Prover.toml create mode 100644 test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 9979bf0cd29..542c23fcd2e 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -92,6 +92,28 @@ pub(crate) fn convert_black_box_call( ) } } + BlackBoxFunc::EcdsaSecp256r1 => { + if let ( + [BrilligVariable::BrilligArray(public_key_x), BrilligVariable::BrilligArray(public_key_y), BrilligVariable::BrilligArray(signature), message], + [BrilligVariable::Simple(result_register)], + ) = (function_arguments, function_results) + { + let message_hash_vector = + convert_array_or_vector(brillig_context, message, bb_func); + brillig_context.black_box_op_instruction(BlackBoxOp::EcdsaSecp256r1 { + hashed_msg: message_hash_vector.to_heap_vector(), + public_key_x: public_key_x.to_heap_array(), + public_key_y: public_key_y.to_heap_array(), + signature: signature.to_heap_array(), + result: *result_register, + }); + } else { + unreachable!( + "ICE: EcdsaSecp256r1 expects four array arguments and one register result" + ) + } + } + BlackBoxFunc::PedersenCommitment => { if let ( [message, BrilligVariable::Simple(domain_separator)], @@ -160,7 +182,18 @@ pub(crate) fn convert_black_box_call( ) } } - _ => unimplemented!("ICE: Black box function {:?} is not implemented", bb_func), + BlackBoxFunc::AND => { + unreachable!("ICE: `BlackBoxFunc::AND` calls should be transformed into a `BinaryOp`") + } + BlackBoxFunc::XOR => { + unreachable!("ICE: `BlackBoxFunc::XOR` calls should be transformed into a `BinaryOp`") + } + BlackBoxFunc::RANGE => unreachable!( + "ICE: `BlackBoxFunc::RANGE` calls should be transformed into a `Instruction::Cast`" + ), + BlackBoxFunc::RecursiveAggregation => unimplemented!( + "ICE: `BlackBoxFunc::RecursiveAggregation` is not implemented by the Brillig VM" + ), } } diff --git a/test_programs/execution_success/brillig_ecdsa/Nargo.toml b/test_programs/execution_success/brillig_ecdsa_secp256k1/Nargo.toml similarity index 62% rename from test_programs/execution_success/brillig_ecdsa/Nargo.toml rename to test_programs/execution_success/brillig_ecdsa_secp256k1/Nargo.toml index 972dd9ce93b..495a49f2247 100644 --- a/test_programs/execution_success/brillig_ecdsa/Nargo.toml +++ b/test_programs/execution_success/brillig_ecdsa_secp256k1/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_ecdsa" +name = "brillig_ecdsa_secp256k1" type = "bin" authors = [""] diff --git a/test_programs/execution_success/brillig_ecdsa/Prover.toml b/test_programs/execution_success/brillig_ecdsa_secp256k1/Prover.toml similarity index 100% rename from test_programs/execution_success/brillig_ecdsa/Prover.toml rename to test_programs/execution_success/brillig_ecdsa_secp256k1/Prover.toml diff --git a/test_programs/execution_success/brillig_ecdsa/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr similarity index 52% rename from test_programs/execution_success/brillig_ecdsa/src/main.nr rename to test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr index 23f017aa336..5d84d885567 100644 --- a/test_programs/execution_success/brillig_ecdsa/src/main.nr +++ b/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr @@ -2,10 +2,15 @@ use dep::std; // Tests a very simple program. // // The features being tested is ecdsa in brillig -fn main(hashed_message: [u8;32], pub_key_x: [u8;32], pub_key_y: [u8;32], signature: [u8;64]) { +fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { assert(ecdsa(hashed_message, pub_key_x, pub_key_y, signature)); } -unconstrained fn ecdsa(hashed_message: [u8;32], pub_key_x: [u8;32], pub_key_y: [u8;32], signature: [u8;64]) -> bool { +unconstrained fn ecdsa( + hashed_message: [u8; 32], + pub_key_x: [u8; 32], + pub_key_y: [u8; 32], + signature: [u8; 64] +) -> bool { std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/Nargo.toml b/test_programs/execution_success/brillig_ecdsa_secp256r1/Nargo.toml new file mode 100644 index 00000000000..0a71e782104 --- /dev/null +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_ecdsa_secp256r1" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/Prover.toml b/test_programs/execution_success/brillig_ecdsa_secp256r1/Prover.toml new file mode 100644 index 00000000000..a45f799877b --- /dev/null +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/Prover.toml @@ -0,0 +1,20 @@ +hashed_message = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] + + diff --git a/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr new file mode 100644 index 00000000000..9da07f531aa --- /dev/null +++ b/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr @@ -0,0 +1,16 @@ +use dep::std; +// Tests a very simple program. +// +// The features being tested is ecdsa in brillig +fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { + assert(ecdsa(hashed_message, pub_key_x, pub_key_y, signature)); +} + +unconstrained fn ecdsa( + hashed_message: [u8; 32], + pub_key_x: [u8; 32], + pub_key_y: [u8; 32], + signature: [u8; 64] +) -> bool { + std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) +} From afe9c7a38bb9d4245205d3aa46d4ce23d70a5671 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 4 Jan 2024 12:45:23 +0000 Subject: [PATCH 130/137] feat: remove range constraints from witnesses which are constrained to be constants (#3928) # Description ## Problem\* Resolves ## Summary\* A range constraint is a weaker constraint than directly asserting the witness to be equal to a value (as long as that value fits within the set number of bits). We can then remove range constraints from these witnesses. I've made sure to keep any range constraints which would conflict with the constant witness assignment. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../compiler/optimizers/redundant_range.rs | 79 +++++++++++++------ 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 7b40c35960a..5d19f9629ba 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -48,25 +48,51 @@ impl RangeOptimizer { /// only store the fact that we have constrained it to /// be 16 bits. fn collect_ranges(circuit: &Circuit) -> BTreeMap { - let mut witness_to_bit_sizes = BTreeMap::new(); + let mut witness_to_bit_sizes: BTreeMap = BTreeMap::new(); for opcode in &circuit.opcodes { - // Extract the witness index and number of bits, - // if it is a range constraint - let (witness, num_bits) = match extract_range_opcode(opcode) { - Some(func_inputs) => func_inputs, - None => continue, + let Some((witness, num_bits)) = (match opcode { + Opcode::AssertZero(expr) => { + // If the opcode is constraining a witness to be equal to a value then it can be considered + // as a range opcode for the number of bits required to hold that value. + if expr.is_degree_one_univariate() { + let (k, witness) = expr.linear_combinations[0]; + let constant = expr.q_c; + let witness_value = -constant / k; + + if witness_value.is_zero() { + Some((witness, 0)) + } else { + // We subtract off 1 bit from the implied witness value to give the weakest range constraint + // which would be stricter than the constraint imposed by this opcode. + let implied_range_constraint_bits = witness_value.num_bits() - 1; + Some((witness, implied_range_constraint_bits)) + } + } else { + None + } + } + + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { + input: FunctionInput { witness, num_bits }, + }) => { + Some((*witness, *num_bits)) + } + + _ => None, + }) else { + continue; }; // Check if the witness has already been recorded and if the witness // size is more than the current one, we replace it - let should_replace = match witness_to_bit_sizes.get(&witness).copied() { - Some(old_range_bits) => old_range_bits > num_bits, - None => true, - }; - if should_replace { - witness_to_bit_sizes.insert(witness, num_bits); - } + witness_to_bit_sizes + .entry(witness) + .and_modify(|old_range_bits| { + *old_range_bits = std::cmp::min(*old_range_bits, num_bits); + }) + .or_insert(num_bits); } witness_to_bit_sizes } @@ -116,16 +142,10 @@ impl RangeOptimizer { /// Extract the range opcode from the `Opcode` enum /// Returns None, if `Opcode` is not the range opcode. fn extract_range_opcode(opcode: &Opcode) -> Option<(Witness, u32)> { - // Range constraints are blackbox function calls - // so we first extract the function call - let func_call = match opcode { - acir::circuit::Opcode::BlackBoxFuncCall(func_call) => func_call, - _ => return None, - }; - - // Skip if it is not a range constraint - match func_call { - BlackBoxFuncCall::RANGE { input } => Some((input.witness, input.num_bits)), + match opcode { + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { + Some((input.witness, input.num_bits)) + } _ => None, } } @@ -246,4 +266,17 @@ mod tests { let (optimized_circuit, _) = optimizer.replace_redundant_ranges(acir_opcode_positions); assert_eq!(optimized_circuit.opcodes.len(), 5); } + + #[test] + fn constant_implied_ranges() { + // The optimizer should use knowledge about constant witness assignments to remove range opcodes. + let mut circuit = test_circuit(vec![(Witness(1), 16)]); + + circuit.opcodes.push(Opcode::AssertZero(Witness(1).into())); + let acir_opcode_positions = circuit.opcodes.iter().enumerate().map(|(i, _)| i).collect(); + let optimizer = RangeOptimizer::new(circuit); + let (optimized_circuit, _) = optimizer.replace_redundant_ranges(acir_opcode_positions); + assert_eq!(optimized_circuit.opcodes.len(), 1); + assert_eq!(optimized_circuit.opcodes[0], Opcode::AssertZero(Witness(1).into())); + } } From 4a2140f1f36bbe3afbc006f8db74820308ae27d5 Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:50:08 +0100 Subject: [PATCH 131/137] feat(lsp): cache definitions for goto requests (#3930) # Description ## Problem\* Goto Definitions still take take too much time to execute leaving user with undesirable experience. On a bigger workspace (beyond simple test cases, eg. [noir-protocol-circuits](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-protocol-circuits)) it can take as much as a second or more to perform goto request. Resolves chore(lsp): improve goto performance by caching ast #3942 ## Summary\* Improvement from `~1s` down to `~11ms` on example project [noir-protocol-circuits](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-protocol-circuits) is achieved by caching definitions resolved during file save or file open. The cost for this optimisation is when user opens noir source file, at which point parsing and resolving is done. This however is not noticeable for user as source code can be seen and operated on. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/hir/mod.rs | 8 --- compiler/noirc_frontend/src/node_interner.rs | 8 ++- tooling/lsp/src/lib.rs | 5 ++ tooling/lsp/src/notifications/mod.rs | 67 ++++++++++++-------- tooling/lsp/src/requests/goto_definition.rs | 15 +++-- 5 files changed, 65 insertions(+), 38 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index 25875385fd9..3683b17a27c 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -194,14 +194,6 @@ impl Context<'_> { .collect() } - /// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId]. - /// Returns [None] when definition is not found. - pub fn get_definition_location_from(&self, location: Location) -> Option { - let interner = &self.def_interner; - - interner.find_location_index(location).and_then(|index| interner.resolve_location(index)) - } - /// Return a Vec of all `contract` declarations in the source code and the functions they contain pub fn get_all_contracts(&self, crate_id: &CrateId) -> Vec { self.def_map(crate_id) diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 7c42e279916..9082df1bcd5 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1271,10 +1271,16 @@ impl NodeInterner { self.selected_trait_implementations.get(&ident_id).cloned() } + /// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId]. + /// Returns [None] when definition is not found. + pub fn get_definition_location_from(&self, location: Location) -> Option { + self.find_location_index(location).and_then(|index| self.resolve_location(index)) + } + /// For a given [Index] we return [Location] to which we resolved to /// We currently return None for features not yet implemented /// TODO(#3659): LSP goto def should error when Ident at Location could not resolve - pub(crate) fn resolve_location(&self, index: impl Into) -> Option { + fn resolve_location(&self, index: impl Into) -> Option { let node = self.nodes.get(index.into())?; match node { diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 90e8e563cd3..271e1e40df3 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -25,6 +25,7 @@ use noirc_driver::{file_manager_with_stdlib, prepare_crate, NOIR_ARTIFACT_VERSIO use noirc_frontend::{ graph::{CrateId, CrateName}, hir::{Context, FunctionNameMatch}, + node_interner::NodeInterner, }; use notifications::{ @@ -59,8 +60,10 @@ pub struct LspState { root_path: Option, client: ClientSocket, solver: WrapperSolver, + open_documents_count: usize, input_files: HashMap, cached_lenses: HashMap>, + cached_definitions: HashMap, } impl LspState { @@ -71,6 +74,8 @@ impl LspState { solver: WrapperSolver(Box::new(solver)), input_files: HashMap::new(), cached_lenses: HashMap::new(), + cached_definitions: HashMap::new(), + open_documents_count: 0, } } } diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 6cefaa134ce..aec3bf61f4e 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -36,7 +36,16 @@ pub(super) fn on_did_open_text_document( params: DidOpenTextDocumentParams, ) -> ControlFlow> { state.input_files.insert(params.text_document.uri.to_string(), params.text_document.text); - ControlFlow::Continue(()) + + let document_uri = params.text_document.uri; + + match process_noir_document(document_uri, state) { + Ok(_) => { + state.open_documents_count += 1; + ControlFlow::Continue(()) + } + Err(err) => ControlFlow::Break(Err(err)), + } } pub(super) fn on_did_change_text_document( @@ -85,6 +94,13 @@ pub(super) fn on_did_close_text_document( ) -> ControlFlow> { state.input_files.remove(¶ms.text_document.uri.to_string()); state.cached_lenses.remove(¶ms.text_document.uri.to_string()); + + state.open_documents_count -= 1; + + if state.open_documents_count == 0 { + state.cached_definitions.clear(); + } + ControlFlow::Continue(()) } @@ -92,27 +108,25 @@ pub(super) fn on_did_save_text_document( state: &mut LspState, params: DidSaveTextDocumentParams, ) -> ControlFlow> { - let file_path = match params.text_document.uri.to_file_path() { - Ok(file_path) => file_path, - Err(()) => { - return ControlFlow::Break(Err(ResponseError::new( - ErrorCode::REQUEST_FAILED, - "URI is not a valid file path", - ) - .into())) - } - }; + let document_uri = params.text_document.uri; - let workspace = match resolve_workspace_for_source_path(&file_path) { - Ok(value) => value, - Err(lsp_error) => { - return ControlFlow::Break(Err(ResponseError::new( - ErrorCode::REQUEST_FAILED, - lsp_error.to_string(), - ) - .into())) - } - }; + match process_noir_document(document_uri, state) { + Ok(_) => ControlFlow::Continue(()), + Err(err) => ControlFlow::Break(Err(err)), + } +} + +fn process_noir_document( + document_uri: lsp_types::Url, + state: &mut LspState, +) -> Result<(), async_lsp::Error> { + let file_path = document_uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(&file_path).map_err(|lsp_error| { + ResponseError::new(ErrorCode::REQUEST_FAILED, lsp_error.to_string()) + })?; let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); @@ -127,6 +141,8 @@ pub(super) fn on_did_save_text_document( Err(errors_and_warnings) => errors_and_warnings, }; + let package_root_dir: String = package.root_dir.as_os_str().to_string_lossy().into(); + // We don't add test headings for a package if it contains no `#[test]` functions if let Some(tests) = get_package_tests_in_crate(&context, &crate_id, &package.name) { let _ = state.client.notify::(NargoPackageTests { @@ -142,7 +158,9 @@ pub(super) fn on_did_save_text_document( package, Some(&file_path), ); - state.cached_lenses.insert(params.text_document.uri.to_string(), collected_lenses); + state.cached_lenses.insert(document_uri.to_string(), collected_lenses); + + state.cached_definitions.insert(package_root_dir, context.def_interner); let fm = &context.file_manager; let files = fm.as_file_map(); @@ -178,14 +196,13 @@ pub(super) fn on_did_save_text_document( .collect() }) .collect(); - let _ = state.client.publish_diagnostics(PublishDiagnosticsParams { - uri: params.text_document.uri, + uri: document_uri, version: None, diagnostics, }); - ControlFlow::Continue(()) + Ok(()) } pub(super) fn on_exit( diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index d2b66682d89..2ff5901ff9c 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -29,20 +29,27 @@ fn on_goto_definition_inner( let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); let package = workspace.members.first().unwrap(); + let package_root_path: String = package.root_dir.as_os_str().to_string_lossy().into(); + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, package); - // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); + let interner; + if let Some(def_interner) = _state.cached_definitions.get(&package_root_path) { + interner = def_interner; + } else { + // We ignore the warnings and errors produced by compilation while resolving the definition + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); + interner = &context.def_interner; + } let files = context.file_manager.as_file_map(); let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( ErrorCode::REQUEST_FAILED, format!("Could not find file in file manager. File path: {:?}", file_path), ))?; - let byte_index = position_to_byte_index(files, file_id, ¶ms.text_document_position_params.position) .map_err(|err| { @@ -58,7 +65,7 @@ fn on_goto_definition_inner( }; let goto_definition_response = - context.get_definition_location_from(search_for_location).and_then(|found_location| { + interner.get_definition_location_from(search_for_location).and_then(|found_location| { let file_id = found_location.file; let definition_position = to_lsp_location(files, file_id, found_location.span)?; let response: GotoDefinitionResponse = From cc4f3a3b147037343e894dc525582ed923199a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Thu, 4 Jan 2024 14:13:25 +0000 Subject: [PATCH 132/137] chore: fixing links to the blackbox functions (#3941) ## Problem\* Links to blackbox functions were pointing to the old ACVM repo ## Summary\* Fixes them to point to the right place --- docs/docs/noir/standard_library/black_box_fns.md | 2 +- .../version-v0.17.0/standard_library/black_box_fns.md | 2 +- .../version-v0.19.0/standard_library/black_box_fns.md | 2 +- .../version-v0.19.1/standard_library/black_box_fns.md | 2 +- .../version-v0.19.2/standard_library/black_box_fns.md | 2 +- .../version-v0.19.3/standard_library/black_box_fns.md | 2 +- .../version-v0.19.4/standard_library/black_box_fns.md | 2 +- .../version-v0.22.0/noir/standard_library/black_box_fns.md | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/docs/noir/standard_library/black_box_fns.md b/docs/docs/noir/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/docs/noir/standard_library/black_box_fns.md +++ b/docs/docs/noir/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md index c758846b688..a412de19d06 100644 --- a/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md @@ -42,4 +42,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md index 1dfabfe8f22..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md @@ -43,4 +43,4 @@ Here is a list of the current black box functions that are supported by UltraPlo Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). From abf751ab7f57f87520be16b2bc6168efdf95a430 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:29:44 +0000 Subject: [PATCH 133/137] feat: implement `Eq` trait on curve points (#3944) # Description ## Problem\* Resolves ## Summary\* This PR just moves the `eq` methods on the ec point structs into `Eq` trait impls. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: jfecher --- noir_stdlib/src/ec/montcurve.nr | 25 ++++++++++++--------- noir_stdlib/src/ec/swcurve.nr | 40 +++++++++++++++++++-------------- noir_stdlib/src/ec/tecurve.nr | 38 ++++++++++++++++++------------- 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/noir_stdlib/src/ec/montcurve.nr b/noir_stdlib/src/ec/montcurve.nr index 82d22837b46..83a17bae322 100644 --- a/noir_stdlib/src/ec/montcurve.nr +++ b/noir_stdlib/src/ec/montcurve.nr @@ -12,6 +12,8 @@ mod affine { use crate::ec::safe_inverse; use crate::ec::sqrt; use crate::ec::ZETA; + use crate::cmp::Eq; + // Curve specification struct Curve { // Montgomery Curve configuration (ky^2 = x^3 + j*x^2 + x) j: Field, @@ -32,11 +34,6 @@ mod affine { Self {x, y, infty: false} } - // Check for equality - fn eq(self, p: Self) -> bool { - (self.infty & p.infty) | (!self.infty & !p.infty & (self.x == p.x) & (self.y == p.y)) - } - // Check if zero pub fn is_zero(self) -> bool { self.infty @@ -76,6 +73,12 @@ mod affine { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + (self.infty & p.infty) | (!self.infty & !p.infty & (self.x == p.x) & (self.y == p.y)) + } + } + impl Curve { // Curve constructor pub fn new(j: Field, k: Field, gen: Point) -> Self { @@ -219,6 +222,7 @@ mod curvegroup { use crate::ec::swcurve::curvegroup::Point as SWPoint; use crate::ec::tecurve::curvegroup::Curve as TECurve; use crate::ec::tecurve::curvegroup::Point as TEPoint; + use crate::cmp::Eq; struct Curve { // Montgomery Curve configuration (ky^2 z = x*(x^2 + j*x*z + z*z)) j: Field, @@ -239,11 +243,6 @@ mod curvegroup { Self {x, y, z} } - // Check for equality - fn eq(self, p: Self) -> bool { - (self.z == p.z) | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z))) - } - // Check if zero pub fn is_zero(self) -> bool { self.z == 0 @@ -277,6 +276,12 @@ mod curvegroup { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + (self.z == p.z) | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z))) + } + } + impl Curve { // Curve constructor pub fn new(j: Field, k: Field, gen: Point) -> Self { diff --git a/noir_stdlib/src/ec/swcurve.nr b/noir_stdlib/src/ec/swcurve.nr index e9b6f661843..e64f5a7be02 100644 --- a/noir_stdlib/src/ec/swcurve.nr +++ b/noir_stdlib/src/ec/swcurve.nr @@ -7,6 +7,8 @@ mod affine { use crate::ec::safe_inverse; use crate::ec::is_square; use crate::ec::sqrt; + use crate::cmp::Eq; + // Curve specification struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + ax + b @@ -28,15 +30,6 @@ mod affine { Self {x, y, infty: false} } - // Check for equality - fn eq(self, p: Point) -> bool { - let Self {x: x1, y: y1, infty: inf1} = self; - let Self {x: x2, y: y2, infty: inf2} = p; - - (inf1 & inf2) - | (!inf1 & !inf2 & (x1 == x2) & (y1 == y2)) - } - // Check if zero pub fn is_zero(self) -> bool { self.eq(Point::zero()) @@ -65,6 +58,16 @@ mod affine { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + let Self {x: x1, y: y1, infty: inf1} = self; + let Self {x: x2, y: y2, infty: inf2} = p; + + (inf1 & inf2) + | (!inf1 & !inf2 & (x1 == x2) & (y1 == y2)) + } + } + impl Curve { // Curve constructor pub fn new(a: Field, b: Field, gen: Point) -> Curve { @@ -182,6 +185,8 @@ mod curvegroup { // Points are represented by three-dimensional Jacobian coordinates. // See for details. use crate::ec::swcurve::affine; + use crate::cmp::Eq; + // Curve specification struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + axz^4 + bz^6 @@ -203,14 +208,6 @@ mod curvegroup { Self {x, y, z} } - // Check for equality - fn eq(self, p: Point) -> bool { - let Self {x: x1, y: y1, z: z1} = self; - let Self {x: x2, y: y2, z: z2} = p; - - ((z1 == 0) & (z2 == 0)) | ((z1 != 0) & (z2 != 0) & (x1*z2*z2 == x2*z1*z1) & (y1*z2*z2*z2 == y2*z1*z1*z1)) - } - // Check if zero pub fn is_zero(self) -> bool { self.eq(Point::zero()) @@ -240,6 +237,15 @@ mod curvegroup { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + let Self {x: x1, y: y1, z: z1} = self; + let Self {x: x2, y: y2, z: z2} = p; + + ((z1 == 0) & (z2 == 0)) | ((z1 != 0) & (z2 != 0) & (x1*z2*z2 == x2*z1*z1) & (y1*z2*z2*z2 == y2*z1*z1*z1)) + } + } + impl Curve { // Curve constructor pub fn new(a: Field, b: Field, gen: Point) -> Curve { diff --git a/noir_stdlib/src/ec/tecurve.nr b/noir_stdlib/src/ec/tecurve.nr index 849b45ff012..5333ece4c4a 100644 --- a/noir_stdlib/src/ec/tecurve.nr +++ b/noir_stdlib/src/ec/tecurve.nr @@ -9,6 +9,8 @@ mod affine { use crate::ec::montcurve::affine::Point as MPoint; use crate::ec::swcurve::affine::Curve as SWCurve; use crate::ec::swcurve::affine::Point as SWPoint; + use crate::cmp::Eq; + // Curve specification struct Curve { // Twisted Edwards curve // Coefficients in defining equation ax^2 + y^2 = 1 + dx^2y^2 @@ -29,14 +31,6 @@ mod affine { Self { x, y } } - // Check for equality - fn eq(self, p: Point) -> bool { - let Self {x: x1, y: y1} = self; - let Self {x: x2, y: y2} = p; - - (x1 == x2) & (y1 == y2) - } - // Check if zero pub fn is_zero(self) -> bool { self.eq(Point::zero()) @@ -74,6 +68,15 @@ mod affine { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + let Self {x: x1, y: y1} = self; + let Self {x: x2, y: y2} = p; + + (x1 == x2) & (y1 == y2) + } + } + impl Curve { // Curve constructor pub fn new(a: Field, d: Field, gen: Point) -> Curve { @@ -198,6 +201,8 @@ mod curvegroup { use crate::ec::montcurve::curvegroup::Point as MPoint; use crate::ec::swcurve::curvegroup::Curve as SWCurve; use crate::ec::swcurve::curvegroup::Point as SWPoint; + use crate::cmp::Eq; + // Curve specification struct Curve { // Twisted Edwards curve // Coefficients in defining equation a(x^2 + y^2)z^2 = z^4 + dx^2y^2 @@ -220,14 +225,6 @@ mod curvegroup { Self {x, y, t, z} } - // Check for equality - fn eq(self, p: Point) -> bool { - let Self {x: x1, y: y1, t: _t1, z: z1} = self; - let Self {x: x2, y: y2, t: _t2, z:z2} = p; - - (x1*z2 == x2*z1) & (y1*z2 == y2*z1) - } - // Check if zero pub fn is_zero(self) -> bool { let Self {x, y, t, z} = self; @@ -259,6 +256,15 @@ mod curvegroup { } } + impl Eq for Point { + fn eq(self, p: Self) -> bool { + let Self {x: x1, y: y1, t: _t1, z: z1} = self; + let Self {x: x2, y: y2, t: _t2, z:z2} = p; + + (x1*z2 == x2*z1) & (y1*z2 == y2*z1) + } + } + impl Curve { // Curve constructor pub fn new(a: Field, d: Field, gen: Point) -> Curve { From 1111465551557ed9e97e4b43d6eccc4b5896a39f Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:29:32 +0000 Subject: [PATCH 134/137] fix: preserve brillig entrypoint functions without arguments (#3951) # Description ## Problem\* Resolves ## Summary\* This PR turns off the optimistic execution of brillig functions for which all arguments are known at compile time when that brillig function is the program entrypoint. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 16 ++++++++++++---- compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 5 ++++- .../brillig_set_slice_of_slice/Nargo.toml | 0 .../brillig_set_slice_of_slice/src/main.nr | 0 .../brillig_to_bits/Nargo.toml | 0 .../brillig_to_bits/src/main.nr | 0 .../unconstrained_empty/Nargo.toml | 0 .../unconstrained_empty/src/main.nr | 0 8 files changed, 16 insertions(+), 5 deletions(-) rename test_programs/{compile_success_empty => execution_success}/brillig_set_slice_of_slice/Nargo.toml (100%) rename test_programs/{compile_success_empty => execution_success}/brillig_set_slice_of_slice/src/main.nr (100%) rename test_programs/{compile_success_empty => execution_success}/brillig_to_bits/Nargo.toml (100%) rename test_programs/{compile_success_empty => execution_success}/brillig_to_bits/src/main.nr (100%) rename test_programs/{compile_success_empty => execution_success}/unconstrained_empty/Nargo.toml (100%) rename test_programs/{compile_success_empty => execution_success}/unconstrained_empty/src/main.nr (100%) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 3bc99b4d054..ddafc0bb570 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -307,6 +307,7 @@ impl AcirContext { inverse_code, vec![AcirValue::Var(var, AcirType::field())], vec![AcirType::field()], + true, )?; let inverted_var = Self::expect_one_var(results); @@ -708,6 +709,7 @@ impl AcirContext { AcirValue::Var(rhs, AcirType::unsigned(bit_size)), ], vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)], + true, )? .try_into() .expect("quotient only returns two values"); @@ -1310,6 +1312,7 @@ impl AcirContext { generated_brillig: GeneratedBrillig, inputs: Vec, outputs: Vec, + attempt_execution: bool, ) -> Result, InternalError> { let b_inputs = try_vecmap(inputs, |i| match i { AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), @@ -1329,10 +1332,15 @@ impl AcirContext { // Optimistically try executing the brillig now, if we can complete execution they just return the results. // This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066) - if let Some(brillig_outputs) = - self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) - { - return Ok(brillig_outputs); + // + // We do _not_ want to do this in the situation where the `main` function is unconstrained, as if execution succeeds + // the entire program will be replaced with witness constraints to its outputs. + if attempt_execution { + if let Some(brillig_outputs) = + self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) + { + return Ok(brillig_outputs); + } } // Otherwise we must generate ACIR for it and execute at runtime. diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 33f00796c9d..edf0461430f 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -266,11 +266,14 @@ impl Context { let code = self.gen_brillig_for(main_func, &brillig)?; + // We specifically do not attempt execution of the brillig code being generated as this can result in it being + // replaced with constraints on witnesses to the program outputs. let output_values = self.acir_context.brillig( self.current_side_effects_enabled_var, code, inputs, outputs, + false, )?; let output_vars: Vec<_> = output_values .iter() @@ -489,7 +492,7 @@ impl Context { let outputs: Vec = vecmap(result_ids, |result_id| dfg.type_of_value(*result_id).into()); - let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs)?; + let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs, true)?; // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); diff --git a/test_programs/compile_success_empty/brillig_set_slice_of_slice/Nargo.toml b/test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/brillig_set_slice_of_slice/Nargo.toml rename to test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml diff --git a/test_programs/compile_success_empty/brillig_set_slice_of_slice/src/main.nr b/test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/brillig_set_slice_of_slice/src/main.nr rename to test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr diff --git a/test_programs/compile_success_empty/brillig_to_bits/Nargo.toml b/test_programs/execution_success/brillig_to_bits/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/brillig_to_bits/Nargo.toml rename to test_programs/execution_success/brillig_to_bits/Nargo.toml diff --git a/test_programs/compile_success_empty/brillig_to_bits/src/main.nr b/test_programs/execution_success/brillig_to_bits/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/brillig_to_bits/src/main.nr rename to test_programs/execution_success/brillig_to_bits/src/main.nr diff --git a/test_programs/compile_success_empty/unconstrained_empty/Nargo.toml b/test_programs/execution_success/unconstrained_empty/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/unconstrained_empty/Nargo.toml rename to test_programs/execution_success/unconstrained_empty/Nargo.toml diff --git a/test_programs/compile_success_empty/unconstrained_empty/src/main.nr b/test_programs/execution_success/unconstrained_empty/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/unconstrained_empty/src/main.nr rename to test_programs/execution_success/unconstrained_empty/src/main.nr From eb566e2125e847a3e3efbd2bc15a88a1c454a7df Mon Sep 17 00:00:00 2001 From: Koby Hall <102518238+kobyhallx@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:27:57 +0100 Subject: [PATCH 135/137] feat(lsp): goto trait from trait impl (#3956) # Description ## Problem\* Resolves feat(lsp): goto definition of trait #3725 ## Summary\* Allows to go to Trait definition from Trait Implementation. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/hir_def/traits.rs | 4 +-- compiler/noirc_frontend/src/node_interner.rs | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/traits.rs b/compiler/noirc_frontend/src/hir_def/traits.rs index ea9c2e2928c..7bf5870e1f5 100644 --- a/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/compiler/noirc_frontend/src/hir_def/traits.rs @@ -6,7 +6,7 @@ use crate::{ Generics, Ident, NoirFunction, Type, TypeVariable, TypeVariableId, }; use fm::FileId; -use noirc_errors::Span; +use noirc_errors::{Location, Span}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct TraitFunction { @@ -56,7 +56,7 @@ pub struct Trait { pub name: Ident, pub generics: Generics, - pub span: Span, + pub location: Location, /// When resolving the types of Trait elements, all references to `Self` resolve /// to this TypeVariable. Then when we check if the types of trait impl elements diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 9082df1bcd5..261b11158cf 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -468,6 +468,7 @@ impl NodeInterner { /// The [Location] may not necessarily point to the beginning of the item /// so we check if the location's span is contained within the start or end /// of each items [Span] + #[tracing::instrument(skip(self))] pub fn find_location_index(&self, location: Location) -> Option> { let mut location_candidate: Option<(&Index, &Location)> = None; @@ -504,7 +505,7 @@ impl NodeInterner { id: type_id, name: unresolved_trait.trait_def.name.clone(), crate_id: unresolved_trait.crate_id, - span: unresolved_trait.trait_def.span, + location: Location::new(unresolved_trait.trait_def.span, unresolved_trait.file_id), generics: vecmap(&unresolved_trait.trait_def.generics, |_| { // Temporary type variable ids before the trait is resolved to its actual ids. // This lets us record how many arguments the type expects so that other types @@ -1142,6 +1143,7 @@ impl NodeInterner { } /// Adds a trait implementation to the list of known implementations. + #[tracing::instrument(skip(self))] pub fn add_trait_implementation( &mut self, object_type: Type, @@ -1274,7 +1276,9 @@ impl NodeInterner { /// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId]. /// Returns [None] when definition is not found. pub fn get_definition_location_from(&self, location: Location) -> Option { - self.find_location_index(location).and_then(|index| self.resolve_location(index)) + self.find_location_index(location) + .and_then(|index| self.resolve_location(index)) + .or_else(|| self.try_resolve_trait_impl_location(location)) } /// For a given [Index] we return [Location] to which we resolved to @@ -1429,6 +1433,24 @@ impl NodeInterner { pub(crate) fn ordering_type(&self) -> Type { self.ordering_type.clone().expect("Expected ordering_type to be set in the NodeInterner") } + + /// Attempts to resolve [Location] of [Trait] based on [Location] of [TraitImpl] + /// This is used by LSP to resolve the location of a trait based on the location of a trait impl. + /// + /// Example: + /// impl Foo for Bar { ... } -> trait Foo { ... } + fn try_resolve_trait_impl_location(&self, location: Location) -> Option { + self.trait_implementations + .iter() + .find(|shared_trait_impl| { + let trait_impl = shared_trait_impl.borrow(); + trait_impl.file == location.file && trait_impl.ident.span().contains(&location.span) + }) + .and_then(|shared_trait_impl| { + let trait_impl = shared_trait_impl.borrow(); + self.traits.get(&trait_impl.trait_id).map(|trait_| trait_.location) + }) + } } impl Methods { From 6efc2d92b5ce1283aa85fdb83db98d3c90091b38 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:42:59 +0000 Subject: [PATCH 136/137] chore: remove usage of term "preprocessed" in favour of "artifact" (#3939) # Description ## Problem\* Resolves ## Summary\* This PR renames `PreprocessedProgram` to `ProgramArtifact` in order to be more accurate. ## Additional Context I'll likely embed `DebugArtifact` inside `ProgramArtifact` in future. ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: kevaundray --- compiler/wasm/src/compile.rs | 52 ++++++++---------------- compiler/wasm/src/compile_new.rs | 8 ++-- tooling/nargo/src/artifacts/contract.rs | 25 ++++++++---- tooling/nargo/src/artifacts/program.rs | 21 ++++++---- tooling/nargo_cli/src/cli/compile_cmd.rs | 40 ++++++++---------- tooling/nargo_cli/src/cli/fs/program.rs | 14 +++---- 6 files changed, 75 insertions(+), 85 deletions(-) diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index c6ae0ae1f42..54fdccf1369 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -2,9 +2,9 @@ use fm::FileManager; use gloo_utils::format::JsValueSerdeExt; use js_sys::{JsString, Object}; use nargo::artifacts::{ - contract::{PreprocessedContract, PreprocessedContractFunction}, + contract::{ContractArtifact, ContractFunctionArtifact}, debug::DebugArtifact, - program::PreprocessedProgram, + program::ProgramArtifact, }; use noirc_driver::{ add_dep, compile_contract, compile_main, file_manager_with_stdlib, prepare_crate, @@ -148,8 +148,8 @@ impl PathToFileSourceMap { } pub enum CompileResult { - Contract { contract: PreprocessedContract, debug: DebugArtifact }, - Program { program: PreprocessedProgram, debug: DebugArtifact }, + Contract { contract: ContractArtifact, debug: DebugArtifact }, + Program { program: ProgramArtifact, debug: DebugArtifact }, } #[wasm_bindgen] @@ -195,7 +195,7 @@ pub fn compile( let optimized_contract = nargo::ops::optimize_contract(compiled_contract, expression_width); - let compile_output = preprocess_contract(optimized_contract); + let compile_output = generate_contract_artifact(optimized_contract); Ok(JsCompileResult::new(compile_output)) } else { let compiled_program = compile_main(&mut context, crate_id, &compile_options, None, true) @@ -210,7 +210,7 @@ pub fn compile( let optimized_program = nargo::ops::optimize_program(compiled_program, expression_width); - let compile_output = preprocess_program(optimized_program); + let compile_output = generate_program_artifact(optimized_program); Ok(JsCompileResult::new(compile_output)) } } @@ -272,50 +272,32 @@ fn add_noir_lib(context: &mut Context, library_name: &CrateName) -> CrateId { prepare_dependency(context, &path_to_lib) } -pub(crate) fn preprocess_program(program: CompiledProgram) -> CompileResult { +pub(crate) fn generate_program_artifact(program: CompiledProgram) -> CompileResult { let debug_artifact = DebugArtifact { - debug_symbols: vec![program.debug], - file_map: program.file_map, - warnings: program.warnings, + debug_symbols: vec![program.debug.clone()], + file_map: program.file_map.clone(), + warnings: program.warnings.clone(), }; - let preprocessed_program = PreprocessedProgram { - hash: program.hash, - abi: program.abi, - noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), - bytecode: program.circuit, - }; - - CompileResult::Program { program: preprocessed_program, debug: debug_artifact } + CompileResult::Program { program: program.into(), debug: debug_artifact } } -// TODO: This method should not be doing so much, most of this should be done in nargo or the driver -pub(crate) fn preprocess_contract(contract: CompiledContract) -> CompileResult { +pub(crate) fn generate_contract_artifact(contract: CompiledContract) -> CompileResult { let debug_artifact = DebugArtifact { debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), file_map: contract.file_map, warnings: contract.warnings, }; - let preprocessed_functions = contract - .functions - .into_iter() - .map(|func| PreprocessedContractFunction { - name: func.name, - function_type: func.function_type, - is_internal: func.is_internal, - abi: func.abi, - bytecode: func.bytecode, - }) - .collect(); - - let preprocessed_contract = PreprocessedContract { + let functions = contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(); + + let contract_artifact = ContractArtifact { noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), name: contract.name, - functions: preprocessed_functions, + functions, events: contract.events, }; - CompileResult::Contract { contract: preprocessed_contract, debug: debug_artifact } + CompileResult::Contract { contract: contract_artifact, debug: debug_artifact } } #[cfg(test)] diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs index 0cd1a2c50e5..e8a01540ff9 100644 --- a/compiler/wasm/src/compile_new.rs +++ b/compiler/wasm/src/compile_new.rs @@ -1,6 +1,6 @@ use crate::compile::{ - file_manager_with_source_map, preprocess_contract, preprocess_program, JsCompileResult, - PathToFileSourceMap, + file_manager_with_source_map, generate_contract_artifact, generate_program_artifact, + JsCompileResult, PathToFileSourceMap, }; use crate::errors::{CompileError, JsCompileError}; use noirc_driver::{ @@ -108,7 +108,7 @@ impl CompilerContext { let optimized_program = nargo::ops::optimize_program(compiled_program, np_language); - let compile_output = preprocess_program(optimized_program); + let compile_output = generate_program_artifact(optimized_program); Ok(JsCompileResult::new(compile_output)) } @@ -133,7 +133,7 @@ impl CompilerContext { let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language); - let compile_output = preprocess_contract(optimized_contract); + let compile_output = generate_contract_artifact(optimized_contract); Ok(JsCompileResult::new(compile_output)) } } diff --git a/tooling/nargo/src/artifacts/contract.rs b/tooling/nargo/src/artifacts/contract.rs index 4ade4f5660e..04699126762 100644 --- a/tooling/nargo/src/artifacts/contract.rs +++ b/tooling/nargo/src/artifacts/contract.rs @@ -1,21 +1,16 @@ use acvm::acir::circuit::Circuit; use noirc_abi::{Abi, ContractEvent}; -use noirc_driver::ContractFunctionType; +use noirc_driver::{ContractFunction, ContractFunctionType}; use serde::{Deserialize, Serialize}; -/// `PreprocessedContract` represents a Noir contract which has been preprocessed by a particular backend proving system. -/// -/// This differs from a generic Noir contract artifact in that: -/// - The ACIR bytecode has had an optimization pass applied to tailor it for the backend. -/// - Proving and verification keys have been pregenerated based on this ACIR. #[derive(Serialize, Deserialize)] -pub struct PreprocessedContract { +pub struct ContractArtifact { /// Version of noir used to compile this contract pub noir_version: String, /// The name of the contract. pub name: String, /// Each of the contract's functions are compiled into a separate program stored in this `Vec`. - pub functions: Vec, + pub functions: Vec, /// All the events defined inside the contract scope. pub events: Vec, } @@ -25,7 +20,7 @@ pub struct PreprocessedContract { /// A contract function unlike a regular Noir program however can have additional properties. /// One of these being a function type. #[derive(Debug, Serialize, Deserialize)] -pub struct PreprocessedContractFunction { +pub struct ContractFunctionArtifact { pub name: String, pub function_type: ContractFunctionType, @@ -40,3 +35,15 @@ pub struct PreprocessedContractFunction { )] pub bytecode: Circuit, } + +impl From for ContractFunctionArtifact { + fn from(func: ContractFunction) -> Self { + ContractFunctionArtifact { + name: func.name, + function_type: func.function_type, + is_internal: func.is_internal, + abi: func.abi, + bytecode: func.bytecode, + } + } +} diff --git a/tooling/nargo/src/artifacts/program.rs b/tooling/nargo/src/artifacts/program.rs index 664db0adca4..96e63e6fe50 100644 --- a/tooling/nargo/src/artifacts/program.rs +++ b/tooling/nargo/src/artifacts/program.rs @@ -1,17 +1,13 @@ use acvm::acir::circuit::Circuit; use noirc_abi::Abi; +use noirc_driver::CompiledProgram; use serde::{Deserialize, Serialize}; -/// `PreprocessedProgram` represents a Noir program which has been preprocessed by a particular backend proving system. -/// -/// This differs from a generic Noir program artifact in that: -/// - The ACIR bytecode has had an optimization pass applied to tailor it for the backend. -/// - Proving and verification keys have been pregenerated based on this ACIR. #[derive(Serialize, Deserialize, Debug)] -pub struct PreprocessedProgram { +pub struct ProgramArtifact { pub noir_version: String, - /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`PreprocessedProgram`] + /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`ProgramArtifact`] /// was compiled. /// /// Used to short-circuit compilation in the case of the source code not changing since the last compilation. @@ -25,3 +21,14 @@ pub struct PreprocessedProgram { )] pub bytecode: Circuit, } + +impl From for ProgramArtifact { + fn from(program: CompiledProgram) -> Self { + ProgramArtifact { + hash: program.hash, + abi: program.abi, + noir_version: program.noir_version, + bytecode: program.circuit, + } + } +} diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 661081778c3..612261fac53 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -3,10 +3,9 @@ use std::path::Path; use acvm::ExpressionWidth; use fm::FileManager; use iter_extended::vecmap; -use nargo::artifacts::contract::PreprocessedContract; -use nargo::artifacts::contract::PreprocessedContractFunction; +use nargo::artifacts::contract::{ContractArtifact, ContractFunctionArtifact}; use nargo::artifacts::debug::DebugArtifact; -use nargo::artifacts::program::PreprocessedProgram; +use nargo::artifacts::program::ProgramArtifact; use nargo::errors::CompileError; use nargo::insert_all_files_for_workspace_into_file_manager; use nargo::package::Package; @@ -173,15 +172,15 @@ fn compile_program( let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); debug_artifact_path.set_file_name(format!("debug_{}.json", package.name)); - let cached_program = if let (Ok(preprocessed_program), Ok(mut debug_artifact)) = ( + let cached_program = if let (Ok(program_artifact), Ok(mut debug_artifact)) = ( read_program_from_file(program_artifact_path), read_debug_artifact_from_file(debug_artifact_path), ) { Some(CompiledProgram { - hash: preprocessed_program.hash, - circuit: preprocessed_program.bytecode, - abi: preprocessed_program.abi, - noir_version: preprocessed_program.noir_version, + hash: program_artifact.hash, + circuit: program_artifact.bytecode, + abi: program_artifact.abi, + noir_version: program_artifact.noir_version, debug: debug_artifact.debug_symbols.remove(0), file_map: debug_artifact.file_map, warnings: debug_artifact.warnings, @@ -239,16 +238,11 @@ fn save_program( circuit_dir: &Path, only_acir_opt: bool, ) { - let preprocessed_program = PreprocessedProgram { - hash: program.hash, - abi: program.abi, - noir_version: program.noir_version, - bytecode: program.circuit, - }; + let program_artifact = ProgramArtifact::from(program.clone()); if only_acir_opt { - only_acir(&preprocessed_program, circuit_dir); + only_acir(&program_artifact, circuit_dir); } else { - save_program_to_file(&preprocessed_program, &package.name, circuit_dir); + save_program_to_file(&program_artifact, &package.name, circuit_dir); } let debug_artifact = DebugArtifact { @@ -263,7 +257,7 @@ fn save_program( fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Path) { // TODO(#1389): I wonder if it is incorrect for nargo-core to know anything about contracts. // As can be seen here, It seems like a leaky abstraction where ContractFunctions (essentially CompiledPrograms) - // are compiled via nargo-core and then the PreprocessedContract is constructed here. + // are compiled via nargo-core and then the ContractArtifact is constructed here. // This is due to EACH function needing it's own CRS, PKey, and VKey from the backend. let debug_artifact = DebugArtifact { debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), @@ -271,7 +265,7 @@ fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Pa warnings: contract.warnings, }; - let preprocessed_functions = vecmap(contract.functions, |func| PreprocessedContractFunction { + let functions = vecmap(contract.functions, |func| ContractFunctionArtifact { name: func.name, function_type: func.function_type, is_internal: func.is_internal, @@ -279,22 +273,22 @@ fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Pa bytecode: func.bytecode, }); - let preprocessed_contract = PreprocessedContract { + let contract_artifact = ContractArtifact { noir_version: contract.noir_version, name: contract.name, - functions: preprocessed_functions, + functions, events: contract.events, }; save_contract_to_file( - &preprocessed_contract, - &format!("{}-{}", package.name, preprocessed_contract.name), + &contract_artifact, + &format!("{}-{}", package.name, contract_artifact.name), circuit_dir, ); save_debug_artifact_to_file( &debug_artifact, - &format!("{}-{}", package.name, preprocessed_contract.name), + &format!("{}-{}", package.name, contract_artifact.name), circuit_dir, ); } diff --git a/tooling/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs index 807df25ba48..1d2f012736e 100644 --- a/tooling/nargo_cli/src/cli/fs/program.rs +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use acvm::acir::circuit::Circuit; use nargo::artifacts::{ - contract::PreprocessedContract, debug::DebugArtifact, program::PreprocessedProgram, + contract::ContractArtifact, debug::DebugArtifact, program::ProgramArtifact, }; use noirc_frontend::graph::CrateName; @@ -11,29 +11,29 @@ use crate::errors::FilesystemError; use super::{create_named_dir, write_to_file}; pub(crate) fn save_program_to_file>( - compiled_program: &PreprocessedProgram, + program_artifact: &ProgramArtifact, crate_name: &CrateName, circuit_dir: P, ) -> PathBuf { let circuit_name: String = crate_name.into(); - save_build_artifact_to_file(compiled_program, &circuit_name, circuit_dir) + save_build_artifact_to_file(program_artifact, &circuit_name, circuit_dir) } /// Writes the bytecode as acir.gz pub(crate) fn only_acir>( - compiled_program: &PreprocessedProgram, + program_artifact: &ProgramArtifact, circuit_dir: P, ) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Circuit::serialize_circuit(&compiled_program.bytecode); + let bytes = Circuit::serialize_circuit(&program_artifact.bytecode); write_to_file(&bytes, &circuit_path); circuit_path } pub(crate) fn save_contract_to_file>( - compiled_contract: &PreprocessedContract, + compiled_contract: &ContractArtifact, circuit_name: &str, circuit_dir: P, ) -> PathBuf { @@ -64,7 +64,7 @@ fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( pub(crate) fn read_program_from_file>( circuit_path: P, -) -> Result { +) -> Result { let file_path = circuit_path.as_ref().with_extension("json"); let input_string = From 043d03d5dd56e9a4d9567887212b430080bafcd7 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:49:08 +0000 Subject: [PATCH 137/137] chore: add `insert_range_check` method to `FunctionBuilder` (#3959) # Description ## Problem\* Resolves ## Summary\* This PR gives an `insert_range_check` method for consistency with the other `Instruction`s. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- .../src/ssa/function_builder/mod.rs | 13 +++++++++++ .../src/ssa/ssa_gen/context.rs | 22 +++++++++---------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index b972afa2990..2871f149b41 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -255,6 +255,19 @@ impl FunctionBuilder { self.insert_instruction(Instruction::Constrain(lhs, rhs, assert_message), None); } + /// Insert a [`Instruction::RangeCheck`] instruction at the end of the current block. + pub(crate) fn insert_range_check( + &mut self, + value: ValueId, + max_bit_size: u32, + assert_message: Option, + ) { + self.insert_instruction( + Instruction::RangeCheck { value, max_bit_size, assert_message }, + None, + ); + } + /// Insert a call instruction at the end of the current block and return /// the results of the call. pub(crate) fn insert_call( diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 5724bf56e8e..f5cf548ddc9 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -349,12 +349,11 @@ impl<'a> FunctionContext<'a> { self.check_shift_overflow(result, rhs, bit_size, location, false) } else { let message = format!("attempt to {} with overflow", op_name); - let range_constraint = Instruction::RangeCheck { - value: result, - max_bit_size: bit_size, - assert_message: Some(message), - }; - self.builder.set_location(location).insert_instruction(range_constraint, None); + self.builder.set_location(location).insert_range_check( + result, + bit_size, + Some(message), + ); result } } @@ -464,12 +463,11 @@ impl<'a> FunctionContext<'a> { let product_field = self.builder.insert_binary(lhs_abs, BinaryOp::Mul, rhs_abs); // It must not already overflow the bit_size let message = "attempt to multiply with overflow".to_string(); - let size_overflow = Instruction::RangeCheck { - value: product_field, - max_bit_size: bit_size, - assert_message: Some(message.clone()), - }; - self.builder.set_location(location).insert_instruction(size_overflow, None); + self.builder.set_location(location).insert_range_check( + product_field, + bit_size, + Some(message.clone()), + ); let product = self.builder.insert_cast(product_field, Type::unsigned(bit_size)); // Then we check the signed product fits in a signed integer of bit_size-bits