From 8348c4c7b1b7bc82c1ce73b512d0b30c96b4e538 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 9 Jan 2024 19:04:29 +0000 Subject: [PATCH 1/3] git subrepo commit (merge) noir subrepo: subdir: "noir" merged: "b2c89b2a0" upstream: origin: "https://github.com/noir-lang/noir" branch: "aztec-packages" commit: "114aa6f90" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "110b9eb" --- noir/.github/workflows/test-cargo.yml | 51 - noir/.github/workflows/test-js-packages.yml | 16 +- noir/.gitrepo | 2 +- noir/Cargo.lock | 2 - .../acir/src/circuit/black_box_functions.rs | 2 +- noir/acvm-repo/acir/src/circuit/mod.rs | 2 +- .../opcodes/black_box_function_call.rs | 15 +- .../acir/tests/test_program_serialization.rs | 10 +- .../acvm/src/compiler/transformers/mod.rs | 3 +- noir/acvm-repo/acvm_js/src/execute.rs | 4 +- .../acvm-repo/acvm_js/test/shared/pedersen.ts | 4 +- .../acvm_js/test/shared/schnorr_verify.ts | 4 +- noir/acvm-repo/brillig_vm/src/black_box.rs | 22 +- .../circuits/recursion/src/main.nr | 20 +- .../test/browser/recursion.test.ts | 1 - .../onchain_recursive_verification.test.ts | 7 +- .../test/node/smart_contract_verifier.test.ts | 4 +- noir/compiler/noirc_driver/src/abi_gen.rs | 2 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 14 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 41 +- .../src/ssa/function_builder/data_bus.rs | 8 +- .../src/ssa/function_builder/mod.rs | 13 + .../noirc_evaluator/src/ssa/ir/dfg.rs | 2 +- .../noirc_evaluator/src/ssa/ir/instruction.rs | 8 +- .../src/ssa/ir/instruction/call.rs | 20 +- .../noirc_evaluator/src/ssa/ir/types.rs | 48 +- .../src/ssa/opt/constant_folding.rs | 14 +- .../src/ssa/opt/flatten_cfg.rs | 4 +- .../src/ssa/ssa_gen/context.rs | 70 +- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 4 +- noir/compiler/noirc_frontend/src/ast/mod.rs | 15 +- .../src/hir/def_collector/dc_crate.rs | 11 +- .../noirc_frontend/src/hir/def_map/mod.rs | 23 + noir/compiler/noirc_frontend/src/hir/mod.rs | 15 +- .../noirc_frontend/src/hir/type_check/expr.rs | 9 +- .../noirc_frontend/src/hir/type_check/mod.rs | 17 +- .../noirc_frontend/src/hir/type_check/stmt.rs | 2 +- .../noirc_frontend/src/hir_def/function.rs | 18 +- .../noirc_frontend/src/hir_def/traits.rs | 5 +- .../noirc_frontend/src/hir_def/types.rs | 190 +- .../noirc_frontend/src/lexer/token.rs | 5 +- .../src/monomorphization/mod.rs | 97 +- .../noirc_frontend/src/node_interner.rs | 39 +- .../noirc_frontend/src/parser/parser.rs | 4 +- noir/compiler/wasm/src/compile.rs | 52 +- noir/compiler/wasm/src/compile_new.rs | 39 +- noir/cspell.json | 6 +- .../docs/noir/concepts/data_types/strings.md | 4 +- .../docs/noir/concepts/data_types/vectors.mdx | 2 - noir/docs/docs/noir/concepts/generics.md | 52 +- .../cryptographic_primitives/scalar.mdx | 2 +- .../docs/noir/standard_library/logging.md | 45 +- .../noir/standard_library/merkle_trees.md | 2 +- .../docs/noir/standard_library/options.md | 4 +- noir/docs/docs/tutorials/noirjs_app.md | 255 +- noir/docs/static/img/memes/flextape.jpeg | Bin 0 -> 78365 bytes noir/docs/static/img/memes/titanic.jpeg | Bin 0 -> 59759 bytes .../static/img/noir_getting_started_1.png | Bin 255402 -> 19135 bytes .../data_types/01_integers.md | 2 +- .../regression_3964/Nargo.toml | 7 + .../regression_3964/src/main.nr | 5 + .../execution_success/prelude/Nargo.toml | 0 .../execution_success/prelude/src/main.nr | 15 +- noir/tooling/bb_abstraction_leaks/build.rs | 2 +- .../bb_abstraction_leaks/src/contract.sol | 2575 ----------------- noir/tooling/bb_abstraction_leaks/src/lib.rs | 7 - noir/tooling/debugger/Cargo.toml | 1 - noir/tooling/debugger/build.rs | 10 - noir/tooling/debugger/tests/debug.rs | 4 +- .../lsp/src/requests/goto_definition.rs | 27 + noir/tooling/nargo/src/artifacts/contract.rs | 25 +- noir/tooling/nargo/src/artifacts/program.rs | 21 +- noir/tooling/nargo/src/constants.rs | 2 + noir/tooling/nargo/src/workspace.rs | 6 +- noir/tooling/nargo_cli/Cargo.toml | 1 - noir/tooling/nargo_cli/build.rs | 7 +- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 10 +- noir/tooling/nargo_cli/src/cli/compile_cmd.rs | 42 +- noir/tooling/nargo_cli/src/cli/export_cmd.rs | 120 + noir/tooling/nargo_cli/src/cli/fs/program.rs | 14 +- noir/tooling/nargo_cli/src/cli/mod.rs | 4 + noir/tooling/nargo_cli/src/cli/test_cmd.rs | 19 +- noir/tooling/noir_codegen/.gitignore | 2 +- noir/tooling/noir_codegen/package.json | 4 +- noir/tooling/noir_codegen/src/index.ts | 4 +- .../test/assert_lt/target/assert_lt.json | 1 - noir/tooling/noir_codegen/test/index.test.ts | 16 +- .../test/{assert_lt => test_lib}/Nargo.toml | 4 +- .../src/main.nr => test_lib/src/lib.nr} | 15 +- .../noir_js_backend_barretenberg/package.json | 2 +- .../noir_js_backend_barretenberg/src/index.ts | 11 +- .../src/public_inputs.ts | 31 +- .../test/public_input_deflattening.test.ts | 8 +- noir/tooling/noir_js_types/src/types.ts | 4 +- noir/tooling/noirc_abi/src/lib.rs | 21 +- noir/yarn.lock | 16 +- 96 files changed, 1092 insertions(+), 3303 deletions(-) delete mode 100644 noir/.github/workflows/test-cargo.yml create mode 100644 noir/docs/static/img/memes/flextape.jpeg create mode 100644 noir/docs/static/img/memes/titanic.jpeg create mode 100644 noir/test_programs/compile_success_empty/regression_3964/Nargo.toml create mode 100644 noir/test_programs/compile_success_empty/regression_3964/src/main.nr rename noir/{tooling/nargo_cli/tests => test_programs}/execution_success/prelude/Nargo.toml (100%) rename noir/{tooling/nargo_cli/tests => test_programs}/execution_success/prelude/src/main.nr (59%) delete mode 100644 noir/tooling/bb_abstraction_leaks/src/contract.sol create mode 100644 noir/tooling/nargo_cli/src/cli/export_cmd.rs delete mode 100644 noir/tooling/noir_codegen/test/assert_lt/target/assert_lt.json rename noir/tooling/noir_codegen/test/{assert_lt => test_lib}/Nargo.toml (55%) rename noir/tooling/noir_codegen/test/{assert_lt/src/main.nr => test_lib/src/lib.nr} (55%) diff --git a/noir/.github/workflows/test-cargo.yml b/noir/.github/workflows/test-cargo.yml deleted file mode 100644 index 8d414daa75b4..000000000000 --- a/noir/.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 diff --git a/noir/.github/workflows/test-js-packages.yml b/noir/.github/workflows/test-js-packages.yml index a298d67a485e..e2ffc5087bef 100644 --- a/noir/.github/workflows/test-js-packages.yml +++ b/noir/.github/workflows/test-js-packages.yml @@ -319,7 +319,7 @@ jobs: run: yarn workspace @noir-lang/noir_wasm test:browser test-noir-codegen: - needs: [build-acvm-js, build-noirc-abi] + needs: [build-acvm-js, build-noirc-abi, build-nargo] name: noir_codegen runs-on: ubuntu-latest timeout-minutes: 30 @@ -328,6 +328,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Download nargo binary + uses: actions/download-artifact@v3 + with: + name: nargo + path: ./nargo + - name: Download acvm_js package artifact uses: actions/download-artifact@v3 with: @@ -339,6 +345,14 @@ jobs: with: name: noirc_abi_wasm path: ./tooling/noirc_abi_wasm + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V - name: Install Yarn dependencies uses: ./.github/actions/setup diff --git a/noir/.gitrepo b/noir/.gitrepo index 97b5260ea5d9..053acae1f4f2 100644 --- a/noir/.gitrepo +++ b/noir/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/noir-lang/noir branch = aztec-packages - commit = c0826b58272bbba28d6cd25bc07dd5de3cc12e61 + commit = 114aa6f90f147fe69ff424e881463a65df26c4e6 parent = 9a80008c623a9d26e1b82c9e86561c304ef185f1 method = merge cmdver = 0.4.6 diff --git a/noir/Cargo.lock b/noir/Cargo.lock index 0334ee5f5526..50892d98ff3f 100644 --- a/noir/Cargo.lock +++ b/noir/Cargo.lock @@ -2682,7 +2682,6 @@ dependencies = [ "assert_fs", "async-lsp", "backend-interface", - "bb_abstraction_leaks", "bn254_blackbox_solver", "build-data", "clap", @@ -2827,7 +2826,6 @@ dependencies = [ "noirc_printable_type", "owo-colors", "rexpect", - "rustc_version", "serde_json", "tempfile", "test-binary", diff --git a/noir/acvm-repo/acir/src/circuit/black_box_functions.rs b/noir/acvm-repo/acir/src/circuit/black_box_functions.rs index 78bc4121de7d..0dcfb3bc9f1e 100644 --- a/noir/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/noir/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -74,7 +74,7 @@ impl BlackBoxFunc { BlackBoxFunc::XOR => "xor", BlackBoxFunc::RANGE => "range", BlackBoxFunc::Keccak256 => "keccak256", - BlackBoxFunc::Keccakf1600 => "keccak_f1600", + BlackBoxFunc::Keccakf1600 => "keccakf1600", BlackBoxFunc::RecursiveAggregation => "recursive_aggregation", BlackBoxFunc::EcdsaSecp256r1 => "ecdsa_secp256r1", } diff --git a/noir/acvm-repo/acir/src/circuit/mod.rs b/noir/acvm-repo/acir/src/circuit/mod.rs index 48c6b14ce695..b248b30b1d96 100644 --- a/noir/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/acvm-repo/acir/src/circuit/mod.rs @@ -99,7 +99,7 @@ impl FromStr for OpcodeLocation { let brillig_index = parts[1].parse()?; Ok(OpcodeLocation::Brillig { acir_index, brillig_index }) } - _ => unreachable!(), + _ => unreachable!("`OpcodeLocation` has too many components"), } } diff --git a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 2ac4d558b68e..7ee4e2498a5f 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -163,8 +163,12 @@ impl BlackBoxFuncCall { vec![*lhs, *rhs] } BlackBoxFuncCall::FixedBaseScalarMul { low, high, .. } => vec![*low, *high], - BlackBoxFuncCall::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, .. } => vec![*input1_x, *input1_y, *input2_x, *input2_y], - BlackBoxFuncCall::EmbeddedCurveDouble { input_x, input_y, .. } => vec![*input_x, *input_y], + BlackBoxFuncCall::EmbeddedCurveAdd { + input1_x, input1_y, input2_x, input2_y, .. + } => vec![*input1_x, *input1_y, *input2_x, *input2_y], + BlackBoxFuncCall::EmbeddedCurveDouble { input_x, input_y, .. } => { + vec![*input_x, *input_y] + } BlackBoxFuncCall::RANGE { input } => vec![*input], BlackBoxFuncCall::SchnorrVerify { public_key_x, @@ -245,8 +249,7 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::Blake2s { outputs, .. } | BlackBoxFuncCall::Blake3 { outputs, .. } | BlackBoxFuncCall::Keccak256 { outputs, .. } - | BlackBoxFuncCall::Keccakf1600 { outputs, .. } - => outputs.to_vec(), + | BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(), BlackBoxFuncCall::AND { output, .. } | BlackBoxFuncCall::XOR { output, .. } | BlackBoxFuncCall::SchnorrVerify { output, .. } @@ -257,7 +260,9 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::PedersenCommitment { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveDouble { outputs, .. } => vec![outputs.0, outputs.1], - BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => vec![], + BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => { + vec![] + } BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } => outputs.to_vec(), } } diff --git a/noir/acvm-repo/acir/tests/test_program_serialization.rs b/noir/acvm-repo/acir/tests/test_program_serialization.rs index 1f25b6655736..7d3b7b32d35e 100644 --- a/noir/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/acvm-repo/acir/tests/test_program_serialization.rs @@ -102,9 +102,9 @@ fn pedersen_circuit() { let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 250, 255, 139, - 163, 162, 130, 72, 16, 149, 241, 3, 135, 84, 164, 172, 173, 213, 175, 251, 45, 198, 96, - 243, 211, 50, 152, 67, 220, 211, 92, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 232, 255, 31, 142, + 138, 10, 34, 65, 84, 198, 15, 28, 82, 145, 178, 182, 86, 191, 238, 183, 24, 131, 205, 79, + 203, 0, 166, 242, 158, 93, 92, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -145,7 +145,7 @@ fn schnorr_verify_circuit() { let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 87, 78, 2, 1, 20, 134, 209, 177, 247, 222, 123, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 221, 133, 251, 95, 130, 145, 27, 206, 36, 78, 50, - 57, 16, 94, 200, 253, 191, 159, 36, 73, 134, 146, 193, 19, 142, 241, 183, 255, 14, 179, + 57, 16, 94, 200, 253, 191, 159, 36, 73, 134, 146, 193, 19, 142, 243, 183, 255, 14, 179, 233, 247, 145, 254, 59, 217, 127, 71, 57, 198, 113, 78, 48, 125, 167, 56, 205, 25, 206, 114, 142, 243, 92, 224, 34, 151, 184, 204, 21, 174, 114, 141, 235, 220, 224, 38, 183, 184, 205, 29, 238, 114, 143, 251, 60, 224, 33, 143, 120, 204, 19, 158, 242, 140, 25, 158, 51, @@ -158,7 +158,7 @@ fn schnorr_verify_circuit() { 91, 159, 218, 56, 99, 219, 172, 77, 115, 182, 204, 219, 176, 96, 187, 162, 205, 74, 182, 42, 219, 168, 98, 155, 170, 77, 106, 182, 168, 219, 160, 225, 246, 77, 55, 111, 185, 113, 219, 109, 59, 110, 218, 117, 203, 158, 27, 166, 55, 75, 239, 150, 184, 101, 250, 252, 1, - 19, 89, 159, 101, 220, 3, 0, 0, + 55, 204, 92, 74, 220, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index bb4dd9e66b2b..99f1ca23b5bc 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -104,7 +104,8 @@ pub(super) fn transform_internal( | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } => { transformer.mark_solvable(*output); } - acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } => (), + acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } => (), acir::circuit::opcodes::BlackBoxFuncCall::SHA256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256VariableLength { diff --git a/noir/acvm-repo/acvm_js/src/execute.rs b/noir/acvm-repo/acvm_js/src/execute.rs index 439a929cc981..3f691e1abf29 100644 --- a/noir/acvm-repo/acvm_js/src/execute.rs +++ b/noir/acvm-repo/acvm_js/src/execute.rs @@ -61,8 +61,8 @@ pub async fn execute_circuit_with_black_box_solver( foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let circuit: Circuit = Circuit::deserialize_circuit(&circuit) + .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); diff --git a/noir/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/acvm-repo/acvm_js/test/shared/pedersen.ts index 668ee2b510b8..e35893fc3552 100644 --- a/noir/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/noir/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,7 +1,7 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 250, 255, 139, 163, 162, 130, 72, 16, 149, - 241, 3, 135, 84, 164, 172, 173, 213, 175, 251, 45, 198, 96, 243, 211, 50, 152, 67, 220, 211, 92, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 232, 255, 31, 142, 138, 10, 34, 65, 84, 198, + 15, 28, 82, 145, 178, 182, 86, 191, 238, 183, 24, 131, 205, 79, 203, 0, 166, 242, 158, 93, 92, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/noir/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/noir/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index f88a70ba4a10..5716cbd30f84 100644 --- a/noir/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/noir/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -2,7 +2,7 @@ export const bytecode = Uint8Array.from([ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 87, 78, 2, 1, 20, 134, 209, 177, 247, 222, 123, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 221, 133, 251, 95, 130, 145, 27, 206, 36, 78, 50, 57, 16, 94, 200, 253, 191, 159, 36, 73, 134, 146, - 193, 19, 142, 241, 183, 255, 14, 179, 233, 247, 145, 254, 59, 217, 127, 71, 57, 198, 113, 78, 48, 125, 167, 56, 205, + 193, 19, 142, 243, 183, 255, 14, 179, 233, 247, 145, 254, 59, 217, 127, 71, 57, 198, 113, 78, 48, 125, 167, 56, 205, 25, 206, 114, 142, 243, 92, 224, 34, 151, 184, 204, 21, 174, 114, 141, 235, 220, 224, 38, 183, 184, 205, 29, 238, 114, 143, 251, 60, 224, 33, 143, 120, 204, 19, 158, 242, 140, 25, 158, 51, 203, 11, 230, 120, 201, 60, 175, 88, 224, 53, 139, 188, 97, 137, 183, 44, 243, 142, 21, 222, 179, 202, 7, 214, 248, 200, 58, 159, 216, 224, 51, 155, 124, 97, 235, @@ -11,7 +11,7 @@ export const bytecode = Uint8Array.from([ 162, 149, 232, 36, 26, 137, 62, 162, 141, 232, 34, 154, 136, 30, 162, 133, 232, 32, 26, 136, 253, 99, 251, 195, 100, 176, 121, 236, 29, 91, 159, 218, 56, 99, 219, 172, 77, 115, 182, 204, 219, 176, 96, 187, 162, 205, 74, 182, 42, 219, 168, 98, 155, 170, 77, 106, 182, 168, 219, 160, 225, 246, 77, 55, 111, 185, 113, 219, 109, 59, 110, 218, 117, 203, - 158, 27, 166, 55, 75, 239, 150, 184, 101, 250, 252, 1, 19, 89, 159, 101, 220, 3, 0, 0, + 158, 27, 166, 55, 75, 239, 150, 184, 101, 250, 252, 1, 55, 204, 92, 74, 220, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/acvm-repo/brillig_vm/src/black_box.rs b/noir/acvm-repo/brillig_vm/src/black_box.rs index 1b67e52f9b0b..732c383e08fb 100644 --- a/noir/acvm-repo/brillig_vm/src/black_box.rs +++ b/noir/acvm-repo/brillig_vm/src/black_box.rs @@ -78,11 +78,7 @@ pub(crate) fn evaluate_black_box( signature, result: result_register, } => { - let bb_func = match op { - BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, - BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, - _ => unreachable!(), - }; + let bb_func = black_box_function_from_op(op); let public_key_x: [u8; 32] = to_u8_vec(read_heap_array( memory, @@ -117,7 +113,7 @@ pub(crate) fn evaluate_black_box( BlackBoxOp::EcdsaSecp256r1 { .. } => { ecdsa_secp256r1_verify(&hashed_msg, &public_key_x, &public_key_y, &signature)? } - _ => unreachable!(), + _ => unreachable!("`BlackBoxOp` is guarded against being a non-ecdsa operation"), }; registers.set(*result_register, result.into()); @@ -187,6 +183,20 @@ pub(crate) fn evaluate_black_box( } } +fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { + match op { + BlackBoxOp::Sha256 { .. } => BlackBoxFunc::SHA256, + BlackBoxOp::Blake2s { .. } => BlackBoxFunc::Blake2s, + BlackBoxOp::Keccak256 { .. } => BlackBoxFunc::Keccak256, + BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, + BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, + BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, + BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, + BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, + BlackBoxOp::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul, + } +} + #[cfg(test)] mod test { use acir::brillig::BlackBoxOp; diff --git a/noir/compiler/integration-tests/circuits/recursion/src/main.nr b/noir/compiler/integration-tests/circuits/recursion/src/main.nr index e60e4e0b61a1..173207766fb9 100644 --- a/noir/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/noir/compiler/integration-tests/circuits/recursion/src/main.nr @@ -1,17 +1,15 @@ use dep::std; fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, -) -> pub [Field;16]{ - let input_aggregation_object = [0; 16]; + verification_key: [Field; 114], + proof: [Field; 93], + public_inputs: [Field; 1], + key_hash: Field +) { std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash, - input_aggregation_object + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash ) } diff --git a/noir/compiler/integration-tests/test/browser/recursion.test.ts b/noir/compiler/integration-tests/test/browser/recursion.test.ts index faa317b2c3ce..2097164ebcb8 100644 --- a/noir/compiler/integration-tests/test/browser/recursion.test.ts +++ b/noir/compiler/integration-tests/test/browser/recursion.test.ts @@ -79,7 +79,6 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. proof: proofAsFields, public_inputs: [main_inputs.y as Field], key_hash: vkHash, - input_aggregation_object: ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'], }; logger.debug('recursion_inputs', recursion_inputs); diff --git a/noir/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/noir/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index 6c20d44882b6..7a25669d22a4 100644 --- a/noir/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/noir/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -12,7 +12,7 @@ import { PathToFileSourceMap, } from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg'; +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; import { Field, InputMap } from '@noir-lang/noirc_abi'; compilerLogLevel('INFO'); @@ -71,10 +71,7 @@ it(`smart contract can verify a recursive proof`, async () => { const contract = await ethers.deployContract('contracts/recursion.sol:UltraVerifier', []); - const result = await contract.verify.staticCall( - recursion_proof.proof, - flattenPublicInputs(recursion_proof.publicInputs), - ); + const result = await contract.verify.staticCall(recursion_proof.proof, recursion_proof.publicInputs); expect(result).to.be.true; }); diff --git a/noir/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/noir/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index 5b3d0e2d3370..a93a2fc15088 100644 --- a/noir/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/noir/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -7,7 +7,7 @@ import toml from 'toml'; 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'; +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; compilerLogLevel('INFO'); @@ -61,7 +61,7 @@ test_cases.forEach((testInfo) => { const contract = await ethers.deployContract(testInfo.compiled, []); - const result = await contract.verify(proofData.proof, flattenPublicInputs(proofData.publicInputs)); + const result = await contract.verify(proofData.proof, proofData.publicInputs); expect(result).to.be.true; }); diff --git a/noir/compiler/noirc_driver/src/abi_gen.rs b/noir/compiler/noirc_driver/src/abi_gen.rs index 9d0d64b63006..e546cd822b70 100644 --- a/noir/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/compiler/noirc_driver/src/abi_gen.rs @@ -33,7 +33,7 @@ pub(super) fn compute_function_abi( ) -> (Vec, Option) { let func_meta = context.def_interner.function_meta(func_id); - let (parameters, return_type) = func_meta.into_function_signature(); + let (parameters, return_type) = func_meta.function_signature(); let parameters = into_abi_params(context, parameters); let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); (parameters, return_type) diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 04152127660e..336e88da48a0 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -238,14 +238,12 @@ impl GeneratedAcir { BlackBoxFunc::Keccakf1600 => { BlackBoxFuncCall::Keccakf1600 { inputs: inputs[0].clone(), outputs } } - BlackBoxFunc::RecursiveAggregation => { - BlackBoxFuncCall::RecursiveAggregation { - verification_key: inputs[0].clone(), - proof: inputs[1].clone(), - public_inputs: inputs[2].clone(), - key_hash: inputs[3][0], - } - } + BlackBoxFunc::RecursiveAggregation => BlackBoxFuncCall::RecursiveAggregation { + verification_key: inputs[0].clone(), + proof: inputs[1].clone(), + public_inputs: inputs[2].clone(), + key_hash: inputs[3][0], + }, }; self.push_opcode(AcirOpcode::BlackBoxFuncCall(black_box_func_call)); diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index edf0461430f5..a1c96a3cd232 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -472,9 +472,9 @@ impl Context { self.acir_context.assert_eq_var(lhs, rhs, assert_message.clone())?; } } - Instruction::Cast(value_id, typ) => { - let result_acir_var = self.convert_ssa_cast(value_id, typ, dfg)?; - self.define_result_var(dfg, instruction_id, result_acir_var); + Instruction::Cast(value_id, _) => { + let acir_var = self.convert_numeric_value(*value_id, dfg)?; + self.define_result_var(dfg, instruction_id, acir_var); } Instruction::Call { func, arguments } => { let result_ids = dfg.instruction_results(instruction_id); @@ -1636,41 +1636,6 @@ impl Context { } } - /// Returns an `AcirVar` that is constrained to fit in the target type by truncating the input. - /// If the target cast is to a `NativeField`, no truncation is required so the cast becomes a - /// no-op. - fn convert_ssa_cast( - &mut self, - value_id: &ValueId, - typ: &Type, - dfg: &DataFlowGraph, - ) -> Result { - let (variable, incoming_type) = match self.convert_value(*value_id, dfg) { - AcirValue::Var(variable, typ) => (variable, typ), - AcirValue::DynamicArray(_) | AcirValue::Array(_) => { - unreachable!("Cast is only applied to numerics") - } - }; - let target_numeric = match typ { - Type::Numeric(numeric) => numeric, - _ => unreachable!("Can only cast to a numeric"), - }; - match target_numeric { - NumericType::NativeField => { - // Casting into a Field as a no-op - Ok(variable) - } - NumericType::Unsigned { bit_size } | NumericType::Signed { bit_size } => { - let max_bit_size = incoming_type.bit_size(); - if max_bit_size <= *bit_size { - // Incoming variable already fits into target bit size - this is a no-op - return Ok(variable); - } - self.acir_context.truncate_var(variable, *bit_size, max_bit_size) - } - } - } - /// Returns an `AcirVar`that is constrained to be result of the truncation. fn convert_ssa_truncate( &mut self, diff --git a/noir/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/noir/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index 7f3370893215..58d9e0f6d157 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -84,7 +84,6 @@ impl FunctionBuilder { databus.values.push_back(value); databus.index += 1; } - Type::Reference(_) => unreachable!(), Type::Array(typ, len) => { assert!(typ.len() == 1, "unsupported composite type"); databus.map.insert(value, databus.index); @@ -98,8 +97,11 @@ impl FunctionBuilder { self.add_to_data_bus(element, databus); } } - Type::Slice(_) => unreachable!(), - Type::Function => unreachable!(), + Type::Reference(_) => { + unreachable!("Attempted to add invalid type (reference) to databus") + } + Type::Slice(_) => unreachable!("Attempted to add invalid type (slice) to databus"), + Type::Function => unreachable!("Attempted to add invalid type (function) to databus"), } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index b972afa29903..2871f149b41d 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/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/noir/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index abddbfb74c7d..931aee9d079c 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -160,7 +160,7 @@ impl DataFlowGraph { call_stack: CallStack, ) -> InsertInstructionResult { use InsertInstructionResult::*; - match instruction.simplify(self, block, ctrl_typevars.clone()) { + match instruction.simplify(self, block, ctrl_typevars.clone(), &call_stack) { SimplifyResult::SimplifiedTo(simplification) => SimplifiedTo(simplification), SimplifyResult::SimplifiedToMultiple(simplification) => { SimplifiedToMultiple(simplification) diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 628ad638e64f..9691017f04bb 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -236,10 +236,7 @@ impl Instruction { // In ACIR, a division with a false predicate outputs (0,0), so it cannot replace another instruction unless they have the same predicate bin.operator != BinaryOp::Div } - Cast(_, _) | Not(_) | ArrayGet { .. } | ArraySet { .. } => true, - - // Unclear why this instruction causes problems. - Truncate { .. } => false, + Cast(_, _) | Truncate { .. } | Not(_) | ArrayGet { .. } | ArraySet { .. } => true, // These either have side-effects or interact with memory Constrain(..) @@ -408,6 +405,7 @@ impl Instruction { dfg: &mut DataFlowGraph, block: BasicBlockId, ctrl_typevars: Option>, + call_stack: &CallStack, ) -> SimplifyResult { use SimplifyResult::*; match self { @@ -551,7 +549,7 @@ impl Instruction { } } Instruction::Call { func, arguments } => { - simplify_call(*func, arguments, dfg, block, ctrl_typevars) + simplify_call(*func, arguments, dfg, block, ctrl_typevars, call_stack) } Instruction::EnableSideEffects { condition } => { if let Some(last) = dfg[block].instructions().last().copied() { diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index 5b3a1669bfff..86e855b2cc05 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -31,6 +31,7 @@ pub(super) fn simplify_call( dfg: &mut DataFlowGraph, block: BasicBlockId, ctrl_typevars: Option>, + call_stack: &CallStack, ) -> SimplifyResult { let intrinsic = match &dfg[func] { Value::Intrinsic(intrinsic) => *intrinsic, @@ -242,7 +243,24 @@ pub(super) fn simplify_call( SimplifyResult::SimplifiedToInstruction(instruction) } Intrinsic::FromField => { - let instruction = Instruction::Cast(arguments[0], ctrl_typevars.unwrap().remove(0)); + let incoming_type = Type::field(); + let target_type = ctrl_typevars.unwrap().remove(0); + + let truncate = Instruction::Truncate { + value: arguments[0], + bit_size: target_type.bit_size(), + max_bit_size: incoming_type.bit_size(), + }; + let truncated_value = dfg + .insert_instruction_and_results( + truncate, + block, + Some(vec![incoming_type]), + call_stack.clone(), + ) + .first(); + + let instruction = Instruction::Cast(truncated_value, target_type); SimplifyResult::SimplifiedToInstruction(instruction) } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs index bae06a805d05..ae53c7705c25 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -18,6 +18,28 @@ pub enum NumericType { NativeField, } +impl NumericType { + /// Returns the bit size of the provided numeric type. + pub(crate) fn bit_size(self: &NumericType) -> u32 { + match self { + NumericType::NativeField => FieldElement::max_num_bits(), + NumericType::Unsigned { bit_size } | NumericType::Signed { bit_size } => *bit_size, + } + } + + /// Returns true if the given Field value is within the numeric limits + /// for the current NumericType. + pub(crate) fn value_is_within_limits(self, field: FieldElement) -> bool { + match self { + NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { + let max = 2u128.pow(bit_size) - 1; + field <= max.into() + } + NumericType::NativeField => true, + } + } +} + /// All types representable in the IR. #[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] pub(crate) enum Type { @@ -68,6 +90,18 @@ impl Type { Type::Numeric(NumericType::NativeField) } + /// Returns the bit size of the provided numeric type. + /// + /// # Panics + /// + /// Panics if `self` is not a [`Type::Numeric`] + pub(crate) fn bit_size(&self) -> u32 { + match self { + Type::Numeric(numeric_type) => numeric_type.bit_size(), + other => panic!("bit_size: Expected numeric type, found {other}"), + } + } + /// Returns the size of the element type for this array/slice. /// The size of a type is defined as representing how many Fields are needed /// to represent the type. This is 1 for every primitive type, and is the number of fields @@ -122,20 +156,6 @@ impl Type { } } -impl NumericType { - /// Returns true if the given Field value is within the numeric limits - /// for the current NumericType. - pub(crate) fn value_is_within_limits(self, field: FieldElement) -> bool { - match self { - NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { - let max = 2u128.pow(bit_size) - 1; - field <= max.into() - } - NumericType::NativeField => true, - } - } -} - /// Composite Types are essentially flattened struct or tuple types. /// Array types may have these as elements where each flattened field is /// included in the array sequentially. diff --git a/noir/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index e944d7d99d88..7d345a9a4abd 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -187,7 +187,7 @@ mod test { instruction::{BinaryOp, Instruction, TerminatorInstruction}, map::Id, types::Type, - value::{Value, ValueId}, + value::Value, }, }; @@ -280,11 +280,11 @@ mod test { let return_value_id = match entry_block.unwrap_terminator() { TerminatorInstruction::Return { return_values, .. } => return_values[0], - _ => unreachable!(), + _ => unreachable!("Should have terminator instruction"), }; let return_element = match &main.dfg[return_value_id] { Value::Array { array, .. } => array[0], - _ => unreachable!(), + _ => unreachable!("Return type should be array"), }; // The return element is expected to refer to the new add instruction result. assert_eq!(main.dfg.resolve(new_add_instr_result), main.dfg.resolve(return_element)); @@ -293,7 +293,7 @@ mod test { #[test] fn instruction_deduplication() { // fn main f0 { - // b0(v0: Field): + // b0(v0: u16): // v1 = cast v0 as u32 // v2 = cast v0 as u32 // constrain v1 v2 @@ -308,7 +308,7 @@ mod test { // Compiling main let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); - let v0 = builder.add_parameter(Type::field()); + let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.insert_cast(v0, Type::unsigned(32)); let v2 = builder.insert_cast(v0, Type::unsigned(32)); @@ -322,7 +322,7 @@ mod test { // Expected output: // // fn main f0 { - // b0(v0: Field): + // b0(v0: u16): // v1 = cast v0 as u32 // } let ssa = ssa.fold_constants(); @@ -332,6 +332,6 @@ mod test { assert_eq!(instructions.len(), 1); let instruction = &main.dfg[instructions[0]]; - assert_eq!(instruction, &Instruction::Cast(ValueId::test_new(0), Type::unsigned(32))); + assert_eq!(instruction, &Instruction::Cast(v0, Type::unsigned(32))); } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index fdd7c66684cb..6bdf2ab1c0af 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -1102,7 +1102,7 @@ mod test { let main = ssa.main(); let ret = match main.dfg[main.entry_block()].terminator() { Some(TerminatorInstruction::Return { return_values, .. }) => return_values[0], - _ => unreachable!(), + _ => unreachable!("Should have terminator instruction"), }; let merged_values = get_all_constants_reachable_from_instruction(&main.dfg, ret); @@ -1473,7 +1473,7 @@ mod test { None => unreachable!("Expected constant 200 for return value"), } } - _ => unreachable!(), + _ => unreachable!("Should have terminator instruction"), } } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 5724bf56e8e8..b34b667c31a7 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -275,6 +275,8 @@ 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); + + // We use unsafe casts here, this is fine as we're casting to a `field` type. 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); @@ -310,12 +312,12 @@ impl<'a> FunctionContext<'a> { match operator { BinaryOpKind::Add | BinaryOpKind::Subtract => { // Result is computed modulo the bit size - let mut result = - self.builder.insert_truncate(result, bit_size, bit_size + 1); - result = self.builder.insert_cast(result, Type::unsigned(bit_size)); + let result = self.builder.insert_truncate(result, bit_size, bit_size + 1); + let result = + self.insert_safe_cast(result, Type::unsigned(bit_size), location); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); - self.builder.insert_cast(result, result_type) + self.insert_safe_cast(result, result_type, location) } BinaryOpKind::Multiply => { // Result is computed modulo the bit size @@ -324,7 +326,7 @@ impl<'a> FunctionContext<'a> { 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) + self.insert_safe_cast(result, result_type, location) } BinaryOpKind::ShiftLeft | BinaryOpKind::ShiftRight => { self.check_shift_overflow(result, rhs, bit_size, location, true) @@ -349,12 +351,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 } } @@ -375,8 +376,11 @@ impl<'a> FunctionContext<'a> { 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 }; + let rhs = if is_signed { + self.insert_safe_cast(rhs, Type::unsigned(bit_size), location) + } else { + rhs + }; // Bit-shift with a negative number is an overflow if is_signed { // We compute the sign of rhs. @@ -432,8 +436,8 @@ impl<'a> FunctionContext<'a> { Type::unsigned(bit_size), ); // We compute the sign of the operands. The overflow checks for signed integers depends on these signs - let lhs_as_unsigned = self.builder.insert_cast(lhs, Type::unsigned(bit_size)); - let rhs_as_unsigned = self.builder.insert_cast(rhs, Type::unsigned(bit_size)); + let lhs_as_unsigned = self.insert_safe_cast(lhs, Type::unsigned(bit_size), location); + let rhs_as_unsigned = self.insert_safe_cast(rhs, Type::unsigned(bit_size), location); let lhs_sign = self.builder.insert_binary(lhs_as_unsigned, BinaryOp::Lt, half_width); let mut rhs_sign = self.builder.insert_binary(rhs_as_unsigned, BinaryOp::Lt, half_width); let message = if is_sub { @@ -464,18 +468,17 @@ 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 let not_same = self.builder.insert_binary(one, BinaryOp::Sub, same_sign); let not_same_sign_field = - self.builder.insert_cast(not_same, Type::unsigned(bit_size)); + self.insert_safe_cast(not_same, Type::unsigned(bit_size), location); let positive_maximum_with_offset = self.builder.insert_binary(half_width, BinaryOp::Add, not_same_sign_field); let product_overflow_check = @@ -665,6 +668,29 @@ impl<'a> FunctionContext<'a> { reshaped_return_values } + /// Inserts a cast instruction at the end of the current block and returns the results + /// of the cast. + /// + /// Compared to `self.builder.insert_cast`, this version will automatically truncate `value` to be a valid `typ`. + pub(super) fn insert_safe_cast( + &mut self, + mut value: ValueId, + typ: Type, + location: Location, + ) -> ValueId { + self.builder.set_location(location); + + // To ensure that `value` is a valid `typ`, we insert an `Instruction::Truncate` instruction beforehand if + // we're narrowing the type size. + let incoming_type_size = self.builder.type_of_value(value).bit_size(); + let target_type_size = typ.bit_size(); + if target_type_size < incoming_type_size { + value = self.builder.insert_truncate(value, target_type_size, incoming_type_size); + } + + self.builder.insert_cast(value, typ) + } + /// Create a const offset of an address for an array load or store pub(super) fn make_offset(&mut self, mut address: ValueId, offset: u128) -> ValueId { if offset != 0 { diff --git a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index c00fbbbcb405..0b8c3a37ef96 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -434,8 +434,8 @@ impl<'a> FunctionContext<'a> { fn codegen_cast(&mut self, cast: &ast::Cast) -> Result { let lhs = self.codegen_non_tuple_expression(&cast.lhs)?; let typ = Self::convert_non_tuple_type(&cast.r#type); - self.builder.set_location(cast.location); - Ok(self.builder.insert_cast(lhs, typ).into()) + + Ok(self.insert_safe_cast(lhs, typ, cast.location).into()) } /// Codegens a for loop, creating three new blocks in the process. diff --git a/noir/compiler/noirc_frontend/src/ast/mod.rs b/noir/compiler/noirc_frontend/src/ast/mod.rs index 5c10d3fe8f04..d9af5893024e 100644 --- a/noir/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/compiler/noirc_frontend/src/ast/mod.rs @@ -257,7 +257,20 @@ impl UnresolvedTypeExpression { BinaryOpKind::Multiply => BinaryTypeOperator::Multiplication, BinaryOpKind::Divide => BinaryTypeOperator::Division, BinaryOpKind::Modulo => BinaryTypeOperator::Modulo, - _ => unreachable!(), // impossible via operator_allowed check + + BinaryOpKind::Equal + | BinaryOpKind::NotEqual + | BinaryOpKind::Less + | BinaryOpKind::LessEqual + | BinaryOpKind::Greater + | BinaryOpKind::GreaterEqual + | BinaryOpKind::And + | BinaryOpKind::Or + | BinaryOpKind::Xor + | BinaryOpKind::ShiftRight + | BinaryOpKind::ShiftLeft => { + unreachable!("impossible via `operator_allowed` check") + } }; Ok(UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, expr.span)) } diff --git a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 8ada3faf756f..b1e559895b83 100644 --- a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -474,18 +474,18 @@ pub(crate) fn check_methods_signatures( 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); let func_name = resolver.interner.function_name(func_id).to_owned(); - let mut typecheck_errors = Vec::new(); - // This is None in the case where the impl block has a method that's not part of the trait. // 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) = trait_methods.iter().find(|method| method.name.0.contents == func_name) { - let impl_function_type = impl_method.typ.instantiate(resolver.interner); + let mut typecheck_errors = Vec::new(); + let impl_method = resolver.interner.function_meta(func_id); + + let (impl_function_type, _) = impl_method.typ.instantiate(resolver.interner); let impl_method_generic_count = impl_method.typ.generic_count() - trait_impl_generic_count; @@ -505,7 +505,7 @@ pub(crate) fn check_methods_signatures( errors.push((error.into(), *file_id)); } - if let Type::Function(impl_params, _, _) = impl_function_type.0 { + if let Type::Function(impl_params, _, _) = impl_function_type { if trait_method.arguments().len() == impl_params.len() { // Check the parameters of the impl method against the parameters of the trait method let args = trait_method.arguments().iter(); @@ -542,6 +542,7 @@ pub(crate) fn check_methods_signatures( // TODO: This is not right since it may bind generic return types trait_method.return_type().unify(&resolved_return_type, &mut typecheck_errors, || { + let impl_method = resolver.interner.function_meta(func_id); let ret_type_span = impl_method.return_type.get_type().span; let expr_span = ret_type_span.expect("return type must always have a span"); diff --git a/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs index 20f05532ce41..9c46ef35854f 100644 --- a/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -173,6 +173,29 @@ impl CrateDefMap { }) }) } + + /// Go through all modules in this crate, and find all functions in + /// each module with the #[export] attribute + pub fn get_all_exported_functions<'a>( + &'a self, + interner: &'a NodeInterner, + ) -> impl Iterator + 'a { + self.modules.iter().flat_map(|(_, module)| { + module.value_definitions().filter_map(|id| { + if let Some(func_id) = id.as_function() { + let attributes = interner.function_attributes(&func_id); + if attributes.secondary.contains(&SecondaryAttribute::Export) { + Some(func_id) + } else { + None + } + } else { + None + } + }) + }) + } + /// Go through all modules in this crate, find all `contract ... { ... }` declarations, /// and collect them all into a Vec. pub fn get_all_contracts(&self, interner: &NodeInterner) -> Vec { diff --git a/noir/compiler/noirc_frontend/src/hir/mod.rs b/noir/compiler/noirc_frontend/src/hir/mod.rs index 3683b17a27cc..c62f357167f0 100644 --- a/noir/compiler/noirc_frontend/src/hir/mod.rs +++ b/noir/compiler/noirc_frontend/src/hir/mod.rs @@ -152,7 +152,7 @@ impl Context<'_> { None } - pub fn function_meta(&self, func_id: &FuncId) -> FuncMeta { + pub fn function_meta(&self, func_id: &FuncId) -> &FuncMeta { self.def_interner.function_meta(func_id) } @@ -194,6 +194,19 @@ impl Context<'_> { .collect() } + pub fn get_all_exported_functions_in_crate(&self, crate_id: &CrateId) -> Vec<(String, FuncId)> { + let interner = &self.def_interner; + let def_map = self.def_map(crate_id).expect("The local crate should be analyzed already"); + + def_map + .get_all_exported_functions(interner) + .map(|function_id| { + let function_name = self.function_name(&function_id).to_owned(); + (function_name, function_id) + }) + .collect() + } + /// 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/noir/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/compiler/noirc_frontend/src/hir/type_check/expr.rs index caa778525602..50ed98a794ad 100644 --- a/noir/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -190,10 +190,11 @@ impl<'interner> TypeChecker<'interner> { // Automatically add `&mut` if the method expects a mutable reference and // the object is not already one. if *func_id != FuncId::dummy_id() { - let func_meta = self.interner.function_meta(func_id); + let function_type = + self.interner.function_meta(func_id).typ.clone(); self.try_add_mutable_reference_to_object( &mut method_call, - &func_meta.typ, + &function_type, &mut args, ); } @@ -561,7 +562,7 @@ impl<'interner> TypeChecker<'interner> { let func_meta = self.interner.function_meta(&func_id); let param_len = func_meta.parameters.len(); - (func_meta.typ, param_len) + (func_meta.typ.clone(), param_len) } HirMethodReference::TraitMethodId(method) => { let the_trait = self.interner.get_trait(method.trait_id); @@ -916,7 +917,7 @@ impl<'interner> TypeChecker<'interner> { &self.current_function.expect("unexpected method outside a function"), ); - for constraint in func_meta.trait_constraints { + for constraint in &func_meta.trait_constraints { if *object_type == constraint.typ { if let Some(the_trait) = self.interner.try_get_trait(constraint.trait_id) { for (method_index, method) in the_trait.methods.iter().enumerate() { diff --git a/noir/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/compiler/noirc_frontend/src/hir/type_check/mod.rs index 092e8631f1b4..c05c233fe34a 100644 --- a/noir/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -50,10 +50,15 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec Vec Vec Vec Vec Vec TypeChecker<'interner> { // Must push new lvalue to the interner, we've resolved any field indices self.interner.update_statement(stmt_id, |stmt| match stmt { HirStatement::Assign(assign) => assign.lvalue = new_lvalue, - _ => unreachable!(), + _ => unreachable!("statement is known to be assignment"), }); let span = self.interner.expr_span(&assign_stmt.expression); diff --git a/noir/compiler/noirc_frontend/src/hir_def/function.rs b/noir/compiler/noirc_frontend/src/hir_def/function.rs index 085bda107e38..9fff301f5f76 100644 --- a/noir/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/compiler/noirc_frontend/src/hir_def/function.rs @@ -131,22 +131,12 @@ impl FuncMeta { } } - pub fn into_function_signature(self) -> FunctionSignature { - // Doesn't use `self.return_type()` so we aren't working with references and don't need a `clone()` - let return_type = match self.typ { - Type::Function(_, ret, _env) => *ret, - Type::Forall(_, typ) => match *typ { - Type::Function(_, ret, _env) => *ret, - _ => unreachable!(), - }, - _ => unreachable!(), - }; - let return_type = match return_type { + pub fn function_signature(&self) -> FunctionSignature { + let return_type = match self.return_type() { Type::Unit => None, - typ => Some(typ), + typ => Some(typ.clone()), }; - - (self.parameters.0, return_type) + (self.parameters.0.clone(), return_type) } /// Gives the (uninstantiated) return type of this function. diff --git a/noir/compiler/noirc_frontend/src/hir_def/traits.rs b/noir/compiler/noirc_frontend/src/hir_def/traits.rs index ea9c2e2928cc..bbe4e1743d28 100644 --- a/noir/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/noir/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 @@ -65,6 +65,7 @@ pub struct Trait { pub self_type_typevar_id: TypeVariableId, pub self_type_typevar: TypeVariable, } + #[derive(Debug)] pub struct TraitImpl { pub ident: Ident, diff --git a/noir/compiler/noirc_frontend/src/hir_def/types.rs b/noir/compiler/noirc_frontend/src/hir_def/types.rs index 977293ec678e..9a9c0c047d1b 100644 --- a/noir/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/compiler/noirc_frontend/src/hir_def/types.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, cell::RefCell, collections::{BTreeSet, HashMap}, rc::Rc, @@ -299,7 +300,7 @@ impl std::fmt::Display for TypeAliasType { write!(f, "{}", self.name)?; if !self.generics.is_empty() { - let generics = vecmap(&self.generics, |(_, binding)| binding.0.borrow().to_string()); + let generics = vecmap(&self.generics, |(_, binding)| binding.borrow().to_string()); write!(f, "{}", generics.join(", "))?; } @@ -415,11 +416,11 @@ pub enum TypeVariableKind { /// A TypeVariable is a mutable reference that is either /// bound to some type, or unbound with a given TypeVariableId. #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct TypeVariable(Shared); +pub struct TypeVariable(TypeVariableId, Shared); impl TypeVariable { pub fn unbound(id: TypeVariableId) -> Self { - TypeVariable(Shared::new(TypeBinding::Unbound(id))) + TypeVariable(id, Shared::new(TypeBinding::Unbound(id))) } /// Bind this type variable to a value. @@ -428,7 +429,7 @@ impl TypeVariable { /// Also Panics if the ID of this TypeVariable occurs within the given /// binding, as that would cause an infinitely recursive type. pub fn bind(&self, typ: Type) { - let id = match &*self.0.borrow() { + let id = match &*self.1.borrow() { TypeBinding::Bound(binding) => { unreachable!("TypeVariable::bind, cannot bind bound var {} to {}", binding, typ) } @@ -436,11 +437,11 @@ impl TypeVariable { }; assert!(!typ.occurs(id)); - *self.0.borrow_mut() = TypeBinding::Bound(typ); + *self.1.borrow_mut() = TypeBinding::Bound(typ); } pub fn try_bind(&self, binding: Type, span: Span) -> Result<(), TypeCheckError> { - let id = match &*self.0.borrow() { + let id = match &*self.1.borrow() { TypeBinding::Bound(binding) => { unreachable!("Expected unbound, found bound to {binding}") } @@ -450,28 +451,28 @@ impl TypeVariable { if binding.occurs(id) { Err(TypeCheckError::TypeAnnotationsNeeded { span }) } else { - *self.0.borrow_mut() = TypeBinding::Bound(binding); + *self.1.borrow_mut() = TypeBinding::Bound(binding); Ok(()) } } /// Borrows this TypeVariable to (e.g.) manually match on the inner TypeBinding. pub fn borrow(&self) -> std::cell::Ref { - self.0.borrow() + self.1.borrow() } /// Unbind this type variable, setting it to Unbound(id). /// /// This is generally a logic error to use outside of monomorphization. pub fn unbind(&self, id: TypeVariableId) { - *self.0.borrow_mut() = TypeBinding::Unbound(id); + *self.1.borrow_mut() = TypeBinding::Unbound(id); } /// Forcibly bind a type variable to a new type - even if the type /// variable is already bound to a different type. This generally /// a logic error to use outside of monomorphization. pub fn force_bind(&self, typ: Type) { - *self.0.borrow_mut() = TypeBinding::Bound(typ); + *self.1.borrow_mut() = TypeBinding::Bound(typ); } } @@ -503,7 +504,7 @@ impl Type { } pub fn type_variable(id: TypeVariableId) -> Type { - let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + let var = TypeVariable::unbound(id); Type::TypeVariable(var, TypeVariableKind::Normal) } @@ -512,14 +513,14 @@ impl Type { pub fn constant_variable(length: u64, interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::Constant(length); - let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + let var = TypeVariable::unbound(id); Type::TypeVariable(var, kind) } pub fn polymorphic_integer(interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::IntegerOrField; - let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + let var = TypeVariable::unbound(id); Type::TypeVariable(var, kind) } @@ -529,7 +530,7 @@ impl Type { /// they shouldn't be bound over until monomorphization. pub fn is_bindable(&self) -> bool { match self { - Type::TypeVariable(binding, _) => match &*binding.0.borrow() { + Type::TypeVariable(binding, _) => match &*binding.borrow() { TypeBinding::Bound(binding) => binding.is_bindable(), TypeBinding::Unbound(_) => true, }, @@ -553,7 +554,7 @@ impl Type { // True if the given type is a NamedGeneric with the target_id let named_generic_id_matches_target = |typ: &Type| { if let Type::NamedGeneric(type_variable, _) = typ { - match &*type_variable.0.borrow() { + match &*type_variable.borrow() { TypeBinding::Bound(_) => { unreachable!("Named generics should not be bound until monomorphization") } @@ -653,7 +654,7 @@ impl Type { match self { Type::Forall(generics, _) => generics.len(), Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { - match &*type_variable.0.borrow() { + match &*type_variable.borrow() { TypeBinding::Bound(binding) => binding.generic_count(), TypeBinding::Unbound(_) => 0, } @@ -668,6 +669,25 @@ impl Type { let polymorphic_type_vars = vecmap(type_bindings, |(id, (type_var, _))| (id, type_var)); Type::Forall(polymorphic_type_vars, Box::new(self)) } + + /// Return this type as a monomorphic type - without a `Type::Forall` if there is one. + /// This is only a shallow check since Noir's type system prohibits `Type::Forall` anywhere + /// inside other types. + pub fn as_monotype(&self) -> &Type { + match self { + Type::Forall(_, typ) => typ.as_ref(), + other => other, + } + } + + /// Return the generics and type within this `Type::Forall`. + /// Panics if `self` is not `Type::Forall` + pub fn unwrap_forall(&self) -> (Cow, &Type) { + match self { + Type::Forall(generics, typ) => (Cow::Borrowed(generics), typ.as_ref()), + other => (Cow::Owned(Generics::new()), other), + } + } } impl std::fmt::Display for Type { @@ -687,23 +707,23 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{num_bits}"), Signedness::Unsigned => write!(f, "u{num_bits}"), }, - Type::TypeVariable(var, TypeVariableKind::Normal) => write!(f, "{}", var.0.borrow()), + Type::TypeVariable(var, TypeVariableKind::Normal) => write!(f, "{}", var.borrow()), Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { - if let TypeBinding::Unbound(_) = &*binding.0.borrow() { + if let TypeBinding::Unbound(_) = &*binding.borrow() { // Show a Field by default if this TypeVariableKind::IntegerOrField is unbound, since that is // what they bind to by default anyway. It is less confusing than displaying it // as a generic. write!(f, "Field") } else { - write!(f, "{}", binding.0.borrow()) + write!(f, "{}", binding.borrow()) } } Type::TypeVariable(binding, TypeVariableKind::Constant(n)) => { - if let TypeBinding::Unbound(_) = &*binding.0.borrow() { + if let TypeBinding::Unbound(_) = &*binding.borrow() { // TypeVariableKind::Constant(n) binds to Type::Constant(n) by default, so just show that. write!(f, "{n}") } else { - write!(f, "{}", binding.0.borrow()) + write!(f, "{}", binding.borrow()) } } Type::Struct(s, args) => { @@ -728,7 +748,7 @@ impl std::fmt::Display for Type { } Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), - Type::NamedGeneric(binding, name) => match &*binding.0.borrow() { + Type::NamedGeneric(binding, name) => match &*binding.borrow() { TypeBinding::Bound(binding) => binding.fmt(f), TypeBinding::Unbound(_) if name.is_empty() => write!(f, "_"), TypeBinding::Unbound(_) => write!(f, "{name}"), @@ -795,7 +815,7 @@ impl Type { target_length: u64, bindings: &mut TypeBindings, ) -> Result<(), UnificationError> { - let target_id = match &*var.0.borrow() { + let target_id = match &*var.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; @@ -814,7 +834,7 @@ impl Type { // A TypeVariable is less specific than a MaybeConstant, so we bind // to the other type variable instead. Type::TypeVariable(new_var, kind) => { - let borrow = new_var.0.borrow(); + let borrow = new_var.borrow(); match &*borrow { TypeBinding::Bound(typ) => { typ.try_bind_to_maybe_constant(var, target_length, bindings) @@ -862,7 +882,7 @@ impl Type { var: &TypeVariable, bindings: &mut TypeBindings, ) -> Result<(), UnificationError> { - let target_id = match &*var.0.borrow() { + let target_id = match &*var.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; @@ -875,7 +895,7 @@ impl Type { Ok(()) } Type::TypeVariable(self_var, TypeVariableKind::IntegerOrField) => { - let borrow = self_var.0.borrow(); + let borrow = self_var.borrow(); match &*borrow { TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var, bindings), // Avoid infinitely recursive bindings @@ -887,7 +907,7 @@ impl Type { } } Type::TypeVariable(binding, TypeVariableKind::Normal) => { - let borrow = binding.0.borrow(); + let borrow = binding.borrow(); match &*borrow { TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var, bindings), // Avoid infinitely recursive bindings @@ -917,7 +937,7 @@ impl Type { var: &TypeVariable, bindings: &mut TypeBindings, ) -> Result<(), UnificationError> { - let target_id = match &*var.0.borrow() { + let target_id = match &*var.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; @@ -945,7 +965,7 @@ impl Type { fn get_inner_type_variable(&self) -> Option> { match self { - Type::TypeVariable(var, _) | Type::NamedGeneric(var, _) => Some(var.0.clone()), + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _) => Some(var.1.clone()), _ => None, } } @@ -1041,9 +1061,9 @@ impl Type { } (NamedGeneric(binding, _), other) | (other, NamedGeneric(binding, _)) - if !binding.0.borrow().is_unbound() => + if !binding.borrow().is_unbound() => { - if let TypeBinding::Bound(link) = &*binding.0.borrow() { + if let TypeBinding::Bound(link) = &*binding.borrow() { link.try_unify(other, bindings) } else { unreachable!("If guard ensures binding is bound") @@ -1052,8 +1072,8 @@ impl Type { (NamedGeneric(binding_a, name_a), NamedGeneric(binding_b, name_b)) => { // Bound NamedGenerics are caught by the check above - assert!(binding_a.0.borrow().is_unbound()); - assert!(binding_b.0.borrow().is_unbound()); + assert!(binding_a.borrow().is_unbound()); + assert!(binding_b.borrow().is_unbound()); if name_a == name_b { Ok(()) @@ -1101,7 +1121,7 @@ impl Type { // bind to the given type or not. bind_variable: impl FnOnce(&mut TypeBindings) -> Result<(), UnificationError>, ) -> Result<(), UnificationError> { - match &*type_variable.0.borrow() { + match &*type_variable.borrow() { // If it is already bound, unify against what it is bound to TypeBinding::Bound(link) => link.try_unify(self, bindings), TypeBinding::Unbound(id) => { @@ -1245,7 +1265,7 @@ impl Type { }) .collect(); - let instantiated = typ.substitute(&replacements); + let instantiated = typ.force_substitute(&replacements); (instantiated, replacements) } other => (other.clone(), HashMap::new()), @@ -1314,7 +1334,7 @@ impl Type { } Type::Forall(_, typ) => typ.find_all_unbound_type_variables(type_variables), Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { - match &*type_variable.0.borrow() { + match &*type_variable.borrow() { TypeBinding::Bound(binding) => { binding.find_all_unbound_type_variables(type_variables); } @@ -1332,64 +1352,106 @@ impl Type { /// given bindings if found. If a type variable is not found within /// the given TypeBindings, it is unchanged. pub fn substitute(&self, type_bindings: &TypeBindings) -> Type { + self.substitute_helper(type_bindings, false) + } + + /// Forcibly substitute any type variables found within this type with the + /// given bindings if found. If a type variable is not found within + /// the given TypeBindings, it is unchanged. + /// + /// Compared to `substitute`, this function will also substitute any type variables + /// from type_bindings, even if they are bound in `self`. Since this can undo previous + /// bindings, this function should be avoided unless necessary. Currently, it is only + /// needed when handling bindings between trait methods and their corresponding impl + /// method during monomorphization. + pub fn force_substitute(&self, type_bindings: &TypeBindings) -> Type { + self.substitute_helper(type_bindings, true) + } + + /// This helper function only differs in the additional parameter which, if set, + /// allows substitutions on already-bound type variables. This should be `false` + /// for most uses, but is currently needed during monomorphization when instantiating + /// trait functions to shed any previous bindings from recursive parent calls to the + /// same trait. + fn substitute_helper( + &self, + type_bindings: &TypeBindings, + substitute_bound_typevars: bool, + ) -> Type { if type_bindings.is_empty() { return self.clone(); } - let substitute_binding = |binding: &TypeVariable| match &*binding.0.borrow() { - TypeBinding::Bound(binding) => binding.substitute(type_bindings), - TypeBinding::Unbound(id) => match type_bindings.get(id) { - Some((_, binding)) => binding.clone(), - None => self.clone(), - }, + let substitute_binding = |binding: &TypeVariable| { + // Check the id first to allow substituting to + // type variables that have already been bound over. + // This is neede for monomorphizing trait impl methods. + match type_bindings.get(&binding.0) { + Some((_, binding)) if substitute_bound_typevars => binding.clone(), + _ => match &*binding.borrow() { + TypeBinding::Bound(binding) => { + binding.substitute_helper(type_bindings, substitute_bound_typevars) + } + TypeBinding::Unbound(id) => match type_bindings.get(id) { + Some((_, binding)) => binding.clone(), + None => self.clone(), + }, + }, + } }; match self { Type::Array(size, element) => { - let size = Box::new(size.substitute(type_bindings)); - let element = Box::new(element.substitute(type_bindings)); - Type::Array(size, element) + let size = size.substitute_helper(type_bindings, substitute_bound_typevars); + let element = element.substitute_helper(type_bindings, substitute_bound_typevars); + Type::Array(Box::new(size), Box::new(element)) } Type::String(size) => { - let size = Box::new(size.substitute(type_bindings)); - Type::String(size) + let size = size.substitute_helper(type_bindings, substitute_bound_typevars); + Type::String(Box::new(size)) } Type::FmtString(size, fields) => { - let size = Box::new(size.substitute(type_bindings)); - let fields = Box::new(fields.substitute(type_bindings)); - Type::FmtString(size, fields) + let size = size.substitute_helper(type_bindings, substitute_bound_typevars); + let fields = fields.substitute_helper(type_bindings, substitute_bound_typevars); + Type::FmtString(Box::new(size), Box::new(fields)) } Type::NamedGeneric(binding, _) | Type::TypeVariable(binding, _) => { substitute_binding(binding) } - // Do not substitute fields, it can lead to infinite recursion + // Do not substitute_helper fields, it ca, substitute_bound_typevarsn lead to infinite recursion // and we should not match fields when type checking anyway. Type::Struct(fields, args) => { - let args = vecmap(args, |arg| arg.substitute(type_bindings)); + let args = vecmap(args, |arg| { + arg.substitute_helper(type_bindings, substitute_bound_typevars) + }); Type::Struct(fields.clone(), args) } Type::Tuple(fields) => { - let fields = vecmap(fields, |field| field.substitute(type_bindings)); + let fields = vecmap(fields, |field| { + field.substitute_helper(type_bindings, substitute_bound_typevars) + }); Type::Tuple(fields) } Type::Forall(typevars, typ) => { - // Trying to substitute a variable defined within a nested Forall + // Trying to substitute_helper a variable de, substitute_bound_typevarsfined within a nested Forall // is usually impossible and indicative of an error in the type checker somewhere. for (var, _) in typevars { assert!(!type_bindings.contains_key(var)); } - let typ = Box::new(typ.substitute(type_bindings)); + let typ = Box::new(typ.substitute_helper(type_bindings, substitute_bound_typevars)); Type::Forall(typevars.clone(), typ) } Type::Function(args, ret, env) => { - let args = vecmap(args, |arg| arg.substitute(type_bindings)); - let ret = Box::new(ret.substitute(type_bindings)); - let env = Box::new(env.substitute(type_bindings)); + let args = vecmap(args, |arg| { + arg.substitute_helper(type_bindings, substitute_bound_typevars) + }); + let ret = Box::new(ret.substitute_helper(type_bindings, substitute_bound_typevars)); + let env = Box::new(env.substitute_helper(type_bindings, substitute_bound_typevars)); Type::Function(args, ret, env) } - Type::MutableReference(element) => { - Type::MutableReference(Box::new(element.substitute(type_bindings))) - } + Type::MutableReference(element) => Type::MutableReference(Box::new( + element.substitute_helper(type_bindings, substitute_bound_typevars), + )), Type::FieldElement | Type::Integer(_, _) @@ -1415,7 +1477,7 @@ impl Type { 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, _) => { - match &*binding.0.borrow() { + match &*binding.borrow() { TypeBinding::Bound(binding) => binding.occurs(target_id), TypeBinding::Unbound(id) => *id == target_id, } @@ -1465,7 +1527,7 @@ impl Type { } Tuple(args) => Tuple(vecmap(args, |arg| arg.follow_bindings())), TypeVariable(var, _) | NamedGeneric(var, _) => { - if let TypeBinding::Bound(typ) = &*var.0.borrow() { + if let TypeBinding::Bound(typ) = &*var.borrow() { return typ.follow_bindings(); } self.clone() @@ -1570,7 +1632,7 @@ impl From<&Type> for PrintableType { Signedness::Signed => PrintableType::SignedInteger { width: *bit_width }, }, Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { - match &*binding.0.borrow() { + match &*binding.borrow() { TypeBinding::Bound(typ) => typ.into(), TypeBinding::Unbound(_) => Type::default_int_type().into(), } diff --git a/noir/compiler/noirc_frontend/src/lexer/token.rs b/noir/compiler/noirc_frontend/src/lexer/token.rs index e6542c643ad9..ab131ccd8803 100644 --- a/noir/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/compiler/noirc_frontend/src/lexer/token.rs @@ -510,6 +510,7 @@ impl Attribute { Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod) } ["event"] => Attribute::Secondary(SecondaryAttribute::Event), + ["export"] => Attribute::Secondary(SecondaryAttribute::Export), ["deprecated", name] => { if !name.starts_with('"') && !name.ends_with('"') { return Err(LexerErrorKind::MalformedFuncAttribute { @@ -588,6 +589,7 @@ pub enum SecondaryAttribute { // the entry point. ContractLibraryMethod, Event, + Export, Field(String), Custom(String), } @@ -602,6 +604,7 @@ impl fmt::Display for SecondaryAttribute { SecondaryAttribute::Custom(ref k) => write!(f, "#[{k}]"), SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"), SecondaryAttribute::Event => write!(f, "#[event]"), + SecondaryAttribute::Export => write!(f, "#[export]"), SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"), } } @@ -625,7 +628,7 @@ impl AsRef for SecondaryAttribute { SecondaryAttribute::Deprecated(None) => "", SecondaryAttribute::Custom(string) | SecondaryAttribute::Field(string) => string, SecondaryAttribute::ContractLibraryMethod => "", - SecondaryAttribute::Event => "", + SecondaryAttribute::Event | SecondaryAttribute::Export => "", } } } diff --git a/noir/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/compiler/noirc_frontend/src/monomorphization/mod.rs index bb0972987e45..3510475e881a 100644 --- a/noir/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -20,14 +20,14 @@ use std::{ use crate::{ hir_def::{ expr::*, - function::{FuncMeta, FunctionSignature, Parameters}, + function::{FunctionSignature, Parameters}, stmt::{HirAssignStatement, HirLValue, HirLetStatement, HirPattern, HirStatement}, types, }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, - Visibility, + ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariable, + TypeVariableId, TypeVariableKind, UnaryOp, Visibility, }; use self::ast::{Definition, FuncId, Function, LocalId, Program}; @@ -58,8 +58,9 @@ struct Monomorphizer<'interner> { /// confuse users. locals: HashMap, - /// Queue of functions to monomorphize next - queue: VecDeque<(node_interner::FuncId, FuncId, TypeBindings)>, + /// Queue of functions to monomorphize next each item in the queue is a tuple of: + /// (old_id, new_monomorphized_id, any type bindings to apply, the trait method if old_id is from a trait impl) + queue: VecDeque<(node_interner::FuncId, FuncId, TypeBindings, Option)>, /// When a function finishes being monomorphized, the monomorphized ast::Function is /// stored here along with its FuncId. @@ -97,23 +98,25 @@ pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Pro let function_sig = monomorphizer.compile_main(main); while !monomorphizer.queue.is_empty() { - let (next_fn_id, new_id, bindings) = monomorphizer.queue.pop_front().unwrap(); + let (next_fn_id, new_id, bindings, trait_method) = monomorphizer.queue.pop_front().unwrap(); monomorphizer.locals.clear(); perform_instantiation_bindings(&bindings); + let impl_bindings = monomorphizer.perform_impl_bindings(trait_method, next_fn_id); monomorphizer.function(next_fn_id, new_id); + undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(bindings); } let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); - let FuncMeta { return_distinctness, return_visibility, .. } = interner.function_meta(&main); + let meta = interner.function_meta(&main); Program::new( functions, function_sig, - return_distinctness, + meta.return_distinctness, monomorphizer.return_location, - return_visibility, + meta.return_visibility, ) } @@ -154,6 +157,7 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::FuncId, expr_id: node_interner::ExprId, typ: &HirType, + trait_method: Option, ) -> Definition { let typ = typ.follow_bindings(); match self.globals.get(&id).and_then(|inner_map| inner_map.get(&typ)) { @@ -177,7 +181,7 @@ impl<'interner> Monomorphizer<'interner> { Definition::Builtin(opcode) } FunctionKind::Normal => { - let id = self.queue_function(id, expr_id, typ); + let id = self.queue_function(id, expr_id, typ, trait_method); Definition::Function(id) } FunctionKind::Oracle => { @@ -217,7 +221,7 @@ impl<'interner> Monomorphizer<'interner> { }, ); let main_meta = self.interner.function_meta(&main_id); - main_meta.into_function_signature() + main_meta.function_signature() } fn function(&mut self, f: node_interner::FuncId, id: FuncId) { @@ -237,7 +241,7 @@ impl<'interner> Monomorphizer<'interner> { _ => meta.return_type(), }); - let parameters = self.parameters(meta.parameters); + let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id); let unconstrained = modifiers.is_unconstrained @@ -254,17 +258,17 @@ impl<'interner> Monomorphizer<'interner> { /// Monomorphize each parameter, expanding tuple/struct patterns into multiple parameters /// and binding any generic types found. - fn parameters(&mut self, params: Parameters) -> Vec<(ast::LocalId, bool, String, ast::Type)> { + fn parameters(&mut self, params: &Parameters) -> Vec<(ast::LocalId, bool, String, ast::Type)> { let mut new_params = Vec::with_capacity(params.len()); - for parameter in params { - self.parameter(parameter.0, ¶meter.1, &mut new_params); + for (parameter, typ, _) in ¶ms.0 { + self.parameter(parameter, typ, &mut new_params); } new_params } fn parameter( &mut self, - param: HirPattern, + param: &HirPattern, typ: &HirType, new_params: &mut Vec<(ast::LocalId, bool, String, ast::Type)>, ) { @@ -276,11 +280,11 @@ impl<'interner> Monomorphizer<'interner> { new_params.push((new_id, definition.mutable, name, self.convert_type(typ))); self.define_local(ident.id, new_id); } - HirPattern::Mutable(pattern, _) => self.parameter(*pattern, typ, new_params), + HirPattern::Mutable(pattern, _) => self.parameter(pattern, typ, new_params), HirPattern::Tuple(fields, _) => { let tuple_field_types = unwrap_tuple_type(typ); - for (field, typ) in fields.into_iter().zip(tuple_field_types) { + for (field, typ) in fields.iter().zip(tuple_field_types) { self.parameter(field, &typ, new_params); } } @@ -288,7 +292,8 @@ impl<'interner> Monomorphizer<'interner> { let struct_field_types = unwrap_struct_type(typ); assert_eq!(struct_field_types.len(), fields.len()); - let mut fields = btree_map(fields, |(name, field)| (name.0.contents, field)); + let mut fields = + btree_map(fields, |(name, field)| (name.0.contents.clone(), field)); // Iterate over `struct_field_types` since `unwrap_struct_type` will always // return the fields in the order defined by the struct type. @@ -684,7 +689,7 @@ impl<'interner> Monomorphizer<'interner> { let location = Some(ident.location); let name = definition.name.clone(); let typ = self.interner.id_type(expr_id); - let definition = self.lookup_function(*func_id, expr_id, &typ); + let definition = self.lookup_function(*func_id, expr_id, &typ, None); let typ = self.convert_type(&typ); let ident = ast::Ident { location, mutable, definition, name, typ: typ.clone() }; let ident_expression = ast::Expression::Ident(ident); @@ -856,7 +861,7 @@ impl<'interner> Monomorphizer<'interner> { .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 { + let func_id = match trait_impl { node_interner::TraitImplKind::Normal(impl_id) => { self.interner.get_trait_implementation(impl_id).borrow().methods [method.method_index] @@ -884,7 +889,7 @@ impl<'interner> Monomorphizer<'interner> { } }; - let func_def = self.lookup_function(hir_func_id, expr_id, &function_type); + let func_def = self.lookup_function(func_id, expr_id, &function_type, Some(method)); let func_id = match func_def { Definition::Function(func_id) => func_id, _ => unreachable!(), @@ -1106,14 +1111,14 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::FuncId, expr_id: node_interner::ExprId, function_type: HirType, + trait_method: Option, ) -> FuncId { let new_id = self.next_function_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); - - self.queue.push_back((id, new_id, bindings)); + self.queue.push_back((id, new_id, bindings, trait_method)); new_id } @@ -1183,7 +1188,7 @@ impl<'interner> Monomorphizer<'interner> { let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let parameters = self.parameters(parameters); + let parameters = self.parameters(¶meters); let body = self.expr(lambda.body); let id = self.next_function_id(); @@ -1234,7 +1239,7 @@ impl<'interner> Monomorphizer<'interner> { let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let mut converted_parameters = self.parameters(parameters); + let mut converted_parameters = self.parameters(¶meters); let id = self.next_function_id(); let name = lambda_name.to_owned(); @@ -1502,6 +1507,46 @@ impl<'interner> Monomorphizer<'interner> { result } + + /// Call sites are instantiated against the trait method, but when an impl is later selected, + /// the corresponding method in the impl will have a different set of generics. `perform_impl_bindings` + /// is needed to apply the generics from the trait method to the impl method. Without this, + /// static method references to generic impls (e.g. `Eq::eq` for `[T; N]`) will fail to re-apply + /// the correct type bindings during monomorphization. + fn perform_impl_bindings( + &self, + trait_method: Option, + impl_method: node_interner::FuncId, + ) -> TypeBindings { + let mut bindings = TypeBindings::new(); + + if let Some(trait_method) = trait_method { + let the_trait = self.interner.get_trait(trait_method.trait_id); + + let trait_method_type = the_trait.methods[trait_method.method_index].typ.as_monotype(); + + // Make each NamedGeneric in this type bindable by replacing it with a TypeVariable + // with the same internal id and binding. + let (generics, impl_method_type) = + self.interner.function_meta(&impl_method).typ.unwrap_forall(); + + let replace_type_variable = |(id, var): &(TypeVariableId, TypeVariable)| { + (*id, (var.clone(), Type::TypeVariable(var.clone(), TypeVariableKind::Normal))) + }; + + // Replace each NamedGeneric with a TypeVariable containing the same internal type variable + let type_bindings = generics.iter().map(replace_type_variable).collect(); + let impl_method_type = impl_method_type.force_substitute(&type_bindings); + + trait_method_type.try_unify(&impl_method_type, &mut bindings).unwrap_or_else(|_| { + unreachable!("Impl method type {} does not unify with trait method type {} during monomorphization", impl_method_type, trait_method_type) + }); + + perform_instantiation_bindings(&bindings); + } + + bindings + } } fn unwrap_tuple_type(typ: &HirType) -> Vec { diff --git a/noir/compiler/noirc_frontend/src/node_interner.rs b/noir/compiler/noirc_frontend/src/node_interner.rs index 9082df1bcd52..e0170ec914fa 100644 --- a/noir/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/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 @@ -767,12 +768,12 @@ impl NodeInterner { } /// Returns the interned meta data corresponding to `func_id` - pub fn function_meta(&self, func_id: &FuncId) -> FuncMeta { - self.func_meta.get(func_id).cloned().expect("ice: all function ids should have metadata") + pub fn function_meta(&self, func_id: &FuncId) -> &FuncMeta { + self.func_meta.get(func_id).expect("ice: all function ids should have metadata") } - pub fn try_function_meta(&self, func_id: &FuncId) -> Option { - self.func_meta.get(func_id).cloned() + pub fn try_function_meta(&self, func_id: &FuncId) -> Option<&FuncMeta> { + self.func_meta.get(func_id) } pub fn function_ident(&self, func_id: &FuncId) -> crate::Ident { @@ -1103,7 +1104,10 @@ impl NodeInterner { recursion_limit: u32, ) -> Result<(), Vec> { for constraint in where_clause { - let constraint_type = constraint.typ.substitute(instantiation_bindings); + // Instantiation bindings are generally safe to force substitute into the same type. + // This is needed here to undo any bindings done to trait methods by monomorphization. + // Otherwise, an impl for (A, B) could get narrowed to only an impl for e.g. (u8, u16). + let constraint_type = constraint.typ.force_substitute(instantiation_bindings); let constraint_type = constraint_type.substitute(type_bindings); self.lookup_trait_implementation_helper( @@ -1142,6 +1146,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 +1279,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 +1436,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 { diff --git a/noir/compiler/noirc_frontend/src/parser/parser.rs b/noir/compiler/noirc_frontend/src/parser/parser.rs index 660c85759b97..b149eb24f073 100644 --- a/noir/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/compiler/noirc_frontend/src/parser/parser.rs @@ -312,7 +312,7 @@ fn function_return_type() -> impl NoirParser<((Distinctness, Visibility), Functi fn attribute() -> impl NoirParser { token_kind(TokenKind::Attribute).map(|token| match token { Token::Attribute(attribute) => attribute, - _ => unreachable!(), + _ => unreachable!("Parser should have already errored due to token not being an attribute"), }) } @@ -369,7 +369,7 @@ fn function_parameters<'a>(allow_self: bool) -> impl NoirParser> + 'a /// This parser always parses no input and fails fn nothing() -> impl NoirParser { - one_of([]).map(|_| unreachable!()) + one_of([]).map(|_| unreachable!("parser should always error")) } fn self_parameter() -> impl NoirParser { diff --git a/noir/compiler/wasm/src/compile.rs b/noir/compiler/wasm/src/compile.rs index c6ae0ae1f424..54fdccf13693 100644 --- a/noir/compiler/wasm/src/compile.rs +++ b/noir/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/noir/compiler/wasm/src/compile_new.rs b/noir/compiler/wasm/src/compile_new.rs index 0cd1a2c50e59..9ac080ffcaef 100644 --- a/noir/compiler/wasm/src/compile_new.rs +++ b/noir/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::{ @@ -79,11 +79,12 @@ impl CompilerContext { 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)); + ) -> Result<(), JsCompileError> { + let parsed_crate_name: CrateName = + crate_name.parse().map_err(|err_string| JsCompileError::new(err_string, Vec::new()))?; + add_dep(&mut self.context, from.0, to.0, parsed_crate_name); + Ok(()) } pub fn compile_program( @@ -108,7 +109,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 +134,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)) } } @@ -188,7 +189,7 @@ pub fn compile_( crate_names.insert(lib_name.clone(), crate_id); // Add the dependency edges - compiler_context.add_dependency_edge(lib_name_string, &root_id, &crate_id); + compiler_context.add_dependency_edge(lib_name_string, &root_id, &crate_id)?; } // Process the transitive dependencies of the root @@ -207,7 +208,11 @@ pub fn compile_( .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); + compiler_context.add_dependency_edge( + dependency_name_string, + &crate_id, + dep_crate_id, + )?; } } @@ -278,8 +283,8 @@ mod test { 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); + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id).unwrap(); + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id).unwrap(); assert_eq!(context.crate_graph().number_of_crates(), 3); } @@ -303,9 +308,9 @@ mod test { 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); + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id).unwrap(); + context.add_dependency_edge("lib2".to_string(), &lib1_crate_id, &lib2_crate_id).unwrap(); + context.add_dependency_edge("lib3".to_string(), &lib2_crate_id, &lib3_crate_id).unwrap(); assert_eq!(context.crate_graph().number_of_crates(), 5); } @@ -328,8 +333,8 @@ mod test { 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); + context.add_dependency_edge("lib1".to_string(), &root_crate_id, &lib1_crate_id).unwrap(); + context.add_dependency_edge("lib3".to_string(), &lib2_crate_id, &lib3_crate_id).unwrap(); assert_eq!(context.crate_graph().number_of_crates(), 5); } diff --git a/noir/cspell.json b/noir/cspell.json index 94449a68a773..8e3f248acfae 100644 --- a/noir/cspell.json +++ b/noir/cspell.json @@ -11,12 +11,13 @@ "arity", "arkworks", "arraysort", + "barebones", "barretenberg", "bincode", "bindgen", "bitand", - "bitxor", "bitor", + "bitxor", "blackbox", "bridgekeeper", "brillig", @@ -29,6 +30,7 @@ "chumsky", "clippy", "codegen", + "codegenned", "codegens", "Codespaces", "codespan", @@ -81,6 +83,7 @@ "jmpif", "jmpifs", "jmps", + "jsdoc", "Jubjub", "keccak", "krate", @@ -96,6 +99,7 @@ "montcurve", "nand", "nargo", + "neovim", "newtype", "nightlies", "nixpkgs", diff --git a/noir/docs/docs/noir/concepts/data_types/strings.md b/noir/docs/docs/noir/concepts/data_types/strings.md index 8d76d4ca654c..311dfd644168 100644 --- a/noir/docs/docs/noir/concepts/data_types/strings.md +++ b/noir/docs/docs/noir/concepts/data_types/strings.md @@ -17,13 +17,13 @@ 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). +`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); + println(message); assert(message == "hello world"); assert(hex_as_string == "0x41"); } diff --git a/noir/docs/docs/noir/concepts/data_types/vectors.mdx b/noir/docs/docs/noir/concepts/data_types/vectors.mdx index 10e35711b74b..aed13183719e 100644 --- a/noir/docs/docs/noir/concepts/data_types/vectors.mdx +++ b/noir/docs/docs/noir/concepts/data_types/vectors.mdx @@ -14,8 +14,6 @@ A vector is a collection type similar to Rust's Vector type. It's convenient way Example: ```rust -use dep::std::collections::vec::Vec; - let mut vector: Vec = Vec::new(); for i in 0..5 { vector.push(i); diff --git a/noir/docs/docs/noir/concepts/generics.md b/noir/docs/docs/noir/concepts/generics.md index 443ca2b45a5a..ec2db95839ab 100644 --- a/noir/docs/docs/noir/concepts/generics.md +++ b/noir/docs/docs/noir/concepts/generics.md @@ -30,25 +30,15 @@ struct RepeatedValue { } 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); + println(self.value); } } } fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); + let repeated = RepeatedValue { value: "Hello!", count: 2 }; repeated.print(); } ``` @@ -80,35 +70,37 @@ impl BigInt { ## 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? +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: ```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result + array1[0] == array2[0] } } fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); - // 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 + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in let array = [MyStruct::new(), MyStruct::new()]; assert(array_eq(array, array, MyStruct::eq)); } + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} ``` -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). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/noir/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx index 1e686303c182..aa4fb8cbaedb 100644 --- a/noir/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx +++ b/noir/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -21,7 +21,7 @@ example ```rust fn main(x : Field) { let scal = std::scalar_mul::fixed_base_embedded_curve(x); - std::println(scal); + println(scal); } ``` diff --git a/noir/docs/docs/noir/standard_library/logging.md b/noir/docs/docs/noir/standard_library/logging.md index 2e163b52ab32..db75ef9f86fa 100644 --- a/noir/docs/docs/noir/standard_library/logging.md +++ b/noir/docs/docs/noir/standard_library/logging.md @@ -27,18 +27,19 @@ It is recommended to use `nargo execute` if you want to debug failing constraint 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, + 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!"); +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); } ``` @@ -46,22 +47,22 @@ You can print different types in the same statement (including strings) with a t ```rust let fmt_str = f"i: {i}, j: {j}"; - std::println(fmt_str); + println(fmt_str); let s = myStruct { y: x, x: y }; - std::println(s); + println(s); - std::println(f"i: {i}, s: {s}"); + println(f"i: {i}, s: {s}"); - std::println(x); - std::println([x, y]); + println(x); + println([x, y]); let foo = fooStruct { my_struct: s, foo: 15 }; - std::println(f"s: {s}, foo: {foo}"); + 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 + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 ``` Examples shown above are interchangeable between the two `print` statements: @@ -69,9 +70,9 @@ Examples shown above are interchangeable between the two `print` statements: ```rust let person = Person { age : age, height : height }; -std::println(person); -std::print(person); +println(person); +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 +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line ``` diff --git a/noir/docs/docs/noir/standard_library/merkle_trees.md b/noir/docs/docs/noir/standard_library/merkle_trees.md index 5b45617812ac..fa4886778840 100644 --- a/noir/docs/docs/noir/standard_library/merkle_trees.md +++ b/noir/docs/docs/noir/standard_library/merkle_trees.md @@ -45,7 +45,7 @@ fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3] 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); + println(root); } ``` diff --git a/noir/docs/docs/noir/standard_library/options.md b/noir/docs/docs/noir/standard_library/options.md index 3d3139fb98b8..970c9cfbf11d 100644 --- a/noir/docs/docs/noir/standard_library/options.md +++ b/noir/docs/docs/noir/standard_library/options.md @@ -11,11 +11,9 @@ struct Option { } ``` -You can import the Option type into your Noir program like so: +The `Option` type, already imported into your Noir program, can be used directly: ```rust -use dep::std::option::Option; - fn main() { let none = Option::none(); let some = Option::some(3); diff --git a/noir/docs/docs/tutorials/noirjs_app.md b/noir/docs/docs/tutorials/noirjs_app.md index 302ee4aeadea..4293aa053fcc 100644 --- a/noir/docs/docs/tutorials/noirjs_app.md +++ b/noir/docs/docs/tutorials/noirjs_app.md @@ -1,37 +1,63 @@ --- -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] +title: Building a web app with NoirJS +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, app] 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. +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). -## Before we start +## Setup :::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. +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.19.x matches `noir_js@0.19.x`, etc. -In this guide, we will be pinned to 0.17.0. +In this guide, we will be pinned to 0.19.4. ::: -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). +Before we start, we want to make sure we have Node and Nargo installed. -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: +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -```bash -nargo compile +As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash ``` -Your folder structure should look like: +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +```nargo new circuit``` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +```nargo compile``` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: ```tree . -└── circuit +└── circuit <---- our working directory ├── Nargo.toml ├── src │ └── main.nr @@ -39,84 +65,46 @@ Your folder structure should look like: └── 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. +### Node and Vite -## Installing dependencies +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/create_a_project) guide. However, we want our app to run on the browser, so we need Vite. -We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. -```bash -npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 -``` +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". -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: +You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: ```bash -npm i --save-dev vite rollup-plugin-copy +npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 ``` -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" -``` +:::info -If you want do build a static website, you can also add some build and preview scripts: +At this point in the tutorial, your folder structure should look like this: -```json - "build": "vite build", - "preview": "vite preview" +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... ``` -## 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. +#### Some cleanup -```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 : [], - ], - }; - } +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. - return {}; -}); -``` +![my heart is ready for you, noir.js](../../static/img/memes/titanic.jpeg) ## HTML -Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: ```html @@ -136,8 +124,12 @@ Here's the simplest HTML with some terrible UI. Create a file called `index.html - -

Very basic Noir app

+ +

Noir app

+
+ + +

Logs

Proof

@@ -146,14 +138,25 @@ Here's the simplest HTML with some terrible UI. Create a file called `index.html ``` +It *could* be a beautiful UI... Depending on which universe you live in. + ## 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: +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: ```js -document.addEventListener('DOMContentLoaded', async () => { - // here's where the magic happens -}); +const setup = async () => { + await Promise.all([ + import("@noir-lang/noirc_abi").then(module => + module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + ), + import("@noir-lang/acvm_js").then(module => + module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) + ) + ]); +} function display(container, msg) { const c = document.getElementById(container); @@ -161,73 +164,83 @@ function display(container, msg) { p.textContent = msg; c.appendChild(p); } + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch(err) { + display("logs", "Oh 💔 Wrong guess") + } +}); + ``` -We can manipulate our website with this little function, so we can see our website working. +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. -## Adding Noir +:::info -If you come from the previous page, your folder structure should look like this: +At this point in the tutorial, 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 +. +└── circuit + └── ...same as above +└── vite-project + ├── main.js + ├── package.json + └── index.html ``` -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. +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. -## Importing our dependencies +::: + +## Some NoirJS -We're starting with the good stuff now. At the top of the new javascript file, import the packages: +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: ```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.md#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js 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: +And instantiate them inside our try-catch block: ```ts -import circuit from './circuit/target/circuit.json'; +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } ``` -## 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 -``` +For the remainder of the tutorial, everything will be happening inside the `try` block ::: -Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: +## Our app -```ts -const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); -``` +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: -## Proving +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` 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 }; +await setup(); // let's squeeze our wasm inits here + display('logs', 'Generating proof... ⌛'); const proof = await noir.generateFinalProof(input); display('logs', 'Generating proof... ✅'); @@ -236,13 +249,17 @@ 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: +From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. ![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. +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! -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: +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: ```js display('logs', 'Verifying proof... ⌛'); @@ -250,9 +267,9 @@ 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 have successfully generated a client-side Noir web app! -You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). +![coded app without math knowledge](../../static/img/memes/flextape.jpeg) ## Further Reading diff --git a/noir/docs/static/img/memes/flextape.jpeg b/noir/docs/static/img/memes/flextape.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..65a8992e9853f2a553ea099f63be5cb3afa8cc97 GIT binary patch literal 78365 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

?vm@Amg=oMP!f^!b*tmj^9c$ zTDJys0$Yxb3bzbk(B-T6g#a%n)kBK(4WB1Y_!zB)5CA{`9AH*H4W%S0#F9sBdQ+EN z2pdlX_oRcvIKiN4vc|8e%%QZfk)8=Y)Vp@}99{~}G5Q*Cg!zjDI3A?dg$@T6k)5OY zf#R)wBpE4%Htxi@Fe$#}CPBs&r1Oe!@F$$-liHCXNmfC@J?hgSxrSbbBq6e#ek`a^ zeX2N79sKARVWideW~vqJZBR&T>aJMXmwvH-I_DX)@kNCY-uc-CUYQ zWD&r{LeP*w{)TBYbmXw98peT{rl51kz!rMOBr3;wK)B*J7wNmkgwB|n96fA)IfJPR8 z-ow~bb>?=3APf`hQuV!UOlRDk9oL-+{t-%m30Jy-?@=j=TAlMjAQ9U&eUN0c9j}&1 z+@J3HlTo|mksPU|G69eX1fD>t3&l7Geed4;)*Mh0hx41Y&N8l zd)KKot-^AlgY90YP%Nbx)pBFqow%66$9&Z-V1Pk8j&qNCF9WL)<6ZtHdKrKnzz-Id zK=%AOP_3HK_9=H4oWDhx3koD5rGzUvIUp<2q8IBz5iUenY^limu-l7KD6N?gDr-=5VM(Uxct z?oGEoY?x7$pcbYM2?X{PU}{YxrR_;|+dI!VN=KHt1f;0?`cz1r4x#HSJ**f(f@LF@ zH#Sb+pditNYRD`hG9Obb3gjUGlll8qWMDY@(yuKkQbrENb3|LT%W(tD$xeL+XsCs~ zrZw%F<93A|wh$h1@RX2}4?oit)QmjIxvjMjfEsM)-{lp>x)RAOY71nS6wqm@0PwS2 zjTN;>nx_-OOD%#A{9g5+FHFgrP0c1NsQ&=gl9R`fM-^V#R8gv}eaH?RW~@u_30Y1s z0|z+zR0iJC5vgqMCPEx5aFUewK<9(?tk3@d8x_mQUl77eK||1Hi$Va6$Gr-J!$Ttg ziZ2rzD?BuC3Vid8>^@tmQh?(JB9UcxQ~>0l!@znp4&pyL zx+qDv<;6(-{ZGRKv{ zSp-*?0xK>mOKhY(p|p{ne*TqDk{c=Jq#(eU3r{F^9DZpunj$3&{vj$-cnbBUVm9QK zh?c?>ris{7+xJ*#CSXEmtj^QugTt05{qv0gYx z$<1yK6}1HZbvq%VbGZDx8g&V>|hmHa$E3ybqU!c92aX;DjFQgAW>_5A5X zsyS?x5~Uv8(^m|3P(oS!UGrLik%Ez3gTVA{B^#BI+ta-y+D7cCk?mWpYCIEKl0e9z zY&fgz+=5RF1bcecj<~#FtNK>E&U;oIBOK0G!iu+Rr58?@t$xFM-W7c@6~b zE#x1)LJ6%T9PSj0*(75XxGKTVdey*F@~Gim@lb+Ea3#U#0;Hb!?@gx^FDY*+Kp6n{ zrw1Fi6UgjogtAnyd!E$@ZrD&jm~{{RRFy=czwFC`|j=O9!q2)fz9J?RCI5uDP_ zD`+B{l9Rz4R4&BIkVXf3NRgtrpYve;lK;H|^7C+bcptg2wb zoRgITM>Xz9=kLutn1=1MRNPsON%E8kd9jw%N49&4Yc_nD&niTMlC|SIP!c%$3XHTS zl%Yvl6pWLM5!`d>=~|N7Kx`*z9FtllYD%{x;QfVR<*Gu4{1R{~iyFG%dvH>BfycE* zrz|1$CjetS3O#W18f=EufuEb-6arC0?%*L?F^`-5;;a#ap$jCbSUXKdF6ni(g*cJ1 zXBnw1k{VirY3v9CIn76|PAM@|>!gPQiBCL_YAAM44aibdcZL=L?UCtTt&GV_<;A$8 z?xh_60F8RIkf~a{UoLvaG%aT&NLrLx-s(bpuueI~DGhrG%LU;~S|hgWNUUk#c?a99)Eg zoE@i)wJ5Y+C2dnOq@~3if?OOVdx9(7EtPIop!ls%r5w7!cwuO5L@6Bi9`t*vcFS8j zfxC{1)7J=A(1DiZASWvI93Ittm$?m6-ckLCcQ*lf30#z8JYSMjA+ZEGs zQtK}^P_h32TQ|2Sz7a{xxMp1Z%`sc!Y;Ji=k`SaaaF11I+N*m&BU0Meoc{n6;-zn0 z9=XewUP4k@LXm+{Yak!mduYyojDOCtzsSXPGW&&? zgZHFIp{bi_ zVjI%a$WzU$1r6sQ($KX9t@VhimV`U%6mUo0xA;p+(q2O?B%TU^#Um=q9pokW@mYEB zdCEb^`_(l53ZSy1$B>^fK`v*2eXDdw43V&4dkVyLsVp{$8yi_1B|V4QmL!FC&OPW? zD3wB9Sl*@o0D89a6i`$Waa#=T&MRO}2pPesQxZv1f9`n4sP(Ou^YNCZ(y#-m1znHj zUQ%|XsASS9Q7>gl^r%t4I2ij@*hm@YwPYxq`d7QuA)=B%2OaCkQAZy1sz&^Rur`d0 z(vP&t6rUm8;EqZ6tFjujl&^xKDbq})g&|L@DF^$!;*e>aHRh-SmE|C2oG_&$_((uf zPdxV&$hu`d5J_oi5!9vv_L1`DgvoS5XgsF!r3`?5XPa7js8E;2uf`&xb$QxKTMNMZaO&Ht7ec* z&G_mvWICXy3UES4VN*woQBox>%yZdaTE(8*F3E09tU?8ptgGZX12hv?>#ZMPV|J%? za9cqDy6Y?3pH4uo-k&}<1q(a}l+$OHqFE%kVVMstNd>YBap_7pRNG!@87ChtR}lO{ zbV^#j9tOR%IIQ3&&nY?e7$T&RHSUz0kR#rrJdw#Mc_$v;wWU+&U7la3DhU8xK{oymO!4`K~1wI0i=H~M?l#H4@}2e&nh44fVZt!$#h zs7f5{laPJQMI_ark`XF!DM<7kusc>-kmE`!Lup^QP_3RV6qN;b;Na2-X-ZM~RF?e} zpT$HEW+j-fr_BpVS?++GVwy{FG9B{+K?fYACyG_XBxNXXAMF}Lgk-H?R7iqpWW28} z1SEh}l^!T-$On_0gHIeOO1Eb}oidc>)%>~Vy+RvD-V%2j%Gc;|US(e=BeiABDLf2S z5N_ts38WlZ$9h$5t8Z^w)=Ocq6S)e=?vtEVuFD$k+6k>xvZ3~;JDF2^c8ubhW4|~R z31Uhlj2`ubttn681pRAbpHgWRB#v`YmW>Z{UPw6yCbH8`I!aq@N+X;B=~~ET=;L#Z zsX6DGg@bO&AqqojQ8+oE4>Xq07D*==BQ$n3ux!Q^1> z)b3ha1grW`3*uXMV@V?_I93mA(djBmN|4Hmk~4yMp!3ljF}-<8K+4oPBkN40iX$>v zb~B}ws1l!A^=m81Tg7ZFxP#e5@@v$@$X?d31X1MNU6Se)Q0mSCkFHPC>q9!F;VLDP z%)GJXhSEw@jycELyRzMI8`l|aZCFtVBxBa19bU+@^N2Jd>OrUiY^Yc;qw$o3g7|yQku)cWyaWm z%qCq!i%`ZCa7XE1LG*lhaBWPsgd{6(Ac|wG*2}AHKM%P{P&ow8opB)2)!T##!M% z?Ee7KT=1wzd6wZyvce7l(!inYeH0tX1jULYhl>dGD?6?aad7TWeijV)Q&hOnn@rfYFdfsflGJd zn+%BxO1}@KUGPE5Q<24FB#e?c6@>x-+nV;`enY~0=QUSEF`cduYbn6&D^--FXK6p< zO(x#$u)tc~N7xWeP8n%8&{8A270FK{KQ|(=Dr;8src!ge)F^SEYK=?PO$LdG*7f%Q z44MZn>2i4jO!Tcp9H9vvzben4Qn4@8-=p#QH8ZBE25$FPF3&B*v=V!59jHv#R~;m- zDz*`hQ^)I0ttL#6Cdg@M8TnFEihXgqG+0s+lmd?FAXgT79#_4d;|>UE;GvChLzN|@ zIE03iw{{2zCZDCy9YPYqu)o8`1t)R6+e>J5#ir)2J6&$tom*q@S2)wJ|FN z!MA0cgf_H-4tb`NYIh-=RZ-5l4CE?w74w9JA&SE3&wK5A& z1RMeC0pR=My21{r_|f<!**50rWd8sUY{f4)?T|%%MPly*nC$ z13(nG2i()vzI9Sbm@;^LP1@l3;bPOCK3TLn^H0x2@xv^-!dBY8r9@_)vvmETP>Zcy ztPD6?N!Yd^rF+x|9fxZA0OqMeM(0ZF&;NOL)m0G0{PM8DNT*aN}|5r4t+TGucR_H zG-TyVT7M4W4k?l^mT8F++=mt9^OY8oe)+17xn0g8<>1u$jE)dv$Bw9nZ;Nu&eIk_9 zd0{~cj#i}=0&|p+z~J|yL&wgHZZc(Ebam=FRIF_={$cqXS9h@&OuUneJQaeT#grfN zq4!-iqNX$C%F@=Sliv%9+5Z44V%Fn-;THT8U*b5@%j1)y*JUWn7dv}N1Lu(tj!);> zq-}Vp=zO-6;MS2+K+Y5}YU#an5207}tyfN;+7-L;?aP1QYB6!}U*US-g`tfWVX5JT zIT}*ZN9stb_hC0`Z2>O_k#x}>u=T^F*Va@s+=eGUl^~q*G83NF#eGfDH~xg`*xGkc z>Ea!Q<|EE{xLKH>N6s=vN85}V*@iHmQ?s9+$K}Dymj~3wt}vybn37s}5uCQ*S09yO zNC7*N-=%Y3fm_a%zG$sSIt_+pzT_pam((3n*jU=Fp&>-$0H43DbgG>oU}Z%58YxF> zqXd@GvWh{-NfegwQ?%2S4Z!bK)95Lxh7YF|Nzl8lOe+V0S#=T8$0dGwUvNgZ@z^zuI4hOX&w1Ta~W~$#s z(85Ykw$-^qjN?AFADEzmpO|tv0;Dqhme-7T@1IJKTnlb)+HV1XWZ1jY>8W<4=pS6)!cmm z;=NKkm9|Vdi;kugqMUL7BE3hsj#$4_thBF*D-@}(N1bev$wP!8N+53My&=`F5YQdd zZ^VHS=bYF;LuD!_j?_&$bEYnb8!~CmXyN#|Uj*PrU zxh`V=0D^_+7gi=&b!7X7q_sU6m)E%oSODWb_0yVndb5$IXO1B^*;&qXYC_mtn>5mcGVsv23=~GK=W9D%n zAImg1S@?+47Womv8F9_(AAqF$_vVDNq&jZk-|+EU-Rga7S2QO~7J%BDw~&*8xB#R6 zbbHhP01_+vvsAl_CX+hhrsnC%A)F=mnovMdPI5pMT}vt`-dBO-Amcppoc{owIlk$w z2W^UGGUF<7r2MExR8I#36b^mmr$9q#DJo$Y3K-e|%_lBc#d9PlHjg$R{D_FN%(>`2 zl$DB)Y0o43QEn(fE*D78_kZ6;Q2Ip4D&5Hn$EIpEVtlcyEw3pGQWD|MpwBdiJI5+9 zN-ug;bbM@iV0OU$DOf0)%!eM2DYNPV)5rMGc-MxVN_O@m+tQy!oY{8?Sit(ypzR@* zxN&v;>2qKS@Br{Y55L)UwPhp8aJICPJ+a98(3av#godFm?jj*0DcyyG&uz-}`c$eE z_$ew=#V-|)mAsG>LvF5HWTk9MX|mG256_RN_CHZZ(rc3TP^uaUM(;ICPH;KzPMQe~ zgF$WX!Hp2G-1SJB|K*Y(lPTccmh#>0aB#;0zUPFKxAtR zTS+^K$T$E3b4*UJT!pB@h~tfJi=<2AC?gPutGR1QtsR9sYr zTUarWJLeyldUA_?rIds5S5>q?=L`P;bs}24G5I!P@wxIk+Dla~I(S>jA9VpkC+ZtK zR|lIll0od321Q5BmI_-?ojOB@`H68re~oP#&8OB1nM))ORi}49b6F?kqQ5FP!@y;K znb77&yNcN+JZIg(#zHthojGp#beP`ww&en@%2B{gFBn*(G37YRN(lM56uVbDaRm{Q z5C_(>PswC|2HbuF68zkPR}WK73;4Vj;x&b3ZZSj&GEpa(jHu|ZiZY#G7y{%s>VO3 z6%L(ombVwRWUKj4ZPei@T!g7gR`qAGJW>xQVvB8|Ao0oP2CJh&ib!_>JJ!sJj0K@9 zN}NJh%9D|}XVZ#W&I-rAJ-c#y8;WSkFSMGV_|9P)`Rqm7vPkLOL;x58UV%J9DU$;CJ= zM?w^*0({S?9jS@%3rs5qOXR67PLfBpF0I0Wjv5-4$iE8!7t8+lIjNq zp^P7|YLi=fp#noeQz9({@N?qKJfI}6~TI@5doRC%XPOtn6gI)|9p2PH&R-J0KM4e5hO23D(M3aD?#-sOr8Gn}HdraO|%Y+l;DH%eK-#kz|T@>YFY`O5saVk6A z2L$>kQbKy4$n&tI{{SF3;(|}nU0Y=ZO+$?#!g4}nriL}7`nc+pBv}|~U&^5|8UFwZ z9n<>*wl9{#cgd1j1x4bfRyMc+hnJpPvTAx~G{f`vLrNjM;Z>ra~M zfeaTNK~eMtLaT`VChEear)L>=(kxm6o;5N^&sHYDP;Qxw-R*OC!N%W zUzDi?ts92Y5^|A6wAQTn%Zm}^zI>&e;46|Umb`Q;#4LF~6>k0ADI2rpxw$7F;X!8E zd{gPC5h0G0L%0^ZDm~OCNAfA+wCUWF`ih*fZL2#~I^RyS1yJL{WeOY|kX4`e*U#_T zD|@ls?N&8PQd^qbnJ8sgA38urdvk%tc=f4F+mDOcjD^SW_}fn}#0Qbl&)yRpj$M~1?AgMK5-^ZJ7|0)=y>ux+KQJR6*{Zw3zMFGN^j^hpx!Zmo zSCCwB3m-6WpPN5kD%*h(nUZ|Bq%#$uHz~&zfCu@XrD=D)o+e723>>5tp4g{T5ZiC9 zwjA?Y2MJgh+&(9%*c>D?FOfdCpajr39gTr$Hc8wJF7`cpP@15>!%Di~uv=+NClBe3gJcwHTX} zyrn4wr#R206nO2~bTUgW%5^O?oRWCTus=G?n}6=t3$m1j6?YA*IR2Hpi%L*jX}5gA zox4c`6e&(jJHyVD7d;kp{c3MlNVvr|5L3yPeA1~$A1+d|M<1nnqwAdPMHX6p!jMm5 zd)KJ9nwBP7G4wZ35T$|f3duWEUB)@}=8jtQe!GB{-H_97?l>WDf@g--?fVeVA93)xm8|e*{EylHwarovGZ& zAIg$H&b3!d3Q|;cG=-7s5y<|vEtRO6Y=01pX8-|A8ox(Gm6DYP^Ui$@F=vwKMD==% zoVEvv(w3CTecSBiD0(Q5_tUlL7*4*Hg!jvZu%5#lQMFz|lBV0n)p89qa^%ulA=0G0 zI~1Qvr=D-K9(X-dyxf6Z=~bHmJ93bRR!HF^nrj!L)@CI)INfCBvyhFTgZ*gRS4A#I zB>dcRbDCXuNesW`f(Ta}Q$HDzab{oc{Xfh`l61nOsVa{#VF=)jyb)WoZA532C*qd0 zr=P>OH2ul0I?ztTkMCxgIWg}vu;WEoPs@%46m{7b$S=le<=jljx4i6=GCZPywG0n$ z{c%Xi)AH^OgsSLUDi~J8_NCJ)^t6z)rv&8V`9&;=ti*6WhXR%pwOselG=GiC*J9s_ z(=L$8Hi+`rB{vx^1o4xEdx9C|@_C9XIrN)dy|&w3R;ZB{JjC;yZ|_doml`Z!8%h+|9nX4? zy5xbBdEhAgzY$qn%~OmR7d+YThE5M zsx5`64iqq~Vv>O>Y&X=WWqg<^NKc>@H?q`GYPhg~l_g^eMsSh8 zl5v140n&X};tRzSH;CO1u*JDOr`n9WlBC>Pj2rXIfv`Nq4aE6QcI~&EWM}L>aKC|W zlb(urx$#S(W5x_y4BH*n)PytTw3t%N=?ym6>{8ftwUNeJS8QUv58$v}?L3n zP+Frxc(~|hmzC6xuxQ&{O*e0OhNZsE;xvV$&2=px>_WE@y=fe08P8xyjoJEx)sDJq z7j$2Ttphtz+?YaKn)(!mqeDuwwNF0bOKs>V*8|D8U+nR94dv$$kn{7VGKZJu5C-ooEiETJgfx+pjGB5J zE?cNI<#j3!JB~n4fj=J-F)VclrZI}JuO)YR`;+t~Fv@fGH3`>|{8RX5l+)dF(rbTB zEzrU>4W>uM+xMIR6rcjx$xr|~gcTg^&MWDLvg?MD(EVQN=SA+&u5RA?l$)}xPseGs zMq~GUbiVJNr7S5skZ_HuR!BM8IjL@|(%OGqX{(-()pn*XR(s4>Ax((-a)+5(NK#L? z2ZA{V1ac_lq{Ag!MPu?BjB?$$`E8*!H(dNcO1(nx^{1iTRi|2tyMpB0S&AF@k2A^x z%uw72&heMx4@EQ7PL63Cbejv(9g5S^FA?LZYiQwkLe>ZXk~sr7 zKA0rC{UiOQOg3CkO|3FiosNp5kXc`Yi%};yzg-9a01Xw?9arkU zhUlJ&mDEn8UCpk+1^BV#%M7j1(S7tXg()ZnTX(pekT@AMOG$+<$}U>{LwC6OwSKwy z@aa{d&0Eyog^AX_p7g)z0F7N zy7VU{1q&(ccXp~r`*REZQJ53;%>=k=wi#NVP1U`G^YeD1l$4)D#|kyTsX%RHo~b;$=}uvAnrR$Zg25S0=vXqVV) zOKAZqRD`61`qtewN-o077S*Et)>>yyTkMR>VfMV-EPn|BARZ54Rn@-X8Vk=C;N};;rs6A*wH0p8K}p3fa1pm4tfXLb+L1XRRj$FZoouB@QnUF`7v!w8xalcVWm!CA=kG@+vKHT#j!7K- zDlt7GI()YK=W?-Boigsmk2s~QsS79x;}qIlri%$>ZH>V2q28B6p&rLQ^G%&(x*b}F z$diMLOzFFe8;U8&4CCcXQCS(u?lWGZ%p*(&{{YjMH_gxe%_A7EPSUnrqeoo znQ~S)6_B8L;*@dHvnx$JXJ(F1Z%oI&-@ab9Ufp24IvW;z1A z%n_eaUbw!cyx)|S5;##bs_?>qK?S`1=|c2mWyeqoao(<&4OrF2R=gE9l6^VNDBN^7 zcBzaj9OQSQ@^1{Xa)&t`zLe%Jph0UPX;QsNt3_=cy3t|8sayo7jCRc`q(^lC2L5#< zWnP(~u3j5bc9#+fImIw?{tJXM@>WyE(5w<_=(->8N+0skjG~CN`)XTHIUEz5jQUg+ zS6K>q#Wt01D((+z*{x44m4;t^Nyn)*ML3ghkBsB5;XxrifIZD3%=V18P~adGk1r?b zQ6?_&i=pQq3fy;KE7qI|%{uUWtL6lr{+^UIV6{Yn+lm`P(&~~D0R(#*4=z(nNJ4iU zs1t#T8*;d`^MC~_C)YixBXDMRoeFYM&{%wC0ye)#jB~vTdVni z#zF7*sQ&=RE<$!KB&{Bu_@vab0Z?=t{ctIpi=s{Y?IZ*(N*t8ndiz#x7uMK7SWW^_ zj1T4Gy+>m>%GbTOf{H=N2k@F*=&VYJqPGZfU4Z8wdb_kvjoj3Wd4{Bivb5xpp8o)q zGPr6N0t>2A$aLT(BegVDnV5)E$y(GfNjW2*)|#~;rRBHKc8=U;fpNiO)?`gvYjH0p z7|#@wAY53(#Hq}j=hNDUIH!{0l9xzFs(pndk39u$#(7Cd=iHM zb}^CdOIzZhXL`Z{bCngG13{qN8gfBwwlSVnMje!>ttjkD+s1M9qFCDG7r@T%dqeY! zkRY`bAm9WZ4n1gt8mOismg_}Mj047VQ7KP(uY5~De1wuc=>DI)TcpEUBsSU{Z1Sag ziaNAag{}JK+iv*?j-BCIPDl7uC&Rt+Mxgzq9WkFE{OT8;J-_NS+CKXbu1Y9~@(Pen zNFR!#o*3dPC+!sJaulFWFF7D%{{V3FYp3F()@1(xLyzYl{+IfnVk$EeLfYWuDb4_ z4hj9AQIQwLw~U6H935vJ&&_i#sz236y7R9;_6_PM{t4ax0QimCHh$v6>)gX=w_qwA>r=- z0MYF$b+=n?7r9o|2~*1amYQa3FFLFtB&k~)R@Cv6fJ#Bgr+;K`{igQ6{r>=6KlFmS zE5sLEG}nhdmfU)^tL^iqS?yAxF)g@BN}ft2N^OrZAw&gj^LJx8AvhiCA{HnB00*ZP z^3Sc0S$dQELUnr9+1~U7w#u~4RDm92 zN@dd?OOf5$p@X&7l$D_1@T8~_=tX>bxOCdx;b+DUt?8YnYtGpmE!^!Zkm8(mF{L0l z5VaCYiWFAfsweQM$aCvQ51F>^d^E0Cl+Xcfyc?|LL_waMlW$qnjk3{ z$Cfcr*LB0s?NoW2LXSN9QARaF-fzqJ!;`=u_OCN>XSBJ*^Zhr`PdrQ3xPTLm6GWo) zbEne-EH!F{xz%F?1Nqbr<#~|?a-CJlNMxMtC%L5{brp!Rn~)j`xQtIpQ?$3Vu?%(-*0-8BjkBJPqE z9cpQ4B?u!skK)gu#c5O7^+%*)*EFz8+?VWJDzs`?@legC=@WBp0D$uu;~ZrERLz;X z;u0}&w8oX`zBVJK^@_zx6e@DMxPFGs=(@1_>Utk>@*wF12j{4n-rC zDBus)xc>n4PKOk(82S6PY&EBx*CIhF9-XNt5LS1LU{dNzhC;EQr6i-Yaxgt{T0iP# zCb2Ayxph(h0C2wszQFlAQWT)C<*1CTtxH)}a(jBzvU1W9xZpQ~x}vK>{{V{OzX;DH z`hBabrS%N4&A~

fL{^iD{ES#iWzL?@gTC%86GAS8?w|nhd(KRN8<@;FH|@(^PT`1;FCug9H zl_RNoK7NN-Fnq>-O?kKkUln)N$GxRd1cx?-fN(wO zy7dyCgo2%^P{}Fv;MT9fh}-3~wxppvk8IY>rW0)!R)Po^PSHnP6~P~NeaYEIT3#qe z0FB+hDsvs#lZTsxq>@1-U=i=$otd#wmz2U2l=>uRG&NT+9#K?{t%3M^8oD6-!@Fu^1d=M_%OI?E zH5I2>A0bf~a1X?NGg)2jrlXP^0crVEIs8=@yj}hkCDbiTO87p&`cP)BFFX=btex3A zsGHl-D#@eTk@p&LDrbZo0lxs#B;S)LhE&Q@w2_^soPGOLb^D4KUgCV!0g^M?hDyAk zJLa~MjEwMbO$xT`jiuQ(nK^|17l=^fImyKfe&7S){h6}=*1`@s(-Y`&b2LypwlxG>vkFL}X4ek7~7p%E?Di7sz__S-_c z07)W@TQuZEE6=z-qkmoRBtx z26IgqviYb&lH!{x88|g(T)aAUD)AaTwp@VHlk=F)Kl7h#s12j-nu}|l0n{#^#AW;a zjYb=o9&~2|sY&C$)5qsoaO<$=mfUho!u*6cRgu^>_pLJv;$y2x=V9zU+oy_ zhFJ3OFFv^k{-e#O{{X*$XeC6q&N)fX=TUx=YfT~2j~KcStNQ-#t7e(9{__*(CM(iB zuQuB$mj3{T$`<0XnnU+G>v{*1ov!{{Vqrpm}O3SN2-# zw1a{V!a2yH{v7(G&szEup?ao=m~rhzWQ`_gkgTD(p&KN&5Bm?L)PLgD3DiH@E#T8t z^#1@<>5D&C-IF@&Wt|E;BTZe?z1J985}c|iNXbwcBoA|3_xm~gXLOUGT>*ck-F?>2 z*ksyoa$d3{_cYl_R0qVql`&v>7^|*5uV^V5v5@Ld9Eb!zvC0bSBQ@c`k$q}De5z~tw(i{ zZCqHNxNcFmhNm*?hs=ID5HN%&@}ZnyWbsiC1fDxB-XHX2E{6DxYUL8gY2KR-q-Hy^ z(;hO4m+;b1jn3^tj@HzKs05Utr71vB7m_MlZ;+NLxb91Xsk-Z;wO!}O2Zmi=Y16kU zmRk&cVf)tL#AU8DA2QmMHRm`6*7vPJDcnZmoM#5Qf~qLqFMKM>jEPP7j_I;cw1ot_ zso}J+54slMP(MO5T>Iin_Lua_PS|cbJHy4(`)jRbHsn?=5ZF?!cEykfoTromWDpgU zC9UZyNeWVX5^_;iz)^B^i0|y>m+{^zd}B*Xp~O3_+bygdg(LTc+$SGQ0bP&RpZf;& z6aN4N?*9P%M(upU{hZx!=}(1g$5Z6><66kFxvCRqTsN0(n>livWX&&?80|Pg1@_4+ z#&>a?9Cd$F{{U#8gNEDiZ+Y(T)K_Ak+FjtGovk_6N0Oib$M#G5HM58~AZL|@~!r#B~LgduzdC!M(Fld5s{rDne$2}@HNUm*|pBi0OIP3rd0 zpaDK?Jg5HvNGdh1^k0Y@Ev5UOjl1dFyNnF{F^20-D0<;uek$~|>iAM#b#kL6#RLG5 zQ@Cf|pIrKh0wuCaWn1FLWVAw^@3Y)ppttG*P+9Q8j5NuGs5b1IbK;uduczpBXd=%eA|4h>{sp$ zLu@wlZb?utjGyPhDegV{Rqf!Rac@0fL`e~+Dhw1mae~2`OEDBU+@utcwGcqh%6t3Q zG^I*p_T>AD>fZo%Ca&6>R?b|Nu&9>yHmnc;DpJl5(+I5IS{I?o1@f!;;LN7nu1?RO z0p_r!Ep32KK*xOgSDQmG7gL0`riMyKtyR)*7ppA6DpZ6#z)D(5Q@Le8al076H8`|P zesn~>uT%rLq=G^9uafy+35&w%SG$eQ55K9ZHel2&uWWl9&z6X8G}_XvI<2`#&J8(} z95x$qr6t5H;HVsOC{aS>JfSM)3J>xnXY|ExgXO!jI|s{81Dw|jK9fWEcO5fsUuSl| zZ@H%ApVY@LC;|Z#-EIW>3QlD9<0uCP)q4(U2$yJ=6gcB6+vO`_f`$%pn&5s5RU65Y z4OhV3%c~t9FKUz**k+MZn{hjWvO69rtoxjHTfu({J%Ufne$5xZu}6KR>WaNr+rq!)j=J$vmHWjoe)M_7>By3~+fBBU|kSx*c;0BeCYA5)4eN zt3Ghf2I1R3TI+bsne)qTM_yUF_oN*kG3hIWHC7ow3$gjLP^5UIQ=WyW5J#~Wd%#+1A=RMG(>hJBs{6ANmpg=d-$=y+dR!G;V-!8m|mH^zKllj(Ba$DIY%;a&3g-3cpLYtcU zRUjNFjxut2#Sn>dTPjKlf`ISMCeGTD_$BNF1$p6EQ68tgEgI&^99P9BobW*v7FFX7 zjGU32fN6u*M;#kbvJ^Q=vGsn zJ?U8Opq5d>coZn-X{&DgDUxr8iV)_^bCciJvcsV*gawVjWOGrMFAkBlwPQW&56ZZqZ7l?C z&m{X*qKSGh2w)|*6czL*ifp^?*A$eaVnIEHMSSx5)RdJKpyzj{MJ(LKG?l5~jn8wO z{{WRm%c6tp)DLakpfaP5d(hS0rI(#SJ5iB=`B3!F1c3YCfOGby6K*J5^YUEBNa zLZzr{pMlHwNlvV~a8!;*9jS}ct`b}aX(>_XXykorz_WDv={xvh2g4kE%YTfM^zTy( zCx=}{K2l$mA+{PCWlOje;n%q(5QYv_M##DgwfRWti*A*nPS|(3; zBGU=y)UV}j1xC6rO7uskXj1L-gYx7uk>;J`BR9LyaL3+8^r*hE!{rIO=t6;hsk?p2WP0U9i{0Hjpq*>hjA^ zG`R9xORc&1kgHdPQ)^BlH zOO86EmeM&|R0tHbOSQUQOI~WzfPO>z*Rjz@$i_-j<$k@HUZZd2k;ivW0rMfsP_;h+ z{2j?!Qd6JlQLC?oeQv|Q4E~riQrP3mY%7ZIWzM&)32rwfqm={CtW9&0`fQwDbk-G?v3wrr{yM!-`1CPJWfwnw1e7o3SkIO1@Hk54A^cmQUVS2+aB6 zrcgjqRrqtB^jM*nCS92y(?Gu>;;u2|qGkA3e*JA~bnBhC89bydDhC{Lc>2=@{3Y4! z>Tta>1IlO($wCMutF}0++gQu<7Hv@Et+>&e@=~Oyf}wyv!j-i&hFEFI3MCCTf&z)& zvIjrbv*w0eP0muN{2+fHl3cQySA*+K)+!&7E;Ex?lzGYdAN;>JT|1S{=AT`)6y-~>C2@%F3oPON28 z6A`DI4?Xg>55Kvs2B7#PmM2`Bb>L6Vf%50repQ+pk0F*#xcw@)>5q=Sc%`pfLN!W>p{ zl@O9g*w(Dy;-(*(khBG4sX5+B9>W>MbRp-nDJ48EpV-5(fB7FYEnO|tlXSu^_kAq$ z&B?eel&Q3+P23yKHj)w%oN`CKbdP|2Ec`2Ow7EYO*w3{5c7h)HcWn-k57^?molIgEOR+{{RrJvXG?v4C6J*$D!XC%N|JYzAF0tTSI-;_>yRz^+Q=E zRp3q1nt4{piDd{axIDt@z~x(s^{ChHM_r5i%1yn8ok7^3+D`N*8RUBNOrh$BuMp7A zqq0hlwsK0+tR+Bpz!Zdt&QFvjY1`86>H})fwuuTz=Op{*71UTW>M}K+mPN(a5B~ta zaWcyV8&*4qskGd3=~c7LkfVZIJRhefj?p_W`bL&H_@mgI&N?BB9x=)M!i^r(R9^=6{ zoa|fNXIZshUx_7^6eu{J6n>mkS|VUL>(Fkucar0uDjZTs8@~9a7Y$(FlE{y9Q^y;m zu!P}FA4KQgu_p4bgGf`#8;10yL}U-GbYbG26tPY}!e8o1YBzKegJOhUcG%PIy|5F% z%)lU1JH4?M$Iz9!6TKxtL19A}pr6_ooCV+tkd8MI>-Y7oV_u<6kfLKDYEm(|BLOGg zx-U-Q3jYA$ehiV^sqz&?;r{?FAsZ9`z&mTzswK~WgvZ$0fE$4=`X1HlT1fB4Z6rq5 zGEknP>WJLo+CMY?`Zu*@DNrO5GHOhXEeMAkEd>$lw0ocWDccqZ$-|DJAOXPRn&q_5 zM3b^L9xKiRv>XvmAzPjcPGsV(4b?mcK|xkiY?*7<~o zn{424NENDJPGPOif--m~&{WFZIy+5y4krUSB#hSc9g66{SM;M%K#=A7K|!e54JdvG=Rk%VtbxXK1@7Pkmyb$o*uH@|mgG1kV2N&iam;IkgHHJ(}%M|H^SdiR!{&6Yt+{j5e%`lYs zNJ`sQ@;L!iJls63<9XUn04FrcRmpB3hK7Cql=xxVxiiaAPLS?x-^*=o0FlNDN2k_< zuI}@QK3+a!__N-cK4iXdauRsRJXfPx-XSYef|HW0`cor|n@G<*>2oJT7pFXze5Z0& zqmi1~O(-wsIXKA8Jw=uGUkgG(IQ8R-EOf5s68D%6GrR-H#XBC4EY+lC%jC59mAP3H zihzZ$a(K=%257CjMcrpSos1|IjHOB#NEI%(+GD^<64U@)S@}-PoK&V;7XfZ<`BxP( zr2MFjw1sWYamFiDd`4fV;Nj{$LknvXBf3YXa3A==d6c!e9mKST(|{JEnzF1KV$l@| zV#98IsjXzV)&NTO{vtEn&}lad3l|$)yJ}2jGS2C%bQL!0@q$1c=fCGgCu_|?c7*!v z&v~(${u^>Ofa^#ngn~IpIPH^5%i-resuAzIb^ieL=1a=YE$@H9A+lW}F)8_)jg(u{ z5RHg^9Jqb3JJHKFvDG@FJhj9_X<@fFFtnY4ZI0vgs%e|l!6`DX4*XJ(cMmrz93I#; zDgMlA>%3O=6YM4(y-6!+1@y8MG1&t&jd!MWkZM`>ruuL6`+nv)YjQiTiy^&hZun;t zY zkFYmxbq6yXQo-_*>^{AzD~`Uip-5B4@r?w=gx|E_gqs8eh6lSM6J72rE{{XuCOYPU_Q`b(ZBHS9r+iSI=-)z@X zl_j?_Tv}98r27sjr2eMPlNd%sxa)PVo6bNfTbT7Zs?r)uZh4I z2b6}8076u7N z=fi~SFu?&0vY?z})009pOnL0VQ>$`Bb0Iq%SXMq?@u>tPPJUr#;qgyLX$jclZebZC z)Trc|6{6GP$o5599$EEa?K^n7PPfZjR{gT0H@OWuoR>N0IL9?Bv|TQUgsAr$E**I| zL0@1GtwtM>Ii$4CpSs(^T2SAO-fFSkE8~y}qc)4(-IpZDxZPNmfFfMYH2pa>DcRe zcg*>ZnsRb}xExTclu7pMf|x|c_N@U}3;BgBB3%!~D=WQoa=5NjNmFQy+e-mp`kbGy z){R8BN4mV+k2@IvW3b)MN&RWIrHK93O4Ma5%4J|Wat7nv0ms^fUT!iXI@DCJ2~p)h zU=O}OD!9Ytb}~%{uJ$WjFEUiQ36S_XO9)N}wn?BNqasiXSx)5;oQ?qYrKerWE^r{B z#u60X_m=XoF^r6R)F)71bwrzjlnaT25&WUn@B)+mCY6&&^%DA*1w4r(I?nkwOUYDF zrd} z6gx}Yq_(H+w_Czkg(0BQ02{&w+Z-N!Gf&Cm@hHbEV@@ym7aZ;{Y=X13gosiQw)FI1 zz57<`iBi-P-v*v8ew?|umnBG(YY%dgFt*gA=m&6WGcAK}TAPO=L*^b_ZQZKx+#W|1 zrLs+~?Q#=ulcAS35~iN>5*Ds72?M@6dQ;wm4APt}H}aoi{rSg-(J+f}w2rhtp3}>#dw>}(U9SXt%6SN~f zB`Qhv$s@mNQ%p~bbhb~u zAbn~+WnZT+{Wn*(gs9|#@`(FV*IU9Qc~O9F;Jv_Yb*vQ=*bE={ed-}`N*tKCQo~U?D5z(*J*phzr*6a(kZ^J9TeCSaQi7;$m6hZ;Q=iJT{{VB~alDaIe{_;5Y9`f1 z{{Xo^x$32|5&-fNw1pK%NCi3lXp)(@Dhp0XyeWnpPVnogIbYl+tBLm+lbvO6vmHTw zgGoGlW{SvmS+C| zYy-}^NNpj7s!Sw7%1zl)6)nDEn6iopo=b$n523B`=hOkIOm!wA%SLBh0$p z$_r>=LnR(sijnj}yHUbfanj4mUlq`NS42)5k>pG^)XR6vad=91ao>;1q)E0WGK5C6 zv7TI3JC9m(Y}1x2^Ncwf(k~Lyx^SeKHab6q1}^d(dX?XiKYYK||&s5%;ey zbf(rY_T*O`;gpvLq;rZ^8%)%povZFX!iKwe!Bb!#zrA^JB~5H8Bm$wx#%YuGYmX0n z42&c3s3eq%7ls)5$t1saX349^ACu19B)D*efzPchW`Lv*I0Tg8M?7YM$ht<0Eil&T zOUeKQ05i>6S`VR`r&dGW%W>IhY75-yR^!{)eQ6r4ZimN1+|*=AGoL+mwvk-i-)+!a zbfLkH06qS~gSjE}Y-y;=UIsRSjD72+Z(bAbR?AcOl;2r()|uX0XZ)jh7pl z#npNL0B?vR4791lh;Sr2qJI)ol!5j3r_trO1*P&*zK^F0}W^8 zXe57A>s~~Kg`o*>9jA)uL&U*y*^(Y#QL5p({f8gAH2h?s7>>O1Rh+u#$OrsUj%h{2 zM9rxo2|{^FQ@{d=TXg*E&gYv!DM%{da!=BoMbmew4>-h2d&=_8)qID5J!?#G;M1#- z&CjXLIW@VkOOOkXB@CpTfRF&m{VI8JvBuHbH4Lew$-K*TE&`FgC`Yj#hLwe=H1>w_ z<1ueV%0r};%l7w5Q`;T+%}DLn{W{F=?JE|*sjee$mJ|*Lz7A`htkmSm6!F5Mx&8kD zufV)k^mrzB#Al(9G&kz-}A2-}lyUw)L&APZZD};chem4BH zB|{^=K+pB2Lrti|kwMl+@w?y|WXCw}<$l9Ckgm`pyKY|OM_=(2(vJk=gF~P=rsTGz zw33AK8^$@TwIqn^QIw*kcS^g`*87#EnC_-+x!DgWVFfGN5%v1lSw>i)^(5cuXMbC> zd!)G27NxL)(uv6&j(=LkwseS2>}}?g=7I@xu;bX%7TinADnf8ZITgErx~+;zl&?xO zqW%lyCufZ9&Uj%DFo1FjocuWU&%GaZ*MRvW`^m%hD(cuG1l5` zBX(B3ywN+HJ498-5T~~5kEE=WpTqR;O3N#IB2t3whHO^H7(?*P706mo@Z4-1BmObZ z`BaVVNvL63{E3h)2xc>TNO8T3SoGwcPuL2B+G5U~ISfLSufi5zfG%6}@Wp-GW$B70~-it9%nOPr{Wap{_nSuamcj+>lYoNIHf z1uXgN%Gb2~splip`qpgNoW7*#1&&ndlD#LY>=x%-wOlmi#ivq@q4hVAIO9229D3rU z0yVxVK)0c454q+jV3fLXfChX1Sg1{s?RdJ&el)w(clh&v3I;Qd0Uvrf4l7E#r*zii zh^Y!nT~Yjb$9VG~FJOG{sO$oZpWtW0OsKH1p zLRL;iPaM-x>^9e@&uONB4 z&KQoDOC>7#f{sWZPHCI!i)1@($ZA^NM&0iupDg=~5zpT>h1=MG>r!MOtQ@Jv{RsQh z8BV_$*!x$f@HKs9EA^}63z8#)U`0rgX!ctTmQVLa{?&Ck_OeM>;w{LpYZjQ7SFFt8G zB!9Yv$D1XXxRu)5FupE3iFofRXo5R&nvX5@MPHiP!94SdU20(=Dse6-leClA3TZKI zJaClZAaFbLOp2r}yA-#(J*jEALs9ctSaAgj3Q`C;Nx{fHy+$aF{$!m)GDYg}>fE|W zJKtK6miL?iov8sMfI9&~V$605%Am4AxB#f|pP(MJ@#{UsF^m5IxurM>-{yIKp45yBboDd)#@_DN z8aU5wr|(B^&RV3k3E5hK$<8u?<~H9RTEDt;>-MbK<1OFz`WTh=F^_hJyLxRGxw0E& zw=$&sGiA?C0=xdTx9=-lR-BJ!lPEB=%WEjY$GPLb=R)MokCznOVq0}vijQ&h$)^_k zb%J~TYTtG-!2S!L&+b9b6r7rPN9$?7^bKT{(g?jS1F;@lOCr3aZBbK&Aw%p(G>y&M zVi{yMB>+d6=^&wAA!e3nxNM7C6fs1kFI51^sy zki>S^64M)MLCTb)%94HksYnl88)ZreN&fn~jC;~$2|iA)mT{9xBj;fTLuqOX9Z5z) zm%lyFv9DH}rVx^clHen_?OvpNayzNX5A?pGvR!ZJv9T>Kyz8Y1K7;1L&*xo5p!_sj zFL7A8-R_E7Rzkd{(}9fp)F(suKaZw$0Gb(E+(Y3?Qj`y6S72#7Dr~lvqTr-7jAZ*) z!~Iq3A0o9&MdPQn*C`}BCh04bfYx4(XgeE7ZJQ)zj@z6`S^l(^y3uwP>=J$s*BPK2 zR(3WAp{dGL1_@S2xTv>LCng<+Qi||Awf6fO`HVcSvsb8VG^E>g%lW^7F-j`WnH^Dt z@_Nk<6hwJ#oDvh99^7KSjdWToarFFPK*(%liuazi$DL?2$*xpw{{WGfPmxM;VXbGh>074N zcaFdCt{Y{S6)sYPYS@Ck%KdA(^?6VBTIP~J{2h7y4RHi_6lBb41oE|lKRWe)*$cfs zsePI`ep&MdRvM;53Ai$*m{N9vGwM!z&>No8@*do-Mse>(HAA_$ww31~oDuh-)0k=a zsBs&QmZ6e(;=b;ZwP&8x^B{$q)h6{JsH{4WrE~Kh0QEH~g=w`}p8hkbxxSSgw$VEi zkMAq})f>06+FWQd@ZFxtJ;$-5&@38?@K#|)A-&lc`9Ku>uDg5;(#nwHUZ9mN_SlNo zleKA55Xy)N!N=$M)V6i~t8+eEmx*k)w4jfM+mfQ6m@Ax~eaWGgi&`|=9DVjvChnw= z7*GWaqt#>GDE6Rm~5{Q?9;ZgfOhF4IHQy0fK&<*EVVznW+3BvidGa9d=qDeQ!q# z^2ywt$0m}2cDY;J^I^+zll|n=huXKb8BQWg?ny}nDcU@|f4-Vbn&hXD*)t-aS_{V#D;i@Ki{)+WETOIdk)KqI*rq_sA*UG?NNEpegwe=3Vf z8<)?i6efC5-suq|t}8$UlA=dG*{vg5E_1f3G#8yx#!^z8?xidkCogrry62$x&Z!Gc zxItKCLrcj}2Y6W+1p8yZ=SU&9+rrP7*k5dn16qi0!4K}v=QqR!prKLs!y zQe15V2pAkziG2xsYSR$E_XhO3ECx2|5d7!(4k^b1G2fJcX|A!cM2ME|HrWn5hfmHF ztodi#J?c8jRP2P7bqAB* zKbfbN=3JEW7*nZ0TCuqHA5%#=mk15AQb(aQv_{sIm8|@}{{UL*U7;v3Bj9a2qNNPJ z>v+nLcq7ozc@8Yd^BXEpt|*yQMZ-Hr*&DuN=m70n#Df{pzH`JZag0*pn&p<*rH=T; zrb?fkZff9G+L7g~;~D;8PT9DkLLQLZHe-g#BPTcq&}NxMg%u7u+m5%ww+-h96yX;b zQdu_EBBd@B<9>Z;X*pdLRJ$bBH=SE8y2D!n2tH~~6`%5{W7o@kwY0_bxY`n&6|C<+ zZhtC@*&KSp$u7ohm81mkJOl4fuX?&vmYcV^Zi?PO%7;0}ts^X7z}UJ&$yRn{ytP|q zGSgd1+e61`AaV!-o!k_emT0!a0x}$iRF$~U+Fagq-|5?$0SUyom!_^yn6zXBjtCs` zKGieRw|8|0*CbopK28#Vq=1qKa;$ea#U@S0J4qI|Scaal+*phyLWt(YECn>HrnlVR{S=U>Aw&I9VUQCAFNhA^2(}5#K*x52uAjy!0 zaNg0yS2~F^+_|W(LXLP!`)wWRo6}c0Xl$d6UX^fW!dhwry;Vvjj2R=g+DP*r|U`G{wgXRN*cn~v~lZ$-n{{fgtwcU zb%dlwYz|Ku09K@gIS9W6?dpNt%A`i3NnQb&~JIBy!MC%#)ms ze@fEq%P4{+!&HF7oG7gcPEJ&p1Md%%vQwwLMGjId2eLS#mJ`DiBUE zeg6QhJ8MO5K&L(-#?u~jjJAaCNEEH3;h{Yc6On(nG8*C zLP!VXKZKt{P0WkLxhRHTaSf~#B^$7iGupMd$GBQ0J7#>OlY$622afrwMQ&F^6)Y{M zSG^~&NIsm>8y2J~)U&w>I3#ukw0I?_RNH*yAC!8U*_)h*>?SgKVaF1+x9*`#qBDD1 zt+DR#ox8?y%XoP$z8gO>+XQEyO!uc6xmK4a$)Bg~@*`VR=x#b(RzMi{`-4o?F(MP_ z5zhBLmAo8<9_F-D4a#|<7JStcxD&ymT~h{~ z_7bsN6>4<1E=db|fA_uCLzcILXl#`<(v(WJ zgV@#_55jxNUn<;pBd|Y8-ro|^-iVQ^Bi!Y)cleJjwo&*Bd!A`abCDcvsViwqb!{QX zmht{@PImq4CRjS)>gXj>R4k9)0knB2Eg+19*Qvy-(@r`J66cZ<0N;$~*ZSA1pJ%N~ zZCXC0p|%*^<)8&;KZiM{?yw{s?>tk^LKDEQVY&Fs(6*bC)|t0vnU=!#EtNjlP*!^p zoaTky{BdYoTvGg*y8@C{32_(+_x_dna(uS7bzOQ{_1F-sNCz zK)}Hm^{=ZMdw=fs*$7w42XRRL(Y3m4K11-+gK2*}e15@r`cPz#Gz;yViM{{Uov z__cd)wO9QN9$9k&n$}DqyOKkL3MyU?Yz)wqC_8OiUx<}*2d+KpN7RHQ-NS7qOWITc z+uxdNrZm#$xT!Oi+c4WZol#aWJ*)00IhXnmrv8!ckMv+9o|I$04@|&k#CKZGT*X)D$bj-s^cLnwn$~M zz4s5{Z3DR{(~Q=Jl-B97m|ZI*^0kzwmc_ow8HNzOzYyw%=N%`w%DZ>K0~9XjA{t#+ z!lZ{3tT-2go&_;;X~xzZP#MpDNui9Xq`aiOlIGLM9A><{1s%=p2abIyveV(6S{A1`{#FvW zNw&_2i6UI3+zB3PT>z&aL*AL7r~o(8KMunUsnopM*5Uj)JB4nA0zU{JoiZ>`j?`0o zxfSx(RtgB-4pK?QK8?5H5afim;p|dZj30U&73GB;;FIhq#er58$=iBKbt)VuI7mNm zaw$1mhtw2)t_G5TW#Lcl0WzEjRA)zvolWIUU4RMd1Y2uhqPBz+D! zp~a=8SPCDndSqp~Hp-U{hXK-s1f+0#p7p!s&CD&em$E)^M+sJYW|oGlVNhlLs#zQw zP3a#3r7*&=yoGki{Ey;0Lc%#dh+JA^a2@A(?Gv1$C3`?6UmZd4T7N5dS59TNh zm4PY7nUy3KnO5{<;OE|tTM=$<={YEM3r5ncZ^t!~YMl>*LQdPzwIn5bQZtfIdP(-A zZCFCHfx?bY6jI*%GDDt2Dsf0jB|dj;B4_)xFbz6>B&g4=sV%K5bG}F7ANu=OnSm|Wkscb-RC&os#y<6?GD#Wd7T*I{*0_&E zTGW*VoP^}#C)@2$nIIV7$Nf8m3XE3q{%#o4$d(!rpl3!?f zlVin?9R98LgP5@!cbL^;)%+B^tg{~X=@KoYbXQd3&|(kQ0Z>Coxw5- zjgCS+57wCk*I={@4L%*-(((pDIHXX@3yBL#$tuUnIH%E?lIx|nGK9E5%7zEppSuMR zmei&uHll)(vXl5ud8Q(W*lohMQN6bJ9FnDb(JMu^*kp$0%xB3!1QffDO(eT;ep7%= zY&hzVl-r{j$@iv{T1++kD%R0kX9S?-B-K88A)BODnwp%yCbl>E+C~ z35`11OJ@ozIH3s=K4&ASIImDWsZ>2HyDkK;1LY^ZS3fK$y5MsrFx~K|l$7~nc1hxj zL9)KM$(s9-n}ikRg*dPZm5$$UwE^;-d1Y#7`Qz~<_Qfoz559oIY4ZHAK-@Aj`OwNO zg=6RiXrCRG#9?Uja5)_D+djsH+#|aE;l?9HOGLP=H@N({H6_0zN!j7Wwb@#gHfybd z^ruthr7Asw5;A_7H66EFrM&oY)h(ncYHYeeDN4NoRy)c%zZI; zxHDmebZrpiKC~rB+&`G8<7hbUDM&a;&6Q=8IH{>^#@zCrR@HfA-~&WvLouZMG&H#4 zK{(t=*6RlHjG|=>1%o z((WqLO{#QtIfaH0-(ckFnk6S_gHFRm#Un~bNDqq+4I1a26{&;~gA3i=Md zoLRiZE8ttaNg#ZjeJ*G@YHf`3(xvJZm4;NPG|U+Uufi(e(zfV3(w+ zdl*xolmbBAASRq=YksrtpDu99!ju9rD+nRK%fGUT1RGsX$+ z+uE&-IpYVY&~8lI?{Zy=%9od3D^i1CV~hdMsIQfJ$I<%#057eMr$-3d`G4{9bF}){ z;e|APQ`Hwpj_K=zo@z+=b%H$)70Xsj<(1h^A=?XHaNY~)P)G?M<5jKm#k337wY2EH zA#{^)hjL(|WR+zpON9#gKqH>R*Vd$Zd8gz)+8a?9k7##ENSf)=O@oW@Hu{xV)mZ7MwxDXFLt05UOh~N5@-}D*V^LN61i)kC)9K zKtJ6{YRf#>TCurnD-oj-w;mmmGuon>gHTMpTu`;Ve3UEXPJ0Ua1zf2d9IoYMg>H$b zuMwSU*vewO0NWX7aUOa^$u? z5w#~I4|;K??|19-?|$;R24j=C#W;inf=}W5Rmv@Jp967zP(yH_rR1t&(w3G^0LfN9 zxa3g_oA#z3TQ>2xx=7`4PA-tA-T-m_- zlSHge#gtKFxRx4Bf+4NXc#?(?+;1@{3EH5tRF!^5ifWc#d9}LQ z)0T$f3V=BJQ})hQm5@oftfL~5CkQI(I>CGW20WYPs;lNKS zM{ns%OIlC^DJvjyd8~$Gp$Sr)AdW>^X)=s0q=!IdX+lr(s9+QM)0HdET4Q`PbSWb{ z(TtjFA=v96p+_mFmbj>&DYiV9ir3rAPbcUq?T{$j(u71?(;X^6{7T6O^UWgaWEK7p z2V;(MDnJowQd^2r^J{O1O430|9_E^@EIR0BDhkt{57Lt7$zqmwqcGWOX#ujH25?FA z0-eTwG&C*eXPD^7I|>Tbx9iPf3uI^Iu*px%wH$&zm4hwrv_3R%XmU|nn`UB=6beDHsa+~YilBes_o(r~TG8&W;7 zii15T<7BD%vV&?@qJB|D2)4T}d_GCRvqsaglQH)rESC18_<)j6u+P@3tD6t1W3TK; z$s~5;KJ@KUn`uM+CCLg;C<;*_AX6r9@*Z{e1V1qjE9O#Bl0KE95R&XelD-1=^}?M9 zLB4Mdwf?Q&ER_N54}a@VTzHsv> zX0AhWon5Wep)L}YY)B{i(L8OtDL9R8>3&R?J{6~y+DGw5;-Zg#^QJLo$eQbH$ayPE zK(vH9k+dfu_xIwpYE;CoOYOeml=3#<4}STiZT73%@r}+CDpYhY%Ujq5Azb(UDfrji z2{SWLTnFM>WG$6sA*E+;9G)pQq|Ati-Gw#ODPJRtCujiw04b&JQk_H=BRr-M;+N)^ zk%Cm7csQZgNl=@3MvUrYFryuTzlPP@m`M4CUd0tCO zZT7s~#U)A#?i1!r4wg5g0#}VYsd-0%}wO6uqEh)E|EJRwuZ~kq$8jfVb15M|i;Q=z<02xS22YwYJv&p| zTrZ8evX|vK9w=7jKaLQe?-AP-DFi!<1|0e8k0JCh;|Ri6yOKw(8IKiK>onL?qzRE+ z!{wx$ZaLuY9D~PUK&}CoCQ6+WYj3^g`E2b;!>y0!2e-fJTD!2emt)LzO_q>Xy+mzU z&PF|{a%#rGq=s;;k}i$PpK4N-_7THL3!IrhKUP zUx!?CxG+xA{R(<=(4gWYA?A)3kemR0K{THFE-hCgDxDVe;#TtfrxV7)oE7_=@ki_q z!-5vmlN@mm9h)}bHczQF9li*c2h%Rs3?Tuqr6DH-tNw~c40)1Mke4=*%8HH!XUQ5m z+Bg3Ic0Y1mchl1&%-a#me1?>StS>1U&)&U2Ql=1;p~-Fq0fW6~HR|WMJ3Vx2k=t$| z?np*SC$Q~IoRI1kP*KSGcB|$-k+L-6P+|f}=9qtDEULOVq_C2dj#5Q+cOFK{Y52~% z%2tGWWm%}D{{T)V^wQ%w7%Y*F*{+zn*sYOar42D3?}3p+H2s#_E=!LX&HSTiI2fx< zRWhvPr1*Mba>CtjAe@w7cdE-?_NKTm55Uy5)m!iiWV%~886p{}g;ri9tqSmJ5 zA!*533IiOD-Nj!z+ecbcX1TQv0NkcjprDL_!K#lyLW3EVJ#m)P5*kL<(o@O6<06x( zP0rAay{Gmo{;l3FO#Cx3VWqSr66%ghmNVZTwFDtpx% z#l*-=IC0SHuO&fFB_Tx#9^TbkzLf;F(~r5zzG0J!H5y5?n$@Z#k6jmey0^V6OfBIk z13x2wgKq%44>3Uh07h@s)99stN(BZy7G=Wt$6Z7*fUY+0JZJK$9;G^6bJESF z=ho7bv|xFMaK`|S)aj*4jTmEbV$QhEp@JGV#-lb8RF@Dy`GCd%^%U8wIa@(78&Z6; zmAa&D7$1K0_B7`7)IW-L8*85>vY4^fLW2X*N>9E(IQrCb?)}ParsiBHDN9}ymQnJA zkUhHrON?aS=mzw{_gmHaYh|XQ{9JZaFrO%d@#;}PuP$7c8=odDbTpxaskVYfeTbqi z-0u-?h;|~Bg{c84Ks&QS97LJ#yu{a>K}b^Z&H}x$=~{5Zky$17G4af;kC~*UN7Wnx zKGZpRT8Z9Lk6e3J?KBji3FHnruQpqC^c|&02j(5JD^y~lA3ntO?n*3P*h7#INss3>`@sW#~ziVA1G5PeZ-|)C?!M%ef{ZH z5CYVIvB1a*6e`zY(7c9RZI;~*AbH8(jOMYFf`XMK=eWf-Dg{|mN%p|aJ7FxB5|f1P z87d~Jt0kV4z-Se#1ntff$)?hqPEqBoDJvNm^rvpF3QEEjrL6Fh4{B!Gnsm0O6S05F zpsWOswMh0;PC~JmZIz@*LdZVUZr^cg%`vNmt@W8v&h&3b0+_V(ait~2tIS9l&v8>Y zuUc&ui4kVn{KB!p*>exGWRm%#xr?+!|lDrBG*Q8+@J>nfkP`xfqNEHk`z!V;}YgYj)w$t+a!<{PILb1OF<-WA{^!(0z2m+B}y6e zrEN&{s+>!a# zX>q`4aRsI)2G=pAr2t?6ykz^+XO@;7T!a;t#zH>zy5}(Mxh6Y`F6ZVOe+Z{g*%BhM z;Mh`6^Be$u=@NsZOe90^S2+d?%4xRHkVl)jIZ@`L52dM$36F&~!j-ioC+0tuOEnd? zLvE=_QFUQlfSxhy$Ec{>b>SOQ0VyPaQ`mY_F{GnFWNpg8g{PR1+WfUCvPcBywGo2M zBXec1nJqY>=BYd!{prl+WxC06K|!=9aM(NN=}$U)aI?RBZqs{X2zX#AN&pYPwQ7w~ znf3&|HY424xUl1kLbsKv&Dlxq$F)WqWwqVBlF?<)I5rXo87BiZIMob@_o*_Wr~Mfu zw%dg8Q}?E@u68E0)xo7gam$2<5<{D?03FCRWEoGfNVPun8-wVMNJ@afB#dXj+Ji`* zyH&+8Epl93cQ6##KO)H;kEiEL&Adu-(jv)APAN_mdCKL&F^m#@IH0OZ6@<95fK)qr zdm6Mstp5OwaovtBz0D1S&?J3*=?9=lhZHJG6NKP{p84%cy%sw&9FFqKiB2~VauxZ} zU*7h=+z;8_V7mVRn1>_2PvHSsP$I9OSjsiUXlS-%B?wA)4b6oTeYvJ`nrQ>fAtg?H z{{Z^?R$Y_v*Ds58u!4kyr6?Q_I~-Edpt&kQOmwZ?!+N%$@&4+r$wLnX#NpS5^+N6W{ zljovv;jm2~D*#4VKhOK|uqbsPwFuQXvqg{IYS$;Na5so4XO=xf)^=RI}(f z2j0A!e24J!YAKBBupA)mC+|aSBsF>B`AI5LmVwFO3PG8Yq$)+d56GE!~N6hf+e4qsD#f4k*Q&CMumvjkF!c*=+OJwZ@W%lbI?WT1toF z^ahOSZl2#YZl9NO)9jbiY-LW&WhX02G5CNVV?eBt+*_}SK4RN%hR_wapQR%sRms@V zr!0}8K?>KWiDI)lrmPeC8ieV%6B9r{Jx<;_TxDKB6y!ayq0BY>%4HM8A8j=pe3;O z14>pE*+k=jNc94(Ek)2h8F_}pd8n4sSYk_L##3lN#$jx%oyk0exKuyd134TRHnHj6 ziVKoMa@%rSuob~Z0f?Zc!1;S9j4RxB#ci+D^W4!N)E*`zT`aSov1yx`kc(@V2y2ki z62r|UXh)gC!isX@P7W21Y>a@1*Bx(YizOE(NL+MGE}}e5t0k9MZ$Il40o?Z~1zpA! z$IKBrQQbJqfvM!U-L*ECZ7j6J!0AhCb+g#2)DtxOC#$2w?-DD~Il!<>2x@as05`~7^LQ;gFCjqdIMoBq2m1)j`*&s)X z^7TFZO^V}gL!2Cpr(uM)<6#Iwnk^_4IpEbAS` z^t&I;Tc~J%1wLY%JHa62EeZqxPY1pYKx|j(I-dTwR}sb(g{_wwQa~wC8NtCLvVrei z39tGIqAm897`92cs6B2(MXARSryMDH=hW(zw*|$x^2(3l^a&L~>1c7S+LBhqIH%-1 z;?|Xp5<&uaKV*;VLpHY9xvjFMSG`QRPl<7kh8$ZsD?-W-DjB5orQXdJ>l%KiY{-m+ zoFf^^vBhoG!op?7P~GPFt`o<9nxkhj+Kx#Lwg}w5`24Fx)hMQOQ)I&b0DVp4d!9&b zvT)GGcB9w|J)+kTKziXYHqtGP6~`qUy6FUj=hWm1iz3$Sr=v%Rz0J52mHz;AdXw!% z?z7u!J9el^1(=*AWBJwn7>w68yY4s2m2}S~UV1wMy+md3o^U3)0 zAgtnhCO9RVK`$w?$tcAMZ@|kHR0C&YA zjmlZeyTZ@R2<=W#pCQ20WlBe>NyShPv8viqQWDY=<{wj73ju-(-Rr_>1zQ;ZqgEP4}8=bhG<)8Z7WJa1mkHLrCfULaB&Q`2#^v0BaQ&A ztWyzeQk1w%$}2*f34OApq#nu`{%@^3X-jqFph#LyH-v+O`qeTtJ%Q%oxRKCXQic>& z+cZ_gISLZI)v07JB>;jmLygf5?Ne}6l%pIKXFpn6e5YqcL5AYVS9GX$rOJqtL)Eg% zqLOV?N1dU>vUkZR2&cRQj@!Aq3D>( z5d0}DtnE8n*sqt5dMOerX2NDHR$23xoaI>B2dSj7kyZ(LN^!CvOG;Lw^EHl0_ooV* zAVLts#NZ9b7_DE7yGx3b7`CzyTX2vLGv6NHdT!u|T0_lEQr5r3*-kO}`p`FMVoXKL zi}D?CrR=RqE&gBn=7TmFk2?ZCn3Xm%m2tPYqB7Ko>GN4mKichD+iY)K^;wMFd@TNpc3dIU*w=5rUFQB!Y9t9AopS(=A+NPVzt@=M}Xp^7|9mW{%$$sLqi( zPFB*k^PHY>{vxaxdM?SQ^vjxx?IfyFJh^Nmj&d>wuc4+XHPAZ|UtTnY-IkI2%I@4K ziyXM%AtM9Vnv5*JlFCB%wp5aQ#SY+B+L9wS z#E7quWqD~>Qa=d_!5Q{AIQ)$pxyOXoma(?d<_YY+;he&V^3Z~zw4nCnW|?ZiYKt;G z-qMEU#G2YdqrSYUwIv`Zo(HJo?@o^(zJd0qUz28$7DbvfjK@!ygS=A8b@jkAe-Uu=Jw#3f%3mk8h~$?^|i* zSuIyXI`?Z6+I0>#fJobto;dnuh@{Z8`*xj1nuB$LdJo;yN?(YURFc|#_Ys5nR+jxs zDkZVz;<*(rID**AAgc%KO=l_qQhp92j9`=a@;<KnaYY5i8QDThR z)3M)%ONmkfRs6)HpT0ZPirAKC>zj+)q1=lW_a2IuTO}(ycx-O%jsU7{u8Fq$Dup`A z8UaXfJQe&EWNk{lcs~47nJ+am(hQZfk0kKdWfFgwf9vZ>&XPZSI;jxRv8iefAw7|m z9DsWo_4eA77Ue{O{CKMgQ$@vYD;V#ban65AE!Ik)d&z# zX4ISk`qa};^)~lrmptLc}1D zUuZr;*TBx;K^$ZbC`7AG=cW3PB6|!wE;{m*EM*R-vFuI<2a1+m5UI_eG4r4WCW5G(n!5#g`qI&C4>0MT)t~Px>n=Iuc4>FZ`t-R;=lfc+J z@N-bNSwsap9^nPX{v>Z{pdLsO8#lswdb zbo-7^H3YLWbeQwawDEX01F2T-bKj58(wi#pa+3k5(jukwGJZm}a#QX0qYSd-G{U(s zRUNqm1#MSl3}ra(KJ}L}wZYQS$;Ty$C5c3-Z#?=|wGyBQuW$0NQHzY(Xp%sW9l%nO R6c4zsRyP-Cpp8;L|JfT}Lh}Fs literal 0 HcmV?d00001 diff --git a/noir/docs/static/img/memes/titanic.jpeg b/noir/docs/static/img/memes/titanic.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a29f06ffb93b41a3be5478f89fa8810f28336100 GIT binary patch literal 59759 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 literal 255402 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� zkoT;$T&(5BVRD_%A--hKKOXMmmAmLx(4yjA$%P6c?YoY4Qi&HwAIN_`^(T}x17YQW?!;Or}DJ@Er_{=Brk-befK9g-UQT*3=R-aiY&3H1rQ_PDOLHerit6@b=r{QB=Yx@Ex{q zIOZtgiX=EwAByOtQeTa2dwu?U4i~jsY#*P(6hW5=1vED$ln)dJ97(%jy;Z#{7Ni(L zisO{xQ((~s@>W~cHT!-I7H()W58eQwl8ZnJVSn}B0fMCX0a(h@%T$ILJdU9mON)6p zAlZBKTk{0yyh2wC#emI+f^))6`=zzDN6W(pa_fWWLEZE#40~IRb)p7$m%)lcVLn) zdR1c5z_MB71%~TeKHv=s-}Hxm9s6l|hi5S#_%VzUpJxqqiB49WK#$&2Uv0zZk<>hf z-d_Cvs!lkt0qR{aaFb&Wo_wL|;>C*gc%{nw5y=ma(r>>m9cId{J16%Zy+L}h9Z}G! zj3A;I-E~xupfYP+v-=4(eTZi_O@%`25_d(4Poop}{F@6RuKf3_6NdD{-7u(kxzOBo zHzmv$32$<##-Ok+Wuzab;@DF72Sz94p>B@qnpZn9%K-+iW-D#O7j~vQVk`0Q30oAZ zg3}z#Dlj3^%7Um9MU?@_AA45IW`^P`@Ie5c;9c*NEGTJ#9$tp}G)rp1{(O+-b-zQs zjIR3jrAV)uaNL}0 z)Ec*~uzw9HVh#RNMCw~|H+Bk50`j(!SCY*HdjWpJACNqZ)+qZ8YojxA!T>rl; znpdlt%QzZ}cZ_8x?goBotU8ZAalZZJJXvMpo6}9fj~~z74j8nXJsn{^Yb&@vH#Fn$w-(d}^q`Na--ANk6$M%l( zYiA9R`@5>Mbah1>xWb>DN1gajefi_yL$Xc!!NvFDvK}QwQq2KcNB&vQ;)+&bm^$mE zq5yZ*3#<})8CN!tN@aC|=9dYl3XiV^7`u>y*%po9ZZX;agl zUSMRl$7ch@XL2id_%6d2a`tcJs@iB-k@xMxDY9(37+F?g&yjq@#5R_7XJ@xo%X?aZ)!W&zN#J)xp*r0h9> z7Z*fK&C|zTa@)6aiUmxJekcE_Yz2od3KGFD>#c26$tvQ8L1jr88eEA3<={-bh;`Gg0U*z|8z z4x8C$XDG{qZqTWgrV^?Ru!e11r8CwnDr<^g6#Br0h16Gpy7;j}=0hN^PW<_J#(m}n zzXLaMwa#4?OyLQ^lQB|X^bRGLCH}p#41nt#7+k{o<1TIk@5stu0yLSky`BZ&F#P=k zXIS;@Sq1wc5iQM_rpjgIUa%br(dy|sSVV3tdlQy(=&!1B*=*mI%8dXD0!{s*OJ4+V z&t_Pk=#5qL;pJ@m__PqVAz*K@_q*@@OkmyO=Cm8o^|uXSR!7oP!KUM>MbD*>z+D+J zA-+6V`LDQVSYWVIFLlxJ%5%=WvU^2i(3Pv;$Mv`nj{xN(n?JoKJG<$NNMc`*%N^dY zO&fssOHi?q?aJ^^q`SXmyS$so6}7(DiG?|F9Q;D|lI0+Z6xpw?4HK9V6Kwkwbvqwh zW`=b5RiI0hAOfR^#b2Z4!o?q5Y8e^5empMD+1D^ZR>WUFsSJ(%yA){IgfJsO`T>z@1g1U*ezJt@T(vJt$IWRN3aA$2ljLpwBELz&R+z}3Q^34gER_aIH> zbjinOjx492A7%J{MAv|G-eodRM_|L8i|b6r z;gs_MI)Jv99@Uas?tPJy&xEIBcE&DY&iS08l2ulynh^%1)6M-8Hlug;xaB-EMP(%# zM5#b(!M?B%Saq+xzf~J36gjILMUZT+R3=`RdRi$W^Yp2ttGTli(AH38z1s{2=Nj|C z7{M0Y`m?p2m;cCUs}QveVk}Pza}(N*=k#8>{q-Xl0>4oXy<8t4xA^|#py&H zWem49%o4V`Ou4#>Z!jZZ9LaHHLQHd`QKeQnN_i6Dgl%k?sp?xbg}u=v?lc2ua24 zaiGCK{Bno=)SM;H?J%nl)KPPl75TS*HM77U!j>O>k|1hS@qO;qmYm>it@_LpnlxGe zcs^!eF*5Hx)a7T6@cwJF#mS*YNicX3Qz z1sWL74rZ$l=>bZy%d@fSXes7r_+h>FDZe`2+gc*g%klFP8DP zX3cE77PmF{)FFPj`J;xnL^a4mbNFjP{*`vfKDDR`MADwSOD2|<|VVyYr{5dP` zJS>Y;y_%CLUgaI<+}7!XFxlOOWx@?tx}Wh>An%j;!JVvI+PbB6U^s4bdM;OnlcLIP z!45I|6?)$d26dfP)+!n-&|d`zXyxTojeo@HzdBMxS~w5DF!54a(w(8>=yjcMi|u@& z{0(q}7PAiti~pQ)`IzZfuI`QzgsYCn=c$d6*X9)&REcyAg+H@Bq19D z-Uh_*E^hjFN)CJ3YR74mcwe-SV_ZC4%FJ|0>C1bqhgYHQ+VUca}R* zN|;I$LC8VEjplUP3oHZ@Q&Un1l&aLZj>T!(g*!!ue?>8*?P^ES3fI9fH#abLjW&j6i* z5BEoAt+LZzL0%>+12Rgr%+E?JDyXmZKeSCP1D;1u?CaRCZ{Eo8HQmEB zc?2?X*VEr|6*i$Q2%8ywuV4VzuhVUdL4PDbmjH^CPMxX7Q@mOaT0TnP<=lQg2;b1v zH_a+Fs;N*LW#W>#p1~hGikl4&47T~`p%;)!gU+qY&)rvDk$&K(R@Ln+o}kA0`t9or zcB7Q?A>RPM@YFXvtQ*MyAi(%)pYyMEnMyH9z~?QB)<=Zsf2f{v}^S#k{zPC#y7QA zP7^@|rTan6Tv*0=s=fxqm|CLhubchf;}3!7&-$J(5!^mV^V7n0K+n&Ku6bLNHV1?? z{UfcxBIv@km)M~h*R4s4&2J{=I?&&}Oo-n&dCS(oBIZi8ReuQ6?m^0Sq4My=*f;m)M>k z77t;jTt0~`x=&;!KXvE1q)L7t+uyggJuWI7`-!P!tl^yz8j(zROHsvH1}NLU90}uv znyEXZCH0r?8~yC$z&(dmK!p8^wx@Y@eWq~6_S6p+4ylZDme~wrsCZ(0;qaah54MAF zq5$jDsCboDzv{eD^PvX$b{ad?WX&204eL&5CG5TYv-RPc)TQt($sc%e^;Y>d=IFKX z@Y;XfJZLguTYQ&y(G+7orw<;!UfdVae1Ad>zXEy&IdI97CjT&}J3uCZrJAKI1>oNl zmBf<7#ME|EaaJWi?U5S!8Gfx_Q%-b8h0-oo*HLLsV{@zTY6=DV5nIel?Q1Z?Lwy$~z!5wGa`W9Y`D2o}EDO>8gkUA5^1v1YTIUc+_q3LqjmTZxA z%{4gi?Ma?j$upxiNc_ri4?6nuGT%pz8dE4`z{Sh#ljT5@Gh!-jE)&lg!|p0N*?6(8 zm%T?(J#f#c5;0Cti-r-H9B7l2(;U)WCg$gC0b;|FB(?s|k(lo9`Yxk;92Xv!O5J~r zGXlqFDZ2P}|9ee|qXH;I&9JMkevJ93G(yqvs?KAg-Js$pSRYZVKMojLt}?LlFM(D6 z`<9ZLq8x2c=l$F#o%0Q z+7_b~n}Q->AW6Ne)JkbT<3P)!lH6}xp%~A#u}8X{?Dsm@AKw-KmQoEsiH0o~5VEiH z?6Z*d69F|mg-?0Tf*q3SWyrP?rD(^$q#2pA0gM^SAz6u5eAlq*ylB{2OeQExQ59P> zM_~i%f;2`oS)pp@akwEJ5JVTgweSy+;&Yax4g!Y8M~`wS9lmkYu2-wLkzlu{)B*Gz zbE=%NJQ?PjwlYQ`>$X*1*FCZRd)@~?Z8Tx}4&_2f_Xo8LXym<0?~5VyDLrfxvwCCY z^Q;Vf3(xuplKO66g=UqM^paR9O2|K$+St$8G(pw*SB?Th;aaIn8vnY0jAh1SvSuG5 zF1q$P^*P*7e8zyr$4g=SYB|u80Ok55WLbE9tu?2m{8;j?3bE`lRR(#A8lLrTgY6QG zU}3+CoQV2mS%*1*=TE9p5|xGcc61Q+Epg7Rk8EU$>>JT9*k$03oSf4t@ ztV)nSS$+5$s2|E07B`7^)`_KKPDAl`JKf5{P=>`w>zXoTrQZ*v73T}ubwgIcy$4}j z)XOW<&q;51em{5YaY}1CU0IW3n_6?H85eCYB=Z0-#z&I8ew#`V(*fsqj}Em20Yy3A zvRO05yll7^17|^rKF_Sh0wEiMl(?GliE#-{vVrch7l4SnP0m1dP=hKY<)v#+b5pBapQA%H<0IcIVX z$S``@;tVbcwI3O!u@48E)9fc!-Y=%OhY@XeZd>|Ay88M3VCBxv!vf}wj{`ju*Lfif zu+KBA1ssw0*=lZ=8L5IbUVjKPF&OGYyUXFgbA?iSowx|b6Khaz?-YGvRS~A}fL+93 z8qZkq<$B=t`pk=STrKj+5n2Adjp0E#7m&~{{Fd1{3h!bVw%r(RzmD9hs6@}`>=N0> zSA82kIBVk_bTC#midL1Vb8F(AWSbaMX8FxmFFU_gvbt>_H*6U$q-DnP7+yXB+mz1V z4c=oit`H-$?mg^0u&=wbZ&Kk`Qelf!@-T0LhTi=JtgsrkuGv*CuNK#Jsj=hPQZ5>k zT)~($N5CGCx+(o^t%H5ez}=Vw(lovLSR01=ANp(a!)}YO~go^&h>=W z0A_SUpkZieXwc~^+9M+>|1BkJsgrW(Kr(@j1t~ z^5ei&P+83(*`fW#5^HL>fMxpo?tW{c4qZnaPdPHJU3H55<61#((N13Bf7>TMsY5=M zyc`qMUBQ0}&>`~np0aq~59NpzERc6lPEBJgzVs7F0qi{k8aoAd#CYmw%z1Eg=B6V} zSrUZA0%Z^2jGbPec4WJ}&EV6ur40Z_ZRr_OI-TLHeEiqN7nVOU}zh=GpfMYsaOcswuZ|dOh~{spgl0VN>|=$G@76 z7#rT=8vpW^UfTGJH}H3G!YXr~FrK_ssCgQBA6$CqI0^VAZ?*`2(4}}j-$j;a1>djK zf&yfV79v}+PJUuh(3P~~0Nmk)g}hyn)&h!^`U}K(`Qi;LZY-`4w$q#TsC`w(Y*)9= zKf8vyBOVyd$)z`+%Db0o4lzvf&LHF@G7$$G;bU>(B=g;Q55%uw?J)aMib`Ov;~BEU z2I3L?JoVya6dF}ec-cEw9!jbovtc22CFcluw%PP5^)dIzclOauk1`{A+bf3n>Ho6T?1Wnsb4mN`ES>LER1_5! z4k}jFe=p8^F5s3)leP{I)0fh71zS(&FUuExd#EYM${f3ST1M&VBr0!Y6puWG`}_J|6&F3R565%eFKHC$^$8U77*L==FVes zA5NP0(HrTpR&d(+8yG75)S~k@Ff7u57?$xp5QT`TW9nC{u8sz>jguVf0XRT#vNB9kfH7zrf&%2<7aN$M)72YL0@^{PNK4!kA^Rr!w zRxDFpQg4jA_UxOSMdVdo{#lNYLKzQ~4>+g#rLUkm_8`v@-T=ClX#}aLPm4TmWQN3* zp_10b+sQfCkvA;gw=hQB)XV7B_$aHZdEbc^4yAg-TD_MX527F)iZ%4C)`lD5SzJ_f z+!_|8*5jH2_nxG_+uB==$%b#QV0%6R&h$6y&J5wH3ic1%a70KbRwY<Y*pMtc15Yj>a> z^C>_^I8`y-ci`NIuM5n|`lBtkOcr(FXDCvnZ>azpQ-_LpP1}SLKBw@E1$_wdy2P<9 zQ^}NWucuJ`-+@U_%8^e8`L8h}y)`&Gy7|;7eBR9rEZ)=mEaysYo_!&%e>cjlMv_Bnq0vsw>&7V1K`LZ&e zzr9#?v=>sK=orz<5_PM>w!fv*{u;mgLC1rCTDFk_fUoV{aBpMA*LJ(nG#kYLMs}gr zAU%KLI94;jYcOBeZn-aOB_2b{a!aWk1j6+?^IAz>&B1KHz0f`%VSWN5^u-SV=6Ir@ zedUf?ruw0vs1X|-%%f4mQ$HMeyYdr?>AH?s(wuzE0D|FEdhTj3MDM}v!}3?$^$c_h z^ig`?*irv-I07U2S24ZXD$DGqcBIj=@kM!(9?gAcvyAA}Gcq zx0_jU|2Dwr)IU+v8u%G1APiZveP=s?@)elMI9`S*s;<)Rw$$*;PbTOsQ51oVSmqRs z4zIv%qfy^?6L%@@U*9pbc_(Ud`|tFw7-I=>vNP{kX||5YbCJo7f|SIVYZrAA{Jkfk zWBFX!$fAj|pTOw0o(NLByU~GnWq11i;%H+^{F#_?Aq-KDU=JfE5jt!XqaVmGJO;H+ zP73?+C*7$EvE>h4%l)DSwDh{-F%wu;nn+Xmw(8~J0f_2>l}7YC=!@>Q?xFSTlYWo(Jt+*e==m;&r`+t-xIsRzY8)h!G}z{(e7%BC=L)sSfuf*?mmL>yL9>MBpG% ze~jx#zL>KD-*W%vXPO5kJ{n0QLq4aLwnPv%f|tIS&FXLTx@V=Sy-NURj`lG2B(@d9)E2RQYxY0ZR>^x< zePAB*7z&J99STY#NZ`YVmdeKUJ;_m<;3xliVpvsB{M0|;;a6#RxW$*A>u0VXFF~Ha zUi}X{Dvw?sbyx)Mdtl0_8SoF|EgT>C(4-u(7?s0TS3koa4<&sv`-gT(_4r7aD|!^H za!&z$*Qgk_gciNmw?BROheiL3uZ38qxol!@mnYQngTG;T@c#VYexbBM){@`9MNuOI z%Rl(aI~_(x7ZxS+6gi6?9nmsU)9BayTm1QX;=g{1$(!SJMgKr&dGO$~XOyJ*4fT76 zJv3gCGm8tt+y36Eu0Y_a9Pq{idmKjZo_)IJT{&b}CeHl#$M*-rKn#dB`(R|iFvFqU zXxY4fWT~76UnVS?Y529l1=YWQt9p!n54X-~R+M|NK84y&;Mv7t06M*|cXn>?9|D*|+j zH9ONerb_P|J-OWpkdKLoh1>X=yHFG;&#E2< z+&GE`CJC)q{_22U>#2Z@T$EpH>u~SzFM$hRZgBqnPk8$pE&70==Hn+2llQlu% zfDJ#r(XC6hp-v8bK~5O2t;sx;UbD;KNUAU@cg--umY6z@eHx78epuukOFFZxm3vZFY5ua0_P}j}@th zRiiqN4iou$Mc7O|Ii?}|kC@I-4Li&Jb-Vk~bI z@m(>^-z(b7-AE<0``o`v{>!i8#!tKB<+5k*AI{tx@!EGG$u06{NY+@V1_1V<)Go9kL8?aWwCidT^ruo2IFcRZ8w6}aeS$VnKHGn z>^B_sv59uC_m3z1dhJ^PSw{`@VjXhe)XxT$i)OyVeIjvx$=!Z*hn6U=N(2c--d?A{ z-n9CIX69E3WT;;z2Wp3~L-c64QxZUSfI3^8?5~oh0l?NM(3D$~7zEafBbNbJ1@->q zh4d-!MegBSFR0|bm)m>4Ms;Wm^wNXKr=Zuj`|^hFwQanJVLI@AQKB1XmYII_S;93^ z3YVjioP95xr-)xGwGd293&6_pagVPI0=XN0i*osQ1DRY^a%7QNaGEG0V0QBWq46hp z@O}z*T;T=vSH5YTXFiyfoxroOIc(qm(Nbeng_0k$i3oij&B!ixQkL!f9#{>7YWvzg zfBuLj=rNdZ!*art-W(8CkmK|;e`NYLO;$sx1N7RJE>GhF^g)OnLdkR3g0#7+{fyXV zfh+<;j135MMJB`_y;iWa1^sSj(yw)Eo)jVUgB*6}VB&gu_ z%+@)v`|oAJUe#ctO={lHm(R{eS9^^UM2Yx}q1}0fM&fGu(5~(_0a=Mi?&ve)bv#J2 zqF-ab1nt~6Qa(`fyey_h9$m4KQw$iryoDwNaXIvF{#d27i9k2}You&jTd(VkRNBW! zOZ&Q`koZ;Dc+bo>Q4`U;aUpqQ{vwzS5hBRN{T=j9=zRo*pGONqi-JF1o5K)rz%gf zgW;L(_tw-OEM-crb&93E@5Go?Bbs$AOL{43^#tpXiGB9PX8qUofI#$YrL zK5R}WLex5?2!2^u6j{HH$|R+u-PYQKuwy#l?JEoxhpjQlI2#R^G1x^U{lWhYN?5wG zR-c#su`1*7BFg$be@=;&T!mR>o+=8PkFR~t-{3>GZtxqlYxtRw5LeDPGF4a6jyDzz-x;5oTsm)}(e(&GRAZ{<%=6RhTz z<=S-~f0BW87^_g7`xGH#q?YI{Lo>iB{CZ&;?1ARX#FhE%t#f}LF=QK8W9IJsqZRfe zJa9;RrcVum?|aBY-31tG*cldYu>wCCu@D}b!K=yzu%Co{xem4phP=+FTpbzM0JitD z%bS3!@Z>DBzyVl!uUnk?T<3Ry3*MF~>BOq1LDGlTgi*W8;_V6&+-#Yl-yE?BD*2+e z6IZI}N3Yo+Gk;m(_PTD7JK~x0+V^NVh3R#X-#AGH4J~bmn+sfe<*2>Z-lAwsc38!V zKpn6x|BeOgZ2)Vngu0&>Z{jL$?}By{-SwXJb%;&FvHZ`2tp9>#OI8WP#RRod(l1@_V0Gtbza1o&)Gn3nfZRV*@ z4=1S8y&OAK=POtGvbu0EITf_rNqS%#Wj)F`*R8-%pVPBD<)P1FFs)>;N-dDQ)Fub`YEf0aeUwS^o4*X3zQ*!h*biQGdu>tMo`~bZl05?FjK=kgRxys$V+A6^_l+9`rG?I3 zg)Z+KJvo3U|2vgLW0|O>AeBHEk@CM&NtIi8YGq2TTXpI!_w1JBb&CpzQj6E#U*f#n zli5yhOA5RiyrPZ-e?)p&0_83AwF;%CScO}S{2lW#-+2D zQujvDSIX0XOsyktb||=iILB@FQOcWNDkhSx%)OtMcCXH7R%+p_Xkm~=k{Fl3|0@jM z{(7Hr$*k}V_07Q>)rcmK(St<~L`0?kv8~V$wXsHAbt9W8g7#_jrJ8NhK%=CKR*b;? zT~e~C$L7OB+P|U-_x8NLu=!QAo$ew8DO78B% zl+&t?_k+pb{!?{W7>`J4{HN-;_`B+GPma;z+0(bKQCV*%X%F3eGV~#;TklXLYgMxi zf2N4T))6}7G7(TF>kAVSUgs$C_jgo`bi4Pp2$#gJe>Z;d)vKXA`1;)%20yTyZHA2K zz6QqlgQk;4D=f~J;zSE!b$7HrlFCxW?Xy?q8-BQ+z}8l3OG~aDH^EyB7k{k%k!XM& z8_AWHaRzEL6}K_Oma_^gy`Ow$NX%{4Jorn01>6WS97^Q979{)R?a_xotQCl(MFsd@{o0nHqLgxWcy6G?o3wL8#9MjsWj3<{4qycfS^WA`WRauNUdFAIB$F) zbr9l&FyGa8C%s|(Y1E}YuJp$Dnc5DLxiQZk zz112N3@?BtG%d}%9edeF;fxvPwJ89z5sadYCaub7ZO)np11}<|a+bjobzsuT#fKND zWu&9E|(Y zo_%1v^osGc;^g^rn?VdR^_K0A;D>=N*-PRPenRIf)#p19Kc~_UpKMz_73O1Y@Wv?3 zfo&T^n!YG3+cd|%_0yQ?a&6uZ|3r($F8)@Ax*wr$%klSGZ}`raW%+dZisRe6$-2yl z>G0apNXy$7Rug3Zf~$7>!tw7DmKR=pV&Z$GcX)7JK$Umt+m=za%coVrdLX9sJ@fYf zRQ=0~>Nqx^s1awyYWPB;jZhnnSD}}4y#qahQp1<oB++VVps+wqd&<`NXh6 zsnLgTyP&AhsyCA4dUMrz;+dV^E72QRU;#AoV`_b}u1a~^C`%((ZHG>Mf7sZdZ2B&F zBDZx%E*duI4)xN4P@e~xRasX~Rk*%&a^X4V;OO9@U*Y61k}mB$mOG3xohyE?ut(n8 z;bevNA}IZ*73_^}aks4&iRD860$izha`s#f_*Tlb)kYgP;_`cd2rWrh_?CUo{{+3%*&hzrXpU=PhayG`f~~|9bmldlCi?yEpl>qWA76yuD5rd zXvCF$VbeG1Rp&~P?a-Yq4Trc~masS!8_JnHuga>ufit%^AUwGd|XST-4eSVRjF1WNbPr4NScEdtDMJ{Bw;?dg56S8gG(Ak`-`rKN1?mRiwS@k zuuaF^YKnb>+n>V~W9sK~1|eFFaN{>&{VR*{krD`P@-Rw^1O6Ogh=Bg=MUZQA6dI@B zFi!aH(T1q;@oI0|n86BY9sKC%`|9*x!gq;+eTv_U7x29Emok^JgVl=fE0Kuj_Ecyd zDZOPlb6%iQLW6uY@_>Mg1RXTU*K>J6w!eN=P;niVOKj#o?cy*|Fus}~_SnXU#KW|4$c8)r!j?%sf zU5-!n?Mr;>oFAW`p8A)Cg(Phe+vrHFAs@q&kGCs{s;SH`qCU&ceGsp=VFBZg?Xm>T z764S>XWx1P?`c1+V|u8#5{u>&d*y9kuRC!5EEKw#j+Vj!HrCqm$%a(mpw^QApeSaK5gPmI#d4qZ!QAB)Q^jA5_PnlW0R?Aas0gBH3?|tco<6Ss zh&#I!#X$%dL`1Bs&PI*J>l5=^_QToze`XaJmRozD$GKD&vr*;One%%U6-KBNs$-3$ zgEwJw#m-9JBvo|s6uQz6QNfA|lvfpatzXlEU zw_Sk*OmgkFv&#sx4^J)6p|z!+z6zYQ{`~HjPwQ)G)y-jP1A*S&-Ikjg@PY81 z44)U(_Y{7OG){Wd^1wGPk|%UBcIvu>gxwdqhZ)a_4ur&ucv8=a8f7j*405r)RDbf` zB69EwFGo7e+Z_0eH0&7D(NZ1!lVFX=Uv-;qKkU&mTVXftIJn81kI;`CH1Xc;=4U zDF4F4!o;%Xl@e`DDtuI?_~k*#r9%H{6P_=6a07}_CB`m{SEUMU5NiO}pB=^mu-_8> z?P?{Yn}&FV+n;VJty`}xIIP6OG+a50Y$Yp6j@i(;EMBxF;y^naR@X>3ztuW#itujN zDuAW>k}+#!RVpvsobx;l0C%^1^=(CoT|9EOE4O+WCLseoSE^rlK0KV*&=T9sy ziyU%}I;MfUeQp-eC{|?M=iY?7ZQ6#VD)=62R1M$py2~r9k#@*}j_w_8AH)Bynxb)F zYz;7Aola#W?g1R4#=B!M@J7k8BA|}yA_E7`eiO-OCvq=-;FcRQj^q&5Ne&y{kPFK( zaJ|bBR6JRdi&#Gu>7C{?UHQ^RA1-zvj!Cp;6H`7D8 zYM}9dSjD1w2bjs!`k4CT2iKLw#LnTGXfzpzIA(VDk;_Q9(kLy0h}RyNOH_eLImv=|3-cx#_H$-}~?2$@w=1ybrbK3XfRFFHrloePz-x-6c(Y}=0=+>mvg zS+f<#GeQ(mNXqtIpWTi;Hs*V6cI^1SoHykv97>eSYv3Pvb+k_L6H`F>Tv@zC%G_R`syLir93}(rVHJwU(XrdqU{iBw(=tC zV}lJ>UjoU4RHnx^Bm5oZev;?AHJjekUBzbs1Wp{g8zlG?#e>HI~z#A4w1~O-iZzj;% zc>AyhZxUR1g}_3W@toK}$RFB(_D`jQ-J^Uxa@I0d1;(4PpX5-sE)WU(xu29tsz7Ju zVPr+cq@|nTtr}-d5A%#)EeB#jqdD+OLGGa7m zzSO4cebZlqWk@ujmZQG7c16e;r~Wfdgu(m9n|eT3?X*7vWY-f{`ND8nCR9&gBAb41 zY4=kgkK5YK?XQU@DN~(ZqpjWp7Y--<5cu?y1cbbn(cHJ8Vm5- z;_}K&75NdmfWia%ljqaAF|4%Zl6aW4T5LC0peQr*cZy(G?6vBz(v%rNUp8 zP~td&7ZpK%W7kD^|LD$#nfWz`l{o5=mCd3^D!Z`WCQN5EEOC8Iz_(S46Uj?3 zdHqRM|GMVkBgmsMRi5j>buC!L;K1PXEd3d$)2H={jIwya$jX|j^+CwsyV7(?N=KFU z^vDYHJ|8dc1)$tp(3x$E9!`m8yHGMKnc~y=L%o-|>+?c*rD`;PO@Y?;hvN@yD6ig5 zUZy`F9THIn$qET`M3+~lZV-dlE+mp@5;+Al+;!mDte`NO{a0QyWD8b zALQr#e#fx-T0p-zS5-h{%oU`o-)xY8iGXiVyl9{0;hv5_-KH;7CcQqBwH|CjU$=~& zJzYgcRCI=aEqPcS6ZuRx_5_`pUx`oi&Cqxjy+WfR{UWmrU?TBpxUkD+KK@Ly#^C>k z*TMfe0Z=gkx<9iYoOyoZKXIymD1rICqnBCF$jFGutwxb+=+>f$_W^2rjy)t_@tJ$y zF4&~Z%&+xk1iJDgCuI&ODzMGGaX6V!v%RozN790~@efkvW?7*9!Z5BG=ZI7;g#n=U7W%7Yupgx4OTy1iHh#^Q%=1@SW!I;g6Iz=EepeL(`{58C%aao9x5U?^ku%BNtDO?& z#L5MTk5vOyu+~2qPI2tpo$p?Rg5u(!pBNsJ553l^2OlDNZ?VaJMH}K-y;X7SqX-(P z?hLo8!?63#2)Kj2O5KSgcZTcln2?8nyK}G#F#eQnyuY0K6Ig)06;m;#zWt>>h6!m@ zY}q>1r=Vf-?}*g04A0asLPRM#aOS{L=X4U7w83g)zJ#dJ;0?5B2_ zo3r(yuJGf6kuNtf+D9N%zC*&7EC*Lgpfc5$zmMa9{Dc$#xvs{;=Zp*e9N)`r)c4CV z(~o0-)Ww3WmK2TvEs(b9;*y5oW{Q{)pW6l>qY-z0)StiDIj9d?vu@=)o{$;E7FBwt z`upc0SZj}Jm*sWox63Z4Y}QLIYJQ8blr>TF;k*~|noVB0l_uTyt=3pZwEdRD)-mO= z%{nZ(EBa8E3%~S{^GVKe7f;Ek-A=ylaobnL00VE}k$sU12eyS1mW3BZm!IKX_ug%F z*R$NawUF892tV8Zn7g=Y<9T1Zev!Mr+5O~%tton+jQ*Dw{xSj|TogT&2&h`&%c^OT zEP!P2WA(M>6K?ZC>yZGuTR`{mLc)OGY3{}2p|?C{-qG9I9#(7?^}az(efeiJ#(h!K zzg@J-OZHE(kvqK96q$3NgN0^sXR86!+tL`vH$J6tEN7rCZ^o!cpPk_9Dl+5^9u6z6EewB+6 z+vtdeM-T`<^`jBUQC?7>Wxrrlu%+_dK4C9uQ(rK?R zRf6}=Tquyd!X$j>Xso>~_VOeUI8iuQ=v$GgvQXK#YsBdt)jPULzx08$pA6hdnwK*H ziS@(9Kzq)6kG^v~+dN=FT<30V;z}fYcUW$-3e#E*@3wJX0DrYI6i$mkl%@!`Nv^Hj z0=;a;>OG7$4z4pNPf&bfyH&;(;>(PZnk1b_Lrznl7R5|+u*e&_m|GM>^6ZEqC1AN zW1wp2(0T`={Urq(?%u@|b){Pr=k{PTK2lln9NQQ7IKYN%H8r_+PX3F0t;=Up{lP>N zOfzZ@Kso}F-U~;hC}qIq+E7b+={Wg%xX2eN%y-rDB0XZhHF0Mg3Kki{>qL(K)Ou@~ zCpXXu))L-CRl6>@U(F2lIc9w#@BV@6c%ZFKl0S&OZCdQP(_)Wq(4K=B+yk-wzZGW% z>T)Z>aQb9-(AETWNvk+{#G+SH^~&(jMKi0JjbYJtvJ%T$KPsLoL+i1`!=ufx9r9(c z7vxa@7$WIm=4>=L&X$r+aE{Qh2F$Lu7YOIEU@{OH^W6(RPv1ncA{~4Ui~c=dwkqi! zxYWMyw4has?OTOtP{n2m2{F!n1YC}q5GHp^()Iw}5Y3a5hq;)jif^~{J0S!W6U&2} zyEz=(F75;g&`fH}4VkKY&sM)0zLJ+CB-W^^Uw!WMY$D`U?aK|ZoC&tbtBT7*?Z1A> z11e0alM>S~Mf&kial3@0>PD%V;s}?-unBX`#_ZIk>kFB)KtXEL`T;kvk{B_{_0J`1Gkpp90xb~uQmwW>>peuYjY@if6!80)#%IW)xzyp*^X5~ zQCv0+m?)CBbJm(wY{7q&OQ`3BwL=_6oq!e-Qe@}6^UMQ92OuM44JjHuT@t(nv;Z$t zNd>oCZ?QIg851$)DxUd6bj#&@m@xZdr)oYZ94$71ib5LAi@D07<`atoDf$Pf7f{hT6oQGlr@_Ua9}>a&2lIQt5yCp+l z!3w~#n3N+FhN_-Dfg-=V)p6xWYO|_bi1D`;k+jsGIbg>55zxlxbN)TG$XMECdxEn4 z)vkl7!1HGMMpb9-&i6J3b5Uu0-q2Oc0pthU5zp13PBl3op=zDm)`CfVbBKi&i0JND zvqv%jk?L~?^@F;Pzqr-ee+@iCio7@33>SvzHg&ZKBGia6j2UVr|y>Eo8#x zlr3$B!3+&F8d)6vg5Z*FB=+Cu9{$>R8AUZmXD?&D&3OB9r~08HibbUQ*5Qizz)==< zWHv?J(3Y0pZnlSy1EeaUzR*wI+i)G#LGs>c_xI7O$?~W+147l(rI+t%A{7-%Kf-es zY05_JzCgm(y9_ux%`^*4{#a4}z@S(xQ&Y*pwegcze_nmhPtP^)-RD;Msf4P<~Z=@?xyj86q zpqIh!s!Sau%E2bz!Cc?7Sm&;Qx38&*cT8%`7eUs0WD|L62Ks+Ud-G^0{6GFTrO-l~ zRF=_($kK*{AxR}kWyU_0kY((9W~QhVMfS2ZO4%9vZbqqWMY0UWzB9%$7-qlk>GS>m z?z!jm{hV{}J*U$j&JoRfdo9n`yP7_6XhJO+B8zeTV9?9jk|-&dkfrpiJ4#Dt+*OdLv2S@ii+g7F=DBP<$!`6EYyg z6DjVsn%E_*eD{4WtA0g4D4H1phOlC#I9`r@2~g#T4y&P~nD$i%g&|c!&x<@o#I5)_ z(yT)gVr9`ShK9i4GskKGm5(#%R!!HZpFnUQ*W|8RDuYg0?-Wj9S-ol9H9fKq7l$gX z;ADUuW(_H(zREtm{C}%(=ZN5RE83J;YZP7_jBah3ru;bnmo}=ETHOg0m z%SlBrXJh!|o|^foHk31Vp3yhNxr*psCNiRJxH&k=nk<_u zwLeEp$y`po;_sdjkL~&IOBMDCT>`#n9XmR4ba!DaLU#S|dmr(J@R}m$b%N;Qf|F{IL4ra-5R;9r<+*xKq zI|Ax1xpe1tPWCzUBV;>eo86m3uTYH%p=fh5VkN>E8!b#aL+dTWIlbbhqbAWeLq8Nz z)sQFGI{G2w?b_i^h;*YOERFFj=syavFIzz41Wx_d#S{0@^^JKFu~)@yu}RM$;4ANem$&sbjmtAQff+FLpp(Um<$rMUjy0VgQ&$b&m5_m6Zg46s1@fH6= z>wcUyD4YXY`okCnmA%4c;F>bJ?+hq?$HffelUf^fzaRo8M702ib>TKFlpLo3hxIIj zSfw%W`

YRJ67x8+n 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 nF-?w|r*iH1)+)D>$E4W#aeY=%1>@ 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 Dpw;^&|GL&Mlb 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 AR{#J2 diff --git a/noir/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md b/noir/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md index b1e7ad11bfd2..1814365800af 100644 --- a/noir/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md +++ b/noir/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md @@ -107,6 +107,6 @@ Example of how it is used: use dep::std; fn main(x: u8, y: u8) -> pub u8 { - std::wrapping_add(x + y) + std::wrapping_add(x, y) } ``` diff --git a/noir/test_programs/compile_success_empty/regression_3964/Nargo.toml b/noir/test_programs/compile_success_empty/regression_3964/Nargo.toml new file mode 100644 index 000000000000..a3fd040bcc26 --- /dev/null +++ b/noir/test_programs/compile_success_empty/regression_3964/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3964" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/noir/test_programs/compile_success_empty/regression_3964/src/main.nr b/noir/test_programs/compile_success_empty/regression_3964/src/main.nr new file mode 100644 index 000000000000..0600a4281a08 --- /dev/null +++ b/noir/test_programs/compile_success_empty/regression_3964/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + let one: u8 = 1; + let p = ((one, 2), (3, 4)); + assert(p == p); +} diff --git a/noir/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml b/noir/test_programs/execution_success/prelude/Nargo.toml similarity index 100% rename from noir/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml rename to noir/test_programs/execution_success/prelude/Nargo.toml diff --git a/noir/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr b/noir/test_programs/execution_success/prelude/src/main.nr similarity index 59% rename from noir/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr rename to noir/test_programs/execution_success/prelude/src/main.nr index 9bf2ec18f3a4..c9ae448c4867 100644 --- a/noir/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr +++ b/noir/test_programs/execution_success/prelude/src/main.nr @@ -1,6 +1,6 @@ -fn main(x: Field, y: pub Field) { - let xs = Vec::new(); - let option = Option::none(); +fn main() { + let _xs = Vec::new(); + let _option = Option::none(); print("42\n"); println("42"); @@ -10,11 +10,10 @@ 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(); + let _xs = Vec::new(); + let _option = Option::none(); print("42\n"); println("42"); @@ -23,8 +22,8 @@ mod a { mod b { fn main() { - let xs = Vec::new(); - let option = Option::none(); + let _xs = Vec::new(); + let _option = Option::none(); print("42\n"); println("42"); diff --git a/noir/tooling/bb_abstraction_leaks/build.rs b/noir/tooling/bb_abstraction_leaks/build.rs index 166e61a5a97f..965a57747f97 100644 --- a/noir/tooling/bb_abstraction_leaks/build.rs +++ b/noir/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.16.0"; +const VERSION: &str = "0.17.0"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/noir/tooling/bb_abstraction_leaks/src/contract.sol b/noir/tooling/bb_abstraction_leaks/src/contract.sol deleted file mode 100644 index 814c81d235e7..000000000000 --- a/noir/tooling/bb_abstraction_leaks/src/contract.sol +++ /dev/null @@ -1,2575 +0,0 @@ -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // ### SUCCESS FLAG MEMORY LOCATIONS - uint256 internal constant GRAND_PRODUCT_SUCCESS_FLAG = 0x3300; - uint256 internal constant ARITHMETIC_TERM_SUCCESS_FLAG = 0x3020; - uint256 internal constant BATCH_OPENING_SUCCESS_FLAG = 0x3340; - uint256 internal constant OPENING_COMMITMENT_SUCCESS_FLAG = 0x3360; - uint256 internal constant PAIRING_PREAMBLE_SUCCESS_FLAG = 0x3380; - uint256 internal constant PAIRING_SUCCESS_FLAG = 0x33a0; - uint256 internal constant RESULT_FLAG = 0x33c0; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3400; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3420; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3440; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3460; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3480; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3500; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3520; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3540; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3560; - - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3580; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3600; - uint256 internal constant PLOOKUP_IDENTITY = 0x3620; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3640; - uint256 internal constant SORT_IDENTITY = 0x3660; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3680; - uint256 internal constant AUX_IDENTITY = 0x36a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x36c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x36e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3700; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3720; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3740; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3760; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3780; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x37a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; - - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant EC_SCALAR_MUL_FAILURE_SELECTOR = 0xf755f369; - bytes4 internal constant PROOF_FAILURE_SELECTOR = 0x0711fcec; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error EC_SCALAR_MUL_FAILURE(); - error PROOF_FAILURE(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - mstore(OPENING_COMMITMENT_SUCCESS_FLAG, success) - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, EC_SCALAR_MUL_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - mstore(PAIRING_PREAMBLE_SUCCESS_FLAG, success) - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - mstore(PAIRING_SUCCESS_FLAG, success) - mstore(RESULT_FLAG, mload(0x00)) - } - if iszero( - and( - and(and(mload(PAIRING_SUCCESS_FLAG), mload(RESULT_FLAG)), mload(PAIRING_PREAMBLE_SUCCESS_FLAG)), - mload(OPENING_COMMITMENT_SUCCESS_FLAG) - ) - ) { - mstore(0x0, PROOF_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/tooling/bb_abstraction_leaks/src/lib.rs b/noir/tooling/bb_abstraction_leaks/src/lib.rs index fec53809ad43..56a4f58cd211 100644 --- a/noir/tooling/bb_abstraction_leaks/src/lib.rs +++ b/noir/tooling/bb_abstraction_leaks/src/lib.rs @@ -7,13 +7,6 @@ pub const ACVM_BACKEND_BARRETENBERG: &str = "acvm-backend-barretenberg"; pub const BB_DOWNLOAD_URL: &str = env!("BB_BINARY_URL"); pub const BB_VERSION: &str = env!("BB_VERSION"); -/// Embed the Solidity verifier file -const ULTRA_VERIFIER_CONTRACT: &str = include_str!("contract.sol"); - -pub fn complete_barretenberg_verifier_contract(contract: String) -> String { - format!("{contract}{ULTRA_VERIFIER_CONTRACT}") -} - /// Removes the public inputs which are prepended to a proof by Barretenberg. pub fn remove_public_inputs(num_pub_inputs: usize, proof: &[u8]) -> Vec { // Barretenberg prepends the public inputs onto the proof so we need to remove diff --git a/noir/tooling/debugger/Cargo.toml b/noir/tooling/debugger/Cargo.toml index 4d37f801d787..4d240c61f90e 100644 --- a/noir/tooling/debugger/Cargo.toml +++ b/noir/tooling/debugger/Cargo.toml @@ -7,7 +7,6 @@ edition.workspace = true license.workspace = true [build-dependencies] -rustc_version = "0.4.0" build-data.workspace = true [dependencies] diff --git a/noir/tooling/debugger/build.rs b/noir/tooling/debugger/build.rs index 5d14ec2bae2a..cedeebcae865 100644 --- a/noir/tooling/debugger/build.rs +++ b/noir/tooling/debugger/build.rs @@ -1,24 +1,14 @@ -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() { diff --git a/noir/tooling/debugger/tests/debug.rs b/noir/tooling/debugger/tests/debug.rs index b2f441f56067..e8b17b8a7af2 100644 --- a/noir/tooling/debugger/tests/debug.rs +++ b/noir/tooling/debugger/tests/debug.rs @@ -28,7 +28,7 @@ mod tests { dbg_session .execute( &format!("{} debug --program-dir {}", nargo_bin, test_program_dir), - &format!(".*\\Starting debugger.*"), + ".*\\Starting debugger.*", ) .expect("Could not start debugger"); @@ -49,7 +49,7 @@ mod tests { // 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.*")) + .exp_regex(".*Circuit witness successfully solved.*") .expect("Expected circuit witness to be successfully solved."); } } diff --git a/noir/tooling/lsp/src/requests/goto_definition.rs b/noir/tooling/lsp/src/requests/goto_definition.rs index 2ff5901ff9cc..267519dfa1e1 100644 --- a/noir/tooling/lsp/src/requests/goto_definition.rs +++ b/noir/tooling/lsp/src/requests/goto_definition.rs @@ -116,6 +116,11 @@ where } } +/// Calculates the byte offset of a given character in a line. +/// LSP Clients (editors, eg. neovim) use a different coordinate (LSP Positions) system than the compiler. +/// +/// LSP Positions navigate through line numbers and character numbers, eg. `(line: 1, character: 5)` +/// meanwhile byte indexes are used within the compiler to navigate through the source code. fn character_to_line_offset(line: &str, character: u32) -> Result { let line_len = line.len(); let mut character_offset = 0; @@ -199,3 +204,25 @@ mod goto_definition_tests { assert!(&response.is_some()); } } + +#[cfg(test)] +mod character_to_line_offset_tests { + use super::*; + + #[test] + fn test_character_to_line_offset() { + let line = "Hello, dark!"; + let character = 8; + + let result = character_to_line_offset(line, character).unwrap(); + assert_eq!(result, 8); + + // In the case of a multi-byte character, the offset should be the byte index of the character + // byte offset for 8 character (黑) is expected to be 10 + let line = "Hello, 黑!"; + let character = 8; + + let result = character_to_line_offset(line, character).unwrap(); + assert_eq!(result, 10); + } +} diff --git a/noir/tooling/nargo/src/artifacts/contract.rs b/noir/tooling/nargo/src/artifacts/contract.rs index 4ade4f5660eb..04699126762d 100644 --- a/noir/tooling/nargo/src/artifacts/contract.rs +++ b/noir/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/noir/tooling/nargo/src/artifacts/program.rs b/noir/tooling/nargo/src/artifacts/program.rs index 664db0adca42..96e63e6fe502 100644 --- a/noir/tooling/nargo/src/artifacts/program.rs +++ b/noir/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/noir/tooling/nargo/src/constants.rs b/noir/tooling/nargo/src/constants.rs index ff8da403c695..0b50d61fe376 100644 --- a/noir/tooling/nargo/src/constants.rs +++ b/noir/tooling/nargo/src/constants.rs @@ -7,6 +7,8 @@ pub const PROOFS_DIR: &str = "proofs"; pub const SRC_DIR: &str = "src"; /// The directory to store circuits' serialized ACIR representations. pub const TARGET_DIR: &str = "target"; +/// The directory to store serialized ACIR representations of exported library functions. +pub const EXPORT_DIR: &str = "export"; // Files /// The file from which Nargo pulls prover inputs diff --git a/noir/tooling/nargo/src/workspace.rs b/noir/tooling/nargo/src/workspace.rs index 65f9ab7e0d9a..5696a7585315 100644 --- a/noir/tooling/nargo/src/workspace.rs +++ b/noir/tooling/nargo/src/workspace.rs @@ -10,7 +10,7 @@ use std::{ }; use crate::{ - constants::{CONTRACT_DIR, PROOFS_DIR, TARGET_DIR}, + constants::{CONTRACT_DIR, EXPORT_DIR, PROOFS_DIR, TARGET_DIR}, package::Package, }; @@ -40,6 +40,10 @@ impl Workspace { pub fn target_directory_path(&self) -> PathBuf { self.root_dir.join(TARGET_DIR) } + + pub fn export_directory_path(&self) -> PathBuf { + self.root_dir.join(EXPORT_DIR) + } } pub enum IntoIter<'a, T> { diff --git a/noir/tooling/nargo_cli/Cargo.toml b/noir/tooling/nargo_cli/Cargo.toml index f280682e15cd..2652adaf3277 100644 --- a/noir/tooling/nargo_cli/Cargo.toml +++ b/noir/tooling/nargo_cli/Cargo.toml @@ -51,7 +51,6 @@ dap.workspace = true # Backends backend-interface = { path = "../backend_interface" } -bb_abstraction_leaks.workspace = true # Logs tracing-subscriber.workspace = true diff --git a/noir/tooling/nargo_cli/build.rs b/noir/tooling/nargo_cli/build.rs index 6f6d65ee89cc..9a0492c99adb 100644 --- a/noir/tooling/nargo_cli/build.rs +++ b/noir/tooling/nargo_cli/build.rs @@ -14,9 +14,6 @@ fn check_rustc_version() { 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 @@ -39,6 +36,10 @@ fn main() { }; let test_dir = root_dir.join("test_programs"); + // Rebuild if the tests have changed + println!("cargo:rerun-if-changed=tests"); + println!("cargo:rerun-if-changed={}", test_dir.as_os_str().to_str().unwrap()); + generate_execution_success_tests(&mut test_file, &test_dir); generate_noir_test_success_tests(&mut test_file, &test_dir); generate_noir_test_failure_tests(&mut test_file, &test_dir); diff --git a/noir/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index fe79c0b8c233..1eb8153ce9bb 100644 --- a/noir/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -7,7 +7,6 @@ use crate::backends::Backend; 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; @@ -83,12 +82,5 @@ fn smart_contract_for_package( let program = compile_bin_package(file_manager, workspace, package, compile_options, expression_width)?; - let mut smart_contract_string = backend.eth_contract(&program.circuit)?; - - if backend.name() == ACVM_BACKEND_BARRETENBERG { - smart_contract_string = - bb_abstraction_leaks::complete_barretenberg_verifier_contract(smart_contract_string); - } - - Ok(smart_contract_string) + Ok(backend.eth_contract(&program.circuit)?) } diff --git a/noir/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/tooling/nargo_cli/src/cli/compile_cmd.rs index 661081778c3e..31105ebe68f2 100644 --- a/noir/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/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, @@ -233,22 +232,17 @@ fn compile_contract( Ok((optimized_contract, warnings)) } -fn save_program( +pub(super) fn save_program( program: CompiledProgram, package: &Package, 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/noir/tooling/nargo_cli/src/cli/export_cmd.rs b/noir/tooling/nargo_cli/src/cli/export_cmd.rs new file mode 100644 index 000000000000..ac3e93e09b7f --- /dev/null +++ b/noir/tooling/nargo_cli/src/cli/export_cmd.rs @@ -0,0 +1,120 @@ +use nargo::errors::CompileError; +use noirc_errors::FileDiagnostic; +use rayon::prelude::*; + +use fm::FileManager; +use iter_extended::try_vecmap; +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::{ + compile_no_check, file_manager_with_stdlib, CompileOptions, CompiledProgram, + NOIR_ARTIFACT_VERSION_STRING, +}; + +use noirc_frontend::graph::CrateName; + +use clap::Args; + +use crate::backends::Backend; +use crate::errors::CliError; + +use super::check_cmd::check_crate_and_report_errors; + +use super::compile_cmd::report_errors; +use super::fs::program::save_program_to_file; +use super::NargoConfig; + +/// Exports functions marked with #[export] attribute +#[derive(Debug, Clone, Args)] +pub(crate) struct ExportCommand { + /// The name of the package to compile + #[clap(long, conflicts_with = "workspace")] + package: Option, + + /// Compile all packages in the workspace + #[clap(long, conflicts_with = "package")] + workspace: bool, + + #[clap(flatten)] + compile_options: CompileOptions, +} + +pub(crate) fn run( + _backend: &Backend, + args: ExportCommand, + config: NargoConfig, +) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let default_selection = + if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; + let selection = args.package.map_or(default_selection, PackageSelection::Selected); + + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), + )?; + + 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 library_packages: Vec<_> = + workspace.into_iter().filter(|package| package.is_library()).collect(); + + library_packages + .par_iter() + .map(|package| { + compile_exported_functions( + &workspace_file_manager, + &workspace, + package, + &args.compile_options, + ) + }) + .collect() +} + +fn compile_exported_functions( + file_manager: &FileManager, + workspace: &Workspace, + package: &Package, + compile_options: &CompileOptions, +) -> Result<(), CliError> { + let (mut context, crate_id) = prepare_package(file_manager, package); + check_crate_and_report_errors( + &mut context, + crate_id, + compile_options.deny_warnings, + compile_options.disable_macros, + compile_options.silence_warnings, + )?; + + let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); + + let exported_programs = try_vecmap( + exported_functions, + |(function_name, function_id)| -> Result<(String, CompiledProgram), CompileError> { + // TODO: We should to refactor how to deal with compilation errors to avoid this. + let program = compile_no_check(&context, compile_options, function_id, None, false) + .map_err(|error| vec![FileDiagnostic::from(error)]); + + let program = report_errors( + program.map(|program| (program, Vec::new())), + file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + )?; + + Ok((function_name, program)) + }, + )?; + + let export_dir = workspace.export_directory_path(); + for (function_name, program) in exported_programs { + save_program_to_file(&program.into(), &function_name.parse().unwrap(), &export_dir); + } + Ok(()) +} diff --git a/noir/tooling/nargo_cli/src/cli/fs/program.rs b/noir/tooling/nargo_cli/src/cli/fs/program.rs index 807df25ba48f..1d2f012736ee 100644 --- a/noir/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/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 = diff --git a/noir/tooling/nargo_cli/src/cli/mod.rs b/noir/tooling/nargo_cli/src/cli/mod.rs index cbed65593a10..01adbe9da980 100644 --- a/noir/tooling/nargo_cli/src/cli/mod.rs +++ b/noir/tooling/nargo_cli/src/cli/mod.rs @@ -17,6 +17,7 @@ mod compile_cmd; mod dap_cmd; mod debug_cmd; mod execute_cmd; +mod export_cmd; mod fmt_cmd; mod info_cmd; mod init_cmd; @@ -69,6 +70,8 @@ enum NargoCommand { Init(init_cmd::InitCommand), Execute(execute_cmd::ExecuteCommand), #[command(hide = true)] // Hidden while the feature is being built out + Export(export_cmd::ExportCommand), + #[command(hide = true)] // Hidden while the feature is being built out Debug(debug_cmd::DebugCommand), Prove(prove_cmd::ProveCommand), Verify(verify_cmd::VerifyCommand), @@ -109,6 +112,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), + NargoCommand::Export(args) => export_cmd::run(&backend, args, config), NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config), NargoCommand::Test(args) => test_cmd::run(&backend, args, config), diff --git a/noir/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/tooling/nargo_cli/src/cli/test_cmd.rs index 32893baa1577..69f03b49cbde 100644 --- a/noir/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/tooling/nargo_cli/src/cli/test_cmd.rs @@ -144,7 +144,7 @@ fn run_tests( for (test_name, test_function) in test_functions { write!(writer, "[{}] Testing {test_name}... ", package.name) - .expect("Failed to write to stdout"); + .expect("Failed to write to stderr"); writer.flush().expect("Failed to flush writer"); match run_test( @@ -159,13 +159,13 @@ fn run_tests( writer .set_color(ColorSpec::new().set_fg(Some(Color::Green))) .expect("Failed to set color"); - writeln!(writer, "ok").expect("Failed to write to stdout"); + writeln!(writer, "ok").expect("Failed to write to stderr"); } TestStatus::Fail { message, error_diagnostic } => { writer .set_color(ColorSpec::new().set_fg(Some(Color::Red))) .expect("Failed to set color"); - writeln!(writer, "{message}\n").expect("Failed to write to stdout"); + writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); if let Some(diag) = error_diagnostic { noirc_errors::reporter::report_all( context.file_manager.as_file_map(), @@ -189,12 +189,13 @@ fn run_tests( writer.reset().expect("Failed to reset writer"); } - write!(writer, "[{}] ", package.name).expect("Failed to write to stdout"); + write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); if count_failed == 0 { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); - writeln!(writer, "{count_all} test{plural} passed").expect("Failed to write to stdout"); + write!(writer, "{count_all} test{plural} passed").expect("Failed to write to stderr"); writer.reset().expect("Failed to reset writer"); + writeln!(writer).expect("Failed to write to stderr"); Ok(()) } else { @@ -207,13 +208,15 @@ fn run_tests( .set_color(ColorSpec::new().set_fg(Some(Color::Green))) .expect("Failed to set color"); write!(writer, "{count_passed} test{plural_passed} passed, ",) - .expect("Failed to write to stdout"); + .expect("Failed to write to stderr"); } + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red))).expect("Failed to set color"); - writeln!(writer, "{count_failed} test{plural_failed} failed") - .expect("Failed to write to stdout"); + write!(writer, "{count_failed} test{plural_failed} failed") + .expect("Failed to write to stderr"); writer.reset().expect("Failed to reset writer"); + // Writes final newline. Err(CliError::Generic(String::new())) } } diff --git a/noir/tooling/noir_codegen/.gitignore b/noir/tooling/noir_codegen/.gitignore index 15ea344d4535..29b0e40ffa84 100644 --- a/noir/tooling/noir_codegen/.gitignore +++ b/noir/tooling/noir_codegen/.gitignore @@ -1,5 +1,5 @@ crs lib -!test/*/target test/codegen +test/test_lib/export diff --git a/noir/tooling/noir_codegen/package.json b/noir/tooling/noir_codegen/package.json index 97bab8157647..7d76b1a91381 100644 --- a/noir/tooling/noir_codegen/package.json +++ b/noir/tooling/noir_codegen/package.json @@ -35,9 +35,9 @@ "dev": "tsc-multi --watch", "build": "tsc", "test": "yarn test:codegen && yarn test:node && yarn test:clean", - "test:codegen": "tsx src/main.ts ./test/assert_lt/target/** --out-dir ./test/codegen", + "test:codegen": "nargo export --program-dir=./test/test_lib && tsx src/main.ts ./test/test_lib/export/** --out-dir ./test/codegen", "test:node": "mocha --timeout 25000 --exit --config ./.mocharc.json", - "test:clean": "rm -rf ./test/codegen", + "test:clean": "rm -rf ./test/codegen ./test/test_lib/export", "prettier": "prettier 'src/**/*.ts'", "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", diff --git a/noir/tooling/noir_codegen/src/index.ts b/noir/tooling/noir_codegen/src/index.ts index 19829cd06ff0..fbbab07bcfee 100644 --- a/noir/tooling/noir_codegen/src/index.ts +++ b/noir/tooling/noir_codegen/src/index.ts @@ -46,14 +46,14 @@ export const codegen = (programs: [string, CompiledCircuit][]): string => { functions.push(codegenFunction(name, stripUnwantedFields(program), function_sig)); } + const structTypeDefinitions: string = codegenStructDefinitions(structTypeMap, primitiveTypeMap); + // Add the primitive Noir types that do not have a 1-1 mapping to TypeScript. const primitiveTypeAliases: string[] = []; for (const value of primitiveTypeMap.values()) { primitiveTypeAliases.push(`export type ${value.aliasName} = ${value.tsType};`); } - const structTypeDefinitions: string = codegenStructDefinitions(structTypeMap, primitiveTypeMap); - results = results.concat(...primitiveTypeAliases, '', structTypeDefinitions, ...functions); return results.join('\n'); diff --git a/noir/tooling/noir_codegen/test/assert_lt/target/assert_lt.json b/noir/tooling/noir_codegen/test/assert_lt/target/assert_lt.json deleted file mode 100644 index be1b134d6424..000000000000 --- a/noir/tooling/noir_codegen/test/assert_lt/target/assert_lt.json +++ /dev/null @@ -1 +0,0 @@ -{"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":"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"} \ No newline at end of file diff --git a/noir/tooling/noir_codegen/test/index.test.ts b/noir/tooling/noir_codegen/test/index.test.ts index 822993b2f1e4..03fb680a537d 100644 --- a/noir/tooling/noir_codegen/test/index.test.ts +++ b/noir/tooling/noir_codegen/test/index.test.ts @@ -1,10 +1,12 @@ import { expect } from 'chai'; -import { assert_lt, MyStruct, u64, ForeignCallHandler } from './codegen/index.js'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore File is codegenned at test time. +import { exported_function_foo, MyStruct, u64, ForeignCallHandler } from './codegen/index.js'; it('codegens a callable function', async () => { - const my_struct = { foo: true, bar: ['12345', '12345', '12345'] }; + const my_struct = { foo: true, bar: ['12345', '12345', '12345'], baz: '0x00' }; - const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt( + const [sum, constant, struct]: [u64, u64, MyStruct] = await exported_function_foo( '2', '3', [0, 0, 0, 0, 0], @@ -18,7 +20,7 @@ it('codegens a callable function', async () => { expect(sum).to.be.eq('0x05'); expect(constant).to.be.eq('0x03'); - expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] }); + expect(struct).to.be.deep.eq(my_struct); }); it('allows passing a custom foreign call handler', async () => { @@ -33,9 +35,9 @@ it('allows passing a custom foreign call handler', async () => { return []; }; - const my_struct = { foo: true, bar: ['12345', '12345', '12345'] }; + const my_struct = { foo: true, bar: ['12345', '12345', '12345'], baz: '0x00' }; - const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt( + const [sum, constant, struct]: [u64, u64, MyStruct] = await exported_function_foo( '2', '3', [0, 0, 0, 0, 0], @@ -100,5 +102,5 @@ it('allows passing a custom foreign call handler', async () => { expect(sum).to.be.eq('0x05'); expect(constant).to.be.eq('0x03'); - expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] }); + expect(struct).to.be.deep.eq(my_struct); }); diff --git a/noir/tooling/noir_codegen/test/assert_lt/Nargo.toml b/noir/tooling/noir_codegen/test/test_lib/Nargo.toml similarity index 55% rename from noir/tooling/noir_codegen/test/assert_lt/Nargo.toml rename to noir/tooling/noir_codegen/test/test_lib/Nargo.toml index f32ec18cae78..74b6167b614a 100644 --- a/noir/tooling/noir_codegen/test/assert_lt/Nargo.toml +++ b/noir/tooling/noir_codegen/test/test_lib/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "assert_lt" -type = "bin" +name = "test_lib" +type = "lib" authors = [""] [dependencies] diff --git a/noir/tooling/noir_codegen/test/assert_lt/src/main.nr b/noir/tooling/noir_codegen/test/test_lib/src/lib.nr similarity index 55% rename from noir/tooling/noir_codegen/test/assert_lt/src/main.nr rename to noir/tooling/noir_codegen/test/test_lib/src/lib.nr index ed370bd87c03..23607c6f65f1 100644 --- a/noir/tooling/noir_codegen/test/assert_lt/src/main.nr +++ b/noir/tooling/noir_codegen/test/test_lib/src/lib.nr @@ -1,6 +1,7 @@ struct MyStruct { foo: bool, bar: [str<5>; 3], + baz: Field } struct NestedStruct { @@ -9,13 +10,8 @@ struct NestedStruct { baz: u64 } -fn main( - x: u64, - y: pub u64, - array: [u8; 5], - my_struct: NestedStruct, - string: str<5> -) -> pub (u64, u64, MyStruct) { +#[export] +fn exported_function_foo(x: u64, y: u64, array: [u8; 5], my_struct: NestedStruct, string: str<5>) -> (u64, u64, MyStruct) { assert(array.len() == 5); assert(my_struct.foo.foo); assert(string == "12345"); @@ -24,3 +20,8 @@ fn main( assert(x < y); (x + y, 3, my_struct.foo) } + +#[export] +fn exported_function_bar(my_struct: NestedStruct) -> (u64) { + my_struct.baz +} diff --git a/noir/tooling/noir_js_backend_barretenberg/package.json b/noir/tooling/noir_js_backend_barretenberg/package.json index 93fdc8563381..1688db1ab2d6 100644 --- a/noir/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.16.0", + "@aztec/bb.js": "0.17.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/tooling/noir_js_backend_barretenberg/src/index.ts b/noir/tooling/noir_js_backend_barretenberg/src/index.ts index 100418debd01..6e619fd59cf3 100644 --- a/noir/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/noir/tooling/noir_js_backend_barretenberg/src/index.ts @@ -5,8 +5,7 @@ import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; import { BackendOptions } from './types.js'; import { deflattenPublicInputs, flattenPublicInputsAsArray } from './public_inputs.js'; -export { flattenPublicInputs } from './public_inputs.js'; - +export { publicInputsToWitnessMap } from './public_inputs.js'; // This is the number of bytes in a UltraPlonk proof // minus the public inputs. const numBytesInProofWithoutPublicInputs: number = 2144; @@ -34,7 +33,7 @@ export class BarretenbergBackend implements Backend { // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); - const api = await Barretenberg.new(this.options.threads); + const api = await Barretenberg.new({ threads: this.options.threads }); const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); const crs = await Crs.new(subgroupSize + 1); @@ -95,7 +94,7 @@ export class BarretenbergBackend implements Backend { const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); const proof = proofWithPublicInputs.slice(splitIndex); - const publicInputs = deflattenPublicInputs(publicInputsConcatenated, this.acirCircuit.abi); + const publicInputs = deflattenPublicInputs(publicInputsConcatenated); return { proof, publicInputs }; } @@ -127,7 +126,9 @@ export class BarretenbergBackend implements Backend { }> { await this.instantiate(); const proof = reconstructProofWithPublicInputs(proofData); - const proofAsFields = await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs); + const proofAsFields = ( + await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs) + ).slice(numOfPublicInputs); // TODO: perhaps we should put this in the init function. Need to benchmark // TODO how long it takes. diff --git a/noir/tooling/noir_js_backend_barretenberg/src/public_inputs.ts b/noir/tooling/noir_js_backend_barretenberg/src/public_inputs.ts index 37bc5b130122..75ee0de68007 100644 --- a/noir/tooling/noir_js_backend_barretenberg/src/public_inputs.ts +++ b/noir/tooling/noir_js_backend_barretenberg/src/public_inputs.ts @@ -1,18 +1,11 @@ import { Abi, WitnessMap } from '@noir-lang/types'; -export function flattenPublicInputs(publicInputs: WitnessMap): string[] { - const publicInputIndices = [...publicInputs.keys()].sort((a, b) => a - b); - const flattenedPublicInputs = publicInputIndices.map((index) => publicInputs.get(index) as string); - return flattenedPublicInputs; -} - -export function flattenPublicInputsAsArray(publicInputs: WitnessMap): Uint8Array { - const flatPublicInputs = flattenPublicInputs(publicInputs); - const flattenedPublicInputs = flatPublicInputs.map(hexToUint8Array); +export function flattenPublicInputsAsArray(publicInputs: string[]): Uint8Array { + const flattenedPublicInputs = publicInputs.map(hexToUint8Array); return flattenUint8Arrays(flattenedPublicInputs); } -export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array, abi: Abi): WitnessMap { +export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array): string[] { const publicInputSize = 32; const chunkedFlattenedPublicInputs: Uint8Array[] = []; @@ -21,6 +14,16 @@ export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array, abi: Ab chunkedFlattenedPublicInputs.push(publicInput); } + return chunkedFlattenedPublicInputs.map(uint8ArrayToHex); +} + +export function witnessMapToPublicInputs(publicInputs: WitnessMap): string[] { + const publicInputIndices = [...publicInputs.keys()].sort((a, b) => a - b); + const flattenedPublicInputs = publicInputIndices.map((index) => publicInputs.get(index) as string); + return flattenedPublicInputs; +} + +export function publicInputsToWitnessMap(publicInputs: string[], abi: Abi): WitnessMap { const return_value_witnesses = abi.return_witnesses; const public_parameters = abi.parameters.filter((param) => param.visibility === 'public'); const public_parameter_witnesses: number[] = public_parameters.flatMap((param) => @@ -35,13 +38,13 @@ export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array, abi: Ab (a, b) => a - b, ); - const publicInputs: WitnessMap = new Map(); + const witnessMap: WitnessMap = new Map(); public_input_witnesses.forEach((witness_index, index) => { - const witness_value = uint8ArrayToHex(chunkedFlattenedPublicInputs[index]); - publicInputs.set(witness_index, witness_value); + const witness_value = publicInputs[index]; + witnessMap.set(witness_index, witness_value); }); - return publicInputs; + return witnessMap; } function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array { diff --git a/noir/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts b/noir/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts index dab1c56436a5..079a1ad268b8 100644 --- a/noir/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts +++ b/noir/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts @@ -1,6 +1,6 @@ import { Abi } from '@noir-lang/types'; import { expect } from 'chai'; -import { flattenPublicInputsAsArray, deflattenPublicInputs, flattenPublicInputs } from '../src/public_inputs.js'; +import { witnessMapToPublicInputs, publicInputsToWitnessMap } from '../src/public_inputs.js'; const abi: Abi = { parameters: [ @@ -69,7 +69,7 @@ it('flattens a witness map in order of its witness indices', async () => { ]), ); - const flattened_public_inputs = flattenPublicInputs(witness_map); + const flattened_public_inputs = witnessMapToPublicInputs(witness_map); expect(flattened_public_inputs).to.be.deep.eq([ '0x0000000000000000000000000000000000000000000000000000000000000002', '0x000000000000000000000000000000000000000000000000000000000000000b', @@ -89,8 +89,8 @@ it('recovers the original witness map when deflattening a public input array', a ]), ); - const flattened_public_inputs = flattenPublicInputsAsArray(witness_map); - const deflattened_public_inputs = deflattenPublicInputs(flattened_public_inputs, abi); + const flattened_public_inputs = witnessMapToPublicInputs(witness_map); + const deflattened_public_inputs = publicInputsToWitnessMap(flattened_public_inputs, abi); expect(deflattened_public_inputs).to.be.deep.eq(witness_map); }); diff --git a/noir/tooling/noir_js_types/src/types.ts b/noir/tooling/noir_js_types/src/types.ts index b997d92425d3..ee4921bd6062 100644 --- a/noir/tooling/noir_js_types/src/types.ts +++ b/noir/tooling/noir_js_types/src/types.ts @@ -1,4 +1,4 @@ -import { Abi, WitnessMap } from '@noir-lang/noirc_abi'; +import { Abi } from '@noir-lang/noirc_abi'; export { Abi, WitnessMap } from '@noir-lang/noirc_abi'; @@ -45,7 +45,7 @@ export interface Backend { * */ export type ProofData = { /** @description Public inputs of a proof */ - publicInputs: WitnessMap; + publicInputs: string[]; /** @description An byte array representing the proof */ proof: Uint8Array; }; diff --git a/noir/tooling/noirc_abi/src/lib.rs b/noir/tooling/noirc_abi/src/lib.rs index 884c49c01066..066b1635ced6 100644 --- a/noir/tooling/noirc_abi/src/lib.rs +++ b/noir/tooling/noirc_abi/src/lib.rs @@ -157,11 +157,7 @@ impl AbiType { .expect("Cannot have variable sized strings as a parameter to main"); Self::String { length: size } } - Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), - Type::Error => unreachable!(), - Type::Unit => unreachable!(), - Type::Constant(_) => unreachable!(), - Type::TraitAsType(..) => unreachable!(), + Type::Struct(def, ref args) => { let struct_type = def.borrow(); let fields = struct_type.get_fields(args); @@ -175,12 +171,17 @@ impl AbiType { let fields = vecmap(fields, |typ| Self::from_type(context, typ)); Self::Tuple { fields } } - Type::TypeVariable(_, _) => unreachable!(), - Type::NamedGeneric(..) => unreachable!(), - Type::Forall(..) => unreachable!(), - Type::Function(_, _, _) => unreachable!(), + Type::Error + | Type::Unit + | Type::Constant(_) + | Type::TraitAsType(..) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(..) + | Type::Forall(..) + | Type::NotConstant + | Type::Function(_, _, _) => unreachable!("Type cannot be used in the abi"), + Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), - Type::NotConstant => unreachable!(), } } diff --git a/noir/yarn.lock b/noir/yarn.lock index 65b977864b4d..01860e559218 100644 --- a/noir/yarn.lock +++ b/noir/yarn.lock @@ -235,6 +235,20 @@ __metadata: languageName: node linkType: hard +"@aztec/bb.js@npm:0.17.0": + version: 0.17.0 + resolution: "@aztec/bb.js@npm:0.17.0" + dependencies: + comlink: ^4.4.1 + commander: ^10.0.1 + debug: ^4.3.4 + tslib: ^2.4.0 + bin: + bb.js: dest/node/main.js + checksum: 459838076e4db7e6ca17f95acbd5c83028ea3b5c21e016a1561cec065a95d20e8d65906ad63e44e071556bc331070ceda6d48c058f5accdb76b3c6daab8ef1a5 + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 resolution: "@babel/code-frame@npm:7.23.5" @@ -3958,7 +3972,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.16.0 + "@aztec/bb.js": 0.17.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 From 7c285348668ad5b1f30229745020bb7908ea8152 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 9 Jan 2024 19:13:15 +0000 Subject: [PATCH 2/3] chore: fix builds --- noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs | 4 ++-- noir/acvm-repo/brillig_vm/src/black_box.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs index db58795c8815..eb16c984b00a 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -177,10 +177,10 @@ pub(crate) fn solve( BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) } - BlackBoxFuncCall::EmbeddedCurveAdd { outputs, input1_x, input1_y, input2_x, input2_y } => { + BlackBoxFuncCall::EmbeddedCurveAdd { .. } => { todo!(); } - BlackBoxFuncCall::EmbeddedCurveDouble { outputs, input_x, input_y } => { + BlackBoxFuncCall::EmbeddedCurveDouble { .. } => { todo!(); } // Recursive aggregation will be entirely handled by the backend and is not solved by the ACVM diff --git a/noir/acvm-repo/brillig_vm/src/black_box.rs b/noir/acvm-repo/brillig_vm/src/black_box.rs index 732c383e08fb..012d527e44ed 100644 --- a/noir/acvm-repo/brillig_vm/src/black_box.rs +++ b/noir/acvm-repo/brillig_vm/src/black_box.rs @@ -194,6 +194,8 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, BlackBoxOp::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul, + BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, + BlackBoxOp::EmbeddedCurveDouble { .. } => BlackBoxFunc::EmbeddedCurveDouble, } } From 9e77976a130af9b9fc3306a47768f7c182769047 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 9 Jan 2024 19:39:36 +0000 Subject: [PATCH 3/3] chore: update lockfile --- yarn-project/yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 6cd9c7ffcd5e..9aefd3093359 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -2766,7 +2766,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@portal:../noir/packages/backend_barretenberg::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@aztec/bb.js": 0.16.0 + "@aztec/bb.js": 0.17.0 "@noir-lang/types": 0.22.0 fflate: ^0.8.0 languageName: node